atomisp: adding atomisp driver from r2 branch
authorTao Jing <jing.tao@intel.com>
Thu, 17 Nov 2011 14:16:23 +0000 (22:16 +0800)
committerGross, Mark <mark.gross@intel.com>
Mon, 21 Nov 2011 09:00:13 +0000 (01:00 -0800)
uploaded origin driver:
78646f18af816f8aee68cb6acb1003bffc8fdf8d

This fit for 0930 CSS FW

Change-Id: I8a7095375eca284edf78771d363723e879822d76
Signed-off-by: Tao Jing <jing.tao@intel.com>
Reviewed-on: http://android.intel.com:8080/24500
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Tested-by: Gross, Mark <mark.gross@intel.com>
Reviewed-on: http://android.intel.com:8080/24687

86 files changed:
drivers/media/video/atomisp/Kconfig [new file with mode: 0644]
drivers/media/video/atomisp/Makefile [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_cmd.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_cmd.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_common.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_csi2.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_csi2.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_file.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_file.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_fops.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_fops.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_ioctl.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_ioctl.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_subdev.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_subdev.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_tpg.c [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_tpg.h [new file with mode: 0644]
drivers/media/video/atomisp/atomisp_v4l2.c [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/bits.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/cell_params.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/css_receiver_ahb_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/dma_v1_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/embed.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/gdc_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/gp_regs_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_host_ids_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_if_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_irq_types_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_monitors_types_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_to_mipi_types_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/if_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/irq_controller_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/isp2300_medfield_params.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/master_port.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/mmu_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/scalar_processor_params.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/sp.map.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/sp_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/hrt/streaming_to_mipi_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_accelerate.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_accelerate.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_binary.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_binary.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_binary_info.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_debug.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_debug.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_defs.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_firmware.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_firmware.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_hrt.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_hw.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_internal.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_metrics.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_metrics.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_params.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_params.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_rx.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_rx.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_sp.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_sp.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_sp_start.c [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_sp_start.h [new file with mode: 0644]
drivers/media/video/atomisp/css/sh_css_types.h [new file with mode: 0644]
drivers/media/video/atomisp/hmm/hmm.c [new file with mode: 0644]
drivers/media/video/atomisp/hmm/hmm_bo.c [new file with mode: 0644]
drivers/media/video/atomisp/hmm/hmm_bo_dev.c [new file with mode: 0644]
drivers/media/video/atomisp/hmm/hmm_vm.c [new file with mode: 0644]
drivers/media/video/atomisp/hrt/hive_isp_css_custom_host_hrt.h [new file with mode: 0644]
drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c [new file with mode: 0644]
drivers/media/video/atomisp/include/atomisp/atomisp_internal.h [new file with mode: 0644]
drivers/media/video/atomisp/include/atomisp/atomisp_tables.h [new file with mode: 0644]
drivers/media/video/atomisp/include/atomisp/atomisp_v4l2.h [new file with mode: 0644]
drivers/media/video/atomisp/include/hmm/hmm.h [new file with mode: 0644]
drivers/media/video/atomisp/include/hmm/hmm_bo.h [new file with mode: 0644]
drivers/media/video/atomisp/include/hmm/hmm_bo_dev.h [new file with mode: 0644]
drivers/media/video/atomisp/include/hmm/hmm_common.h [new file with mode: 0644]
drivers/media/video/atomisp/include/hmm/hmm_vm.h [new file with mode: 0644]
drivers/media/video/atomisp/include/mmu/isp_mmu.h [new file with mode: 0644]
drivers/media/video/atomisp/include/mmu/sh_mmu.h [new file with mode: 0644]
drivers/media/video/atomisp/mmu/isp_mmu.c [new file with mode: 0644]

diff --git a/drivers/media/video/atomisp/Kconfig b/drivers/media/video/atomisp/Kconfig
new file mode 100644 (file)
index 0000000..0af43bf
--- /dev/null
@@ -0,0 +1,19 @@
+config VIDEO_ATOMISP
+        tristate "Medfield Penwell Image Signal Processor Driver"
+        depends on VIDEO_V4L2
+       select  VIDEOBUF_VMALLOC 
+       select VIDEO_OV2720
+       select VIDEO_DIS71430M
+       select VIDEO_AS3645A
+       select VIDEO_LM3554
+       select VIDEO_MT9E013
+       select VIDEO_MT9M114
+
+       default m
+
+        ---help---
+          Say Y here if your platform support camera imaging subsystem on
+         the intel Medifield platform.
+
+          To compile this driver as a module, choose M here: the
+          module will be called atomisp.
diff --git a/drivers/media/video/atomisp/Makefile b/drivers/media/video/atomisp/Makefile
new file mode 100644 (file)
index 0000000..cd276ba
--- /dev/null
@@ -0,0 +1,46 @@
+atomisp-objs := \
+                css/sh_css.o \
+                css/sh_css_binary.o \
+                css/sh_css_debug.o  \
+                css/sh_css_hrt.o  \
+               css/sh_css_params.o \
+                css/sh_css_sp.o \
+               css/sh_css_rx.o \
+               css/sh_css_sp_start.o \
+               css/sh_css_metrics.o \
+               css/sh_css_firmware.o \
+               css/sh_css_accelerate.o \
+                mmu/isp_mmu.o \
+                hmm/hmm.o \
+                hmm/hmm_bo.o \
+                hmm/hmm_bo_dev.o \
+                hmm/hmm_vm.o \
+                hrt/hive_isp_css_mm_hrt.o \
+               atomisp_ioctl.o \
+               atomisp_cmd.o \
+               atomisp_fops.o \
+               atomisp_subdev.o \
+               atomisp_csi2.o \
+               atomisp_tpg.o \
+               atomisp_file.o \
+               atomisp_v4l2.o
+
+obj-$(CONFIG_VIDEO_ATOMISP) = atomisp.o
+
+INC    := $(src)/include
+INCLUDES := -I$(INC) \
+            -I$(INC)/atomisp \
+            -I$(src) \
+            -I$(src)/hrt \
+            -I$(src)/css \
+            -I$(src)/css/hrt \
+           -I$(src)/../../../staging/mrst/bc_video
+
+DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -DHRT_KERNEL
+DEFINES += -DUSE_DYNAMIC_BIN
+DEFINES += -DISP_POWER_GATING
+DEFINES += -DUSE_INTERRUPTS
+DEFINES += -DUSE_SSSE3
+DEFINES += -DPUNIT_CAMERA_BUSY
+
+EXTRA_CFLAGS := $(INCLUDES) $(DEFINES) -fno-common
diff --git a/drivers/media/video/atomisp/atomisp_cmd.c b/drivers/media/video/atomisp/atomisp_cmd.c
new file mode 100644 (file)
index 0000000..6b10bb5
--- /dev/null
@@ -0,0 +1,3774 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include "atomisp_tables.h"
+#include "atomisp_ioctl.h"
+#include "atomisp_cmd.h"
+#include "atomisp_fops.h"
+#include "hrt/css_receiver_ahb_defs.h"
+#include "css/sh_css_debug.h"
+#include "css/sh_css_hrt.h"
+#include "css/sh_css_binary_info.h"
+#include "css/sh_css_accelerate.h"
+#include "hrt/bits.h"
+#include "linux/intel_mid_pm.h"
+#include <linux/kernel.h>
+
+/* We should never need to run the flash for more than 2 frames.
+ * At 15fps this means 133ms. We set the timeout a bit longer.
+ * Each flash driver is supposed to set its own timeout, but
+ * just in case someone else changed the timeout, we set it
+ * here to make sure we don't damage the flash hardware. */
+#define FLASH_TIMEOUT 800 /* ms */
+
+union host {
+       struct {
+               void *kernel_ptr;
+               void __user *user_ptr;
+               int size;
+       } scalar;
+       struct {
+               void *hmm_ptr;
+       } ptr;
+};
+
+static void
+atomisp_acc_fw_free_args(struct atomisp_device *isp, struct sh_css_acc_fw *fw);
+static void
+atomisp_acc_fw_free(struct atomisp_device *isp, struct sh_css_acc_fw *fw);
+
+/*
+ * get sensor:dis71430/ov2720 related info from v4l2_subdev->priv data field.
+ * subdev->priv is set in mrst.c
+ */
+struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd)
+{
+       return (struct camera_mipi_info *)v4l2_get_subdev_hostdata(sd);
+}
+
+/*
+ * get struct atomisp_video_pipe from v4l2 video_device
+ */
+struct atomisp_video_pipe *atomisp_to_video_pipe(struct video_device *dev)
+{
+       return (struct atomisp_video_pipe *)
+           container_of(dev, struct atomisp_video_pipe, vdev);
+}
+
+/*
+ * interrupt enable/disable functions
+ */
+static void enable_isp_irq(enum hrt_isp_css_irq irq, bool enable)
+{
+       if (enable) {
+               sh_css_hrt_irq_enable(irq, true, false);
+               switch (irq) { /*We only have sp interrupt right now*/
+               case hrt_isp_css_irq_sp:
+                       sh_css_hrt_irq_enable_sp(true);
+                       break;
+               default:
+                       break;
+               }
+
+       } else {
+               sh_css_hrt_irq_disable(irq);
+               switch (irq) {
+               case hrt_isp_css_irq_sp:
+                       sh_css_hrt_irq_enable_sp(false);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+}
+
+/*
+ * interrupt clean function
+ */
+static void clear_isp_irq(enum hrt_isp_css_irq irq)
+{
+       switch (irq) {
+       case hrt_isp_css_irq_sp:
+               sh_css_hrt_irq_clear_sp();
+       default:
+               break;
+       }
+}
+
+void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev)
+{
+       u32 msg_ret;
+       u32 msi_address;
+       u16 msi_data;
+
+       pci_read_config_dword(dev, PCI_MSI_ADDR, &msi_address);
+       pci_read_config_word(dev, PCI_MSI_DATA, &msi_data);
+       msi_data = msi_data & 0xffff;
+
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_ADDRESS, msi_address);
+
+       msg_ret = atomisp_msg_read32(isp, IUNIT_PORT, MSI_CAPID);
+       msg_ret |= 1 << MSI_ENABLE_BIT;
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_CAPID, msg_ret);
+
+       msg_ret = (1 << INTR_IER) | (1 << INTR_IIR);
+       atomisp_msg_write32(isp, IUNIT_PORT, INTR_CTL, msg_ret);
+
+       msg_ret = atomisp_msg_read32(isp, IUNIT_PORT, PCICMDSTS);
+       msg_ret |= (1 << MEMORY_SPACE_ENABLE |
+                   1 << BUS_MASTER_ENABLE |
+                   1 << INTR_DISABLE_BIT);
+       atomisp_msg_write32(isp, IUNIT_PORT, PCICMDSTS, msg_ret);
+
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_DATA, msi_data);
+}
+
+void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev)
+{
+       u32 msg_ret;
+
+       msg_ret = atomisp_msg_read32(isp, IUNIT_PORT, MSI_CAPID);
+       msg_ret &=  ~(1 << MSI_ENABLE_BIT);
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_CAPID, msg_ret);
+
+       msg_ret = 0x0;
+       atomisp_msg_write32(isp, IUNIT_PORT, INTR_CTL, msg_ret);
+
+       msg_ret = atomisp_msg_read32(isp, IUNIT_PORT, PCICMDSTS);
+       msg_ret &= ~(1 << INTR_DISABLE_BIT |
+                    1 << BUS_MASTER_ENABLE);
+       atomisp_msg_write32(isp, IUNIT_PORT, PCICMDSTS, msg_ret);
+}
+
+static void print_csi_rx_errors(void)
+{
+       u32 infos = 0;
+       sh_css_rx_get_interrupt_info(&infos);
+
+       v4l2_info(&atomisp_dev, "CSI Receiver errors:\n");
+       if (infos & SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN)
+               v4l2_err(&atomisp_dev, "  buffer overrun");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_SOT)
+               v4l2_err(&atomisp_dev,
+                               "  start-of-transmission error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_SOT_SYNC)
+               v4l2_err(&atomisp_dev,
+                               "  start-of-transmission sync error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_CONTROL)
+               v4l2_err(&atomisp_dev, "  control error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE)
+               v4l2_err(&atomisp_dev, "  2 or more ECC errors");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_CRC)
+               v4l2_err(&atomisp_dev, "  CRC mismatch");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID)
+               v4l2_err(&atomisp_dev, "  unknown error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC)
+               v4l2_err(&atomisp_dev, "  frame sync error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_DATA)
+               v4l2_err(&atomisp_dev, "  frame data error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT)
+               v4l2_err(&atomisp_dev, "  data timeout");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC)
+               v4l2_err(&atomisp_dev,
+                               "  unknown escape command entry");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_LINE_SYNC)
+               v4l2_err(&atomisp_dev, "  line sync error");
+}
+
+/* interrupt handling function*/
+irqreturn_t atomisp_isr(int irq, void *dev)
+{
+       u32 msg_ret;
+       struct atomisp_device *isp = (struct atomisp_device *)dev;
+       enum sh_css_err err;
+       unsigned int irq_infos = 0;
+       bool signal_worker = false;
+       bool signal_statistics = false;
+       bool signal_acceleration = false;
+
+       spin_lock(&isp->irq_lock);
+       /*got triggered interrupt*/
+       err = sh_css_translate_interrupt(&irq_infos);
+       if (err != sh_css_success) {
+               v4l2_warn(&atomisp_dev, "%s:failed to translate irq (err = %d,"
+                         " infos = %d)\n", __func__, err, irq_infos);
+               spin_unlock(&isp->irq_lock);
+               return IRQ_NONE;
+       }
+
+       isp->irq_infos = irq_infos;
+       if (irq_infos & SH_CSS_IRQ_INFO_FRAME_DONE ||
+           irq_infos & SH_CSS_IRQ_INFO_START_NEXT_STAGE) {
+               /* Wake up sleep thread for next binary */
+               signal_worker = true;
+               if (irq_infos & SH_CSS_IRQ_INFO_STATISTICS_READY) {
+                       signal_statistics = true;
+                       isp->isp3a_stat_ready = true;
+               }
+               if (irq_infos & SH_CSS_IRQ_INFO_FW_ACC_DONE) {
+                       signal_acceleration = true;
+               }
+       } else if (irq_infos & SH_CSS_IRQ_INFO_CSS_RECEIVER_ERROR) {
+               /* handle mipi receiver error*/
+               u32 rx_infos;
+               print_csi_rx_errors();
+               sh_css_rx_get_interrupt_info(&rx_infos);
+               sh_css_rx_clear_interrupt_info(rx_infos);
+               if (rx_infos & SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN) {
+                       signal_worker = true;
+                       signal_statistics = true;
+                       signal_acceleration = true;
+               }
+       }
+
+       /*
+        * After every iteration of acceleration there will be an interrupt
+        * which needs priority.
+        */
+       if (signal_acceleration)
+               /* wake up acceleration api */
+               complete(&isp->acc_fw_complete);
+
+       if (signal_worker)
+               /*make work queue run*/
+               complete(&isp->wq_frame_complete);
+       if (signal_statistics)
+               /*make work queue run*/
+               complete(&isp->dis_state_complete);
+
+       /* Clear irq reg at PENWELL B0 */
+       msg_ret = atomisp_msg_read32(isp, IUNIT_PORT, INTR_CTL);
+       msg_ret |=  (1 << INTR_IIR);
+       atomisp_msg_write32(isp, IUNIT_PORT, INTR_CTL, msg_ret);
+
+       spin_unlock(&isp->irq_lock);
+       return IRQ_HANDLED;
+}
+/*
+ * dequeue a buffer from video buffer list
+ * if no buffer queued, wait for queue_buf is called
+ * will return 1 when streaming off.
+ */
+static int atomisp_buf_pre_dequeue(struct atomisp_video_pipe *pipe,
+                             struct videobuf_buffer **vb)
+{
+       unsigned long flags;
+       struct atomisp_device *isp = pipe->isp;
+
+       spin_lock_irqsave(&pipe->irq_lock, flags);
+       if (list_empty(&pipe->activeq)) {
+               spin_unlock_irqrestore(&pipe->irq_lock, flags);
+               if (wait_event_interruptible(pipe->capq.wait,
+                                            (!list_empty(&pipe->activeq) &&
+                                             !isp->sw_contex.updating_uptr) ||
+                                            !isp->sw_contex.isp_streaming))
+                       return -EINVAL;
+
+               spin_lock_irqsave(&pipe->irq_lock, flags);
+               if (list_empty(&pipe->activeq)) {
+                       spin_unlock_irqrestore(&pipe->irq_lock, flags);
+                       return -EINVAL;
+               }
+       }
+
+       if (!isp->sw_contex.isp_streaming) {
+               spin_unlock_irqrestore(&pipe->irq_lock, flags);
+               return 1;
+       }
+
+       /*retrieve video buffer from activeq, keep video buffer on capq*/
+       *vb = list_entry(pipe->activeq.next, struct videobuf_buffer, queue);
+       list_del(&(*vb)->queue);
+       (*vb)->state = VIDEOBUF_ACTIVE;
+       spin_unlock_irqrestore(&pipe->irq_lock, flags);
+       return 0;
+}
+
+/* set the bit range [lsb, lsb+num_bits] of in_val to new_val
+ * and return the result.
+ */
+static uint32_t u32_set_bits(uint32_t in_val, unsigned int lsb,
+            unsigned int num_bits, uint32_t new_val)
+{
+       unsigned int bit_mask;
+       /* avoid overflow in calculating the bit masks */
+       if (num_bits > 32)
+               return in_val;
+       if (num_bits == 32)
+               return new_val;
+       /* calculate number of 1 bits in mask */
+       bit_mask = (1<<(num_bits+1)) - 1;
+       /* make sure new_val doesn't contain more than num_bits */
+       new_val &= bit_mask;
+       /* shift bits into the target place */
+       bit_mask <<= lsb;
+       /* clear old bits */
+       in_val &= ~bit_mask;
+       /* assign new_val to the output position */
+       in_val |= new_val << lsb;
+       return in_val;
+}
+
+/* The term_en_count is set via 2 registers, one for the 4lane port and one
+   for the 1lane port. */
+#define TERM_EN_COUNT_1LANE_START_BIT 16
+#define PNW_B0_TERM_EN_COUNT_4LANE_START_BIT 20
+#define PNW_B0_TERM_EN_COUNT_NUM_BITS        4
+#define TERM_EN_COUNT_4LANE_START_BIT 24
+#define TERM_EN_COUNT_NUM_BITS        7
+
+static void set_term_en_count(struct atomisp_device *isp, int b0)
+{
+       uint32_t val;
+       unsigned int lane1_start_bit,
+                    lane4_start_bit,
+                    num_bits;
+
+       lane1_start_bit = TERM_EN_COUNT_1LANE_START_BIT;
+       if (b0) {
+               lane4_start_bit = PNW_B0_TERM_EN_COUNT_4LANE_START_BIT;
+               num_bits = PNW_B0_TERM_EN_COUNT_NUM_BITS;
+       } else {
+               lane4_start_bit = TERM_EN_COUNT_4LANE_START_BIT;
+               num_bits = TERM_EN_COUNT_NUM_BITS;
+       }
+
+       val = atomisp_msg_read32(isp, IUNITPHY_PORT, CSI_CONTROL);
+       /* 1 lane CSI port */
+       val = u32_set_bits(val, lane1_start_bit, num_bits, 0xF);
+       /* 4 lane CSI port */
+       val = u32_set_bits(val, lane4_start_bit, num_bits, 0xF);
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, val);
+}
+
+static int atomisp_buffer_dequeue(struct atomisp_device *isp,
+                           struct videobuf_buffer **vb_capture,
+                           struct videobuf_buffer **vb_preview)
+{
+       struct videobuf_vmalloc_memory *vmem;
+       struct atomisp_video_pipe *vf_pipe = NULL;
+       struct atomisp_video_pipe *mo_pipe = NULL;
+       int ret;
+
+       if (!(*vb_capture)) {
+               mo_pipe = &isp->isp_subdev.video_out_mo;
+               ret = atomisp_buf_pre_dequeue(mo_pipe, vb_capture);
+               if (ret)
+                       return -EINVAL;
+
+               vmem = (*vb_capture)->priv;
+               if (vmem->vmalloc == NULL)
+                       return -EINVAL;
+
+               /*frame structure is stored in videobuf->priv->vmalloc*/
+               isp->regular_output_frame = vmem->vmalloc;
+       }
+
+       if (atomisp_is_viewfinder_support(isp) && !(*vb_preview)) {
+               vf_pipe = &isp->isp_subdev.video_out_vf;
+               ret = atomisp_buf_pre_dequeue(vf_pipe, vb_preview);
+               if (ret)
+                       return -EINVAL;
+
+               vmem = (*vb_preview)->priv;
+               isp->vf_frame = vmem->vmalloc;
+       }
+       return 0;
+}
+
+static int atomisp_start_binary(struct atomisp_device *isp)
+{
+       int ret;
+
+       /*Start the isp binary*/
+       switch (isp->sw_contex.run_mode) {
+       case CI_MODE_STILL_CAPTURE:
+               ret = sh_css_capture_start(isp->raw_output_frame,
+                                          isp->regular_output_frame,
+                                          isp->vf_frame);
+               if (sh_css_success != ret) {
+                       v4l2_err(&atomisp_dev,
+                                "start capture error!\n");
+
+                       return -EINVAL;
+               }
+               break;
+       case CI_MODE_PREVIEW:
+               sh_css_preview_start(NULL, isp->regular_output_frame);
+               break;
+       case CI_MODE_VIDEO:
+               if (isp->params.video_dis_en) {
+                       sh_css_video_set_dis_vector(isp->params.dis_x,
+                                                   isp->params.dis_y);
+               }
+               sh_css_video_start(NULL, isp->regular_output_frame,
+                                  isp->vf_frame);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int atomisp_streamon_input(struct atomisp_device *isp)
+{
+       int is_b0, ret;
+
+       if (isp->sw_contex.file_input) {
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      video, s_stream, 1);
+                       return ret;
+       }
+
+       if (isp->sw_contex.sensor_streaming == false) {
+               is_b0 = (isp->pdev->revision == 6) ? 0 : 1;
+               set_term_en_count(isp, is_b0);
+               /*
+                * stream on the sensor, power on is called before
+                * work queue start
+                */
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      video, s_stream, 1);
+               if (ret)
+                       return -EINVAL;
+
+               isp->sw_contex.sensor_streaming = true;
+       }
+       return 0;
+}
+
+static void atomisp_pipe_reset(struct atomisp_device *isp)
+{
+       v4l2_warn(&atomisp_dev, "ISP timeout. Recovering\n");
+
+       /* clear irq */
+       enable_isp_irq(hrt_isp_css_irq_sp, false);
+       clear_isp_irq(hrt_isp_css_irq_sp);
+       /* stream off sensor */
+       if (!isp->sw_contex.file_input) {
+               v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                video, s_stream, 0);
+               isp->sw_contex.sensor_streaming = false;
+       }
+       /* power cycle ISP */
+       sh_css_suspend();
+       pm_runtime_put_sync(isp->dev);
+       pm_runtime_get_sync(isp->dev);
+       sh_css_resume();
+}
+
+static int atomisp_timeout_handler(struct atomisp_device *isp, int cnt)
+{
+       u32 rx_infos;
+
+       v4l2_err(&atomisp_dev, "ISP timeout\n");
+
+       /* Try 5 times for autorecovery */
+       if (cnt < 5) {
+               atomisp_pipe_reset(isp);
+               return 0;
+       }
+
+       /* Can't recover from isp timeout, error will be reported*/
+       if (!sh_css_hrt_sp_is_idle())
+               v4l2_err(&atomisp_dev,
+                        "error: SP is not idle\n");
+       else
+               v4l2_err(&atomisp_dev,
+                        "error: lost interrupt\n");
+
+       sh_css_dump_debug_info();
+       print_csi_rx_errors();
+       sh_css_rx_get_interrupt_info(&rx_infos);
+       sh_css_rx_clear_interrupt_info(rx_infos);
+       return -ETIMEDOUT;
+}
+
+static bool atomisp_flash_error(struct atomisp_device *isp)
+{
+       struct v4l2_control ctrl;
+
+       ctrl.id = V4L2_CID_FLASH_STATUS;
+       if (v4l2_subdev_call(isp->flash, core, g_ctrl, &ctrl))
+               return true;
+       if (ctrl.value != ATOMISP_FLASH_STATUS_OK)
+               v4l2_err(&atomisp_dev, "flash failed (%d)\n", ctrl.value);
+       return ctrl.value != ATOMISP_FLASH_STATUS_OK;
+}
+
+static int atomisp_stop_flash(struct atomisp_device *isp)
+{
+       struct v4l2_control ctrl;
+
+       ctrl.id = V4L2_CID_FLASH_STROBE;
+       ctrl.value = 0;
+       if (v4l2_subdev_call(isp->flash, core, s_ctrl, &ctrl)) {
+               v4l2_err(&atomisp_dev, "flash failed\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int atomisp_start_flash(struct atomisp_device *isp)
+{
+       struct v4l2_control ctrl;
+
+       /* switch flash into flash mode */
+       ctrl.id = V4L2_CID_FLASH_MODE;
+       ctrl.value = ATOMISP_FLASH_MODE_FLASH;
+
+       if (v4l2_subdev_call(isp->flash, core, s_ctrl, &ctrl)) {
+               v4l2_err(&atomisp_dev, "flash failed\n");
+               return -EINVAL;
+       }
+
+       /* make sure the timeout is set */
+       ctrl.id = V4L2_CID_FLASH_TIMEOUT;
+       ctrl.value = FLASH_TIMEOUT;
+
+       if (v4l2_subdev_call(isp->flash, core, s_ctrl, &ctrl)) {
+               v4l2_err(&atomisp_dev, "flash failed\n");
+               return -EINVAL;
+       }
+
+       /* trigger the flash */
+       ctrl.id = V4L2_CID_FLASH_STROBE;
+       ctrl.value = 1;
+       /* for now we treat it as on/off */
+       if (v4l2_subdev_call(isp->flash, core, s_ctrl, &ctrl)) {
+               v4l2_err(&atomisp_dev, "flash failed\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+void atomisp_work(struct work_struct *work)
+{
+       struct atomisp_device *isp = container_of(work, struct atomisp_device,
+                                                 work);
+       struct videobuf_buffer *vb_preview = NULL;
+       struct videobuf_buffer *vb_capture = NULL;
+       int ret, timeout_cnt = 0;
+       bool timeout_flag,
+            flash_in_progress = false,
+            flash_enabled = false;
+       enum atomisp_frame_status fr_status = ATOMISP_FRAME_STATUS_OK;
+
+       isp->sw_contex.error = false;
+       for (;;) {
+               timeout_flag = false;
+               ret = atomisp_buffer_dequeue(isp, &vb_capture,
+                                            &vb_preview);
+               if (ret)
+                       goto error;
+
+               INIT_COMPLETION(isp->wq_frame_complete);
+               /* Hold the locker when ISP is running, when dis and digital
+                * zoom can not be configured
+                */
+               mutex_lock(&isp->isp_lock);
+
+               ret = atomisp_start_binary(isp);
+               if (ret) {
+                       mutex_unlock(&isp->isp_lock);
+                       goto error;
+               }
+
+               ret = atomisp_streamon_input(isp);
+               if (ret) {
+                       mutex_unlock(&isp->isp_lock);
+                       v4l2_err(&atomisp_dev,
+                                "stream on input error.\n");
+                       goto error;
+               }
+
+               /* if the previous frame was partially exposed, this one is
+                * going to be fully exposed. */
+               if (flash_in_progress &&
+                   fr_status == ATOMISP_FRAME_STATUS_FLASH_PARTIAL) {
+                       /* If flash is in progress and the previous frame
+                        * was partially exposed, then this frame will be
+                        * correctly exposed. */
+                       fr_status = ATOMISP_FRAME_STATUS_FLASH_EXPOSED;
+               } else if (flash_in_progress &&
+                          fr_status == ATOMISP_FRAME_STATUS_FLASH_EXPOSED) {
+                       /* If the previous frame was flash-exposed, we assume
+                        * that some of the flash leaked into the current frame
+                        * so we tell the app not to use this frame. */
+                       fr_status = ATOMISP_FRAME_STATUS_FLASH_PARTIAL;
+                       flash_in_progress = false;
+               } else {
+                       fr_status = ATOMISP_FRAME_STATUS_OK;
+               }
+
+               if (isp->params.num_flash_frames) {
+                       int ret = atomisp_start_flash(isp);
+
+                       /* The flash failed frame status is needed to signal to
+                        * the appication that flash has been attempted but no
+                        * flash frames will be generated. Without this, the
+                        * applicaton would end up an in endless loop waiting
+                        * for a flash-exposed frame.
+                        */
+                       if (ret)
+                               fr_status = ATOMISP_FRAME_STATUS_FLASH_FAILED;
+                       else {
+                               fr_status = ATOMISP_FRAME_STATUS_FLASH_PARTIAL;
+                               flash_in_progress = true;
+                               flash_enabled = true;
+                       }
+                       isp->params.num_flash_frames = 0;
+               }
+
+               /*Check ISP processing pipeline if any binary left*/
+               do {
+                       long time_left;
+                       /* wait for different binary to be processed */
+                       time_left =
+                           wait_for_completion_timeout(&isp->wq_frame_complete,
+                                                       1 * HZ);
+
+                       if (time_left == 0) {
+                               ret = atomisp_timeout_handler(isp,
+                                                             timeout_cnt++);
+                               if (ret) {
+                                       mutex_unlock(&isp->isp_lock);
+                                       goto error;
+                               }
+                               timeout_flag = true;
+                               break;
+                       }
+
+                       INIT_COMPLETION(isp->acc_fw_complete);
+                       if (isp->irq_infos & SH_CSS_IRQ_INFO_FW_ACC_DONE)
+                               sh_css_terminate_firmware();
+
+                       /*
+                        * If there is any firware marked for deletion, do it
+                        * now. Firware cannot be unloaded in the middle of a
+                        * frame, so it has to be done when a frame done
+                        * interrupt is processed.
+                        * TODO: Check if this is the correct location.
+                        * TODO: Check how to handle multiple firmware cases.
+                        */
+                       if (isp->marked_fw_for_unload != NULL) {
+                               atomisp_acc_fw_free_args(isp,
+                                                   isp->marked_fw_for_unload);
+                               sh_css_unload_acceleration(
+                                               isp->marked_fw_for_unload);
+                               atomisp_acc_fw_free(isp,
+                                                   isp->marked_fw_for_unload);
+                               isp->marked_fw_for_unload = NULL;
+                               complete(&isp->acc_unload_fw_complete);
+                       }
+
+                       /* regardless of timeout or not, we disable the flash */
+                       if (flash_enabled && fr_status ==
+                                       ATOMISP_FRAME_STATUS_FLASH_EXPOSED) {
+                               atomisp_stop_flash(isp);
+                               /* always check the result, this clears any
+                                * errors that may have occurred.
+                                */
+                               if (atomisp_flash_error(isp))
+                                       fr_status =
+                                       ATOMISP_FRAME_STATUS_FLASH_FAILED;
+                               flash_enabled = false;
+                       }
+
+                       /* proc interrupt */
+                       INIT_COMPLETION(isp->wq_frame_complete);
+                       if (isp->irq_infos &
+                               SH_CSS_IRQ_INFO_START_NEXT_STAGE) {
+                               sh_css_start_next_stage();
+
+                               /* Getting 3A statistics if ready */
+                               if (isp->isp3a_stat_ready) {
+                                       mutex_lock(&isp->isp3a_lock);
+                                       ret = sh_css_get_3a_statistics
+                                               (isp->params.s3a_output_buf);
+                                       mutex_unlock(&isp->isp3a_lock);
+
+                                       isp->isp3a_stat_ready = false;
+                                       if (ret != sh_css_success)
+                                               v4l2_err(&atomisp_dev,
+                                                       "get 3a statistics"
+                                                       " failed, not "
+                                                       "enough memory.\n");
+                               }
+                       }
+               } while (!(isp->irq_infos & SH_CSS_IRQ_INFO_FRAME_DONE));
+
+               mutex_unlock(&isp->isp_lock);
+
+               if (!timeout_flag) {
+                       if (vb_capture) {
+                               isp->frame_status[vb_capture->i] = fr_status;
+                               do_gettimeofday(&vb_capture->ts);
+                               vb_capture->field_count++;
+                               /*mark videobuffer done for dequeue*/
+                               vb_capture->state = VIDEOBUF_DONE;
+                       }
+
+                       if (vb_preview) {
+                               do_gettimeofday(&vb_preview->ts);
+                               vb_preview->field_count++;
+                               /*mark videobuffer done for dequeue*/
+                               vb_preview->state = VIDEOBUF_DONE;
+                       }
+
+                       /*
+                        * Frame capture done, wake up any process block on
+                        * current active buffer
+                        */
+                       if (vb_preview)
+                               wake_up(&vb_preview->done);
+                       if (vb_capture)
+                               wake_up(&vb_capture->done);
+
+                       vb_preview = NULL;
+                       vb_capture = NULL;
+                       timeout_cnt = 0;
+               }
+       }
+
+error:
+       if (isp->isp_subdev.video_out_vf.opened)
+               isp->vf_frame = NULL;
+
+       isp->sw_contex.error = true;
+       timeout_cnt = 0;
+
+       if (vb_preview)
+               vb_preview->state = VIDEOBUF_ERROR;
+       if (vb_capture)
+               vb_capture->state = VIDEOBUF_ERROR;
+
+       /*
+        * Frame capture error, wake up any process block on current
+        * active buffer
+        */
+       if (vb_preview)
+               wake_up(&vb_preview->done);
+       if (vb_capture)
+               wake_up(&vb_capture->done);
+       return;
+}
+
+/*
+ * utils for buffer allocation/free
+ */
+#define bytes_to_pgnr_ceil(bytes) \
+    (((bytes) + ((1<<PAGE_SHIFT) - 1)) >> PAGE_SHIFT)
+
+int atomisp_get_frame_pgnr(const struct sh_css_frame *frame, u32 * p_pgnr)
+{
+       if (!frame) {
+               v4l2_err(&atomisp_dev,
+                           "%s: NULL frame pointer ERROR.\n",
+                           __func__);
+               return -EINVAL;
+       }
+
+       (*p_pgnr) = bytes_to_pgnr_ceil(frame->data_bytes);
+       return 0;
+}
+
+/*
+ * Get internal fmt according to V4L2 fmt
+ */
+enum sh_css_frame_format v4l2_fmt_to_sh_fmt(u32 fmt)
+{
+       switch (fmt) {
+       case V4L2_PIX_FMT_YUV420:
+               return SH_CSS_FRAME_FORMAT_YUV420;
+       case V4L2_PIX_FMT_YVU420:
+               return SH_CSS_FRAME_FORMAT_YV12;
+       case V4L2_PIX_FMT_YUV422P:
+               return SH_CSS_FRAME_FORMAT_YUV422;
+       case V4L2_PIX_FMT_YUV444:
+               return SH_CSS_FRAME_FORMAT_YUV444;
+       case V4L2_PIX_FMT_NV12:
+               return SH_CSS_FRAME_FORMAT_NV12;
+       case V4L2_PIX_FMT_NV21:
+               return SH_CSS_FRAME_FORMAT_NV21;
+       case V4L2_PIX_FMT_NV16:
+               return SH_CSS_FRAME_FORMAT_NV16;
+       case V4L2_PIX_FMT_NV61:
+               return SH_CSS_FRAME_FORMAT_NV61;
+       case V4L2_PIX_FMT_UYVY:
+               return SH_CSS_FRAME_FORMAT_UYVY;
+       case V4L2_PIX_FMT_YUYV:
+               return SH_CSS_FRAME_FORMAT_YUYV;
+       case V4L2_PIX_FMT_RGB24:
+               return SH_CSS_FRAME_FORMAT_PLANAR_RGB888;
+       case V4L2_PIX_FMT_RGB32:
+               return SH_CSS_FRAME_FORMAT_RGBA888;
+       case V4L2_PIX_FMT_RGB565:
+               return SH_CSS_FRAME_FORMAT_RGB565;
+       case V4L2_PIX_FMT_SBGGR16:
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return SH_CSS_FRAME_FORMAT_RAW;
+       default:
+               return -EINVAL;
+       }
+}
+/*
+ * raw format match between SH format and V4L2 format
+ */
+static int raw_output_format_match_input(u32 input, u32 output)
+{
+       if ((input == SH_CSS_INPUT_FORMAT_RAW_12) &&
+           ((output == V4L2_PIX_FMT_SRGGB12) ||
+            (output == V4L2_PIX_FMT_SGRBG12) ||
+            (output == V4L2_PIX_FMT_SBGGR12) ||
+            (output == V4L2_PIX_FMT_SGBRG12)))
+               return 0;
+
+       if ((input == SH_CSS_INPUT_FORMAT_RAW_10) &&
+           ((output == V4L2_PIX_FMT_SRGGB10) ||
+            (output == V4L2_PIX_FMT_SGRBG10) ||
+            (output == V4L2_PIX_FMT_SBGGR10) ||
+            (output == V4L2_PIX_FMT_SGBRG10)))
+               return 0;
+
+       if ((input == SH_CSS_INPUT_FORMAT_RAW_8) &&
+           ((output == V4L2_PIX_FMT_SRGGB8) ||
+            (output == V4L2_PIX_FMT_SGRBG8) ||
+            (output == V4L2_PIX_FMT_SBGGR8) ||
+            (output == V4L2_PIX_FMT_SGBRG8)))
+               return 0;
+
+       if ((input == SH_CSS_INPUT_FORMAT_RAW_16) &&
+           (output == V4L2_PIX_FMT_SBGGR16))
+               return 0;
+
+       return -EINVAL;
+}
+/*
+ * 2 types of format: SH format, v4l2 format
+ * atomisp_format_bridge is a wrapper format for the other 2
+ */
+struct atomisp_format_bridge *get_atomisp_format_bridge(
+                                       unsigned int pixelformat)
+{
+       u32 i;
+       for (i = 0; i < atomisp_output_fmts_num; i++) {
+               if (atomisp_output_fmts[i].pixelformat == pixelformat)
+                       return (struct atomisp_format_bridge *)
+                                       (&(atomisp_output_fmts[i]));
+       }
+       return NULL;
+}
+
+struct atomisp_format_bridge *get_atomisp_format_bridge_from_mbus(
+                               enum v4l2_mbus_pixelcode mbus_code)
+{
+       int i;
+       for (i = 0; i < atomisp_output_fmts_num; i++) {
+               if (atomisp_output_fmts[i].mbus_code == mbus_code)
+                       return (struct atomisp_format_bridge *)
+                               (&(atomisp_output_fmts[i]));
+       }
+       return NULL;
+}
+static u32 get_pixel_depth(u32 pixelformat)
+{
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_YVU420:
+               return 12;
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_SBGGR16:
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               return 16;
+       case V4L2_PIX_FMT_RGB24:
+       case V4L2_PIX_FMT_YUV444:
+               return 24;
+       case V4L2_PIX_FMT_RGB32:
+               return 32;
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return 8;
+       default:
+               return 8 * 2;   /* raw type now */
+       }
+}
+
+static int is_pixelformat_raw(u32 pixelformat)
+{
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_SBGGR16:
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int is_mbusformat_raw(u32 pixelformat)
+{
+       switch (pixelformat) {
+       case V4L2_MBUS_FMT_SBGGR8_1X8:
+       case V4L2_MBUS_FMT_SGRBG8_1X8:
+       case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
+       case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
+       case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
+       case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
+       case V4L2_MBUS_FMT_SBGGR10_1X10:
+       case V4L2_MBUS_FMT_SGBRG10_1X10:
+       case V4L2_MBUS_FMT_SGRBG10_1X10:
+       case V4L2_MBUS_FMT_SRGGB10_1X10:
+       case V4L2_MBUS_FMT_SBGGR12_1X12:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int get_sh_input_format(u32 pixelformat)
+{
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+               return SH_CSS_INPUT_FORMAT_YUV420_8;
+
+       case V4L2_PIX_FMT_YUV422P:
+               return SH_CSS_INPUT_FORMAT_YUV422_8;
+
+       case V4L2_PIX_FMT_RGB565:
+               return SH_CSS_INPUT_FORMAT_RGB_565;
+
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return SH_CSS_INPUT_FORMAT_RAW_8;
+
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               return SH_CSS_INPUT_FORMAT_RAW_10;
+
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+               return SH_CSS_INPUT_FORMAT_RAW_12;
+
+       case V4L2_PIX_FMT_SBGGR16:
+               return SH_CSS_INPUT_FORMAT_RAW_16;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+/* return whether v4l2 format is supported */
+int atomisp_is_pixelformat_supported(u32 pixelformat)
+{
+       int i;
+
+       for (i = 0; i < atomisp_output_fmts_num; i++) {
+               if (pixelformat == atomisp_output_fmts[i].pixelformat)
+                       return 1;
+       }
+       return 0;
+}
+/*
+ * for different isp run mode: preview/still/video.
+ * return which mode support viewfinder output
+ * still/video support dual stream output
+ */
+bool atomisp_is_viewfinder_support(struct atomisp_device *isp)
+{
+       if (isp->sw_contex.run_mode == CI_MODE_PREVIEW)
+               return false;
+
+       if ((isp->sw_contex.run_mode == CI_MODE_STILL_CAPTURE) &&
+           (isp->main_format->out_sh_fmt == SH_CSS_FRAME_FORMAT_RAW) &&
+           (isp->sw_contex.bypass))
+               return false;
+
+       if (!isp->isp_subdev.video_out_vf.opened)
+               return false;
+
+       return true;
+}
+
+/*
+ * ISP features control function
+ */
+
+/*
+ * Function to enable/disable lens geometry distortion correction (GDC) and
+ * chromatic aberration correction (CAC)
+ */
+int atomisp_gdc_cac(struct atomisp_device *isp, int flag, __s32 * value)
+{
+       struct sh_css_morph_table *tab;
+
+       if (flag == 0) {
+               *value = isp->params.gdc_cac_en;
+               return 0;
+       }
+
+       isp->params.gdc_cac_en = (*value == 0) ? 0 : 1;
+       if (isp->params.gdc_cac_en) {
+               tab = isp->inputs[isp->input_curr].morph_table;
+               if (tab) {
+                       sh_css_morph_table_free(tab);
+                       isp->inputs[isp->input_curr].morph_table = NULL;
+               }
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+       } else {
+               sh_css_set_morph_table(NULL);
+               if (!isp->params.macc_en)
+                       sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_PRIMARY);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to enable/disable extra nosie reduction (XNR) in low light
+ * condition
+ */
+int atomisp_xnr(struct atomisp_device *isp, int flag, int *arg)
+{
+       int xnr_enable = (*arg == 0) ? 0 : 1;
+
+       if (flag == 0) {
+               *arg = isp->params.xnr_en;
+               return 0;
+       }
+
+       sh_css_capture_enable_xnr(xnr_enable);
+
+       return 0;
+}
+
+/*
+ * Function to configure bayer nosie reduction
+ */
+int atomisp_bayer_nr(struct atomisp_device *isp, int flag,
+                            void *config)
+{
+       struct atomisp_nr_config *arg = (struct atomisp_nr_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.nr_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Get nr config from current setup */
+       if (flag == 0) {
+               memcpy(arg, &isp->params.nr_config, sizeof(*arg));
+       } else {
+               /* Set nr config to isp parameters */
+               memcpy(&isp->params.nr_config, arg,
+                       sizeof(struct sh_css_nr_config));
+               sh_css_set_nr_config(&isp->params.nr_config);
+       }
+       return 0;
+}
+
+/*
+ * Function to configure temporal nosie reduction (TNR)
+ */
+int atomisp_tnr(struct atomisp_device *isp, int flag,
+                       void *config)
+{
+       struct atomisp_tnr_config *arg = (struct atomisp_tnr_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.tnr_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Get tnr config from current setup */
+       if (flag == 0) {
+               /* Get tnr config from current setup */
+               memcpy(arg, &isp->params.tnr_config, sizeof(*arg));
+       } else {
+               /* Set tnr config to isp parameters */
+               memcpy(&isp->params.tnr_config, arg,
+                       sizeof(struct sh_css_tnr_config));
+               sh_css_set_tnr_config(&isp->params.tnr_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to get histogram data for image frame
+ */
+int atomisp_histogram(struct atomisp_device *isp, int flag, void *config)
+{
+       struct atomisp_histogram *arg = (struct atomisp_histogram *)config;
+       struct sh_css_histogram *histogram;
+       int ret = 0;
+       unsigned int *buffer;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(*histogram)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               buffer = kzalloc(2048 * sizeof(unsigned int), GFP_KERNEL);
+               if (buffer == NULL) {
+                       v4l2_err(&atomisp_dev,
+                                       "buffer allocate error\n");
+                       return -ENOMEM;
+               }
+
+               ret = sh_css_histogram_allocate(2048, &histogram);
+               if (ret != sh_css_success) {
+                       v4l2_err(&atomisp_dev,
+                                       "sh_css_histogram_allocate failed\n");
+                       goto buffer_free;
+               }
+
+               if (isp->vf_frame == NULL) {
+                       v4l2_err(&atomisp_dev,
+                                       "No frame for histogram\n");
+                       ret = -EINVAL;
+                       goto histogram_free;
+               }
+
+               ret = sh_css_histogram_start(isp->vf_frame, histogram);
+               if (ret != sh_css_success) {
+                       v4l2_err(&atomisp_dev,
+                                       "sh_css_get_y_histogram failed\n");
+                       goto histogram_free;
+               }
+               sh_css_wait_for_completion();
+
+               ret = hmm_load(histogram->data, buffer,
+                       histogram->num_elements * sizeof(unsigned int));
+               if (ret) {
+                       v4l2_err(&atomisp_dev, "hmm_load failed\n");
+                       goto histogram_free;
+               }
+
+               ret = copy_to_user(arg->data, buffer,
+                       histogram->num_elements * sizeof(unsigned int));
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                       "copy to user failed\n");
+                       ret = -EFAULT;
+                       goto histogram_free;
+               }
+
+               ret = 0;
+               arg->num_elements = histogram->num_elements;
+
+histogram_free:
+               sh_css_histogram_free(histogram);
+buffer_free:
+               kfree(buffer);
+
+               return ret;
+       }
+
+       isp->params.histogram_elenum = arg->num_elements;
+
+       return 0;
+}
+
+/*
+ * Function to configure black level compensation
+ */
+int atomisp_black_level(struct atomisp_device *isp, int flag,
+                               void *config)
+{
+       struct atomisp_ob_config *arg = (struct atomisp_ob_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.ob_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get ob config from current setup */
+               const struct sh_css_ob_config *ob_config;
+               sh_css_get_ob_config(&ob_config);
+               memcpy(arg, ob_config, sizeof(*arg));
+       } else {
+               /* Set ob config to isp parameters */
+               memcpy(&isp->params.ob_config, arg,
+                       sizeof(struct sh_css_ob_config));
+               sh_css_set_ob_config(&isp->params.ob_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to configure Ycc nosie reduction
+ */
+int atomisp_ycc_nr(struct atomisp_device *isp, int flag,
+                          void *config)
+{
+       struct atomisp_nr_config *arg = (struct atomisp_nr_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.nr_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get nr config from current setup */
+               const struct sh_css_nr_config *nr_config;
+               sh_css_get_nr_config(&nr_config);
+               memcpy(arg, nr_config, sizeof(*arg));
+       } else {
+               /* Set nr config to isp parameters */
+               memcpy(&isp->params.nr_config, arg,
+                       sizeof(isp->params.nr_config));
+               sh_css_set_nr_config(&isp->params.nr_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to configure edge enhancement
+ */
+int atomisp_ee(struct atomisp_device *isp, int flag,
+                      void *config)
+{
+       struct atomisp_ee_config *arg = (struct atomisp_ee_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.ee_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get ee config from current setup */
+               const struct sh_css_ee_config *ee_config;
+               sh_css_get_ee_config(&ee_config);
+               memcpy(arg, ee_config, sizeof(*arg));
+       } else {
+               /* Set ee config to isp parameters */
+               memcpy(&isp->params.ee_config, arg,
+                      sizeof(isp->params.ee_config));
+               sh_css_set_ee_config(&isp->params.ee_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to update Gamma table for gamma, brightness and contrast config
+ */
+int atomisp_gamma(struct atomisp_device *isp, int flag,
+                         void *config)
+{
+       struct atomisp_gamma_table *arg = (struct atomisp_gamma_table *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.gamma_table)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get gamma table from current setup */
+               const struct sh_css_gamma_table *tab;
+               sh_css_get_gamma_table(&tab);
+               memcpy(arg, tab, sizeof(*arg));
+       } else {
+               /* Set gamma table to isp parameters */
+               memcpy(&isp->params.gamma_table, arg,
+                      sizeof(isp->params.gamma_table));
+               sh_css_set_gamma_table(&isp->params.gamma_table);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to update Ctc table for Chroma Enhancement
+ */
+int atomisp_ctc(struct atomisp_device *isp, int flag,
+                         void *config)
+{
+       struct atomisp_ctc_table *arg = (struct atomisp_ctc_table *) config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.ctc_table)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get ctc table from current setup */
+               const struct sh_css_ctc_table *tab;
+               sh_css_get_ctc_table(&tab);
+               memcpy(arg, tab, sizeof(*arg));
+       } else {
+               /* Set gamma table to isp parameters */
+               memcpy(&isp->params.ctc_table, arg,
+                       sizeof(isp->params.ctc_table));
+               sh_css_set_ctc_table(&isp->params.ctc_table);
+       }
+
+       return 0;
+}
+
+void atomisp_free_internal_buffers(struct atomisp_device *isp)
+{
+       struct sh_css_morph_table *tab;
+
+       tab = isp->inputs[isp->input_curr].morph_table;
+       if (tab) {
+               sh_css_morph_table_free(tab);
+               isp->inputs[isp->input_curr].morph_table = NULL;
+       }
+
+       if (isp->params.vf_overlay) {
+               if (isp->params.vf_overlay->frame)
+                       sh_css_frame_free(isp->params.vf_overlay->frame);
+               kfree(isp->params.vf_overlay);
+               isp->params.vf_overlay = NULL;
+       }
+
+       if (isp->raw_output_frame) {
+               sh_css_frame_free(isp->raw_output_frame);
+               isp->raw_output_frame = NULL;
+       }
+}
+
+void atomisp_free_3a_buffers(struct atomisp_device *isp)
+{
+       /* 3A statistics use vmalloc, DIS use kmalloc */
+       if (isp->params.s3a_output_buf)
+               vfree(isp->params.s3a_output_buf);
+       isp->params.s3a_output_buf = NULL;
+       isp->params.s3a_output_bytes = 0;
+}
+
+void atomisp_free_dis_buffers(struct atomisp_device *isp)
+{
+       if (isp->params.dis_hor_proj_buf)
+               kfree(isp->params.dis_hor_proj_buf);
+       if (isp->params.dis_ver_proj_buf)
+               kfree(isp->params.dis_ver_proj_buf);
+       if (isp->params.dis_hor_coef_buf)
+               kfree(isp->params.dis_hor_coef_buf);
+       if (isp->params.dis_ver_coef_buf)
+               kfree(isp->params.dis_ver_coef_buf);
+       isp->params.dis_hor_proj_buf = NULL;
+       isp->params.dis_ver_proj_buf = NULL;
+       isp->params.dis_hor_coef_buf = NULL;
+       isp->params.dis_ver_coef_buf = NULL;
+       isp->params.dis_hor_proj_bytes = 0;
+       isp->params.dis_ver_proj_bytes = 0;
+       isp->params.dis_hor_coef_bytes = 0;
+       isp->params.dis_ver_coef_bytes = 0;
+}
+
+static void atomisp_update_grid_info(struct atomisp_device *isp)
+{
+       struct sh_css_grid_info old_info = isp->params.curr_grid_info;
+
+       switch (isp->sw_contex.run_mode) {
+       case CI_MODE_PREVIEW:
+               sh_css_preview_get_grid_info(&isp->params.curr_grid_info);
+               break;
+       case CI_MODE_VIDEO:
+               sh_css_video_get_grid_info(&isp->params.curr_grid_info);
+               break;
+       default:
+               sh_css_capture_get_grid_info(&isp->params.curr_grid_info);
+               break;
+       }
+       /* If the grid info has changed, we need to reallocate
+          the buffers for 3A and DIS statistics. */
+       if (memcmp(&old_info, &isp->params.curr_grid_info, sizeof(old_info)) ||
+           !isp->params.s3a_output_buf || !isp->params.dis_hor_coef_buf) {
+               /* We must free all buffers because they no longer match
+                  the grid size. */
+               atomisp_free_3a_buffers(isp);
+               atomisp_free_dis_buffers(isp);
+               /* 3A statistics. These can be big, so we use vmalloc. */
+               isp->params.s3a_output_bytes =
+                                       isp->params.curr_grid_info.s3a_width *
+                                       isp->params.curr_grid_info.s3a_height *
+                                       sizeof(*isp->params.s3a_output_buf);
+
+               isp->params.s3a_output_buf = vmalloc(
+                               isp->params.s3a_output_bytes);
+
+               if (isp->params.s3a_output_buf == NULL)
+                       goto err_3a;
+
+               /* DIS coefficients. */
+               isp->params.dis_hor_coef_bytes =
+                               isp->params.curr_grid_info.dis_hor_coef_num *
+                               SH_CSS_DIS_NUM_COEF_TYPES *
+                               sizeof(*isp->params.dis_hor_coef_buf);
+
+               isp->params.dis_ver_coef_bytes =
+                               isp->params.curr_grid_info.dis_ver_coef_num *
+                               SH_CSS_DIS_NUM_COEF_TYPES *
+                               sizeof(*isp->params.dis_ver_coef_buf);
+
+               isp->params.dis_hor_coef_buf =
+                       kzalloc(isp->params.dis_hor_coef_bytes, GFP_KERNEL);
+               if (isp->params.dis_hor_coef_buf == NULL)
+                       goto err_dis;
+
+               isp->params.dis_ver_coef_buf =
+                       kzalloc(isp->params.dis_ver_coef_bytes, GFP_KERNEL);
+               if (isp->params.dis_ver_coef_buf == NULL)
+                       goto err_dis;
+
+               /* DIS projections. */
+               isp->params.dis_hor_proj_bytes =
+                               isp->params.curr_grid_info.dis_height *
+                               SH_CSS_DIS_NUM_COEF_TYPES *
+                               sizeof(*isp->params.dis_hor_proj_buf);
+
+               isp->params.dis_ver_proj_bytes =
+                               isp->params.curr_grid_info.dis_width *
+                               SH_CSS_DIS_NUM_COEF_TYPES *
+                               sizeof(*isp->params.dis_ver_proj_buf);
+
+               isp->params.dis_hor_proj_buf =
+                       kzalloc(isp->params.dis_hor_proj_bytes, GFP_KERNEL);
+               if (isp->params.dis_hor_proj_buf == NULL)
+                       goto err_dis;
+
+               isp->params.dis_ver_proj_buf =
+                       kzalloc(isp->params.dis_ver_proj_bytes, GFP_KERNEL);
+               if (isp->params.dis_ver_proj_buf == NULL)
+                       goto err_dis;
+       }
+       return;
+       /* Failure for 3A buffers does not influence DIS buffers */
+err_3a:
+       v4l2_err(&atomisp_dev,
+                   "Failed allocate memory for 3A statistics\n");
+       atomisp_free_3a_buffers(isp);
+       return;
+err_dis:
+       v4l2_err(&atomisp_dev,
+                   "Failed allocate memory for DIS statistics\n");
+       atomisp_free_dis_buffers(isp);
+
+}
+
+static void atomisp_curr_user_grid_info(struct atomisp_device *isp,
+                                   struct atomisp_grid_info_user *info)
+{
+       info->s3a_width             = isp->params.curr_grid_info.s3a_width;
+       info->s3a_height            = isp->params.curr_grid_info.s3a_height;
+       info->s3a_bqs_per_grid_cell =
+           isp->params.curr_grid_info.s3a_bqs_per_grid_cell;
+       info->dis_width             = isp->params.curr_grid_info.dis_width;
+       info->dis_height            = isp->params.curr_grid_info.dis_height;
+       info->dis_bqs_per_grid_cell =
+           isp->params.curr_grid_info.dis_bqs_per_grid_cell;
+       info->dis_hor_coef_num      =
+           isp->params.curr_grid_info.dis_hor_coef_num;
+       info->dis_ver_coef_num      =
+           isp->params.curr_grid_info.dis_ver_coef_num;
+}
+
+/*
+ * Function to update Gdc table for gdc
+ */
+int atomisp_gdc_cac_table(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       int ret;
+       int i;
+       struct atomisp_morph_table *arg = (struct atomisp_morph_table *)config;
+
+       if (flag == 0) {
+               /* Get gamma table from current setup */
+               const struct sh_css_morph_table *tab;
+               sh_css_get_morph_table(&tab);
+
+               arg->width = tab->width;
+               arg->height = tab->height;
+
+               for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+                       ret = copy_to_user(arg->coordinates_x[i],
+                               tab->coordinates_x[i], tab->height *
+                               tab->width * sizeof(*tab->coordinates_x[i]));
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                                       "Failed to copy to User for x\n");
+                               return -EFAULT;
+                       }
+                       ret = copy_to_user(arg->coordinates_y[i],
+                               tab->coordinates_y[i], tab->height *
+                               tab->width * sizeof(*tab->coordinates_y[i]));
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                                       "Failed to copy to User for y\n");
+                               return -EFAULT;
+                       }
+               }
+       } else {
+               struct sh_css_morph_table *tab;
+               tab = isp->inputs[isp->input_curr].morph_table;
+               /* free first if we have one */
+               if (tab) {
+                       sh_css_morph_table_free(tab);
+                       isp->inputs[isp->input_curr].morph_table = NULL;
+               }
+
+               /* allocate new one */
+               tab = sh_css_morph_table_allocate(arg->width, arg->height);
+
+               if (!tab) {
+                       v4l2_err(&atomisp_dev, "out of memory\n");
+                       return -EINVAL;
+               }
+
+               for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+                       ret = copy_from_user(tab->coordinates_x[i],
+                               (void __user *)arg->coordinates_x[i],
+                               arg->height * arg->width *
+                               sizeof(*arg->coordinates_x[i]));
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                               "Failed to copy from User for x, ret %d\n",
+                               ret);
+                               sh_css_morph_table_free(tab);
+                               return -EFAULT;
+                       }
+                       ret = copy_from_user(tab->coordinates_y[i],
+                               (void __user *)arg->coordinates_y[i],
+                               arg->height * arg->width *
+                               sizeof(*arg->coordinates_y[i]));
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                               "Failed to copy from User for y, ret is %d\n",
+                               ret);
+                               sh_css_morph_table_free(tab);
+                               return -EFAULT;
+                       }
+               }
+               isp->inputs[isp->input_curr].morph_table = tab;
+               sh_css_set_morph_table(tab);
+       }
+
+       return 0;
+}
+
+int atomisp_macc_table(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct sh_css_macc_table *macc_table;
+       struct atomisp_macc_config *arg = (struct atomisp_macc_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(arg->table) != sizeof(*macc_table)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (arg->color_effect) {
+       case V4L2_COLORFX_SKY_BLUE:
+               macc_table = &blue_macc_table;
+               break;
+       case V4L2_COLORFX_GRASS_GREEN:
+               macc_table = &green_macc_table;
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN_LOW:
+               macc_table = &skin_low_macc_table;
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN:
+               macc_table = &skin_medium_macc_table;
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN_HIGH:
+               macc_table = &skin_high_macc_table;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get macc table from current setup */
+               memcpy(&arg->table, macc_table,
+                      sizeof(struct sh_css_macc_table));
+       } else {
+               memcpy(macc_table, &arg->table,
+                      sizeof(struct sh_css_macc_table));
+       }
+
+       return 0;
+}
+
+int atomisp_dis_vector(struct atomisp_device *isp,
+                      void *config)
+{
+       struct atomisp_dis_config *arg = (struct atomisp_dis_config *)config;
+
+       /* The dis parameter is initialized at start_video_capture
+        * in atomisp_work
+        */
+       mutex_lock(&isp->isp_lock);
+       isp->params.dis_x = arg->dis_x;
+       isp->params.dis_y = arg->dis_y;
+       mutex_unlock(&isp->isp_lock);
+       return 0;
+}
+
+/*
+ * Function to set/get image stablization statistics
+ */
+int atomisp_dis_stat(struct atomisp_device *isp, int flag,
+                    void *config)
+{
+       int error;
+       struct atomisp_dis_config *arg = (struct atomisp_dis_config *)config;
+
+       if (flag == 0) {
+               long time_left;
+
+               if (arg->w_sdis_vertproj_tbl == NULL ||
+                   arg->w_sdis_horiproj_tbl == NULL ||
+                   isp->params.dis_hor_proj_buf    == NULL ||
+                   isp->params.dis_ver_proj_buf    == NULL)
+                       return -EINVAL;
+
+               /* isp need to be streaming to get DIS statistics */
+               if (!isp->sw_contex.isp_streaming)
+                       return -EINVAL;
+               if (!isp->params.video_dis_en)
+                       return -EINVAL;
+
+               INIT_COMPLETION(isp->dis_state_complete);
+
+               time_left =
+                   wait_for_completion_timeout(&isp->dis_state_complete,
+                                               1 * HZ);
+
+               /* Timeout to get the statistics */
+               if (time_left == 0) {
+                       v4l2_err(&atomisp_dev,
+                                "Failed to wait frame DIS state\n");
+                       return -EINVAL;
+               }
+
+
+               sh_css_get_dis_projections(isp->params.dis_hor_proj_buf,
+                                          isp->params.dis_ver_proj_buf);
+
+               error = copy_to_user(arg->w_sdis_vertproj_tbl,
+                                    isp->params.dis_ver_proj_buf,
+                                    isp->params.dis_ver_proj_bytes);
+               if (error)
+                       return -EFAULT;
+
+               error = copy_to_user(arg->w_sdis_horiproj_tbl,
+                                    isp->params.dis_hor_proj_buf,
+                                    isp->params.dis_hor_proj_bytes);
+               if (error)
+                       return -EFAULT;
+       } else {
+               if (arg->sdis_vertcoef_tbl == NULL ||
+                   arg->sdis_horicoef_tbl == NULL ||
+                   isp->params.dis_hor_coef_buf  == NULL ||
+                   isp->params.dis_ver_coef_buf  == NULL)
+                       return -EINVAL;
+
+               error = copy_from_user(isp->params.dis_hor_coef_buf,
+                                      (void __user *)arg->sdis_horicoef_tbl,
+                                      isp->params.dis_hor_coef_bytes);
+               if (error)
+                       return -EFAULT;
+               error = copy_from_user(isp->params.dis_ver_coef_buf,
+                                      (void __user *)arg->sdis_vertcoef_tbl,
+                                      isp->params.dis_ver_coef_bytes);
+               if (error)
+                       return -EFAULT;
+               sh_css_set_dis_coefficients(isp->params.dis_hor_coef_buf,
+                                           isp->params.dis_ver_coef_buf);
+       }
+       return 0;
+}
+
+/*
+ * Function to set/get 3A stat from isp
+ */
+int atomisp_3a_stat(struct atomisp_device *isp, int flag,
+                   void *config)
+{
+       struct atomisp_3a_statistics *arg =
+           (struct atomisp_3a_statistics *)config;
+       unsigned long ret;
+
+       if (flag != 0)
+               return -EINVAL;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       /* sanity check to avoid writing into unallocated memory. */
+       if (isp->params.s3a_output_bytes == 0)
+               return -EINVAL;
+
+       /* If the grid info in the argument differs from the current
+          grid info, we tell the caller to reset the grid size and
+          try again. */
+       if (memcmp(&arg->grid_info, &isp->params.curr_grid_info,
+                  sizeof(isp->params.curr_grid_info)) != 0)
+               return -EAGAIN;
+
+       mutex_lock(&isp->isp3a_lock);
+       ret = copy_to_user(arg->data, isp->params.s3a_output_buf,
+                          isp->params.s3a_output_bytes);
+       mutex_unlock(&isp->isp3a_lock);
+       if (ret) {
+               v4l2_err(&atomisp_dev,
+                           "copy to user failed: copied %lu bytes\n", ret);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+/*
+ * Function to set/get isp parameters to isp
+ */
+int atomisp_param(struct atomisp_device *isp, int flag,
+                         void *config)
+{
+       struct atomisp_parm *arg = (struct atomisp_parm *)config;
+
+       /* Read parameter for 3A bianry info */
+       if (flag == 0) {
+               if (&arg->info == NULL) {
+                       v4l2_err(&atomisp_dev,
+                                   "ERROR: NULL pointer in grid_info\n");
+                       return -EINVAL;
+               }
+               atomisp_curr_user_grid_info(isp, &arg->info);
+               return 0;
+       }
+
+       if (sizeof(arg->wb_config) != sizeof(isp->params.wb_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->cc_config) != sizeof(isp->params.cc_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->ob_config) != sizeof(isp->params.ob_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->de_config) != sizeof(isp->params.de_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->dp_config) != sizeof(isp->params.dp_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->nr_config) != sizeof(isp->params.nr_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->ee_config) != sizeof(isp->params.ee_config))
+               goto INVALID_PARM;
+       if (sizeof(arg->tnr_config) != sizeof(isp->params.tnr_config))
+               goto INVALID_PARM;
+
+       memcpy(&isp->params.wb_config, &arg->wb_config,
+              sizeof(struct sh_css_wb_config));
+       memcpy(&isp->params.ob_config, &arg->ob_config,
+              sizeof(struct sh_css_ob_config));
+       memcpy(&isp->params.dp_config, &arg->dp_config,
+              sizeof(struct sh_css_dp_config));
+       memcpy(&isp->params.de_config, &arg->de_config,
+              sizeof(struct sh_css_de_config));
+       memcpy(&isp->params.nr_config, &arg->nr_config,
+              sizeof(struct sh_css_nr_config));
+       memcpy(&isp->params.ee_config, &arg->ee_config,
+              sizeof(struct sh_css_ee_config));
+       memcpy(&isp->params.tnr_config, &arg->tnr_config,
+              sizeof(struct sh_css_tnr_config));
+
+       if (isp->params.color_effect == V4L2_COLORFX_NEGATIVE) {
+               arg->cc_config.matrix[3] = -arg->cc_config.matrix[3];
+               arg->cc_config.matrix[4] = -arg->cc_config.matrix[4];
+               arg->cc_config.matrix[5] = -arg->cc_config.matrix[5];
+               arg->cc_config.matrix[6] = -arg->cc_config.matrix[6];
+               arg->cc_config.matrix[7] = -arg->cc_config.matrix[7];
+               arg->cc_config.matrix[8] = -arg->cc_config.matrix[8];
+       }
+
+       if (isp->params.color_effect != V4L2_COLORFX_SEPIA &&
+           isp->params.color_effect != V4L2_COLORFX_BW) {
+               memcpy(&isp->params.cc_config, &arg->cc_config,
+                      sizeof(struct sh_css_cc_config));
+               sh_css_set_cc_config(&isp->params.cc_config);
+       }
+
+       sh_css_set_wb_config(&isp->params.wb_config);
+       sh_css_set_ob_config(&isp->params.ob_config);
+       sh_css_set_de_config(&isp->params.de_config);
+       sh_css_set_dp_config(&isp->params.dp_config);
+       sh_css_set_nr_config(&isp->params.nr_config);
+       sh_css_set_ee_config(&isp->params.ee_config);
+       sh_css_set_tnr_config(&isp->params.tnr_config);
+
+       return 0;
+
+INVALID_PARM:
+       v4l2_err(&atomisp_dev,
+               "%s: incompatible param.\n", __func__);
+       return -EINVAL;
+}
+
+/*
+ * Function to configure color effect of the image
+ */
+int atomisp_color_effect(struct atomisp_device *isp, int flag, __s32 *effect)
+{
+       const struct sh_css_cc_config *cc_config = NULL;
+       const struct sh_css_macc_table *macc_table = NULL;
+       const struct sh_css_ctc_table *ctc_table = NULL;
+
+       if (flag == 0) {
+               *effect = isp->params.color_effect;
+               return 0;
+       }
+
+       if (*effect == isp->params.color_effect)
+               return 0;
+
+       switch (*effect) {
+       case V4L2_COLORFX_NONE:
+               cc_config  = isp->params.default_cc_config;
+               macc_table = isp->params.default_macc_table;
+               ctc_table  = isp->params.default_ctc_table;
+               isp->params.macc_en = false;
+               if (!isp->params.gdc_cac_en)
+                       sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_PRIMARY);
+               break;
+       case V4L2_COLORFX_SEPIA:
+               cc_config = &sepia_cc_config;
+               break;
+       case V4L2_COLORFX_NEGATIVE:
+               cc_config = &nega_cc_config;
+               break;
+       case V4L2_COLORFX_BW:
+               cc_config = &mono_cc_config;
+               break;
+       case V4L2_COLORFX_SKY_BLUE:
+               macc_table = &blue_macc_table;
+               isp->params.macc_en = true;
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+               break;
+       case V4L2_COLORFX_GRASS_GREEN:
+               macc_table = &green_macc_table;
+               isp->params.macc_en = true;
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN_LOW:
+               macc_table = &skin_low_macc_table;
+               isp->params.macc_en = true;
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN:
+               macc_table = &skin_medium_macc_table;
+               isp->params.macc_en = true;
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+               break;
+       case V4L2_COLORFX_SKIN_WHITEN_HIGH:
+               macc_table = &skin_high_macc_table;
+               isp->params.macc_en = true;
+               sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_ADVANCED);
+               break;
+       case V4L2_COLORFX_VIVID:
+               ctc_table = &vivid_ctc_table;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (cc_config)
+               sh_css_set_cc_config(cc_config);
+       if (macc_table)
+               sh_css_set_macc_table(macc_table);
+       if (ctc_table)
+               sh_css_set_ctc_table(ctc_table);
+       isp->params.color_effect = (u32)*effect;
+       return 0;
+}
+
+/*
+ * Function to configure bad pixel correction
+ */
+int atomisp_bad_pixel(struct atomisp_device *isp, int flag, __s32 *value)
+{
+
+       if (flag == 0) {
+               *value = isp->params.bad_pixel_en;
+               return 0;
+       }
+       isp->params.bad_pixel_en = (*value == 0) ? 0 : 1;
+
+       return 0;
+}
+
+/*
+ * Function to configure bad pixel correction params
+ */
+int atomisp_bad_pixel_param(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct atomisp_dp_config *arg = (struct atomisp_dp_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.dp_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get bad pixel from current setup */
+               memcpy(arg, &isp->params.dp_config, sizeof(*arg));
+       } else {
+               /* Set bad pixel to isp parameters */
+               memcpy(&isp->params.dp_config, arg, sizeof(*arg));
+               sh_css_set_dp_config(&isp->params.dp_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to enable/disable video image stablization
+ */
+int atomisp_video_stable(struct atomisp_device *isp, int flag, __s32 * value)
+{
+       if (flag == 0)
+               *value = isp->params.video_dis_en;
+       else
+               isp->params.video_dis_en = (*value == 0) ? 0 : 1;
+
+       return 0;
+}
+
+/*
+ * Function to configure fixed pattern noise
+ */
+int atomisp_fixed_pattern(struct atomisp_device *isp, int flag, __s32 * value)
+{
+
+       if (flag == 0) {
+               *value = isp->params.fpn_en;
+               return 0;
+       }
+
+       if (*value == 0) {
+               isp->params.fpn_en = 0;
+               return 0;
+       }
+
+       /* Add function to get black from from sensor with shutter off */
+       return 0;
+}
+
+/*
+ * Function to configure fixed pattern noise table
+ */
+int atomisp_fixed_pattern_table(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct atomisp_frame *arg = (struct atomisp_frame *)config;
+       struct sh_css_frame *raw_black_frame = NULL;
+       struct sh_css_frame_info info;
+       char *tmp_buf;
+       int ret = 0;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(*raw_black_frame)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0)
+               return -EINVAL;
+       else {
+               memcpy(&info, &arg->info, sizeof(struct sh_css_frame_info));
+
+               tmp_buf = vmalloc(arg->data_bytes);
+               if (!tmp_buf)
+                       return -ENOMEM;
+
+               if (sh_css_frame_allocate_from_info(&raw_black_frame, &info)) {
+                       ret = -ENOMEM;
+                       goto failed1;
+               }
+
+               if (copy_from_user(tmp_buf, arg->data, arg->data_bytes)) {
+                       ret = -EFAULT;
+                       goto failed2;
+               }
+
+               if (hmm_store(raw_black_frame->data, tmp_buf,
+                       arg->data_bytes)){
+                       ret = -EINVAL;
+                       goto failed2;
+               }
+
+               sh_css_set_black_frame(raw_black_frame);
+failed2:
+               sh_css_frame_free(raw_black_frame);
+failed1:
+               vfree(tmp_buf);
+       }
+
+       return ret;
+}
+
+/*
+ * Function to configure vf overlay image
+ */
+int atomisp_vf_overlay(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct atomisp_overlay *arg = (struct atomisp_overlay *)config;
+       int ret = 0;
+       struct sh_css_frame vf_frame;
+       char *tmp_buf;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(*isp->params.vf_overlay)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (!arg->frame)
+               /* from siliconhive, passing NULL means disable the feature */
+               sh_css_overlay_set_for_viewfinder(NULL);
+
+       if (copy_from_user(&vf_frame, arg->frame,
+                            sizeof(struct sh_css_frame)))
+               return -EFAULT;
+
+       tmp_buf = vmalloc(vf_frame.data_bytes);
+       if (!tmp_buf)
+               return -ENOMEM;
+
+       if (isp->params.vf_overlay) {
+               if (isp->params.vf_overlay->frame)
+                       sh_css_frame_free(isp->params.vf_overlay->frame);
+               kfree(isp->params.vf_overlay);
+       }
+
+       isp->params.vf_overlay = kmalloc(sizeof(struct sh_css_overlay),
+                                                       GFP_KERNEL);
+       if (!isp->params.vf_overlay) {
+               ret =  -ENOMEM;
+               goto fail1;
+       }
+
+       if (sh_css_frame_allocate_from_info(&isp->params.vf_overlay->frame,
+                                          &vf_frame.info)) {
+               ret = -ENOMEM;
+               goto fail2;
+       }
+
+       isp->params.vf_overlay->bg_y = arg->bg_y;
+       isp->params.vf_overlay->bg_u = arg->bg_u;
+       isp->params.vf_overlay->bg_v = arg->bg_v;
+       isp->params.vf_overlay->blend_input_perc_y = arg->blend_input_perc_y;
+       isp->params.vf_overlay->blend_input_perc_u = arg->blend_input_perc_u;
+       isp->params.vf_overlay->blend_input_perc_v = arg->blend_input_perc_v;
+       isp->params.vf_overlay->blend_overlay_perc_y =
+                                               arg->blend_overlay_perc_y;
+       isp->params.vf_overlay->blend_overlay_perc_u =
+                                               arg->blend_overlay_perc_u;
+       isp->params.vf_overlay->blend_overlay_perc_v =
+                                               arg->blend_overlay_perc_v;
+       isp->params.vf_overlay->overlay_start_x = arg->overlay_start_x;
+       isp->params.vf_overlay->overlay_start_y = arg->overlay_start_y;
+
+       /* copy for YUV 420 */
+       if (copy_from_user(tmp_buf, vf_frame.data, vf_frame.data_bytes)) {
+                       ret = -EFAULT;
+                       goto fail2;
+       }
+
+       if (hmm_store(isp->params.vf_overlay->frame->data, tmp_buf,
+               vf_frame.data_bytes)){
+               ret = -EINVAL;
+               goto fail2;
+       }
+
+       sh_css_overlay_set_for_viewfinder(isp->params.vf_overlay);
+
+       vfree(tmp_buf);
+
+       return ret;
+
+fail2:
+       kfree(isp->params.vf_overlay);
+fail1:
+       vfree(tmp_buf);
+       return ret;
+}
+
+/*
+ * Function to configure false color correction
+ */
+int atomisp_false_color(struct atomisp_device *isp, int flag, __s32 *value)
+{
+       /* Get nr config from current setup */
+       if (flag == 0) {
+               *value = isp->params.false_color;
+               return 0;
+       }
+
+       /* Set nr config to isp parameters */
+       if (*value) {
+               sh_css_set_de_config(isp->params.default_de_config);
+       } else {
+               isp->params.de_config.pixelnoise = 0;
+               sh_css_set_de_config(&isp->params.de_config);
+       }
+       isp->params.false_color = *value;
+       return 0;
+}
+
+/*
+ * Function to configure bad pixel correction params
+ */
+int atomisp_false_color_param(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct atomisp_de_config *arg =
+           (struct atomisp_de_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.de_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get false color from current setup */
+               memcpy(arg, &isp->params.de_config, sizeof(*arg));
+       } else {
+               /* Set false color to isp parameters */
+               memcpy(&isp->params.de_config, arg, sizeof(*arg));
+               sh_css_set_de_config(&isp->params.de_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to configure white balance params
+ */
+int atomisp_white_balance_param(struct atomisp_device *isp, int flag,
+       void *config)
+{
+       struct atomisp_wb_config *arg = (struct atomisp_wb_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.wb_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get white balance from current setup */
+               memcpy(arg, &isp->params.wb_config, sizeof(*arg));
+       } else {
+               /* Set white balance to isp parameters */
+               memcpy(&isp->params.wb_config, arg, sizeof(*arg));
+               sh_css_set_wb_config(&isp->params.wb_config);
+       }
+
+       return 0;
+}
+
+int atomisp_3a_config_param(struct atomisp_device *isp, int flag,
+                           void *config)
+{
+       struct atomisp_3a_config *arg = (struct atomisp_3a_config *)config;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (sizeof(*arg) != sizeof(isp->params.s3a_config)) {
+               v4l2_err(&atomisp_dev,
+                       "%s: incompatible param.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (flag == 0) {
+               /* Get white balance from current setup */
+               memcpy(arg, &isp->params.s3a_config, sizeof(*arg));
+       } else {
+               /* Set white balance to isp parameters */
+               memcpy(&isp->params.s3a_config, arg, sizeof(*arg));
+               sh_css_set_3a_config(&isp->params.s3a_config);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to enable/disable lens shading correction
+ */
+int atomisp_shading_correction(struct atomisp_device *isp, int flag,
+                                      __s32 *value)
+{
+       if (flag == 0) {
+               *value = isp->params.sc_en;
+               return 0;
+       }
+
+       if (*value == 0) {
+               sh_css_set_shading_table(NULL);
+       } else {
+               sh_css_set_shading_table(
+                       isp->inputs[isp->input_curr].shading_table);
+       }
+
+       isp->params.sc_en = *value;
+
+       return 0;
+}
+
+/*
+ * Function to setup digital zoom
+ */
+int atomisp_digital_zoom(struct atomisp_device *isp, int flag, __s32 *value)
+{
+       u32 zoom;
+
+       if (flag == 0) {
+               sh_css_get_zoom_factor(&zoom, &zoom);
+               *value = 64 - zoom;
+       } else {
+               if (*value < 0)
+                       return -EINVAL;
+
+               zoom = *value;
+               if (zoom >= 64)
+                       zoom = 64;
+               zoom = 64 - zoom;
+
+               sh_css_set_zoom_factor(zoom, zoom);
+       }
+
+       return 0;
+}
+
+/*
+ * Function to get sensor specific info for current resolution,
+ * which will be used for auto exposure conversion.
+ */
+int atomisp_get_sensor_mode_data(struct atomisp_device *isp,
+                               void *config)
+{
+       struct atomisp_sensor_mode_data *arg =
+                       (struct atomisp_sensor_mode_data *)config;
+       struct camera_mipi_info *mipi_info;
+
+       mipi_info =
+       atomisp_to_sensor_mipi_info(isp->inputs[isp->input_curr].camera);
+       if (mipi_info == NULL)
+               return -EINVAL;
+
+       memcpy(arg, &mipi_info->data, sizeof(*arg));
+       return 0;
+}
+
+int atomisp_get_fmt(struct video_device *vdev, struct v4l2_format *f)
+{
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev,
+                           "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       memset(f, 0, sizeof(struct v4l2_format));
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       /* VIDIOC_S_FMT already called,*/
+       /* return fmt setted by app */
+       if ((pipe->format) && (pipe->format->out.width != 0))
+               memcpy(&f->fmt.pix, &pipe->format->out,
+                       sizeof(struct v4l2_pix_format));
+       else {
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
+               f->fmt.pix.pixelformat = atomisp_output_fmts[0].pixelformat;
+               f->fmt.pix.bytesperline =
+                       get_pixel_depth(f->fmt.pix.pixelformat) *
+                                               f->fmt.pix.width;
+               f->fmt.pix.sizeimage = f->fmt.pix.height *
+                                               f->fmt.pix.bytesperline;
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       }
+
+       return 0;
+}
+
+
+/* This function looks up the closest available resolution. */
+int atomisp_try_fmt(struct video_device *vdev, struct v4l2_format *f,
+                                               bool *res_overflow)
+{
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct v4l2_mbus_framefmt snr_mbus_fmt;
+       struct atomisp_format_bridge *fmt;
+       u32 out_width = f->fmt.pix.width;
+       u32 out_height = f->fmt.pix.height;
+       u32 pixelformat = f->fmt.pix.pixelformat;
+       u32 in_width = 0;
+       u32 in_height = 0;
+       int ret;
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev, "Wrong v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (isp->inputs[isp->input_curr].camera == NULL)
+               return -EINVAL;
+
+       fmt = get_atomisp_format_bridge(pixelformat);
+       if (fmt == NULL) {
+               v4l2_err(&atomisp_dev, "unsupported pixelformat!\n");
+               fmt = (struct atomisp_format_bridge *)&atomisp_output_fmts[0];
+       }
+
+
+       /*set TPG format*/
+       if (isp->inputs[isp->input_curr].type == TEST_PATTERN) {
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                       video, try_fmt, f);
+               in_width = f->fmt.pix.width;
+               in_height = f->fmt.pix.height;
+               goto done;
+       }
+
+       snr_mbus_fmt.code = fmt->mbus_code;
+       snr_mbus_fmt.height = out_height;
+       snr_mbus_fmt.width = out_width;
+
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                       video, try_mbus_fmt, &snr_mbus_fmt);
+       if (ret) {
+               /*In case camera sensor driver don't support try_mbus_fmt*/
+               v4l2_err(&atomisp_dev,
+                       "failed to try_mbus_fmt for sensor\n");
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                       video, try_fmt, f);
+               if (ret)
+                       return ret;
+               in_width = f->fmt.pix.width;
+               in_height = f->fmt.pix.height;
+       } else {
+               in_width = snr_mbus_fmt.width;
+               in_height = snr_mbus_fmt.height;
+               fmt = get_atomisp_format_bridge_from_mbus(snr_mbus_fmt.code);
+               if (fmt == NULL) {
+                       f->fmt.pix.pixelformat = pixelformat;
+                       v4l2_err(&atomisp_dev, "unknown sensor format.\n");
+               } else
+                       f->fmt.pix.pixelformat = fmt->pixelformat;
+       }
+
+done:
+       v4l2_info(&atomisp_dev, "return snr_try_fmt, (wxh: %d*%d)\n",
+                   in_width, in_height);
+       if ((in_width < out_width) && (in_height < out_height)) {
+               out_width = in_width;
+               out_height = in_height;
+               /* Set the flag when resolution requested is
+                * beyond the max value supported by sensor
+                */
+               if (res_overflow != NULL)
+                       *res_overflow = true;
+       }
+
+       /* app vs isp */
+       out_width = min(out_width, (u32)ATOM_ISP_MAX_WIDTH);
+       out_height = min(out_height, (u32)ATOM_ISP_MAX_HEIGHT);
+
+       out_width = max(out_width, (u32)ATOM_ISP_MIN_WIDTH);
+       out_height = max(out_height, (u32)ATOM_ISP_MIN_HEIGHT);
+
+       out_width = out_width - out_width % ATOM_ISP_STEP_WIDTH;
+       out_height = out_height - out_height % ATOM_ISP_STEP_HEIGHT;
+
+       f->fmt.pix.width = out_width;
+       f->fmt.pix.height = out_height;
+
+       return 0;
+}
+
+int atomisp_try_fmt_file(struct atomisp_device *isp, struct v4l2_format *f)
+{
+       u32 width = f->fmt.pix.width;
+       u32 height = f->fmt.pix.height;
+       u32 pixelformat = f->fmt.pix.pixelformat;
+       enum v4l2_field field = f->fmt.pix.field;
+       u32 depth;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev, "Wrong v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (!atomisp_is_pixelformat_supported(pixelformat)) {
+               v4l2_err(&atomisp_dev, "Wrong output pixelformat\n");
+               return -EINVAL;
+       }
+
+       depth = get_pixel_depth(pixelformat);
+
+       if (!field || field == V4L2_FIELD_ANY)
+               field = V4L2_FIELD_NONE;
+       else if (field != V4L2_FIELD_NONE) {
+               v4l2_err(&atomisp_dev, "Wrong output field\n");
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = field;
+
+       if (width > ATOM_ISP_MAX_WIDTH)
+               width = ATOM_ISP_MAX_WIDTH;
+       else if (width < ATOM_ISP_MIN_WIDTH)
+               width = ATOM_ISP_MIN_WIDTH;
+
+       if (height > ATOM_ISP_MAX_HEIGHT)
+               height = ATOM_ISP_MAX_HEIGHT;
+       else if (height < ATOM_ISP_MIN_HEIGHT)
+               height = ATOM_ISP_MIN_HEIGHT;
+
+       width = width - width % ATOM_ISP_STEP_WIDTH;
+       height = height - height % ATOM_ISP_STEP_HEIGHT;
+
+       f->fmt.pix.width = width;
+       f->fmt.pix.height = height;
+
+       f->fmt.pix.bytesperline = (width * depth) >> 3;
+
+       return 0;
+}
+
+static bool atomisp_input_format_is_raw(enum atomisp_input_format format)
+{
+       switch (format) {
+       case ATOMISP_INPUT_FORMAT_RAW_6:
+       case ATOMISP_INPUT_FORMAT_RAW_7:
+       case ATOMISP_INPUT_FORMAT_RAW_8:
+       case ATOMISP_INPUT_FORMAT_RAW_10:
+       case ATOMISP_INPUT_FORMAT_RAW_12:
+       case ATOMISP_INPUT_FORMAT_RAW_14:
+       case ATOMISP_INPUT_FORMAT_RAW_16:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static inline void
+atomisp_set_sensor_mipi_to_isp(struct camera_mipi_info *mipi_info)
+{
+       if (mipi_info) {
+               v4l2_info(&atomisp_dev,
+                         "MIPI info from sensor:\n"
+                         "  port: %d\n"
+                         "  number of lanes: %d\n"
+                         "  input format: %d\n"
+                         "  bayer order: %d\n",
+                         mipi_info->port,
+                         mipi_info->num_lanes,
+                         mipi_info->input_format,
+                         mipi_info->raw_bayer_order);
+               if (atomisp_input_format_is_raw(mipi_info->input_format))
+                       sh_css_input_set_bayer_order(
+                                       mipi_info->raw_bayer_order);
+               sh_css_input_set_format(mipi_info->input_format);
+               sh_css_input_configure_port(mipi_info->port,
+                                           mipi_info->num_lanes,
+                                           0xffff4);
+       } else {
+               /*Use default MIPI configuration*/
+               v4l2_info(&atomisp_dev,
+                           "no sensor config info\n");
+               sh_css_input_set_bayer_order(sh_css_bayer_order_grbg);
+               sh_css_input_set_format(SH_CSS_INPUT_FORMAT_RAW_10);
+               v4l2_info(&atomisp_dev, "MIPI 2 lane\n");
+               sh_css_input_configure_port(SH_CSS_MIPI_PORT_4LANE,
+                                               2, 0xffff4);
+       }
+}
+
+static int atomisp_set_fmt_to_isp(struct video_device *vdev,
+                                  struct sh_css_frame_info *output_info,
+                                  struct sh_css_frame_info *raw_output_info,
+                                  int width, int height,
+                                  unsigned int pixelformat)
+{
+       struct camera_mipi_info *mipi_info;
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct atomisp_format_bridge *format;
+       int effective_input_width = pipe->format->in.width;
+       int effective_input_height = pipe->format->in.height;
+       int ret;
+
+       format = get_atomisp_format_bridge(pixelformat);
+       if (format == NULL)
+               return -EINVAL;
+
+       isp->main_format->out_sh_fmt = format->sh_fmt;
+       pipe->format->out.pixelformat = pixelformat;
+
+       if (isp->inputs[isp->input_curr].type != TEST_PATTERN &&
+               isp->inputs[isp->input_curr].type != FILE_INPUT) {
+               mipi_info = atomisp_to_sensor_mipi_info(
+                       isp->inputs[isp->input_curr].camera);
+               atomisp_set_sensor_mipi_to_isp(mipi_info);
+
+               if ((format->sh_fmt == SH_CSS_FRAME_FORMAT_RAW) &&
+                    raw_output_format_match_input(
+                       mipi_info->input_format, pixelformat))
+                       return -EINVAL;
+       }
+
+       sh_css_input_set_resolution(isp->input_format->out.width,
+                                   isp->input_format->out.height);
+
+       if (sh_css_input_set_effective_resolution(effective_input_width,
+                                                 effective_input_height))
+               return -EINVAL;
+
+       v4l2_info(&atomisp_dev, "effective resolution  %dx%d\n",
+                   effective_input_width, effective_input_height);
+
+       if (!isp->vf_format)
+               isp->vf_format =
+                       kzalloc(sizeof(struct atomisp_video_pipe_format),
+                                                       GFP_KERNEL);
+       if (!isp->vf_format) {
+               v4l2_err(&atomisp_dev, "Failed to alloc vf_format memory\n");
+               return -ENOMEM;
+       }
+
+       isp->vf_format->out.width = 640;
+       isp->vf_format->out.height = 480;
+       isp->vf_format->out_sh_fmt = SH_CSS_FRAME_FORMAT_YUV420;
+
+       if ((isp->vf_format->out.width > width) ||
+           (isp->vf_format->out.height > height)) {
+               if ((width <  640) || (height < 480)) {
+                       isp->vf_format->out.width = width;
+                       isp->vf_format->out.height = height;
+               } else {
+                       isp->vf_format->out.width = 640;
+                       isp->vf_format->out.height = 480;
+               }
+       }
+
+       switch (isp->sw_contex.run_mode) {
+       case CI_MODE_PREVIEW:
+               if (sh_css_preview_configure_pp_input(
+                               effective_input_width, effective_input_height))
+                       return -EINVAL;
+
+               if (sh_css_preview_configure_output(width, height,
+                                       format->sh_fmt))
+                       return -EINVAL;
+
+               if (sh_css_preview_get_output_frame_info(output_info))
+                       return -EINVAL;
+               break;
+       case CI_MODE_VIDEO:
+               if (sh_css_video_configure_viewfinder(
+                                       isp->vf_format->out.width,
+                                       isp->vf_format->out.height,
+                                       isp->vf_format->out_sh_fmt))
+                       return -EINVAL;
+
+               if (sh_css_video_configure_output(width, height,
+                                                 format->sh_fmt))
+                       return -EINVAL;
+
+               if (sh_css_video_get_output_frame_info(output_info))
+                       return -EINVAL;
+               break;
+       default:
+               if (format->sh_fmt == SH_CSS_FRAME_FORMAT_RAW) {
+                       v4l2_info(&atomisp_dev, "ISP raw mode\n");
+                       sh_css_capture_set_mode(SH_CSS_CAPTURE_MODE_RAW);
+               }
+
+               sh_css_capture_enable_online(isp->params.online_process);
+
+               if (sh_css_capture_configure_pp_input(
+                                               effective_input_width,
+                                               effective_input_height))
+                       return -EINVAL;
+
+               if (sh_css_capture_configure_viewfinder(
+                                       isp->vf_format->out.width,
+                                       isp->vf_format->out.height,
+                                       isp->vf_format->out_sh_fmt))
+                       return -EINVAL;
+
+               if (sh_css_capture_configure_output(width, height,
+                                                   format->sh_fmt))
+                       return -EINVAL;
+
+               ret = sh_css_capture_get_output_frame_info(output_info);
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                   "Resolution set mismatach error %d\n",
+                                   ret);
+                       return -EINVAL;
+               }
+
+               if (!isp->params.online_process)
+                       if (sh_css_capture_get_output_raw_frame_info(
+                                               raw_output_info))
+                               return -EINVAL;
+               if (isp->sw_contex.run_mode != CI_MODE_STILL_CAPTURE) {
+                       v4l2_err(&atomisp_dev,
+                                   "Need to set the running mode first\n");
+                       isp->sw_contex.run_mode = CI_MODE_STILL_CAPTURE;
+               }
+               break;
+       }
+
+       atomisp_update_grid_info(isp);
+
+       /* Free the raw_dump buffer first */
+       sh_css_frame_free(isp->raw_output_frame);
+       isp->raw_output_frame = NULL;
+
+       if (!isp->params.online_process && !isp->sw_contex.file_input) {
+               if (sh_css_frame_allocate_from_info(&isp->raw_output_frame,
+                                                   raw_output_info))
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int atomisp_get_effective_resolution(struct atomisp_device *isp,
+                                           unsigned int pixelformat,
+                                           int out_width, int out_height,
+                                           int padding_w, int padding_h)
+{
+       struct atomisp_format_bridge *format;
+       struct v4l2_pix_format *in_fmt = &isp->main_format->in;
+       struct v4l2_pix_format *out_fmt = &isp->input_format->out;
+       unsigned int no_padding_w, no_padding_h;
+
+       format = get_atomisp_format_bridge(pixelformat);
+       if (format == NULL)
+               return -EINVAL;
+       if (!isp->params.yuv_ds_en) {
+               in_fmt->width = out_width;
+               in_fmt->height = out_height;
+               return 0;
+       }
+       no_padding_w = out_fmt->width - padding_w;
+       no_padding_h = out_fmt->height - padding_h;
+       /* enable YUV downscaling automatically */
+       if (no_padding_w > out_width || no_padding_h > out_height) {
+               /* keep a right ratio of width and height*/
+               in_fmt->width = no_padding_w;
+               in_fmt->height = DIV_RND_UP(in_fmt->width * out_height,
+                                                       out_width);
+               if (in_fmt->height > no_padding_h) {
+                       in_fmt->height = no_padding_h;
+                       in_fmt->width = DIV_RND_UP(in_fmt->height * out_width,
+                                                               out_height);
+
+               }
+               in_fmt->width = (in_fmt->width &
+                                       ~(ATOM_ISP_STEP_WIDTH - 1));
+               in_fmt->height = (in_fmt->height &
+                                       ~(ATOM_ISP_STEP_HEIGHT - 1));
+               if (isp->params.gdc_cac_en) {
+                       if (in_fmt->width > ISP_POST_GDC_MAX_OUTPUT_WIDTH)
+                               in_fmt->width = ISP_POST_GDC_MAX_OUTPUT_WIDTH;
+                       if (in_fmt->height > ISP_POST_GDC_MAX_OUTPUT_HEIGHT)
+                               in_fmt->height = ISP_POST_GDC_MAX_OUTPUT_HEIGHT;
+               }
+       } else {
+               in_fmt->width = out_width;
+               in_fmt->height = out_height;
+       }
+       return 0;
+}
+
+static void atomisp_set_dis_envelop(struct atomisp_device *isp,
+                           unsigned int width, unsigned int height,
+                           unsigned int *dvs_env_w,
+                           unsigned int *dvs_env_h)
+{
+       /* if subdev type is SOC camera,we do not need to set DVS */
+       if (isp->inputs[isp->input_curr].type == SOC_CAMERA)
+               isp->params.video_dis_en = 0;
+
+       if (isp->params.video_dis_en &&
+           isp->sw_contex.run_mode == CI_MODE_VIDEO) {
+               /* envelope is 20% of the output resolution */
+               /*
+                * dvs envelope cannot be round up.
+                * it would cause ISP timeout and color switch issue
+                */
+               *dvs_env_w = width / 5;
+               *dvs_env_h = height / 5;
+               sh_css_video_set_dis_envelope(*dvs_env_w, *dvs_env_h);
+       } else {
+               /* if DVS gets disabled, make sure it's indeed turned off */
+               sh_css_video_set_dis_envelope(0, 0);
+       }
+}
+
+static int atomisp_set_fmt_to_snr(struct atomisp_device *isp,
+                         struct v4l2_format *f, unsigned int pixelformat,
+                         unsigned int padding_w, unsigned int padding_h,
+                         unsigned int dvs_env_w, unsigned int dvs_env_h)
+{
+       struct atomisp_format_bridge *format;
+       struct v4l2_mbus_framefmt snr_mbus_fmt;
+       struct v4l2_format snr_fmt;
+       struct atomisp_video_pipe *out_pipe = &isp->isp_subdev.video_in;
+       int ret;
+
+       format = get_atomisp_format_bridge(pixelformat);
+       if (format == NULL)
+               return -EINVAL;
+
+               if (!isp->sw_contex.file_input) {
+                       v4l2_fill_mbus_format(&snr_mbus_fmt, &f->fmt.pix,
+                                               format->mbus_code);
+                       snr_mbus_fmt.height += padding_h + dvs_env_h;
+                       snr_mbus_fmt.width += padding_w + dvs_env_w;
+
+                       ret = v4l2_subdev_call(
+                                       isp->inputs[isp->input_curr].camera,
+                                       video, s_mbus_fmt, &snr_mbus_fmt);
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                                       "call s_mbus_fmt for sensor failed\n");
+
+                               snr_fmt = *f;
+                               snr_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                               snr_fmt.fmt.pix.height += padding_h + dvs_env_h;
+                               snr_fmt.fmt.pix.width += padding_w + dvs_env_w;
+
+                               /*
+                                * In case the camera driver
+                                * not support mbus function
+                                */
+                               ret = v4l2_subdev_call(
+                                       isp->inputs[isp->input_curr].camera,
+                                       video, s_fmt, &snr_fmt);
+                               if (ret) {
+                                       v4l2_err(&atomisp_dev,
+                                       "call s_fmt for sensor failed\n");
+                                       return ret;
+                               }
+                               isp->input_format->out.width =
+                                                       snr_fmt.fmt.pix.width;
+                               isp->input_format->out.height =
+                                                       snr_fmt.fmt.pix.height;
+                               isp->input_format->out.pixelformat =
+                                               snr_fmt.fmt.pix.pixelformat;
+               } else {
+                       isp->input_format->out.width = snr_mbus_fmt.width;
+                       isp->input_format->out.height = snr_mbus_fmt.height;
+                       isp->input_format->out.pixelformat =
+                           snr_mbus_fmt.code;
+               }
+
+               v4l2_info(&atomisp_dev,
+                         "sensor output resolution %dx%d\n",
+                         isp->input_format->out.width,
+                         isp->input_format->out.height);
+
+       } else {        /* file input case */
+               isp->input_format->out.width = out_pipe->out_fmt->width;
+               isp->input_format->out.height = out_pipe->out_fmt->height;
+       }
+
+       if (isp->input_format->out.width < ATOM_ISP_STEP_WIDTH ||
+           isp->input_format->out.height < ATOM_ISP_STEP_HEIGHT)
+                       return -EINVAL;
+
+       return 0;
+}
+void atomisp_get_yuv_ds_status(struct atomisp_device *isp,
+                              unsigned int width, unsigned int height)
+{
+       /* no YUV downscaling if sensor output is 10% larger than isp output */
+       unsigned int w_tmp =  isp->input_format->out.width -
+                               DIV_RND_UP(isp->input_format->out.width, 10);
+       unsigned int h_tmp =  isp->input_format->out.height -
+                               DIV_RND_UP(isp->input_format->out.height , 10);
+       /*
+        * yuv downscaling is not enabled in video binary,
+        * ,raw format output, soc sensor. effective resolution should
+        * be the same as isp output.
+        */
+       if ((w_tmp < width && h_tmp < height)
+               || isp->sw_contex.run_mode == CI_MODE_VIDEO
+               || isp->sw_contex.bypass
+               || isp->sw_contex.file_input)
+               isp->params.yuv_ds_en = false;
+       else
+               isp->params.yuv_ds_en = true;
+       v4l2_info(&atomisp_dev, "yuv downscaling is %s.\n",
+              isp->params.yuv_ds_en ? "enabled" : "disabled");
+
+}
+int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
+{
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct atomisp_format_bridge *format_bridge;
+       struct sh_css_frame_info output_info, raw_output_info;
+       struct v4l2_format snr_fmt = *f;
+       unsigned int width = f->fmt.pix.width;
+       unsigned int height = f->fmt.pix.height;
+       unsigned int pixelformat = f->fmt.pix.pixelformat;
+       unsigned int sh_format;
+       unsigned int dvs_env_w = 0,
+                    dvs_env_h = 0;
+       unsigned int padding_w = pad_w,
+                    padding_h = pad_h;
+       bool res_overflow = false;
+       struct v4l2_streamparm sensor_parm;
+       int ret;
+
+       if ((f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+           (f->type != V4L2_BUF_TYPE_PRIVATE)) {
+               v4l2_err(&atomisp_dev, "Wrong v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       format_bridge = get_atomisp_format_bridge(pixelformat);
+       if (format_bridge == NULL)
+               return -EINVAL;
+
+       sh_format = format_bridge->sh_fmt;
+       if (!pipe->is_main) {
+               switch (isp->sw_contex.run_mode) {
+               case CI_MODE_VIDEO:
+                       sh_css_video_configure_viewfinder(
+                                       width, height, sh_format);
+                       sh_css_video_get_viewfinder_frame_info(&output_info);
+                       break;
+               case CI_MODE_STILL_CAPTURE:
+                       sh_css_capture_configure_viewfinder(
+                                       width, height, sh_format);
+                       sh_css_capture_get_viewfinder_frame_info(&output_info);
+                       break;
+               }
+               goto done;
+       }
+
+       /* V4L2_BUF_TYPE_PRIVATE will set offline processing */
+       if (f->type == V4L2_BUF_TYPE_PRIVATE)
+               isp->params.online_process = 0;
+       else
+               isp->params.online_process = 1;
+
+       /* setting run mode to the sensor */
+       sensor_parm.parm.capture.capturemode = isp->sw_contex.run_mode;
+       v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                               video, s_parm, &sensor_parm);
+
+       /* get sensor resolution and format */
+       snr_fmt = *f;
+       atomisp_try_fmt(vdev, &snr_fmt, &res_overflow);
+       width = snr_fmt.fmt.pix.width;
+       height = snr_fmt.fmt.pix.height;
+
+       /*
+        * bypass mode is enabled when sensor output format is not raw
+        * or isp output format is raw.
+        */
+       if (isp->inputs[isp->input_curr].type != TEST_PATTERN &&
+               (!is_pixelformat_raw(snr_fmt.fmt.pix.pixelformat) ||
+                       is_pixelformat_raw(pixelformat))) {
+               isp->sw_contex.bypass = true;
+               padding_h = 0;
+               padding_w = 0;
+       } else
+               isp->sw_contex.bypass = false;
+
+       /* construct resolution supported by isp */
+       if (res_overflow) {
+               width -= padding_w;
+               height -= padding_h;
+               /* app vs isp */
+               width = min(width, (u32)ATOM_ISP_MAX_WIDTH);
+               height = min(height, (u32)ATOM_ISP_MAX_HEIGHT);
+
+               width = max(width, (u32)ATOM_ISP_MIN_WIDTH);
+               height = max(height, (u32)ATOM_ISP_MIN_HEIGHT);
+
+               width = width - width % ATOM_ISP_STEP_WIDTH;
+               height = height - height % ATOM_ISP_STEP_HEIGHT;
+
+               f->fmt.pix.width = width;
+               f->fmt.pix.height = height;
+       }
+
+       /* set dis envelop if video and dis are enabled */
+       atomisp_set_dis_envelop(isp, width, height, &dvs_env_w, &dvs_env_h);
+
+       if (!isp->input_format)
+               isp->input_format =
+               kzalloc(sizeof(struct atomisp_video_pipe_format), GFP_KERNEL);
+       if (!isp->input_format) {
+               v4l2_err(&atomisp_dev, "Failed to alloc input_format memory\n");
+               return -ENOMEM;
+       }
+
+       /* set format info to sensor */
+       ret = atomisp_set_fmt_to_snr(isp, f, pixelformat,
+                                    padding_w, padding_h,
+                                    dvs_env_w, dvs_env_h);
+       if (ret)
+               return -EINVAL;
+
+       /* Only main stream pipe will be here */
+       isp->main_format = pipe->format;
+       if (!isp->main_format) {
+               v4l2_err(&atomisp_dev, "Internal error\n");
+               return -EINVAL;
+       }
+
+       atomisp_get_yuv_ds_status(isp, width, height);
+
+       /*
+        * calculate effective solution to enable yuv downscaling and keep
+        * ratio of width and height
+        */
+       ret = atomisp_get_effective_resolution(isp, pixelformat, width, height,
+                                              padding_w, padding_h);
+       if (ret)
+               return -EINVAL;
+
+       /* set format to isp */
+       ret = atomisp_set_fmt_to_isp(vdev, &output_info, &raw_output_info,
+                                    width, height, pixelformat);
+       if (ret)
+               return -EINVAL;
+done:
+       pipe->format->out.width = width;
+       pipe->format->out.height = height;
+       pipe->format->out.pixelformat = pixelformat;
+       pipe->format->out.bytesperline =
+           DIV_RND_UP(format_bridge->depth * output_info.padded_width, 8);
+       pipe->format->out.sizeimage =
+           PAGE_ALIGN(height * pipe->format->out. bytesperline);
+       if (f->fmt.pix.field == V4L2_FIELD_ANY)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+       pipe->format->out.field = f->fmt.pix.field;
+       pipe->format->out_sh_fmt = sh_format;
+
+       memcpy(&f->fmt.pix, &pipe->format->out,
+                       sizeof(struct v4l2_pix_format));
+       f->fmt.pix.priv = PAGE_ALIGN(pipe->format->out.width *
+                                    pipe->format->out.height * 2);
+
+       pipe->capq.field = f->fmt.pix.field;
+
+       v4l2_info(&atomisp_dev,
+                   "ISP output resolution: %dx%d, format = %s\n",
+                   pipe->format->out.width, pipe->format->out.height,
+                   format_bridge->description);
+       return 0;
+}
+
+int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f)
+{
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       enum sh_css_input_format sh_input_format;
+       int ret = 0;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev,
+                               "Wrong v4l2 buf type for output\n");
+               return -EINVAL;
+       }
+
+       switch (isp->sw_contex.output_mode) {
+       case OUTPUT_MODE_FILE:
+               ret = atomisp_try_fmt_file(isp, f);
+               if (ret)
+                       return ret;
+
+               pipe->out_fmt->pixelformat = f->fmt.pix.pixelformat;
+               pipe->out_fmt->framesize = f->fmt.pix.sizeimage;
+               pipe->out_fmt->imagesize = f->fmt.pix.sizeimage;
+               pipe->out_fmt->depth = get_pixel_depth(f->fmt.pix.pixelformat);
+               pipe->out_fmt->bytesperline = f->fmt.pix.bytesperline;
+
+               pipe->out_fmt->bayer_order = f->fmt.pix.priv;
+               pipe->out_fmt->width = f->fmt.pix.width;
+               pipe->out_fmt->height = f->fmt.pix.height;
+               sh_input_format = get_sh_input_format(
+                                               pipe->out_fmt->pixelformat);
+               if (sh_input_format == -EINVAL) {
+                       v4l2_err(&atomisp_dev,
+                                       "Wrong v4l2 format for output\n");
+                       return -EINVAL;
+               }
+
+               sh_css_input_set_format(sh_input_format);
+               sh_css_input_set_mode(SH_CSS_INPUT_MODE_FIFO);
+               sh_css_input_set_bayer_order(pipe->out_fmt->bayer_order);
+               sh_css_input_configure_port(SH_CSS_MIPI_PORT_4LANE, 2, 0xffff4);
+               return 0;
+
+       case OUTPUT_MODE_TEXT:
+               pipe->out_fmt->framesize = f->fmt.pix.sizeimage;
+               pipe->out_fmt->imagesize = f->fmt.pix.sizeimage;
+               return 0;
+
+       default:
+               v4l2_err(&atomisp_dev, "Unspported output mode\n");
+               return -EINVAL;
+       }
+}
+
+/*
+ * atomisp_acc_get_fw - Search for firmware with given handle
+ *
+ * This function will search for given handle until:
+ * - Handle is found
+ * - Reached end of isp->acc_fw[] array
+ * - Function has found total number of non-NULL slots
+ */
+static struct sh_css_acc_fw *
+atomisp_acc_get_fw(struct atomisp_device *isp, unsigned int handle)
+{
+       int i, count;
+
+       if (isp->acc_fw_count == 0)
+               return NULL;
+
+       for (i = 0, count = isp->acc_fw_count;
+            count > 0 && i < ATOMISP_ACC_FW_MAX; i++) {
+               if (isp->acc_fw[i] == NULL)
+                       continue;
+               if (isp->acc_fw[i]->handle == handle)
+                       break;
+               count--;
+       }
+
+       return i < ATOMISP_ACC_FW_MAX || count > 0 ? isp->acc_fw[i] : NULL;
+}
+
+/*
+ * atomisp_acc_get_index - Search for firmware index in isp->acc_fw[] array
+ *
+ * This function will search for firmware index until:
+ * - Given firmware is found
+ * - Reached end of isp->acc_fw[] array
+ * - Function has searched all non-NULL slots
+ */
+static int
+atomisp_acc_get_index(struct atomisp_device *isp, struct sh_css_acc_fw *fw)
+{
+       int i, count;
+
+       if (isp->acc_fw_count == 0)
+               return -EINVAL;
+
+       for (i = 0, count = isp->acc_fw_count;
+            count > 0 && i < ATOMISP_ACC_FW_MAX; i++) {
+               if (isp->acc_fw[i] == fw)
+                       break;
+               if (isp->acc_fw[i] != NULL)
+                       count--;
+       }
+
+       return i < ATOMISP_ACC_FW_MAX || count > 0 ? i : -EINVAL;
+}
+
+static void
+atomisp_acc_fw_free_args(struct atomisp_device *isp, struct sh_css_acc_fw *fw)
+{
+       int i = atomisp_acc_get_index(isp, fw);
+
+       /* Sanity check */
+       if (i < 0) {
+               WARN_ON(1);
+               return;
+       }
+
+       /* Free `host' data for all arguments */
+       for (i = 0; ; i++) {
+               union host *host;
+               enum sh_css_acc_arg_type type;
+
+               host = sh_css_argument_get_host(fw, i);
+               if (sh_css_argument_set_host(fw, i, NULL))
+                       break;          /* Failure: all arguments freed */
+               if (!host)
+                       continue;
+               type = sh_css_argument_type(fw, i);
+               switch (type) {
+               case SH_CSS_ACC_ARG_SCALAR_IN:
+                       kfree(host->scalar.kernel_ptr);
+                       break;
+               case ATOMISP_ACC_ARG_FRAME:
+               case SH_CSS_ACC_ARG_PTR_IN:
+               case SH_CSS_ACC_ARG_PTR_OUT:
+               case SH_CSS_ACC_ARG_PTR_IO:
+                       hrt_isp_css_mm_free(host->ptr.hmm_ptr);
+                       break;
+               default:
+                       v4l2_err(&atomisp_dev, "%s: Invalid argument type.\n",
+                                __func__);
+                       break;
+               }
+               kfree(host);
+       }
+}
+
+static void
+atomisp_acc_fw_free(struct atomisp_device *isp, struct sh_css_acc_fw *fw)
+{
+       int i = atomisp_acc_get_index(isp, fw);
+
+       /* Sanity check */
+       if (i < 0) {
+               WARN_ON(1);
+               return;
+       }
+
+       isp->acc_fw[i] = NULL;
+       isp->acc_fw_count--;
+
+       kfree(fw);
+}
+
+static struct sh_css_acc_fw *
+atomisp_acc_fw_alloc(struct atomisp_device *isp,
+                    struct atomisp_acc_fw_load *user_fw)
+{
+       struct sh_css_acc_fw *fw;
+       int ret;
+       int i;
+
+       /* REVISIT: does size need to be multiple of page size? */
+       fw = kzalloc(user_fw->size, GFP_KERNEL);
+
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "%s: Failed to alloc acc fw blob\n",
+                        __func__);
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = copy_from_user(fw, user_fw->data, user_fw->size);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "%s: Failed to copy acc fw blob\n",
+                        __func__);
+               ret = -EIO;
+               goto err;
+       }
+
+       mutex_lock(&isp->isp_lock);
+       if (isp->acc_fw_count >= ATOMISP_ACC_FW_MAX) {
+               mutex_unlock(&isp->isp_lock);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* Find first free slot */
+       for (i = 0; i < ATOMISP_ACC_FW_MAX; i++) {
+               if (isp->acc_fw[i] == NULL)
+                       break;
+       }
+       user_fw->fw_handle = isp->acc_fw_handle;
+       fw->handle = isp->acc_fw_handle;
+       isp->acc_fw[i] = fw;
+
+       isp->acc_fw_handle++;
+       isp->acc_fw_count++;
+       mutex_unlock(&isp->isp_lock);
+
+       return fw;
+
+err:
+       kfree(fw);
+       return ERR_PTR(ret);
+}
+
+int atomisp_acc_load(struct atomisp_device *isp,
+                    struct atomisp_acc_fw_load *user_fw)
+{
+       struct sh_css_acc_fw *fw;
+       int ret;
+
+       mutex_lock(&isp->input_lock);
+       fw = atomisp_acc_fw_alloc(isp, user_fw);
+       if (IS_ERR(fw)) {
+               v4l2_err(&atomisp_dev, "%s: Acceleration firmware allocation "
+                                      "failed\n", __func__);
+               ret = PTR_ERR(fw);
+               goto out;
+       }
+
+       mutex_lock(&isp->isp_lock);
+       ret = sh_css_load_acceleration(fw);
+       if (ret) {
+               atomisp_acc_fw_free(isp, fw);
+               mutex_unlock(&isp->isp_lock);
+               v4l2_err(&atomisp_dev, "%s: Failed to load acceleration "
+                                      "firmware\n", __func__);
+               ret = -EAGAIN;
+               goto out;
+       }
+       mutex_unlock(&isp->isp_lock);
+       init_completion(&isp->acc_fw_complete);
+
+out:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+int atomisp_acc_unload(struct atomisp_device *isp, unsigned int *handle)
+{
+       struct sh_css_acc_fw *fw;
+       int ret = 0;
+
+       mutex_lock(&isp->input_lock);
+       fw = atomisp_acc_get_fw(isp, *handle);
+
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "%s: Invalid acceleration firmware "
+                                      "handle\n", __func__);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (!fw->header.loaded) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (isp->marked_fw_for_unload != NULL) {
+               v4l2_err(&atomisp_dev, "%s: Acceleration firmware unload "
+                                      "pending\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (isp->sw_contex.isp_streaming == false) {
+               /* We're not streaming, so it's safe to unload now */
+               mutex_lock(&isp->isp_lock);
+               atomisp_acc_fw_free_args(isp, fw);
+               sh_css_unload_acceleration(fw);
+               atomisp_acc_fw_free(isp, fw);
+               mutex_unlock(&isp->isp_lock);
+               ret = 0;
+               goto out;
+       }
+
+       /*
+        * If we're streaming, unload should be synced with end of frame.
+        * We mark it for unload on atomisp_work() and wait for it.
+        */
+       init_completion(&isp->acc_unload_fw_complete);
+       isp->marked_fw_for_unload = fw;
+       mutex_unlock(&isp->input_lock);
+       wait_for_completion_timeout(&isp->acc_unload_fw_complete, 1 * HZ);
+
+       return 0;
+
+out:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+int atomisp_acc_set_arg(struct atomisp_device *isp,
+                       struct atomisp_acc_fw_arg *fw_arg)
+{
+       struct sh_css_acc_fw *fw;
+       enum atomisp_acc_arg_type type;
+       void *frame_ptr;
+       unsigned int handle = fw_arg->fw_handle;
+       unsigned int index = fw_arg->index;
+       unsigned int size = fw_arg->size;
+       unsigned int pgnr;
+       union host *host;
+       int ret;
+
+       mutex_lock(&isp->input_lock);
+       fw = atomisp_acc_get_fw(isp, handle);
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "Invalid fw handle\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = sh_css_set_acceleration_argument(fw, index, NULL, 0);
+       if (ret != 0)
+               goto out;
+
+       /* Allocate `host' union if not already done so */
+       host = (union host *)sh_css_argument_get_host(fw, index);
+
+       if (!host) {
+               /* Allocate new */
+               host = kzalloc(sizeof(*host), GFP_KERNEL);
+               if (!host) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ret = sh_css_argument_set_host(fw, index, host);
+               if (ret != 0) {
+                       kfree(host);
+                       goto out;
+               }
+       }
+
+       type = sh_css_argument_type(fw, index);
+       switch (type) {
+       case SH_CSS_ACC_ARG_SCALAR_IN:
+               /* Free old argument data if one already exists */#
+                       kfree(host->scalar.kernel_ptr);
+
+               /* Allocate and copy data into kernel space */
+               host->scalar.kernel_ptr = kmalloc(size, GFP_KERNEL);
+               if (!host->scalar.kernel_ptr)
+                       return -ENOMEM;
+               if (copy_from_user(host->scalar.kernel_ptr,
+                                       fw_arg->value, size)) {
+                       kfree(host->scalar.kernel_ptr);
+                       host->scalar.kernel_ptr = NULL;
+                       return -EFAULT;
+               }
+               host->scalar.size = size;
+               host->scalar.user_ptr = fw_arg->value;
+               ret = sh_css_set_acceleration_argument(fw, index,
+                                       host->scalar.kernel_ptr, size);
+               break;
+       case ATOMISP_ACC_ARG_FRAME:
+       case SH_CSS_ACC_ARG_PTR_IN:
+       case SH_CSS_ACC_ARG_PTR_OUT:
+       case SH_CSS_ACC_ARG_PTR_IO:
+               /* Free old argument data if one already exists */
+               hrt_isp_css_mm_free(host->ptr.hmm_ptr);
+               pgnr = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+               mutex_lock(&isp->isp_lock);
+               hrt_isp_css_mm_set_user_ptr((unsigned int)fw_arg->value, pgnr);
+               frame_ptr = hrt_isp_css_mm_alloc(size);
+               hrt_isp_css_mm_set_user_ptr(0, 0);
+               mutex_unlock(&isp->isp_lock);
+
+               if (IS_ERR_OR_NULL(frame_ptr)) {
+                       v4l2_err(&atomisp_dev, "%s: Failed to allocate frame "
+                                "for acceleration firmware\n", __func__);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               host->ptr.hmm_ptr = frame_ptr;
+               ret = sh_css_set_acceleration_argument(fw, index, frame_ptr,
+                                                      size);
+               break;
+
+
+       default:
+               v4l2_err(&atomisp_dev, "Invalid fw argument type\n");
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+int atomisp_acc_start(struct atomisp_device *isp, unsigned int *handle)
+{
+       struct sh_css_acc_fw *fw;
+       unsigned int ret;
+
+       mutex_lock(&isp->input_lock);
+       mutex_lock(&isp->isp_lock);
+       fw = atomisp_acc_get_fw(isp, *handle);
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "%s: Invalid firmware handle\n",
+                        __func__);
+               mutex_unlock(&isp->isp_lock);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = sh_css_start_acceleration(fw);
+       mutex_unlock(&isp->isp_lock);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "%s: Failed to start acceleration "
+                                      "firmware\n", __func__);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* Initialize the interrupt here if it's a standalone binary */
+       if (fw->header.type == ATOMISP_ACC_STANDALONE)
+               INIT_COMPLETION(isp->acc_fw_complete);
+
+out:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+int atomisp_acc_wait(struct atomisp_device *isp, unsigned int *handle)
+{
+       struct sh_css_acc_fw *fw;
+       unsigned int time_left;
+
+       mutex_lock(&isp->input_lock);
+       mutex_lock(&isp->isp_lock);
+
+       fw = atomisp_acc_get_fw(isp, *handle);
+
+       mutex_unlock(&isp->isp_lock);
+       mutex_unlock(&isp->input_lock);
+
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "Invalid fw handle\n");
+               return -EINVAL;
+       }
+
+       if (fw->header.type != ATOMISP_ACC_STANDALONE)
+               return -EINVAL;
+
+       time_left =
+           wait_for_completion_timeout(&isp->acc_fw_complete,
+                                       1 * HZ);
+
+       /* Timeout to get the acc fw */
+       if (time_left == 0) {
+               v4l2_err(&atomisp_dev,
+                        "%s: Acceleration firmware timeout to finish\n",
+                        __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&isp->isp_lock);
+       sh_css_acceleration_done(fw);
+       mutex_unlock(&isp->isp_lock);
+
+       return 0;
+}
+
+int atomisp_acc_abort(struct atomisp_device *isp,
+                     struct atomisp_acc_fw_abort *abort)
+{
+       struct sh_css_acc_fw *fw;
+       int ret = 0;
+
+       mutex_lock(&isp->input_lock);
+       mutex_lock(&isp->isp_lock);
+
+       fw = atomisp_acc_get_fw(isp, abort->fw_handle);
+       if (fw == NULL) {
+               v4l2_err(&atomisp_dev, "%s: Invalid firmware handle\n",
+                        __func__);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       sh_css_abort_acceleration(fw, abort->timeout);
+
+out:
+       mutex_unlock(&isp->isp_lock);
+       mutex_unlock(&isp->input_lock);
+
+       return ret;
+}
+
+int atomisp_save_iunit_reg(struct atomisp_device *isp)
+{
+       /*Clear those register value first*/
+       isp->hw_contex.pcicmdsts = 0;
+       isp->hw_contex.ispmmadr = 0;
+       isp->hw_contex.msicap = 0;
+       isp->hw_contex.msi_addr = 0;
+       isp->hw_contex.msi_data = 0;
+       isp->hw_contex.intr = 0;
+       isp->hw_contex.interrupt_control = 0;
+       isp->hw_contex.pmcs = 0;
+       isp->hw_contex.cg_dis = 0;
+       isp->hw_contex.i_control = 0;
+       isp->hw_contex.pci_cmd = 0;
+       isp->hw_contex.csi_rcomp_config = 0;
+       isp->hw_contex.csi_afe_dly = 0;
+       isp->hw_contex.csi_control = 0;
+
+       isp->hw_contex.pcicmdsts = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                     PCICMDSTS);
+       isp->hw_contex.ispmmadr = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                    ISPMMADR);
+       isp->hw_contex.msicap = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                  MSI_CAPID);
+       isp->hw_contex.msi_addr = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                    MSI_ADDRESS);
+       isp->hw_contex.msi_data = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                    MSI_DATA);
+       isp->hw_contex.intr = atomisp_msg_read32(isp, IUNIT_PORT, INTR);
+       isp->hw_contex.interrupt_control = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                             INTR_CTL);
+       isp->hw_contex.pmcs = atomisp_msg_read32(isp, IUNIT_PORT, PMCS);
+       isp->hw_contex.cg_dis = atomisp_msg_read32(isp, IUNIT_PORT, CG_DIS);
+       isp->hw_contex.i_control = atomisp_msg_read32(isp, IUNIT_PORT,
+                                                     I_CONTROL);
+       isp->hw_contex.csi_rcomp_config = atomisp_msg_read32(isp, IUNITPHY_PORT,
+                                                            CSI_RCOMP);
+       isp->hw_contex.csi_afe_dly = atomisp_msg_read32(isp, IUNITPHY_PORT,
+                                                       CSI_AFE);
+       isp->hw_contex.csi_control = atomisp_msg_read32(isp, IUNITPHY_PORT,
+                                                       CSI_CONTROL);
+
+       pci_read_config_word(isp->pdev, PCI_COMMAND, &isp->hw_contex.pci_cmd);
+
+
+       return 0;
+}
+
+int atomisp_restore_iunit_reg(struct atomisp_device *isp)
+{
+       pci_write_config_word(isp->pdev, PCI_COMMAND, isp->hw_contex.pci_cmd);
+
+       atomisp_msg_write32(isp, IUNIT_PORT, PCICMDSTS,
+                           isp->hw_contex.pcicmdsts);
+       atomisp_msg_write32(isp, IUNIT_PORT, ISPMMADR,
+                           isp->hw_contex.ispmmadr);
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_CAPID,
+                           isp->hw_contex.msicap);
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_ADDRESS,
+                           isp->hw_contex.msi_addr);
+       atomisp_msg_write32(isp, IUNIT_PORT, MSI_DATA,
+                           isp->hw_contex.msi_data);
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, 0xFF0003);
+       atomisp_msg_write32(isp, IUNIT_PORT, INTR, isp->hw_contex.intr);
+       atomisp_msg_write32(isp, IUNIT_PORT, INTR_CTL,
+                               isp->hw_contex.interrupt_control);
+       atomisp_msg_write32(isp, IUNIT_PORT, PMCS, isp->hw_contex.pmcs);
+       atomisp_msg_write32(isp, IUNIT_PORT, CG_DIS, isp->hw_contex.cg_dis);
+       atomisp_msg_write32(isp, IUNIT_PORT, I_CONTROL,
+                           isp->hw_contex.i_control);
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_RCOMP,
+                               isp->hw_contex.csi_rcomp_config);
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_AFE,
+                           isp->hw_contex.csi_afe_dly);
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL,
+                               isp->hw_contex.csi_control);
+
+       return 0;
+}
+
+/*Turn off ISP power island*/
+int atomisp_ospm_power_island_down(struct atomisp_device *isp)
+{
+       u32 pwr_cnt = 0;
+
+       /* power down DPHY */
+       pwr_cnt = atomisp_msg_read32(isp, IUNITPHY_PORT, CSI_CONTROL);
+       pwr_cnt |= 0x300;
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, pwr_cnt);
+
+       /* Power down IPH/ISP */
+       if (pmu_nc_set_power_state(APM_ISP_ISLAND | APM_IPH_ISLAND,
+                              OSPM_ISLAND_DOWN, APM_REG_TYPE))
+               return -EINVAL;
+
+       isp->sw_contex.power_state = ATOM_ISP_POWER_DOWN;
+       return 0;
+}
+
+/*Turn on ISP power island*/
+int atomisp_ospm_power_island_up(struct atomisp_device *isp)
+{
+       u32 pwr_cnt = 0;
+
+       /* Power up IPH/ISP */
+       if (pmu_nc_set_power_state(APM_ISP_ISLAND | APM_IPH_ISLAND,
+                              OSPM_ISLAND_UP, APM_REG_TYPE))
+               return -EINVAL;
+
+       /* power on DPHY */
+       pwr_cnt = atomisp_msg_read32(isp, IUNITPHY_PORT, CSI_CONTROL);
+       pwr_cnt &= ~0x300;
+       atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, pwr_cnt);
+
+       isp->sw_contex.power_state = ATOM_ISP_POWER_UP;
+       return 0;
+}
+
+
+int atomisp_exif_makernote(struct atomisp_device *isp,
+       void *config)
+{
+       struct atomisp_makernote_info *arg =
+                       (struct atomisp_makernote_info *)config;
+       struct v4l2_control ctrl;
+
+       ctrl.id = V4L2_CID_FOCAL_ABSOLUTE;
+       if (v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                core, g_ctrl, &ctrl))
+               v4l2_warn(&atomisp_dev, "failed to g_ctrl for focal length\n");
+       else
+               arg->focal_length = ctrl.value;
+
+       ctrl.id = V4L2_CID_FNUMBER_ABSOLUTE;
+       if (v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                               core, g_ctrl, &ctrl))
+               v4l2_warn(&atomisp_dev, "failed to g_ctrl for f-number\n");
+       else
+               arg->f_number_curr = ctrl.value;
+
+       ctrl.id = V4L2_CID_FNUMBER_RANGE;
+       if (v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                               core, g_ctrl, &ctrl))
+               v4l2_warn(&atomisp_dev,
+                               "failed to g_ctrl for f number range\n");
+       else
+               arg->f_number_range = ctrl.value;
+
+       return 0;
+}
+
+int atomisp_flash_enable(struct atomisp_device *isp, int num_frames)
+{
+       if (num_frames <= 0)
+               return -EINVAL;
+       /* a requested flash is still in progress. */
+       if (isp->params.num_flash_frames)
+               return -EBUSY;
+
+       isp->params.num_flash_frames = num_frames;
+       return 0;
+}
diff --git a/drivers/media/video/atomisp/atomisp_cmd.h b/drivers/media/video/atomisp/atomisp_cmd.h
new file mode 100644 (file)
index 0000000..7598c8a
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __ATOMISP_CMD_H__
+#define        __ATOMISP_CMD_H__
+
+#include "atomisp_common.h"
+#include <linux/atomisp.h>
+
+#define DIV_RND_UP(a, b) (((a) + (b) - 1) / b)
+#define MSI_ENABLE_BIT         16
+#define INTR_DISABLE_BIT       10
+#define BUS_MASTER_ENABLE      2
+#define MEMORY_SPACE_ENABLE    1
+#define INTR_IER               24
+#define INTR_IIR               16
+
+/*
+ * Helper function
+ */
+
+struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd);
+struct atomisp_video_pipe *atomisp_to_video_pipe(struct video_device *dev);
+
+
+extern void __iomem *atomisp_io_base;
+
+static inline void __iomem *atomisp_get_io_virt_addr(unsigned int address)
+{
+       unsigned int ret = 0;
+       ret = ((unsigned int)atomisp_io_base) + (address & 0x003FFFFF);
+       return (void __iomem *)ret;
+}
+
+/*
+ * Interrupt functions
+ */
+void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev);
+void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev);
+irqreturn_t atomisp_isr(int irq, void *dev);
+void atomisp_work(struct work_struct *work);
+int atomisp_get_frame_pgnr(const struct sh_css_frame *frame, u32 * p_pgnr);
+
+/*
+ * Get internal fmt according to V4L2 fmt
+ */
+
+int atomisp_is_pixelformat_supported(u32 pixelformat);
+bool atomisp_is_viewfinder_support(struct atomisp_device *isp);
+
+/*
+ * ISP features control function
+ */
+
+/*
+ * Function to enable/disable lens geometry distortion correction (GDC) and
+ * chromatic aberration correction (CAC)
+ */
+int atomisp_gdc_cac(struct atomisp_device *isp, int flag, __s32 * value);
+
+/*
+ * Function to enable/disable extra nosie reduction (XNR) in low light
+ * condition
+ */
+int atomisp_xnr(struct atomisp_device *isp, int flag, int *arg);
+
+/*
+ * Function to configure bayer nosie reduction
+ */
+int atomisp_bayer_nr(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to configure temporal nosie reduction (TNR)
+ */
+int atomisp_tnr(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to get histogram data for image frame
+ */
+int atomisp_histogram(struct atomisp_device *isp,
+       int flag, void *config);
+
+/*
+ * Function to configure black level compensation
+ */
+int atomisp_black_level(struct atomisp_device *isp, int flag, void *config);
+
+/*
+ * Function to configure Ycc nosie reduction
+ */
+int atomisp_ycc_nr(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to configure edge enhancement
+ */
+int atomisp_ee(struct atomisp_device *isp, int flag,
+                      void *config);
+
+/*
+ * Function to update Gamma table for gamma, brightness and contrast config
+ */
+int atomisp_gamma(struct atomisp_device *isp, int flag,
+       void *config);
+/*
+ * Function to update Ctc table for Chroma Enhancement
+ */
+int atomisp_ctc(struct atomisp_device *isp, int flag,
+                         void *config);
+
+/*
+ * Function to update Gdc table for gdc
+ */
+int atomisp_gdc_cac_table(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to update table for macc
+ */
+int atomisp_macc_table(struct atomisp_device *isp, int flag,
+       void *config);
+/*
+ * Function to set/get image stablization statistics
+ */
+int atomisp_dis_stat(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to set/get 3A stat from isp
+ */
+int atomisp_3a_stat(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to set/get isp parameters to isp
+ */
+int atomisp_param(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to configure color effect of the image
+ */
+int atomisp_color_effect(struct atomisp_device *isp, int flag, __s32 *effect);
+
+/*
+ * Function to configure bad pixel correction
+ */
+int atomisp_bad_pixel(struct atomisp_device *isp, int flag, __s32 *value);
+
+/*
+ * Function to configure bad pixel correction params
+ */
+int atomisp_bad_pixel_param(struct atomisp_device *isp, int flag,
+       void *config);
+
+int atomisp_dis_vector(struct atomisp_device *isp,
+                      void *arg);
+
+/*
+ * Function to enable/disable video image stablization
+ */
+int atomisp_video_stable(struct atomisp_device *isp, int flag, __s32 * value);
+
+/*
+ * Function to configure fixed pattern noise
+ */
+int atomisp_fixed_pattern(struct atomisp_device *isp, int flag, __s32 * value);
+
+/*
+ * Function to configure fixed pattern noise table
+ */
+int atomisp_fixed_pattern_table(struct atomisp_device *isp, int flag,
+                               void *config);
+
+/*
+ * Function to configure vf overlay image
+ */
+int atomisp_vf_overlay(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to configure false color correction
+ */
+int atomisp_false_color(struct atomisp_device *isp, int flag, __s32 * value);
+
+/*
+ * Function to configure false color correction params
+ */
+int atomisp_false_color_param(struct atomisp_device *isp, int flag,
+       void *config);
+
+/*
+ * Function to configure white balance params
+ */
+int atomisp_white_balance_param(struct atomisp_device *isp, int flag,
+       void *config);
+
+int atomisp_3a_config_param(struct atomisp_device *isp, int flag,
+                           void *config);
+
+/*
+ * Function to enable/disable lens shading correction
+ */
+int atomisp_shading_correction(struct atomisp_device *isp, int flag,
+                                      __s32 *value);
+
+/*
+ * Function to setup digital zoom
+ */
+int atomisp_digital_zoom(struct atomisp_device *isp, int flag, __s32 * value);
+
+int atomisp_get_sensor_mode_data(struct atomisp_device *isp,
+                                void *config);
+
+int atomisp_get_fmt(struct video_device *vdev, struct v4l2_format *f);
+
+
+/* This function looks up the closest available resolution. */
+int atomisp_try_fmt(struct video_device *vdev, struct v4l2_format *f,
+                                               bool *res_overflow);
+
+int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f);
+int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f);
+
+int atomisp_save_iunit_reg(struct atomisp_device *isp);
+int atomisp_restore_iunit_reg(struct atomisp_device *isp);
+
+int atomisp_ospm_power_island_down(struct atomisp_device *isp);
+int atomisp_ospm_power_island_up(struct atomisp_device *isp);
+int atomisp_exif_makernote(struct atomisp_device *isp,
+       void *config);
+
+void atomisp_free_internal_buffers(struct atomisp_device *isp);
+void atomisp_free_3a_buffers(struct atomisp_device *isp);
+void atomisp_free_dis_buffers(struct atomisp_device *isp);
+
+int  atomisp_flash_enable(struct atomisp_device *isp, int num_frames);
+
+int atomisp_acc_load(struct atomisp_device *isp,
+                    struct atomisp_acc_fw_load *fw);
+
+int atomisp_acc_unload(struct atomisp_device *isp,
+                      unsigned int *handler);
+
+int atomisp_acc_set_arg(struct atomisp_device *isp,
+                       struct atomisp_acc_fw_arg *fw_arg);
+
+int atomisp_acc_start(struct atomisp_device *isp,
+                     unsigned int *handler);
+
+int atomisp_acc_wait(struct atomisp_device *isp,
+                    unsigned int *handler);
+
+int atomisp_acc_abort(struct atomisp_device *isp,
+                     struct atomisp_acc_fw_abort *abort);
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_common.h b/drivers/media/video/atomisp/atomisp_common.h
new file mode 100644 (file)
index 0000000..6db77ad
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __ATOMISP_COMMON_H__
+#define        __ATOMISP_COMMON_H__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>      /* atomisp_dbg */
+#include <linux/version.h>     /* atomisp_dbg */
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>                /* for kmalloc */
+#include <linux/mm.h>          /* for GFP_ATOMIC */
+#include <linux/pci.h>         /* for DMA */
+#include <linux/pm_runtime.h>  /* for runtime pm */
+#include <linux/stringify.h>
+#include <linux/io.h>          /* ioremap */
+#include <linux/uaccess.h>     /* access_ok */
+#include <linux/param.h>       /* access_ok */
+#include <linux/gpio.h>
+#include <asm/irq.h>
+#include <linux/poll.h>
+#include <linux/stddef.h>
+#include <linux/firmware.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/mrst.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h>
+
+#include <hmm/hmm.h>
+#include <css/sh_css.h>
+
+#include "atomisp_internal.h"
+
+extern int dbg_level;
+extern int mipicsi_flag;
+extern int pad_w;
+extern int pad_h;
+
+#define PUNIT_PORT             0x04
+#define IUNIT_PORT             0x08
+#define IUNITPHY_PORT          0x09
+
+#define CSI_RCOMP              0x00
+#define PCICMDSTS              0x01
+#define CSI_AFE                        0x02
+#define CSI_CONTROL            0x03
+#define ISPMMADR               0x04
+#define INTR                   0x0f
+#define MSI_CAPID              0x24
+#define MSI_ADDRESS            0x25
+#define MSI_DATA               0x26
+#define INTR_CTL               0x27
+#define PMCS                   0x35
+#define CG_DIS                 0x36
+#define I_CONTROL              0x3f
+#define OR1                    0x72
+#define APMBA                  0x7a
+
+#define PCI_MSI_ADDR           0x94
+#define PCI_MSI_DATA           0x98
+#define PCI_PRI_D0             0xd0
+#define PCI_PRI_D4             0xd4
+#define PCI_MEM_ACCESS         0x100002
+
+struct atomisp_tvnorm {
+       char *name;
+       v4l2_std_id id;
+       u32 cxiformat;
+       u32 cxoformat;
+};
+
+struct atomisp_format_bridge {
+       unsigned int pixelformat;
+       unsigned int depth;
+       enum v4l2_mbus_pixelcode mbus_code;
+       enum sh_css_frame_format sh_fmt;
+       unsigned char description[32];  /* the same as struct v4l2_fmtdesc */
+};
+
+struct atomisp_resolution {
+       u32 width;
+       u32 height;
+};
+
+struct atomisp_fmt {
+       u32 pixelformat;
+       u32 depth;
+       u32 bytesperline;
+       u32 framesize;
+       u32 imagesize;
+       u32 width;
+       u32 height;
+       u32 bayer_order;
+};
+
+struct atomisp_buffer {
+       struct videobuf_buffer  vb;
+       struct sh_css_frame     *handle;
+       struct atomisp_fmt              *fmt;
+};
+
+/*Message bus access functions*/
+static inline u32 atomisp_msg_read32(struct atomisp_device *isp,
+                                    uint port, uint offset)
+{
+       int mcr;
+       uint32_t ret_val;
+       struct pci_dev *pci_root;
+
+       ret_val = 0;
+       mcr = (0x10<<24) | (port << 16) | (offset << 8);
+       if (isp == NULL)
+               pci_root = pci_get_bus_and_slot(0, 0);
+       else
+               pci_root = isp->hw_contex.pci_dev;
+
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       pci_read_config_dword(pci_root, 0xD4, &ret_val);
+       if (isp == NULL)
+               pci_dev_put(pci_root);
+       return ret_val;
+}
+
+static inline void atomisp_msg_write32(struct atomisp_device *isp,
+                                      uint port, uint offset, u32 value)
+{
+       int mcr;
+       struct pci_dev *pci_root;
+       mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+
+       if (isp == NULL)
+               pci_root = pci_get_bus_and_slot(0, 0);
+       else
+               pci_root = isp->hw_contex.pci_dev;
+       pci_write_config_dword(pci_root, 0xD4, value);
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       if (isp == NULL)
+               pci_dev_put(pci_root);
+}
+
+/*
+ * supported V4L2 fmts and resolutions
+ */
+extern const struct atomisp_format_bridge atomisp_output_fmts[];
+extern const u32 atomisp_output_fmts_num;
+extern struct v4l2_device atomisp_dev;
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_csi2.c b/drivers/media/video/atomisp/atomisp_csi2.c
new file mode 100644 (file)
index 0000000..f7af2e0
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include "atomisp_internal.h"
+
+static const unsigned int csi2_input_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+};
+
+static const unsigned int csi2_output_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+};
+
+
+/* V4L2 subdev operations */
+
+static struct v4l2_mbus_framefmt *
+__csi2_get_format(struct atomisp_mipi_csi2_device *csi2,
+               struct v4l2_subdev_fh *fh,
+               unsigned int pad,
+               enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       else
+               return &csi2->formats[pad];
+}
+
+enum v4l2_mbus_pixelcode
+isp_video_uncompressed_code(enum v4l2_mbus_pixelcode code)
+{
+       switch (code) {
+       case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+               return V4L2_MBUS_FMT_SBGGR10_1X10;
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+               return V4L2_MBUS_FMT_SGRBG10_1X10;
+       case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+               return V4L2_MBUS_FMT_SRGGB10_1X10;
+       case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
+               return V4L2_MBUS_FMT_SGBRG10_1X10;
+       default:
+               return code;
+       }
+}
+
+static void
+csi2_try_format(struct atomisp_mipi_csi2_device *csi2,
+       struct v4l2_subdev_fh *fh,
+       unsigned int pad,
+       struct v4l2_mbus_framefmt *fmt,
+       enum v4l2_subdev_format_whence which)
+{
+       enum v4l2_mbus_pixelcode pixelcode;
+       struct v4l2_mbus_framefmt *format;
+       unsigned int i;
+
+       switch (pad) {
+       case CSI2_PAD_SINK:
+                /* Clamp the width and height to valid range (1-8191). */
+                for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
+                       if (fmt->code == csi2_input_fmts[i])
+                               break;
+                }
+
+                /* If not found, use SGRBG10 as default */
+                if (i >= ARRAY_SIZE(csi2_input_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SBGGR10_1X10;
+
+                fmt->width = clamp_t(u32, fmt->width, 1, 4608);
+                fmt->height = clamp_t(u32, fmt->height, 1, 8191);
+                break;
+
+       case CSI2_PAD_SOURCE:
+               /* Source format same as sink format, except for DPCM
+               * compression.
+               */
+               pixelcode = fmt->code;
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               /* allow dpcm decompression */
+               if (isp_video_uncompressed_code(fmt->code) == pixelcode)
+                       fmt->code = pixelcode;
+
+               break;
+       default:
+               break;
+       }
+
+       /* RGB, non-interlaced */
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * csi2_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_pad_mbus_code_enum structure
+ * return -EINVAL or zero on success
+*/
+static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
+                       struct v4l2_subdev_fh *fh,
+                       struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       if (code->pad == CSI2_PAD_SINK) {
+               if (code->index >= ARRAY_SIZE(csi2_input_fmts))
+                       return -EINVAL;
+               code->code = csi2_input_fmts[code->index];
+       } else {
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
+                       V4L2_SUBDEV_FORMAT_TRY);
+               switch (code->index) {
+               case 0:
+                       /* Passthrough sink pad code */
+                       code->code = format->code;
+                       break;
+               case 1:
+                       /* Uncompressed code */
+                       code->code = isp_video_uncompressed_code(format->code);
+                       break;
+               default:
+                       /* Fallthrough if above is false */
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int csi2_enum_frame_size(struct v4l2_subdev *sd,
+                        struct v4l2_subdev_fh *fh,
+                        struct v4l2_subdev_frame_size_enum *fse)
+{
+        struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+        struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+        format.code = fse->code;
+        format.width = 1;
+        format.height = 1;
+        csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+        fse->min_width = format.width;
+        fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+        format.code = fse->code;
+        format.width = -1;
+        format.height = -1;
+        csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+        fse->max_width = format.width;
+        fse->max_height = format.height;
+
+        return 0;
+}
+
+/*
+ * csi2_get_format - Handle get format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @pad: pad num
+ * @fmt: pointer to v4l2 format structure
+ * return -EINVAL or zero on sucess
+*/
+static int csi2_get_format(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt)
+{
+       struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * csi2_set_format - Handle set format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @pad: pad num
+ * @fmt: pointer to v4l2 format structure
+ * return -EINVAL or zero on success
+*/
+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                   struct v4l2_subdev_format *fmt)
+{
+       struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == CSI2_PAD_SINK) {
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
+                       fmt->which);
+               *format = fmt->format;
+               csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
+       }
+
+       return 0;
+}
+
+/*
+ * csi2_set_stream - Enable/Disable streaming on the CSI2 module
+ * @sd: ISP CSI2 V4L2 subdevice
+ * @enable: Enable/disable stream (1/0)
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
+{
+        v4l2_info(&atomisp_dev, "csi2_set_stream\n");
+        return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops csi2_core_ops = {
+       .queryctrl = v4l2_subdev_queryctrl,
+       .querymenu = v4l2_subdev_querymenu,
+       .g_ctrl = v4l2_subdev_g_ctrl,
+       .s_ctrl = v4l2_subdev_s_ctrl,
+       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops csi2_video_ops = {
+       .s_stream = csi2_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
+       .enum_mbus_code = csi2_enum_mbus_code,
+       .enum_frame_size = csi2_enum_frame_size,
+       .get_fmt = csi2_get_format,
+       .set_fmt = csi2_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops csi2_ops = {
+       .core = &csi2_core_ops,
+       .video = &csi2_video_ops,
+       .pad = &csi2_pad_ops,
+};
+
+
+/*
+ * csi2_link_setup - Setup CSI2 connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL or zero on success
+*/
+static int csi2_link_setup(struct media_entity *entity,
+           const struct media_pad *local,
+           const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       u32 result = local->index | media_entity_type(remote->entity);
+
+       switch (result) {
+       case CSI2_PAD_SOURCE | MEDIA_ENTITY_TYPE_DEVNODE:
+               /* not supported yet */
+               return -EINVAL;
+
+       case CSI2_PAD_SOURCE | MEDIA_ENTITY_TYPE_V4L2_SUBDEV:
+               if (flags & MEDIA_LINK_FLAG_ENABLED) {
+                       if (csi2->output & ~CSI2_OUTPUT_ISP_SUBDEV)
+                               return -EBUSY;
+                               csi2->output |= CSI2_OUTPUT_ISP_SUBDEV;
+                       } else {
+                               csi2->output &= ~CSI2_OUTPUT_ISP_SUBDEV;
+               }
+               break;
+
+       default:
+               /* Link from camera to CSI2 is fixed... */
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations csi2_media_ops = {
+       .link_setup = csi2_link_setup,
+};
+
+/*
+* ispcsi2_init_entities - Initialize subdev and media entity.
+* @csi2: Pointer to ispcsi2 structure.
+* return -ENOMEM or zero on success
+*/
+static int mipi_csi2_init_entities(struct atomisp_mipi_csi2_device *csi2,
+                                       int port)
+{
+       struct v4l2_subdev *sd = &csi2->subdev;
+       struct media_pad *pads = csi2->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       v4l2_subdev_init(sd, &csi2_ops);
+       if (port == ATOMISP_CAMERA_PORT_SECONDARY)
+               strlcpy(sd->name, "ATOM ISP CSI2-1p", sizeof(sd->name));
+       else if (port == ATOMISP_CAMERA_PORT_PRIMARY)
+               strlcpy(sd->name, "ATOM ISP CSI2-4p", sizeof(sd->name));
+
+       v4l2_set_subdevdata(sd, csi2);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FLAG_OUTPUT;
+       pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FLAG_INPUT;
+
+       me->ops = &csi2_media_ops;
+       me->type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
+       ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       csi2->formats[CSI2_PAD_SINK].code = V4L2_MBUS_FMT_SBGGR10_1X10;
+       csi2->formats[CSI2_PAD_SOURCE].code = V4L2_MBUS_FMT_SBGGR10_1X10;
+
+       return 0;
+}
+
+void
+atomisp_mipi_csi2_unregister_entities(struct atomisp_mipi_csi2_device *csi2)
+{
+       media_entity_cleanup(&csi2->subdev.entity);
+       v4l2_device_unregister_subdev(&csi2->subdev);
+}
+
+int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2,
+                       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       atomisp_mipi_csi2_unregister_entities(csi2);
+       return ret;
+}
+
+/*
+ * atomisp_mipi_csi2_cleanup - Routine for module driver cleanup
+*/
+void atomisp_mipi_csi2_cleanup(struct atomisp_device *isp)
+{
+}
+
+
+int atomisp_mipi_csi2_init(struct atomisp_device *isp)
+{
+       struct atomisp_mipi_csi2_device *csi2_4p = &isp->csi2_4p;
+       struct atomisp_mipi_csi2_device *csi2_1p = &isp->csi2_1p;
+       int ret;
+
+       csi2_4p->isp = isp;
+       csi2_1p->isp = isp;
+
+       ret = mipi_csi2_init_entities(csi2_4p, ATOMISP_CAMERA_PORT_PRIMARY);
+       if (ret < 0)
+               goto fail;
+
+       ret = mipi_csi2_init_entities(csi2_1p, ATOMISP_CAMERA_PORT_SECONDARY);
+       if (ret < 0)
+               goto fail;
+       return 0;
+
+fail:
+       atomisp_mipi_csi2_cleanup(isp);
+       return ret;
+}
+
diff --git a/drivers/media/video/atomisp/atomisp_csi2.h b/drivers/media/video/atomisp/atomisp_csi2.h
new file mode 100644 (file)
index 0000000..cb3ba46
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef _MIPI_CSI2_H_
+#define _MIPI_CSI2_H_
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+#define CSI2_PAD_SINK          0
+#define CSI2_PAD_SOURCE                1
+#define CSI2_PADS_NUM          2
+
+#define CSI2_OUTPUT_ISP_SUBDEV (1 << 0)
+#define CSI2_OUTPUT_MEMORY     (1 << 1)
+
+struct atomisp_mipi_csi2_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[CSI2_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
+
+       struct v4l2_ctrl_handler ctrls;
+       struct atomisp_device *isp;
+
+       u32 output; /* output direction */
+};
+
+int atomisp_mipi_csi2_init(struct atomisp_device *isp);
+void atomisp_mipi_csi2_cleanup(struct atomisp_device *isp);
+void atomisp_mipi_csi2_unregister_entities(
+                                       struct atomisp_mipi_csi2_device *csi2);
+int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2,
+                       struct v4l2_device *vdev);
+
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_file.c b/drivers/media/video/atomisp/atomisp_file.c
new file mode 100644 (file)
index 0000000..41d9ead
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <css/sh_css.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include "atomisp_internal.h"
+#include "atomisp_common.h"
+#include "atomisp_subdev.h"
+#include "atomisp_cmd.h"
+#include "atomisp_file.h"
+
+static int file_input_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct atomisp_file_device *file_dev = v4l2_get_subdevdata(sd);
+       struct atomisp_device *isp = file_dev->isp;
+       struct atomisp_video_pipe *out_pipe = &isp->isp_subdev.video_in;
+       unsigned char *buf =
+                  videobuf_to_vmalloc(out_pipe->outq.bufs[0]);
+       int width = isp->input_format->out.width;
+       int height = isp->input_format->out.height;
+       unsigned short *data = (unsigned short *)buf;
+       int i, j;
+
+       /* extend RAW8 pixel type to unsigned short */
+       if (out_pipe->out_fmt->depth == 8) {
+               data = vmalloc(width*height*2);
+               if (!data) {
+                       v4l2_err(&atomisp_dev,
+                               "Failed to allocate memory for file input\n");
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < height; i++)
+                       for (j = 0; j < width; j++)
+                               *data++ = (unsigned short)*buf++;
+               data -= width*height;
+       }
+
+       while (!sh_css_isp_has_started())
+               /* we are facing ISP timeout, if removed this delay */
+               mdelay(1);
+
+       sh_css_send_input_frame(data, width, height);
+
+       if (out_pipe->out_fmt->depth == 8)
+               vfree(data);
+       return 0;
+}
+
+static int file_input_enum_fmt(struct v4l2_subdev *sd,
+               struct v4l2_fmtdesc *fmtdesc)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+static int file_input_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+static int file_input_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_g_parm(struct v4l2_subdev *sd,
+               struct v4l2_streamparm *param)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_s_parm(struct v4l2_subdev *sd,
+               struct v4l2_streamparm *param)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_enum_framesizes(struct v4l2_subdev *sd,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_enum_frameintervals(struct v4l2_subdev *sd,
+                                     struct v4l2_frmivalenum *fival)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+                               enum v4l2_mbus_pixelcode *code)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_try_mbus_fmt(struct v4l2_subdev *sd,
+                              struct v4l2_mbus_framefmt *fmt)
+{
+       struct atomisp_file_device *file_dev = v4l2_get_subdevdata(sd);
+       struct atomisp_device *isp = file_dev->isp;
+       struct atomisp_video_pipe *out_pipe = &isp->isp_subdev.video_in;
+
+       if (fmt == NULL)
+               return -EINVAL;
+
+       if ((fmt->width > out_pipe->out_fmt->width) ||
+           (fmt->height > out_pipe->out_fmt->height))
+               return -EINVAL;
+
+       fmt->width = out_pipe->out_fmt->width;
+       fmt->height = out_pipe->out_fmt->height;
+       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+       return 0;
+}
+
+static int file_input_g_mbus_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_mbus_framefmt *fmt)
+{
+       struct atomisp_file_device *file_dev = v4l2_get_subdevdata(sd);
+       struct atomisp_device *isp = file_dev->isp;
+       struct atomisp_video_pipe *out_pipe = &isp->isp_subdev.video_in;
+
+       if (fmt == NULL)
+               return -EINVAL;
+
+       fmt->width = out_pipe->out_fmt->width;
+       fmt->height = out_pipe->out_fmt->height;
+       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+       return 0;
+}
+
+static int file_input_s_mbus_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_mbus_framefmt *fmt)
+{
+       /*to fake*/
+       struct atomisp_file_device *file_dev = v4l2_get_subdevdata(sd);
+       struct atomisp_device *isp = file_dev->isp;
+       struct atomisp_video_pipe *out_pipe = &isp->isp_subdev.video_in;
+       int ret;
+
+       if (fmt == NULL)
+               return -EINVAL;
+
+       ret = file_input_try_mbus_fmt(sd, fmt);
+       if (ret) {
+               v4l2_err(sd, "file input try fmt failed\n");
+               return ret;
+       }
+
+       fmt->width = out_pipe->out_fmt->width;
+       fmt->height = out_pipe->out_fmt->height;
+       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+       sh_css_input_set_mode(SH_CSS_INPUT_MODE_FIFO);
+       return 0;
+}
+
+static int file_input_g_chip_ident(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_chip_ident *chip)
+{
+       struct atomisp_file_device *dev;
+       dev = container_of(sd, struct atomisp_file_device, sd);
+
+       if (!chip)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int file_input_log_status(struct v4l2_subdev *sd)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_s_config(struct v4l2_subdev *sd, int irq,
+                               void *platform_data)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_queryctrl(struct v4l2_subdev *sd,
+               struct v4l2_queryctrl *qc)
+{
+       /*to fake*/
+       return -EINVAL;
+}
+
+static int file_input_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       /*to fake*/
+       return -EINVAL;
+}
+
+static int file_input_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_s_power(struct v4l2_subdev *sd, int on)
+{
+       /* to fake */
+       return 0;
+}
+
+static int file_input_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_enum_frame_size(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_frame_size_enum *fse)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int file_input_enum_frame_ival(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_frame_interval_enum *fie)
+{
+       /*to fake*/
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops file_input_video_ops = {
+       .s_stream = file_input_s_stream,
+       .enum_fmt = file_input_enum_fmt,
+       .try_fmt = file_input_try_fmt,
+       .g_fmt = file_input_g_fmt,
+       .s_fmt = file_input_s_fmt,
+       .g_parm = file_input_g_parm,
+       .s_parm = file_input_s_parm,
+       .enum_framesizes = file_input_enum_framesizes,
+       .enum_frameintervals = file_input_enum_frameintervals,
+       .enum_mbus_fmt = file_input_enum_mbus_fmt,
+       .try_mbus_fmt = file_input_try_mbus_fmt,
+       .g_mbus_fmt = file_input_g_mbus_fmt,
+       .s_mbus_fmt = file_input_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_core_ops file_input_core_ops = {
+       .g_chip_ident = file_input_g_chip_ident,
+       .log_status = file_input_log_status,
+       .s_config = file_input_s_config,
+       .queryctrl = file_input_queryctrl,
+       .g_ctrl = file_input_g_ctrl,
+       .s_ctrl = file_input_s_ctrl,
+       .s_power = file_input_s_power,
+};
+
+static const struct v4l2_subdev_pad_ops file_input_pad_ops = {
+       .enum_mbus_code = file_input_enum_mbus_code,
+       .enum_frame_size = file_input_enum_frame_size,
+       .enum_frame_interval = file_input_enum_frame_ival,
+};
+
+static const struct v4l2_subdev_ops file_input_ops = {
+       .core = &file_input_core_ops,
+       .video = &file_input_video_ops,
+       .pad = &file_input_pad_ops,
+};
+
+static const struct media_entity_operations file_input_entity_ops = {
+       .set_power = v4l2_subdev_set_power,
+};
+
+void
+atomisp_file_input_unregister_entities(struct atomisp_file_device *file_dev)
+{
+       v4l2_device_unregister_subdev(&file_dev->sd);
+}
+
+int atomisp_file_input_register_entities(struct atomisp_file_device *file_dev,
+                       struct v4l2_device *vdev)
+{
+       /* Register the subdev and video nodes. */
+       return  v4l2_device_register_subdev(vdev, &file_dev->sd);
+}
+
+void atomisp_file_input_cleanup(struct atomisp_device *isp)
+{
+       return;
+}
+
+int atomisp_file_input_init(struct atomisp_device *isp)
+{
+       struct atomisp_file_device *file_dev = &isp->file_dev;
+       struct v4l2_subdev *sd = &file_dev->sd;
+       struct media_pad *pads = file_dev->pads;
+       struct media_entity *me = &sd->entity;
+       struct camera_mipi_info *file_input_info = NULL;
+       int ret;
+
+       file_dev->isp = isp;
+       v4l2_subdev_init(sd, &file_input_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       strcpy(sd->name, "file_input_subdev");
+       v4l2_set_subdevdata(sd, file_dev);
+
+       file_input_info = kzalloc(sizeof(*file_input_info), GFP_KERNEL);
+       if (!file_input_info) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to allocate memory for file input\n");
+               return -ENOMEM;
+       }
+
+       file_input_info->port = ATOMISP_CAMERA_PORT_PRIMARY;
+       file_input_info->input_format = SH_CSS_INPUT_FORMAT_RAW_10;
+       file_input_info->raw_bayer_order = sh_css_bayer_order_bggr;
+       v4l2_set_subdev_hostdata(sd, (void *)file_input_info);
+
+       pads[0].flags = MEDIA_PAD_FLAG_INPUT;
+       me->type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
+
+       ret = media_entity_init(me, 1, pads, 0);
+       if (ret < 0)
+               goto fail;
+       return 0;
+fail:
+       kfree(file_input_info);
+       atomisp_file_input_cleanup(isp);
+       return ret;
+}
diff --git a/drivers/media/video/atomisp/atomisp_file.h b/drivers/media/video/atomisp/atomisp_file.h
new file mode 100644 (file)
index 0000000..6346a20
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __FILE_INPUT_H__
+#define __FILE_INPUT_H__
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+struct atomisp_file_device {
+       struct v4l2_subdev sd;
+       struct atomisp_device *isp;
+       struct media_pad pads[1];
+};
+
+void atomisp_file_input_cleanup(struct atomisp_device *isp);
+int atomisp_file_input_init(struct atomisp_device *isp);
+void atomisp_file_input_unregister_entities(
+                               struct atomisp_file_device *file_dev);
+int atomisp_file_input_register_entities(struct atomisp_file_device *file_dev,
+                       struct v4l2_device *vdev);
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_fops.c b/drivers/media/video/atomisp/atomisp_fops.c
new file mode 100644 (file)
index 0000000..28ef74c
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "atomisp_ioctl.h"
+#include "atomisp_cmd.h"
+#include "atomisp_fops.h"
+#include "atomisp_common.h"
+#include "hrt/hive_isp_css_mm_hrt.h"
+
+#define ISP_LEFT_PAD   128     /* equal to 2*NWAY */
+
+/*
+ * input image data, and current frame resolution for test
+ */
+#define        ISP_PARAM_MMAP_OFFSET   0xfffff000
+
+#define MAGIC_CHECK(is, should)        \
+       if (unlikely((is) != (should))) { \
+               printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \
+                       is, should); \
+               BUG(); \
+       }
+
+/*
+ * Videobuf ops
+ */
+int atomisp_buf_setup(struct videobuf_queue *vq,
+                     unsigned int *count,
+                     unsigned int *size)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       *size = pipe->format->out.sizeimage;
+
+       return 0;
+}
+
+int atomisp_buf_prepare(struct videobuf_queue *vq,
+                       struct videobuf_buffer *vb,
+                       enum v4l2_field field)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       vb->size = pipe->format->out.sizeimage;
+       vb->width = pipe->format->out.width;
+       vb->height = pipe->format->out.height;
+       vb->field = field;
+       vb->state = VIDEOBUF_PREPARED;
+
+       return 0;
+}
+
+void atomisp_buf_queue(struct videobuf_queue *vq,
+                      struct videobuf_buffer *vb)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       list_add_tail(&vb->queue, &pipe->activeq);
+       vb->state = VIDEOBUF_QUEUED;
+}
+
+void atomisp_buf_release(struct videobuf_queue *vq,
+                        struct videobuf_buffer *vb)
+{
+       /*
+        * only set flag here. buffer free will done by req 0 buffer
+        */
+       vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+int atomisp_buf_setup_output(struct videobuf_queue *vq,
+                            unsigned int *count,
+                            unsigned int *size)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       *size = pipe->out_fmt->imagesize;
+
+       return 0;
+}
+
+int atomisp_buf_prepare_output(struct videobuf_queue *vq,
+                              struct videobuf_buffer *vb,
+                              enum v4l2_field field)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       vb->size = pipe->out_fmt->imagesize;
+       vb->width = pipe->out_fmt->width;
+       vb->height = pipe->out_fmt->height;
+       vb->field = field;
+       vb->state = VIDEOBUF_PREPARED;
+
+       return 0;
+}
+
+void atomisp_buf_queue_output(struct videobuf_queue *vq,
+                             struct videobuf_buffer *vb)
+{
+       struct atomisp_video_pipe *pipe = vq->priv_data;
+
+       list_add_tail(&vb->queue, &pipe->activeq_out);
+       vb->state = VIDEOBUF_QUEUED;
+}
+
+void atomisp_buf_release_output(struct videobuf_queue *vq,
+                               struct videobuf_buffer *vb)
+{
+       videobuf_vmalloc_free(vb);
+       vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static struct videobuf_queue_ops videobuf_qops = {
+       .buf_setup      = atomisp_buf_setup,
+       .buf_prepare    = atomisp_buf_prepare,
+       .buf_queue      = atomisp_buf_queue,
+       .buf_release    = atomisp_buf_release,
+};
+
+static struct videobuf_queue_ops videobuf_qops_output = {
+       .buf_setup      = atomisp_buf_setup_output,
+       .buf_prepare    = atomisp_buf_prepare_output,
+       .buf_queue      = atomisp_buf_queue_output,
+       .buf_release    = atomisp_buf_release_output,
+};
+
+static int atomisp_uninit_pipe(struct atomisp_video_pipe *pipe)
+{
+       if (pipe->format) {
+               kfree(pipe->format);
+               pipe->format = NULL;
+       }
+
+       if (pipe->out_fmt) {
+               kfree(pipe->out_fmt);
+               pipe->out_fmt = NULL;
+       }
+
+       pipe->opened = false;
+       return 0;
+}
+
+static int atomisp_init_pipe(struct atomisp_video_pipe *pipe)
+{
+
+       pipe->out_fmt = kzalloc(sizeof(struct atomisp_fmt), GFP_KERNEL);
+       if (pipe->out_fmt == NULL) {
+               v4l2_err(&atomisp_dev, "fail to allocte memory\n");
+               return -ENOMEM;
+       }
+
+       pipe->format =
+       kzalloc(sizeof(struct atomisp_video_pipe_format), GFP_KERNEL);
+       if (pipe->format == NULL) {
+               v4l2_err(&atomisp_dev, "failed to alloca memory\n");
+               kfree(pipe->out_fmt);
+               return -ENOMEM;
+       }
+
+       videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL,
+                                   &pipe->irq_lock,
+                                   V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                                   V4L2_FIELD_NONE,
+                                   sizeof(struct atomisp_buffer),
+                                   pipe);
+
+       videobuf_queue_vmalloc_init(&pipe->outq,
+                                   &videobuf_qops_output, NULL,
+                                   &pipe->irq_lock,
+                                   V4L2_BUF_TYPE_VIDEO_OUTPUT,
+                                   V4L2_FIELD_NONE,
+                                   sizeof(struct atomisp_buffer),
+                                   pipe);
+
+       /* init locks */
+       spin_lock_init(&pipe->irq_lock);
+       mutex_init(&pipe->mutex);
+       INIT_LIST_HEAD(&pipe->activeq);
+       INIT_LIST_HEAD(&pipe->activeq_out);
+       pipe->opened = true;
+
+       return 0;
+}
+
+int atomisp_init_struct(struct atomisp_device *isp)
+{
+       if (isp == NULL)
+               return -EINVAL;
+
+       isp->main_format = NULL;
+       isp->vf_format = NULL;
+       isp->input_format = NULL;
+       isp->sw_contex.run_mode = CI_MODE_STILL_CAPTURE;
+       isp->params.color_effect = V4L2_COLORFX_NONE;
+       isp->params.bad_pixel_en = 1;
+       isp->params.gdc_cac_en = 0;
+       isp->params.video_dis_en = 0;
+       isp->params.sc_en = 0;
+       isp->params.fpn_en = 0;
+       isp->params.xnr_en = 0;
+       isp->params.false_color = 0;
+       isp->params.online_process = 1;
+       isp->params.yuv_ds_en = 0;
+       isp->params.vf_overlay = NULL;
+       isp->sw_contex.sensor_streaming = false;
+       isp->sw_contex.isp_streaming = false;
+       isp->sw_contex.work_queued = false;
+       isp->sw_contex.error = false;
+       isp->sw_contex.file_input = 0;
+
+       /* Add for channel */
+       if (isp->inputs[0].camera)
+               isp->input_curr = 0;
+
+       /* obtain the pointers to the default configurations */
+       sh_css_get_tnr_config(&isp->params.default_tnr_config);
+       sh_css_get_nr_config(&isp->params.default_nr_config);
+       sh_css_get_ee_config(&isp->params.default_ee_config);
+       sh_css_get_ob_config(&isp->params.default_ob_config);
+       sh_css_get_dp_config(&isp->params.default_dp_config);
+       sh_css_get_wb_config(&isp->params.default_wb_config);
+       sh_css_get_cc_config(&isp->params.default_cc_config);
+       sh_css_get_de_config(&isp->params.default_de_config);
+       sh_css_get_gc_config(&isp->params.default_gc_config);
+       sh_css_get_3a_config(&isp->params.default_3a_config);
+       sh_css_get_macc_table(&isp->params.default_macc_table);
+       sh_css_get_ctc_table(&isp->params.default_ctc_table);
+       sh_css_get_gamma_table(&isp->params.default_gamma_table);
+
+       /* we also initialize our configurations with the defaults */
+       isp->params.tnr_config  = *isp->params.default_tnr_config;
+       isp->params.nr_config   = *isp->params.default_nr_config;
+       isp->params.ee_config   = *isp->params.default_ee_config;
+       isp->params.ob_config   = *isp->params.default_ob_config;
+       isp->params.dp_config   = *isp->params.default_dp_config;
+       isp->params.wb_config   = *isp->params.default_wb_config;
+       isp->params.cc_config   = *isp->params.default_cc_config;
+       isp->params.de_config   = *isp->params.default_de_config;
+       isp->params.gc_config   = *isp->params.default_gc_config;
+       isp->params.s3a_config  = *isp->params.default_3a_config;
+       isp->params.macc_table  = *isp->params.default_macc_table;
+       isp->params.ctc_table   = *isp->params.default_ctc_table;
+       isp->params.gamma_table = *isp->params.default_gamma_table;
+
+       return 0;
+}
+
+/*Wrap functions to pass into css framework*/
+static void *kernel_malloc(size_t bytes)
+{
+       return kzalloc(bytes, GFP_KERNEL);
+}
+
+/* kfree is declared with const void * argument even though it's
+   clearly not const. We work around this here. */
+static void kernel_free(void *ptr)
+{
+       kfree(ptr);
+}
+
+/*
+ * file operation functions
+ */
+static int atomisp_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       int ret = -EINVAL;
+
+       if (!isp || isp->sw_contex.probed == 0)
+               return -ENODEV;
+
+       /* if (atomisp_get(isp) == NULL) { */
+       mutex_lock(&isp->input_lock);
+
+       if (!isp->input_cnt) {
+               v4l2_err(&atomisp_dev, "no camera attached\n");
+               goto error;
+       }
+
+       if (pipe->opened)
+               goto done;
+
+       if (atomisp_init_pipe(pipe) < 0)
+               goto error;
+
+       if (isp->sw_contex.init) {
+               v4l2_err(&atomisp_dev, "skip init isp in open\n");
+               goto done;
+       }
+
+#ifdef CONFIG_PM
+       /* runtime power management, turn on ISP */
+       if (pm_runtime_get_sync(vdev->v4l2_dev->dev) < 0) {
+               v4l2_err(&atomisp_dev,
+                        "Failed to power on device\n");
+               goto runtime_get_failed;
+       }
+#endif
+       /* if the driver gets closed and reopened, the HMM is not reinitialized
+        * This means we need to put the L1 page table base address back into
+        * the ISP. */
+       if (isp->hw_contex.mmu_l1_base)
+               sh_css_mmu_set_page_table_base_address(
+                                               isp->hw_contex.mmu_l1_base);
+
+       /* Init ISP */
+       if (sh_css_init(kernel_malloc,
+                       kernel_free,
+                       SH_CSS_INTERRUPT_SETTING_PULSE,
+                       isp->firmware->data,
+                       isp->firmware->size))
+               goto css_init_failed;
+       /* CSS has default zoom factor of 61x61, we want no zoom
+          because the zoom binary for capture is broken (XNR). */
+       sh_css_set_zoom_factor(64, 64);
+
+       atomisp_init_struct(isp);
+
+       isp->sw_contex.init = true;
+       v4l2_dbg(1, dbg_level, &atomisp_dev, "open done\n");
+done:
+       mutex_unlock(&isp->input_lock);
+
+       return 0;
+
+css_init_failed:
+#ifdef CONFIG_PM
+       pm_runtime_put(vdev->v4l2_dev->dev);
+#endif
+runtime_get_failed:
+       atomisp_uninit_pipe(pipe);
+error:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+static int atomisp_release(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct v4l2_requestbuffers req;
+       int ret = 0;
+
+       req.count = 0;
+       if (isp == NULL)
+               return -EBADF;
+
+       mutex_lock(&isp->input_lock);
+
+       if (pipe->capq.streaming &&
+           atomisp_streamoff(file, NULL,
+                             V4L2_BUF_TYPE_VIDEO_CAPTURE))
+               goto error;
+
+       if (pipe->opened == false)
+               goto done;
+
+       if (atomisp_reqbufs(file, NULL, &req))
+               goto error;
+
+       /* in case image buf is not freed */
+       if (pipe->capq.bufs[0]) {
+               mutex_lock(&pipe->capq.vb_lock);
+               videobuf_queue_cancel(&pipe->capq);
+               mutex_unlock(&pipe->capq.vb_lock);
+       }
+
+       if (pipe->format) {
+               kfree(pipe->format);
+               pipe->format = NULL;
+               isp->main_format = NULL;
+       }
+
+       if (pipe->outq.bufs[0]) {
+               mutex_lock(&pipe->outq.vb_lock);
+               videobuf_queue_cancel(&pipe->outq);
+               mutex_unlock(&pipe->outq.vb_lock);
+       }
+
+       if (pipe->out_fmt) {
+               kfree(pipe->out_fmt);
+               pipe->out_fmt = NULL;
+       }
+
+       if (isp->vf_format) {
+               kfree(isp->vf_format);
+               isp->vf_format = NULL;
+       }
+
+       if (isp->input_format) {
+               kfree(isp->input_format);
+               isp->input_format = NULL;
+       }
+
+       if (!pipe->is_main)
+               goto done;
+
+       if (isp->sw_contex.init == false) {
+               v4l2_info(&atomisp_dev,
+                         "device already closed\n");
+               goto done;
+       }
+       if ((!isp->isp_subdev.video_out_vf.opened) &&
+           (isp->vf_frame)) {
+               sh_css_frame_free(isp->vf_frame);
+               isp->vf_frame = NULL;
+       }
+
+
+       atomisp_free_3a_buffers(isp);
+       atomisp_free_dis_buffers(isp);
+       atomisp_free_internal_buffers(isp);
+       sh_css_uninit();
+       hrt_isp_css_mm_clear();
+
+       /*uninit the camera subdev*/
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                              core, init, 0);
+       if (ret == -1 || ret == -EINVAL)
+               v4l2_err(&atomisp_dev, "sensor firmware failed\n");
+
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      core, s_power, 0);
+       if (ret)
+               v4l2_warn(&atomisp_dev, "Failed to power-off sensor\n");
+
+       /* store L1 base address for next time we init the CSS */
+       isp->hw_contex.mmu_l1_base = sh_css_mmu_get_page_table_base_address();
+       isp->sw_contex.init = false;
+
+#ifdef CONFIG_PM
+       if (pm_runtime_put_sync(vdev->v4l2_dev->dev))
+               v4l2_err(&atomisp_dev,
+                        "Failed to power off device\n");
+#endif
+done:
+       pipe->opened = false;
+       mutex_unlock(&isp->input_lock);
+
+       return 0;
+error:
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+/*
+ * Memory help functions for image frame and private parameters
+ */
+static int do_isp_mm_remap(struct vm_area_struct *vma,
+                   void *isp_virt, u32 host_virt, u32 pgnr)
+{
+       u32 pfn;
+
+       while (pgnr) {
+               pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
+               if (remap_pfn_range(vma, host_virt, pfn,
+                                   PAGE_SIZE, PAGE_SHARED)) {
+                       v4l2_err(&atomisp_dev,
+                                   "remap_pfn_range err.\n");
+                       return -EAGAIN;
+               }
+
+               isp_virt += PAGE_SIZE;
+               host_virt += PAGE_SIZE;
+               pgnr--;
+       }
+
+       return 0;
+}
+
+static int frame_mmap(const struct sh_css_frame *frame,
+       struct vm_area_struct *vma)
+{
+       void *isp_virt;
+       u32 host_virt;
+       u32 pgnr;
+
+       if (!frame) {
+               v4l2_err(&atomisp_dev,
+                           "%s: NULL frame pointer.\n", __func__);
+               return -EINVAL;
+       }
+
+       host_virt = vma->vm_start;
+       isp_virt = frame->data;
+       atomisp_get_frame_pgnr(frame, &pgnr);
+
+       if (do_isp_mm_remap(vma, isp_virt, host_virt, pgnr))
+               return -EAGAIN;
+
+       return 0;
+}
+
+int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
+       struct vm_area_struct *vma)
+{
+       u32 offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret = -EINVAL, i;
+       struct videobuf_vmalloc_memory *vm_mem;
+       struct videobuf_mapping *map;
+
+       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
+               v4l2_err(&atomisp_dev, "map appl bug:"
+                           " PROT_WRITE and MAP_SHARED are required\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&q->vb_lock);
+       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+               struct videobuf_buffer *buf = q->bufs[i];
+               if (buf == NULL)
+                       continue;
+
+               map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
+               if (map == NULL) {
+                       mutex_unlock(&q->vb_lock);
+                       return -ENOMEM;
+               }
+
+               buf->map = map;
+               map->start = vma->vm_start;
+               map->end = vma->vm_end;
+               map->q = q;
+
+               buf->baddr = vma->vm_start;
+
+               if (buf && buf->memory == V4L2_MEMORY_MMAP &&
+                   buf->boff == offset) {
+                       vm_mem = buf->priv;
+                       ret = frame_mmap(vm_mem->vmalloc, vma);
+                       vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+                       break;
+               }
+       }
+       mutex_unlock(&q->vb_lock);
+
+       return ret;
+}
+
+/* The input frame contains left and right padding that need to be removed.
+ * There is always ISP_LEFT_PAD padding on the left side.
+ * There is also padding on the right (padded_width - width).
+ */
+static int
+remove_pad_from_frame(struct sh_css_frame *in_frame, __u32 width, __u32 height)
+{
+       unsigned int i;
+       unsigned short *buffer;
+       int ret = 0;
+       unsigned short *load = in_frame->data;
+       unsigned short *store = load;
+
+       buffer = kmalloc(width*sizeof(*load), GFP_KERNEL);
+       if (!buffer) {
+               v4l2_err(&atomisp_dev, "out of memory.\n");
+               return -ENOMEM;
+       }
+
+       load += ISP_LEFT_PAD;
+       for (i = 0; i < height; i++) {
+               ret = hrt_isp_css_mm_load(load, buffer, width*sizeof(*load));
+               if (ret < 0)
+                       goto remove_pad_error;
+
+               ret = hrt_isp_css_mm_store(store, buffer, width*sizeof(*store));
+               if (ret < 0)
+                       goto remove_pad_error;
+
+               load  += in_frame->info.padded_width;
+               store += width;
+       }
+
+remove_pad_error:
+       kfree(buffer);
+       return ret;
+}
+
+static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct sh_css_frame *raw_virt_addr;
+       u32 start = vma->vm_start;
+       u32 end = vma->vm_end;
+       u32 size = end - start;
+       u32 origin_size, new_size;
+
+       if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
+               return -EACCES;
+
+       if (!(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+
+       new_size = pipe->format->out.width *
+               pipe->format->out.height * 2;
+
+       /* mmap for ISP offline raw data */
+       if ((pipe->is_main) &&
+           (vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT))) {
+               int ret;
+               if (isp->params.online_process != 0)
+                       return -EINVAL;
+               raw_virt_addr = isp->raw_output_frame;
+               if (raw_virt_addr == NULL) {
+                       v4l2_err(&atomisp_dev,
+                                "Failed to request RAW frame\n");
+                       return -EINVAL;
+               }
+
+               ret = remove_pad_from_frame(raw_virt_addr,
+                                     pipe->format->out.width,
+                                     pipe->format->out.height);
+               if (ret < 0) {
+                       v4l2_err(&atomisp_dev, "remove pad failed.\n");
+                       return ret;
+               }
+               origin_size = raw_virt_addr->data_bytes;
+               raw_virt_addr->data_bytes = new_size;
+
+               v4l2_info(&atomisp_dev,
+                         "raw = %x, size = %d, ALIGN = %d\n",
+                         (unsigned int)raw_virt_addr, size,
+                         PAGE_ALIGN(raw_virt_addr->data_bytes));
+               if (size != PAGE_ALIGN(new_size)) {
+                       v4l2_err(&atomisp_dev,
+                                "incorrect size for mmap ISP"
+                                " Raw Frame\n");
+                       return -EINVAL;
+               }
+
+               if (frame_mmap(raw_virt_addr, vma)) {
+                       v4l2_err(&atomisp_dev,
+                                "frame_mmap failed.\n");
+                       raw_virt_addr->data_bytes = origin_size;
+                       return -EAGAIN;
+               }
+               raw_virt_addr->data_bytes = origin_size;
+               vma->vm_flags |= VM_RESERVED;
+               return 0;
+       }
+
+       /*
+        * mmap for normal frames
+        */
+       if (size != pipe->format->out.sizeimage) {
+               v4l2_err(&atomisp_dev,
+                           "incorrect size for mmap ISP frames\n");
+               return -EINVAL;
+       }
+
+       return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
+}
+
+int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       return videobuf_mmap_mapper(&pipe->outq, vma);
+}
+
+static unsigned int
+atomisp_poll(struct file *file, struct poll_table_struct *pt)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       if (pipe->capq.streaming != 1)
+               return POLLERR;
+
+       return videobuf_poll_stream(file, &pipe->capq, pt);
+}
+
+const struct v4l2_file_operations atomisp_fops = {
+       .owner = THIS_MODULE,
+       .open = atomisp_open,
+       .release = atomisp_release,
+       .mmap = atomisp_mmap,
+       .ioctl = video_ioctl2,
+       .poll = atomisp_poll,
+};
+
+const struct v4l2_file_operations atomisp_file_fops = {
+       .owner = THIS_MODULE,
+       .open = atomisp_open,
+       .release = atomisp_release,
+       .mmap = atomisp_file_mmap,
+       .ioctl = video_ioctl2,
+       .poll = atomisp_poll,
+};
+
diff --git a/drivers/media/video/atomisp/atomisp_fops.h b/drivers/media/video/atomisp/atomisp_fops.h
new file mode 100644 (file)
index 0000000..d3ed1de
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __ATOMISP_FCTRL_H__
+#define        __ATOMISP_FCTRL_H__
+
+#include "atomisp_common.h"
+
+/*
+ * Videobuf ops
+ */
+int atomisp_buf_setup(struct videobuf_queue *vq,
+                       unsigned int *count,
+                       unsigned int *size);
+
+int atomisp_buf_prepare(struct videobuf_queue *vq,
+                         struct videobuf_buffer *vb,
+                         enum v4l2_field field);
+
+void atomisp_buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb);
+
+void atomisp_buf_release(struct videobuf_queue *vq,
+                          struct videobuf_buffer *vb);
+
+int atomisp_init_struct(struct atomisp_device *isp);
+
+/*
+ * Memory help functions for image frame and private parameters
+ */
+
+int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
+                                    struct vm_area_struct *vma);
+
+int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma);
+
+extern struct v4l2_device atomisp_dev;
+
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_ioctl.c b/drivers/media/video/atomisp/atomisp_ioctl.c
new file mode 100644 (file)
index 0000000..d4798f9
--- /dev/null
@@ -0,0 +1,1689 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "atomisp_ioctl.h"
+#include "atomisp_cmd.h"
+#include "atomisp_fops.h"
+#include "css/sh_css.h"
+#include <css/sh_css_debug.h>
+#include "bufferclass_video_linux.h"
+
+/* for v4l2_capability */
+static const char *DRIVER = "atomisp"; /* max size 15 */
+static const char *CARD = "ATOM ISP";  /* max size 31 */
+static const char *BUS_INFO = "PCI-3"; /* max size 31 */
+static const u32 VERSION = DRIVER_VERSION;
+
+static struct v4l2_queryctrl ci_v4l2_controls[] = {
+       {
+               .id = V4L2_CID_AUTO_WHITE_BALANCE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Automatic White Balance",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_RED_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Red Balance",
+               .minimum = 0x00,
+               .maximum = 0xff,
+               .step = 1,
+               .default_value = 0x00,
+       },
+       {
+               .id = V4L2_CID_BLUE_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Blue Balance",
+               .minimum = 0x00,
+               .maximum = 0xff,
+               .step = 1,
+               .default_value = 0x00,
+       },
+       {
+               .id = V4L2_CID_GAMMA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Gamma",
+               .minimum = 0x00,
+               .maximum = 0xff,
+               .step = 1,
+               .default_value = 0x00,
+       },
+       {
+               .id = V4L2_CID_HFLIP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Image h-flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_VFLIP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Image v-flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_COLORFX,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Image Color Effect",
+               .minimum = 0,
+               .maximum = 9,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Bad Pixel Correction",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "GDC/CAC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Video Stablization",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Fixed Pattern Noise Reduction",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "False Color Correction",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_ATOMISP_SHADING_CORRECTION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Lens Shading Correction",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_REQUEST_FLASH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Request flash frames",
+               .minimum = 0,
+               .maximum = 10,
+               .step = 1,
+               .default_value = 1,
+       }
+};
+static const u32 ctrls_num = ARRAY_SIZE(ci_v4l2_controls);
+
+/*
+ * v4l2 ioctls
+ * return ISP capabilities
+ *
+ * FIXME: capabilities should be different for video0/video2/video3
+ */
+static int atomisp_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       int ret = 0;
+
+       memset(cap, 0, sizeof(struct v4l2_capability));
+       strncpy(cap->driver, DRIVER, strlen(DRIVER));
+       strncpy(cap->card, CARD, strlen(CARD));
+       strncpy(cap->bus_info, BUS_INFO, strlen(BUS_INFO));
+       cap->version = VERSION;
+
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_STREAMING |
+                               V4L2_CAP_VIDEO_OUTPUT;
+
+       return ret;
+}
+
+/*
+ * return sensor chip identification
+ */
+static int atomisp_g_chip_ident(struct file *file, void *fh,
+       struct v4l2_dbg_chip_ident *chip)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int ret = 0;
+
+       mutex_lock(&isp->input_lock);
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                              core, g_chip_ident, chip);
+       mutex_unlock(&isp->input_lock);
+
+       if (ret)
+               v4l2_err(&atomisp_dev,
+                           "failed to g_chip_ident for sensor\n");
+       return ret;
+}
+
+/*
+ * crop capability is the max resolution both ISP and Sensor supported
+ */
+static int atomisp_cropcap(struct file *file, void *fh,
+       struct v4l2_cropcap *cropcap)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct v4l2_mbus_framefmt snr_mbus_fmt;
+       int ret;
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev, "unsupport v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       /*Only capture node supports cropcap*/
+       if (!pipe->is_main)
+               return 0;
+
+       cropcap->bounds.left = 0;
+       cropcap->bounds.top = 0;
+
+       snr_mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+       snr_mbus_fmt.height = ATOM_ISP_MAX_HEIGHT_TMP;
+       snr_mbus_fmt.width = ATOM_ISP_MAX_WIDTH_TMP;
+
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                              video, try_mbus_fmt, &snr_mbus_fmt);
+       if (ret) {
+               v4l2_err(&atomisp_dev,
+                       "failed to try_mbus_fmt for sensor"
+                       ", try try_fmt\n");
+       } else {
+               cropcap->bounds.width = snr_mbus_fmt.width;
+               cropcap->bounds.height = snr_mbus_fmt.height;
+               isp->snr_max_width = snr_mbus_fmt.width;
+               isp->snr_max_height = snr_mbus_fmt.height;
+               isp->snr_pixelformat = snr_mbus_fmt.code;
+       }
+
+       memcpy(&cropcap->defrect, &cropcap->bounds, sizeof(struct v4l2_rect));
+       cropcap->pixelaspect.numerator = 1;
+       cropcap->pixelaspect.denominator = 1;
+       return 0;
+}
+/*
+ *  FIXME:G_CROP and S_CROP are used for bayer downscaling case
+ */
+static int atomisp_g_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       /*
+        * g_crop is used to enable bayer downscaling previously.
+        * current bayer ds is replaced by yuv ds.
+        * so remove the support of cropping.
+        */
+       v4l2_err(&atomisp_dev,
+               "crop is unavailable now\n");
+       return -EINVAL;
+
+}
+
+static int atomisp_s_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       /*
+        * s_crop is used to enable bayer downscaling previously.
+        * current bayer ds is replaced by yuv ds.
+        * so remove the support of cropping.
+        */
+       v4l2_err(&atomisp_dev,
+               "crop is unavailable now\n");
+       return -EINVAL;
+}
+/*
+ * enum input are used to check primary/secondary camera
+ */
+static int atomisp_enum_input(struct file *file, void *fh,
+       struct v4l2_input *input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int index = input->index;
+
+       if (index >= isp->input_cnt)
+               return -EINVAL;
+
+       if (!isp->inputs[index].camera)
+               return -EINVAL;
+
+       memset(input, 0, sizeof(struct v4l2_input));
+       strcpy(input->name, isp->inputs[index].camera->name);
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       input->index = index;
+       input->reserved[0] = isp->inputs[index].type;
+       input->reserved[1] = isp->inputs[index].port;
+
+       return 0;
+}
+/*
+ * get input are used to get current primary/secondary camera
+ */
+static int atomisp_g_input(struct file *file, void *fh, unsigned int *input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+
+       *input = isp->input_curr;
+
+       return 0;
+}
+/*
+ * set input are used to set current primary/secondary camera
+ */
+static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct v4l2_subdev *camera = NULL;
+       int ret;
+
+       if (input >= ATOM_ISP_MAX_INPUTS || input > isp->input_cnt)
+               return -EINVAL;
+
+       mutex_lock(&isp->input_lock);
+       camera = isp->inputs[input].camera;
+       if (!camera) {
+               mutex_unlock(&isp->input_lock);
+               return -EINVAL;
+       }
+
+       if ((isp->isp_subdev.video_out_vf.capq.streaming == 1) ||
+           (isp->isp_subdev.video_out_mo.capq.streaming == 1) ||
+           (isp->isp_subdev.video_in.capq.streaming == 1)) {
+               v4l2_err(&atomisp_dev,
+                        "ISP is still streaming, stop first\n");
+               mutex_unlock(&isp->input_lock);
+               return -EINVAL;
+       }
+
+       /* power off the current sensor, as it is not used this time */
+       if (isp->input_curr != input) {
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      core, s_power, 0);
+               if (ret)
+                       v4l2_warn(&atomisp_dev,
+                                   "Failed to power-off sensor\n");
+       }
+
+       /* powe on the new sensor */
+       if (!isp->sw_contex.file_input) {
+               ret = v4l2_subdev_call(isp->inputs[input].camera,
+                                      core, s_power, 1);
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                   "Failed to power-on sensor\n");
+                       mutex_unlock(&isp->input_lock);
+                       return -EINVAL;
+               }
+       }
+
+       isp->input_curr = input;
+
+       mutex_unlock(&isp->input_lock);
+
+       return 0;
+}
+
+static int atomisp_g_std(struct file *file, void *fh, v4l2_std_id * id)
+{
+       return -EINVAL;
+}
+
+static int atomisp_s_std(struct file *file, void *fh, v4l2_std_id * id)
+{
+       return -EINVAL;
+}
+
+static int atomisp_enum_fmt_cap(struct file *file, void *fh,
+       struct v4l2_fmtdesc *f)
+{
+       u32 index = f->index;
+
+       /* check buf index */
+       if (index >= atomisp_output_fmts_num) {
+               v4l2_err(&atomisp_dev,
+                           "fmt index extends maxiumn"
+                           " supported fmts number\n");
+               return -EINVAL;
+       }
+       /* check buf type */
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev,
+                           "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       f->pixelformat = atomisp_output_fmts[index].pixelformat;
+       memset(f->description, 0, sizeof(char)*32);
+       strncpy(f->description, atomisp_output_fmts[index].description,
+               strlen(atomisp_output_fmts[index].description));
+
+       return 0;
+}
+
+static int atomisp_g_fmt_cap(struct file *file, void *fh,
+       struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       int ret;
+
+       ret = atomisp_get_fmt(vdev, f);
+       return ret;
+}
+
+static int atomisp_g_fmt_file(struct file *file, void *fh,
+               struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       int ret;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev,
+                               "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       memset(f, 0, sizeof(struct v4l2_format));
+       f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+       switch (isp->sw_contex.output_mode) {
+       case OUTPUT_MODE_FILE:
+               f->fmt.pix.width = pipe->out_fmt->width;
+               f->fmt.pix.height = pipe->out_fmt->height;
+               f->fmt.pix.pixelformat = pipe->out_fmt->pixelformat;
+               f->fmt.pix.bytesperline = pipe->out_fmt->bytesperline;
+               f->fmt.pix.sizeimage = pipe->out_fmt->imagesize;
+               break;
+       case OUTPUT_MODE_TEXT:
+               f->fmt.pix.sizeimage = pipe->out_fmt->framesize;
+               break;
+       default:
+               v4l2_err(&atomisp_dev, "Unspported output mode\n");
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/* This function looks up the closest available resolution. */
+static int atomisp_try_fmt_cap(struct file *file, void *fh,
+       struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       int ret;
+
+       ret = atomisp_try_fmt(vdev, f, NULL);
+       return ret;
+}
+
+static int atomisp_s_fmt_cap(struct file *file, void *fh,
+       struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       int ret;
+
+       ret = atomisp_set_fmt(vdev, f);
+       return ret;
+}
+
+static int atomisp_s_fmt_file(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       struct video_device *vdev = video_devdata(file);
+       int ret;
+
+       ret = atomisp_set_fmt_file(vdev, f);
+       return ret;
+}
+
+/*
+ * This ioctl allows applications to enumerate all frame sizes that the
+ * device supports for the given pixel format.
+ * discrete means the applicatons should increase the index until EINVAL is
+ * returned.
+ */
+static int atomisp_enum_framesizes(struct file *file, void *fh,
+       struct v4l2_frmsizeenum *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+
+       if (!atomisp_is_pixelformat_supported(arg->pixel_format))
+               return -EINVAL;
+
+       return v4l2_subdev_call(isp->inputs[isp->input_curr].camera, video,
+                               enum_framesizes, arg);
+}
+
+/*
+ * is_resolution_supported - Check whether resolution is supported
+ * @width: check resolution width
+ * @height: check resolution height
+ *
+ * Return 1 on supported or 0 otherwise.
+*/
+static int is_resolution_supported(u32 width, u32 height)
+{
+       if ((width > ATOM_ISP_MIN_WIDTH) && (width <= ATOM_ISP_MAX_WIDTH) &&
+           (height > ATOM_ISP_MIN_HEIGHT) && (height <= ATOM_ISP_MAX_HEIGHT)) {
+               if (!(width % ATOM_ISP_STEP_WIDTH) &&
+                   !(height % ATOM_ISP_STEP_HEIGHT))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * This ioctl allows applications to enumerate all frame intervals that the
+ * device supports for the given pixel format and frame size.
+ *
+ * framerate =  1 / frameintervals
+ */
+static int atomisp_enum_frameintervals(struct file *file, void *fh,
+       struct v4l2_frmivalenum *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int ret;
+
+       if (arg->index != 0)
+               return -EINVAL;
+
+       if (!atomisp_is_pixelformat_supported(arg->pixel_format))
+               return -EINVAL;
+
+       if (!is_resolution_supported(arg->width, arg->height))
+               return -EINVAL;
+
+       ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+               video, enum_frameintervals, arg);
+
+       if (ret) {
+               /* set the FPS to default 15*/
+               arg->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+               arg->discrete.numerator = 1;
+               arg->discrete.denominator = 15;
+       }
+
+       v4l2_info(&atomisp_dev, "%s: sensor_support:%d "
+               "FPS:%d\n", __func__, ret, arg->discrete.denominator);
+
+       return 0;
+}
+/*
+ * this function is used to free video buffer
+ */
+static void atomisp_videobuf_free(struct videobuf_queue *q)
+{
+       int i;
+       struct videobuf_vmalloc_memory *vm_mem;
+
+       mutex_lock(&q->vb_lock);
+
+       if (!q) {
+               mutex_unlock(&q->vb_lock);
+               return;
+       }
+
+       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+               if (NULL == q->bufs[i])
+                       continue;
+               vm_mem = q->bufs[i]->priv;
+
+               if (vm_mem && vm_mem->vmalloc) {
+                       sh_css_frame_free(vm_mem->vmalloc);
+                       vm_mem->vmalloc = NULL;
+               }
+               kfree(q->bufs[i]);
+               q->bufs[i] = NULL;
+       }
+
+       mutex_unlock(&q->vb_lock);
+}
+
+/*
+ * Initiate Memory Mapping or User Pointer I/O
+ */
+int atomisp_reqbufs(struct file *file, void *fh,
+       struct v4l2_requestbuffers *req)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct sh_css_frame_info out_info, vf_info;
+       struct sh_css_frame *frame;
+       struct videobuf_vmalloc_memory *vm_mem;
+       int ret = 0, i = 0;
+
+       if (req->count == 0) {
+               atomisp_videobuf_free(&pipe->capq);
+               if ((!isp->isp_subdev.video_out_vf.opened) &&
+               (isp->vf_frame)) {
+                       sh_css_frame_free(isp->vf_frame);
+                       isp->vf_frame = NULL;
+               }
+               return 0;
+       }
+
+       if ((!pipe->is_main) && (!atomisp_is_viewfinder_support(isp)))
+               return -EINVAL;
+
+       ret = videobuf_reqbufs(&pipe->capq, req);
+       if (ret)
+               return ret;
+
+       switch (isp->sw_contex.run_mode) {
+       case CI_MODE_STILL_CAPTURE:
+               if (isp->main_format->out_sh_fmt != SH_CSS_FRAME_FORMAT_RAW) {
+                       if (sh_css_capture_get_viewfinder_frame_info(&vf_info))
+                               goto error;
+                       if ((!isp->isp_subdev.video_out_vf.opened) &&
+                           (sh_css_frame_allocate_from_info(&isp->vf_frame,
+                                                            &vf_info)))
+                                       goto error;
+               }
+               if (sh_css_capture_get_output_frame_info(&out_info))
+                       goto error;
+               break;
+       case CI_MODE_VIDEO:
+               if (sh_css_video_get_viewfinder_frame_info(&vf_info))
+                       goto error;
+
+               if ((!isp->isp_subdev.video_out_vf.opened) &&
+                   (sh_css_frame_allocate_from_info(&isp->vf_frame, &vf_info)))
+                               goto error;
+
+               if (sh_css_video_get_output_frame_info(&out_info))
+                       goto error;
+               break;
+       case CI_MODE_PREVIEW:
+               if (sh_css_preview_get_output_frame_info(&out_info))
+                       goto error;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * for user pointer type, buffers are not really allcated here,
+        * buffers are setup in QBUF operation through v4l2_buffer structure
+        */
+       if (req->memory == V4L2_MEMORY_USERPTR) {
+               v4l2_info(&atomisp_dev,
+                           "user pointer, not really allocate"
+                           " memory here.\n");
+               return 0;
+       }
+
+       if (!pipe->is_main)
+               /*
+                * Allocate the real frame here for preview node using our
+                * memery management function
+                */
+               for (i = 0; i < req->count; i++) {
+                       if (sh_css_frame_allocate_from_info(&frame, &vf_info))
+                               goto error;
+                       vm_mem = pipe->capq.bufs[i]->priv;
+                       vm_mem->vmalloc = frame;
+               }
+       else
+               /*
+                * Allocate the real frame here for capture node using our
+                * memery management function
+                */
+               for (i = 0; i < req->count; i++) {
+                       if (sh_css_frame_allocate_from_info(&frame, &out_info))
+                               goto error;
+                       vm_mem = pipe->capq.bufs[i]->priv;
+                       vm_mem->vmalloc = frame;
+               }
+
+       return ret;
+
+error:
+       while (i--) {
+               vm_mem = pipe->capq.bufs[i]->priv;
+               sh_css_frame_free(vm_mem->vmalloc);
+       }
+
+       if (isp->vf_frame)
+               sh_css_frame_free(isp->vf_frame);
+       return -ENOMEM;
+}
+
+static int atomisp_reqbufs_file(struct file *file, void *fh,
+               struct v4l2_requestbuffers *req)
+{
+       int ret;
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       if (req->count == 0) {
+               atomisp_videobuf_free(&pipe->outq);
+               return 0;
+       }
+
+       ret = videobuf_reqbufs(&pipe->outq, req);
+       if (ret)
+               return ret;
+
+       if (isp->sw_contex.output_mode == OUTPUT_MODE_TEXT)
+               return 0;
+
+       /*
+        *  TODO: Implement file input function
+        */
+
+       return 0;
+}
+
+/* application query the status of a buffer */
+static int atomisp_querybuf(struct file *file, void *fh,
+       struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       return videobuf_querybuf(&pipe->capq, buf);
+}
+
+static int atomisp_querybuf_file(struct file *file, void *fh,
+                               struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       return videobuf_querybuf(&pipe->outq, buf);
+}
+
+/*
+ * Applications call the VIDIOC_QBUF ioctl to enqueue an empty (capturing) or
+ * filled (output) buffer in the drivers incoming queue.
+ */
+static int atomisp_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       unsigned long userptr = buf->m.userptr;
+       struct videobuf_buffer *vb;
+       struct videobuf_vmalloc_memory *vm_mem;
+       struct sh_css_frame_info out_info, vf_info;
+       struct sh_css_frame *handle = NULL;
+       u32 length;
+       u32 pgnr;
+       int ret = 0;
+
+       if ((!pipe->is_main) &&
+           (!atomisp_is_viewfinder_support(isp)))
+               return -EINVAL;
+
+       if (!buf || buf->index >= VIDEO_MAX_FRAME ||
+               !pipe->capq.bufs[buf->index]) {
+               v4l2_err(&atomisp_dev,
+                           "Invalid index for qbuf.\n");
+               return -EINVAL;
+       }
+
+       v4l2_dbg(2, dbg_level, &atomisp_dev, "%s\n", __func__);
+       /*
+        * For userptr type frame, we convert user space address to physic
+        * address and reprograme out page table properly
+        */
+       if (buf->memory == V4L2_MEMORY_USERPTR) {
+               vb = pipe->capq.bufs[buf->index];
+               vm_mem = vb->priv;
+               if (!vm_mem)
+                       return -EINVAL;
+
+               length = vb->bsize;
+               pgnr = (length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+               /* We must stop to atomisp to remove the
+               * race condition when updating the new userptr. */
+               if (buf->flags & V4L2_BUF_FLAG_BUFFER_INVALID) {
+                       isp->sw_contex.updating_uptr = true;
+                       return 0;
+               }
+               /* Check whether need to start the atomisp_work */
+               if (buf->flags & V4L2_BUF_FLAG_BUFFER_VALID) {
+                       isp->sw_contex.updating_uptr = false;
+                       wake_up_interruptible_sync(&pipe->capq.wait);
+                       return 0;
+               }
+
+               if ((vb->baddr == userptr) && (vm_mem->vmalloc))
+                       goto done;
+
+               switch (isp->sw_contex.run_mode) {
+               case CI_MODE_STILL_CAPTURE:
+                       if ((isp->main_format->out_sh_fmt !=
+                               SH_CSS_FRAME_FORMAT_RAW) &&
+                       sh_css_capture_get_viewfinder_frame_info(&vf_info))
+                               goto error;
+
+                       if (sh_css_capture_get_output_frame_info(&out_info))
+                               goto error;
+                       break;
+               case CI_MODE_VIDEO:
+                       if (sh_css_video_get_viewfinder_frame_info(&vf_info))
+                               goto error;
+                       if (sh_css_video_get_output_frame_info(&out_info))
+                               goto error;
+                       break;
+               case CI_MODE_PREVIEW:
+                       if (sh_css_preview_get_output_frame_info(&out_info))
+                               goto error;
+                       break;
+               }
+
+               hrt_isp_css_mm_set_user_ptr(userptr, pgnr);
+               if (!pipe->is_main)
+                       sh_css_frame_allocate_from_info(&handle, &vf_info);
+               else
+                       sh_css_frame_allocate_from_info(&handle, &out_info);
+
+               hrt_isp_css_mm_set_user_ptr(0, 0);
+               if (IS_ERR(handle)) {
+                       v4l2_err(&atomisp_dev, "Error to allocate"
+                                   " frame for userptr capture %ld\n",
+                                   PTR_ERR(handle));
+
+                       return PTR_ERR(handle);
+               }
+
+               if (vm_mem->vmalloc) {
+                       mutex_lock(&pipe->capq.vb_lock);
+                       sh_css_frame_free(vm_mem->vmalloc);
+                       vm_mem->vmalloc = NULL;
+                       vb->state = VIDEOBUF_NEEDS_INIT;
+                       mutex_unlock(&pipe->capq.vb_lock);
+               }
+
+               vm_mem->vmalloc = handle;
+
+               buf->flags &= ~V4L2_BUF_FLAG_MAPPED;
+               buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               buf->flags &= ~V4L2_BUF_FLAG_DONE;
+
+       } else if (buf->memory == V4L2_MEMORY_MMAP) {
+               buf->flags |= V4L2_BUF_FLAG_MAPPED;
+               buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       }
+
+done:
+       ret = videobuf_qbuf(&pipe->capq, buf);
+       return ret;
+
+error:
+       v4l2_err(&atomisp_dev, "get_output_frame_info error\n");
+       return -EINVAL;
+}
+
+static int atomisp_qbuf_file(struct file *file, void *fh,
+                                       struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+       if (!buf || buf->index >= VIDEO_MAX_FRAME ||
+               !pipe->outq.bufs[buf->index]) {
+               v4l2_err(&atomisp_dev,
+                           "Invalid index for qbuf.\n");
+               return -EINVAL;
+       }
+
+       if (buf->memory != V4L2_MEMORY_MMAP) {
+               v4l2_err(&atomisp_dev, "Unsupported memory method\n");
+               return -EINVAL;
+       }
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev, "Unsupported buffer type\n");
+               return -EINVAL;
+       }
+
+       return videobuf_qbuf(&pipe->outq, buf);
+}
+
+/*
+ * Applications call the VIDIOC_DQBUF ioctl to dequeue a filled (capturing) or
+ * displayed (output buffer)from the driver's outgoing queue
+ */
+static int atomisp_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int ret = 0;
+
+       v4l2_dbg(2, dbg_level, &atomisp_dev, "%s\n", __func__);
+
+       if ((!pipe->is_main) &&
+           (!atomisp_is_viewfinder_support(isp)))
+               return -EINVAL;
+
+       if (isp->sw_contex.error) {
+               v4l2_err(&atomisp_dev, "ISP ERROR\n");
+               return -EINVAL;
+       }
+
+       ret = videobuf_dqbuf(&pipe->capq, buf, file->f_flags & O_NONBLOCK);
+       if (ret)
+               return ret;
+       buf->bytesused = pipe->format->out.sizeimage;
+       buf->reserved = isp->frame_status[buf->index];
+
+       return 0;
+}
+
+/*
+ * This ioctl start the capture during streaming I/O.
+ */
+static int atomisp_streamon(struct file *file, void *fh,
+       enum v4l2_buf_type type)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int ret;
+#ifdef PUNIT_CAMERA_BUSY
+       u32 msg_ret;
+#endif
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev,
+                           "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       if (list_empty(&(pipe->capq.stream))) {
+               v4l2_err(&atomisp_dev,
+                               "no buffer in the queue\n");
+               return -EINVAL;
+       }
+
+       ret = videobuf_streamon(&pipe->capq);
+       if (ret)
+               return ret;
+       isp->sw_contex.isp_streaming = true;
+
+       if (isp->sw_contex.work_queued)
+               goto done;
+
+#ifdef PUNIT_CAMERA_BUSY
+       /*
+        * As per h/w architect and ECO 697611 we need to throttle the
+        * GFX performance (freq) while camera is up to prevent peak
+        * current issues. this is done by setting the camera busy bit.
+        */
+       msg_ret = atomisp_msg_read32(isp, PUNIT_PORT, OR1);
+       msg_ret |= 0x100;
+       atomisp_msg_write32(isp, PUNIT_PORT, OR1, msg_ret);
+#endif
+
+       /*stream on sensor in work thread*/
+       queue_work(isp->work_queue, &isp->work);
+       isp->sw_contex.work_queued = true;
+
+done:
+       return 0;
+}
+
+/*This ioctl stop the capture or output process during streaming I/O.*/
+int atomisp_streamoff(struct file *file, void *fh,
+       enum v4l2_buf_type type)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+       struct atomisp_video_pipe *vf_pipe = NULL;
+       struct atomisp_video_pipe *mo_pipe = NULL;
+       int ret;
+#ifdef PUNIT_CAMERA_BUSY
+       u32 msg_ret;
+#endif
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev,
+                           "unsupported v4l2 buf type\n");
+               return -EINVAL;
+       }
+
+       isp->sw_contex.isp_streaming = false;
+
+       /* cancel work queue*/
+       if (isp->sw_contex.work_queued) {
+               mo_pipe = &isp->isp_subdev.video_out_mo;
+               wake_up_interruptible(&mo_pipe->capq.wait);
+               if (atomisp_is_viewfinder_support(isp)) {
+                       vf_pipe = &isp->isp_subdev.video_out_vf;
+                       wake_up_interruptible(&vf_pipe->capq.wait);
+               }
+               cancel_work_sync(&isp->work);
+               isp->sw_contex.work_queued = false;
+       }
+
+       ret = videobuf_streamoff(&pipe->capq);
+       if (ret)
+               return ret;
+       /*stream off sensor, power off is called in senor driver*/
+       if (!pipe->is_main)
+               return 0;
+       if (!isp->sw_contex.file_input)
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      video, s_stream, 0);
+
+       if (isp->flash)
+               ret += v4l2_subdev_call(isp->flash, core, s_power, 0);
+
+       isp->sw_contex.sensor_streaming = false;
+
+#ifdef PUNIT_CAMERA_BUSY
+       /* Free camera_busy bit */
+       msg_ret = atomisp_msg_read32(isp, PUNIT_PORT, OR1);
+       msg_ret &= ~0x100;
+       atomisp_msg_write32(isp, PUNIT_PORT, OR1, msg_ret);
+#endif
+
+       /* ISP work around, need to power cycle isp*/
+       if (pipe->is_main && isp->sw_contex.power_state == ATOM_ISP_POWER_UP) {
+               sh_css_suspend();
+               pm_runtime_put_sync(vdev->v4l2_dev->dev);
+               pm_runtime_get_sync(vdev->v4l2_dev->dev);
+               sh_css_resume();
+       }
+
+       return ret;
+}
+
+/*
+ * To get the current value of a control.
+ * applications initialize the id field of a struct v4l2_control and
+ * call this ioctl with a pointer to this structure
+ */
+static int atomisp_g_ctrl(struct file *file, void *fh,
+       struct v4l2_control *control)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int i, ret = -EINVAL;
+
+       mutex_lock(&isp->input_lock);
+
+       for (i = 0; i < ctrls_num; i++) {
+               if (ci_v4l2_controls[i].id == control->id) {
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if (ret) {
+               mutex_unlock(&isp->input_lock);
+               return ret;
+       }
+
+       switch (control->id) {
+       case V4L2_CID_IRIS_ABSOLUTE:
+       case V4L2_CID_EXPOSURE_ABSOLUTE:
+       case V4L2_CID_HFLIP:
+       case V4L2_CID_VFLIP:
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      core, g_ctrl, control);
+               break;
+       case V4L2_CID_COLORFX:
+               ret = atomisp_color_effect(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
+               ret = atomisp_bad_pixel(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
+               ret = atomisp_gdc_cac(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
+               ret = atomisp_video_stable(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
+               ret = atomisp_fixed_pattern(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
+               ret = atomisp_false_color(isp, 0, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_SHADING_CORRECTION:
+               ret = atomisp_shading_correction(isp, 0, &control->value);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+/*
+ * To change the value of a control.
+ * applications initialize the id and value fields of a struct v4l2_control
+ * and call this ioctl.
+ */
+static int atomisp_s_ctrl(struct file *file, void *fh,
+                         struct v4l2_control *control)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int i, ret = -EINVAL;
+
+       mutex_lock(&isp->input_lock);
+
+       for (i = 0; i < ctrls_num; i++) {
+               if (ci_v4l2_controls[i].id == control->id) {
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if (ret) {
+               mutex_unlock(&isp->input_lock);
+               return ret;
+       }
+
+       switch (control->id) {
+       case V4L2_CID_HFLIP:
+       case V4L2_CID_VFLIP:
+               ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                      core, s_ctrl, control);
+               break;
+       case V4L2_CID_COLORFX:
+               ret = atomisp_color_effect(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
+               ret = atomisp_bad_pixel(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
+               ret = atomisp_gdc_cac(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
+               ret = atomisp_video_stable(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
+               ret = atomisp_fixed_pattern(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
+               ret = atomisp_false_color(isp, 1, &control->value);
+               break;
+       case V4L2_CID_ATOMISP_SHADING_CORRECTION:
+               ret = atomisp_shading_correction(isp, 1, &control->value);
+               break;
+       case V4L2_CID_REQUEST_FLASH:
+               ret = atomisp_flash_enable(isp, control->value);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+/*
+ * To query the attributes of a control.
+ * applications set the id field of a struct v4l2_queryctrl and call the
+ * this ioctl with a pointer to this structure. The driver fills
+ * the rest of the structure.
+ */
+static int atomisp_queryctl(struct file *file, void *fh,
+                           struct v4l2_queryctrl *qc)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int i, ret = -EINVAL;
+
+       if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+               return ret;
+
+       mutex_lock(&isp->input_lock);
+
+       for (i = 0; i < ctrls_num; i++) {
+               if (ci_v4l2_controls[i].id == qc->id) {
+                       memcpy(qc, &ci_v4l2_controls[i],
+                              sizeof(struct v4l2_queryctrl));
+                       qc->reserved[0] = 0;
+                       ret = 0;
+                       break;
+               }
+       }
+       if (ret != 0)
+               qc->flags = V4L2_CTRL_FLAG_DISABLED;
+
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh,
+       struct v4l2_ext_controls *c)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       for (i = 0; i < c->count; i++) {
+               ctrl.id = c->controls[i].id;
+               ctrl.value = c->controls[i].value;
+               switch (ctrl.id) {
+               case V4L2_CID_EXPOSURE_ABSOLUTE:
+               case V4L2_CID_IRIS_ABSOLUTE:
+                       /*
+                        * Exposure related control will be handled by sensor
+                        * driver
+                        */
+                       ret = v4l2_subdev_call(isp->inputs
+                                              [isp->input_curr].camera,
+                                              core, g_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_FOCUS_ABSOLUTE:
+               case V4L2_CID_FOCUS_RELATIVE:
+               case V4L2_CID_FOCUS_STATUS:
+               case V4L2_CID_FOCUS_AUTO:
+                       if (isp->motor)
+                               ret = v4l2_subdev_call(
+                                       isp->motor, core, g_ctrl, &ctrl);
+                       else
+                               ret = v4l2_subdev_call(
+                                       isp->inputs[isp->input_curr].camera,
+                                       core, g_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_FLASH_STATUS:
+               case V4L2_CID_FLASH_INTENSITY:
+               case V4L2_CID_FLASH_TORCH_INTENSITY:
+               case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+               case V4L2_CID_FLASH_TIMEOUT:
+               case V4L2_CID_FLASH_STROBE:
+               case V4L2_CID_FLASH_MODE:
+                       if (isp->flash)
+                               ret = v4l2_subdev_call(
+                                       isp->flash, core, g_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_ZOOM_ABSOLUTE:
+                       ret = atomisp_digital_zoom(isp, 0, &ctrl.value);
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+
+               if (ret) {
+                       c->error_idx = i;
+                       break;
+               }
+               c->controls[i].value = ctrl.value;
+       }
+       return ret;
+}
+
+/* This ioctl allows the application to get multiple controls by class */
+static int atomisp_g_ext_ctrls(struct file *file, void *fh,
+       struct v4l2_ext_controls *c)
+{
+       struct v4l2_control ctrl;
+       int i, ret = 0;
+
+       /* input_lock is not need for the Camera releated IOCTLs
+        * The input_lock downgrade the FPS of 3A*/
+       if (c->ctrl_class == V4L2_CTRL_CLASS_CAMERA) {
+               ret = atomisp_camera_g_ext_ctrls(file, fh, c);
+               return ret;
+       }
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       ret = atomisp_g_ctrl(file, fh, &ctrl);
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+       return -EINVAL;
+}
+
+static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh,
+       struct v4l2_ext_controls *c)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       for (i = 0; i < c->count; i++) {
+               ctrl.id = c->controls[i].id;
+               ctrl.value = c->controls[i].value;
+               switch (ctrl.id) {
+               case V4L2_CID_EXPOSURE_ABSOLUTE:
+               case V4L2_CID_IRIS_ABSOLUTE:
+               case V4L2_CID_VCM_TIMEING:
+               case V4L2_CID_VCM_SLEW:
+               case V4L2_CID_TEST_PATTERN:
+                       ret = v4l2_subdev_call(
+                               isp->inputs[isp->input_curr].camera,
+                               core, s_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_FOCUS_ABSOLUTE:
+               case V4L2_CID_FOCUS_RELATIVE:
+               case V4L2_CID_FOCUS_STATUS:
+               case V4L2_CID_FOCUS_AUTO:
+                       if (isp->motor)
+                               ret = v4l2_subdev_call(isp->motor,
+                                       core, s_ctrl, &ctrl);
+                       else
+                               ret = v4l2_subdev_call(
+                                       isp->inputs[isp->input_curr].camera,
+                                       core, s_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_FLASH_STATUS:
+               case V4L2_CID_FLASH_INTENSITY:
+               case V4L2_CID_FLASH_TORCH_INTENSITY:
+               case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+               case V4L2_CID_FLASH_TIMEOUT:
+               case V4L2_CID_FLASH_STROBE:
+               case V4L2_CID_FLASH_MODE:
+                       if (isp->flash)
+                               ret = v4l2_subdev_call(isp->flash,
+                                       core, s_ctrl, &ctrl);
+                       break;
+               case V4L2_CID_ZOOM_ABSOLUTE:
+                       ret = atomisp_digital_zoom(isp, 1, &ctrl.value);
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+
+               if (ret) {
+                       c->error_idx = i;
+                       break;
+               }
+               c->controls[i].value = ctrl.value;
+       }
+       return ret;
+}
+
+/* This ioctl allows the application to set multiple controls by class */
+static int atomisp_s_ext_ctrls(struct file *file, void *fh,
+       struct v4l2_ext_controls *c)
+{
+       struct v4l2_control ctrl;
+       int i, ret = 0;
+
+       /* input_lock is not need for the Camera releated IOCTLs
+        * The input_lock downgrade the FPS of 3A*/
+       if (c->ctrl_class == V4L2_CTRL_CLASS_CAMERA) {
+               ret = atomisp_camera_s_ext_ctrls(file, fh, c);
+               return ret;
+       }
+
+       if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+               for (i = 0; i < c->count; i++) {
+                       ctrl.id = c->controls[i].id;
+                       ctrl.value = c->controls[i].value;
+                       ret = atomisp_s_ctrl(file, fh, &ctrl);
+                       c->controls[i].value = ctrl.value;
+                       if (ret) {
+                               c->error_idx = i;
+                               break;
+                       }
+               }
+               return ret;
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * vidioc_g/s_param are used to switch isp running mode
+ */
+static int atomisp_g_parm(struct file *file, void *fh,
+       struct v4l2_streamparm *parm)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+
+       mutex_lock(&isp->input_lock);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev,
+                           "unsupport v4l2 buf type\n");
+               mutex_unlock(&isp->input_lock);
+               return -EINVAL;
+       }
+
+       parm->parm.capture.capturemode = isp->sw_contex.run_mode;
+
+       mutex_unlock(&isp->input_lock);
+       return 0;
+}
+
+static int atomisp_s_parm(struct file *file, void *fh,
+       struct v4l2_streamparm *parm)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+       int ret = 0;
+
+       mutex_lock(&isp->input_lock);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               v4l2_err(&atomisp_dev,
+                           "unsupport v4l2 buf type\n");
+               mutex_unlock(&isp->input_lock);
+               return -EINVAL;
+       }
+
+       isp->sw_contex.run_mode = parm->parm.capture.capturemode;
+
+       mutex_unlock(&isp->input_lock);
+       return ret;
+}
+
+static int atomisp_s_parm_file(struct file *file, void *fh,
+                               struct v4l2_streamparm *parm)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_err(&atomisp_dev,
+                           "unsupport v4l2 buf type for output\n");
+               return -EINVAL;
+       }
+
+       isp->sw_contex.output_mode = parm->parm.output.outputmode;
+       if (isp->sw_contex.output_mode == OUTPUT_MODE_FILE)
+               isp->sw_contex.file_input = 1;
+
+
+       return 0;
+}
+
+/* set default atomisp ioctl value */
+static long atomisp_vidioc_default(struct file *file, void *fh,
+       int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct atomisp_device *isp = video_get_drvdata(vdev);
+
+       switch (cmd) {
+       case ATOMISP_IOC_G_XNR:
+               return atomisp_xnr(isp, 0, arg);
+
+       case ATOMISP_IOC_S_XNR:
+               return atomisp_xnr(isp, 1, arg);
+
+       case ATOMISP_IOC_G_BAYER_NR:
+               return atomisp_bayer_nr(isp, 0, arg);
+
+       case ATOMISP_IOC_S_BAYER_NR:
+               return atomisp_bayer_nr(isp, 1, arg);
+
+       case ATOMISP_IOC_G_TNR:
+               return atomisp_tnr(isp, 0, arg);
+
+       case ATOMISP_IOC_S_TNR:
+               return atomisp_tnr(isp, 1, arg);
+
+       case ATOMISP_IOC_G_HISTOGRAM:
+               return atomisp_histogram(isp, 0, arg);
+
+       case ATOMISP_IOC_S_HISTOGRAM:
+               return atomisp_histogram(isp, 1, arg);
+
+       case ATOMISP_IOC_G_BLACK_LEVEL_COMP:
+               return atomisp_black_level(isp, 0, arg);
+
+       case ATOMISP_IOC_S_BLACK_LEVEL_COMP:
+               return atomisp_black_level(isp, 1, arg);
+
+       case ATOMISP_IOC_G_YCC_NR:
+               return atomisp_ycc_nr(isp, 0, arg);
+
+       case ATOMISP_IOC_S_YCC_NR:
+               return atomisp_ycc_nr(isp, 1, arg);
+
+       case ATOMISP_IOC_G_EE:
+               return atomisp_ee(isp, 0, arg);
+
+       case ATOMISP_IOC_S_EE:
+               return atomisp_ee(isp, 1, arg);
+
+       case ATOMISP_IOC_G_DIS_STAT:
+               return atomisp_dis_stat(isp, 0, arg);
+
+       case ATOMISP_IOC_S_DIS_STAT:
+               return atomisp_dis_stat(isp, 1, arg);
+
+       case ATOMISP_IOC_S_DIS_VECTOR:
+               return atomisp_dis_vector(isp, arg);
+
+       case ATOMISP_IOC_G_ISP_PARM:
+               return atomisp_param(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_PARM:
+               return atomisp_param(isp, 1, arg);
+
+       case ATOMISP_IOC_G_3A_STAT:
+               return atomisp_3a_stat(isp, 0, arg);
+
+       case ATOMISP_IOC_G_ISP_GAMMA:
+               return atomisp_gamma(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_GAMMA:
+               return atomisp_gamma(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_GDC_TAB:
+               return atomisp_gdc_cac_table(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_GDC_TAB:
+               return atomisp_gdc_cac_table(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_MACC:
+               return atomisp_macc_table(isp, 0,
+                       (struct atomisp_macc_config *)arg);
+
+       case ATOMISP_IOC_S_ISP_MACC:
+               return atomisp_macc_table(isp, 1,
+                       (struct atomisp_macc_config *)arg);
+
+       case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION:
+               return atomisp_bad_pixel_param(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION:
+               return atomisp_bad_pixel_param(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION:
+               return atomisp_false_color_param(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION:
+               return atomisp_false_color_param(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_CTC:
+               return atomisp_ctc(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_CTC:
+               return atomisp_ctc(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_WHITE_BALANCE:
+               return atomisp_white_balance_param(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_WHITE_BALANCE:
+               return atomisp_white_balance_param(isp, 1, arg);
+
+       case ATOMISP_IOC_G_3A_CONFIG:
+               return atomisp_3a_config_param(isp, 0, arg);
+
+       case ATOMISP_IOC_S_3A_CONFIG:
+               return atomisp_3a_config_param(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_FPN_TABLE:
+               return atomisp_fixed_pattern_table(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_FPN_TABLE:
+               return atomisp_fixed_pattern_table(isp, 1, arg);
+
+       case ATOMISP_IOC_G_ISP_OVERLAY:
+               return atomisp_vf_overlay(isp, 0, arg);
+
+       case ATOMISP_IOC_S_ISP_OVERLAY:
+               return atomisp_vf_overlay(isp, 1, arg);
+
+       case ATOMISP_IOC_ISP_MAKERNOTE:
+               return atomisp_exif_makernote(isp, arg);
+
+       case ATOMISP_IOC_G_SENSOR_MODE_DATA:
+               return atomisp_get_sensor_mode_data(isp, arg);
+
+       case ATOMISP_IOC_S_EXPOSURE:
+       case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP:
+       case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
+               return v4l2_subdev_call(isp->inputs[isp->input_curr].camera,
+                                       core, ioctl, cmd, arg);
+
+       case ATOMISP_IOC_ACC_LOAD:
+               return atomisp_acc_load(isp, arg);
+
+       case ATOMISP_IOC_ACC_UNLOAD:
+               return atomisp_acc_unload(isp, arg);
+
+       case ATOMISP_IOC_ACC_S_ARG:
+               return atomisp_acc_set_arg(isp, arg);
+
+       case ATOMISP_IOC_ACC_START:
+               return atomisp_acc_start(isp, arg);
+
+       case ATOMISP_IOC_ACC_WAIT:
+               return atomisp_acc_wait(isp, arg);
+
+       case ATOMISP_IOC_ACC_ABORT:
+               return atomisp_acc_abort(isp, arg);
+
+       case ATOMISP_IOC_CAMERA_BRIDGE:
+               /* here we convert the atomisp struct to a BC_Video struct.
+                * We do this to avoid exporting the BC_Video struct in
+                * atomisp.h which causes duplicate structure compilation
+                * errors. */
+               return BC_Camera_Bridge((BC_Video_ioctl_package *)arg,
+                                       (unsigned long) NULL);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+const struct v4l2_ioctl_ops atomisp_ioctl_ops = {
+       .vidioc_querycap = atomisp_querycap,
+       .vidioc_g_chip_ident = atomisp_g_chip_ident,
+       .vidioc_enum_input = atomisp_enum_input,
+       .vidioc_g_input = atomisp_g_input,
+       .vidioc_s_input = atomisp_s_input,
+       .vidioc_queryctrl = atomisp_queryctl,
+       .vidioc_s_ctrl = atomisp_s_ctrl,
+       .vidioc_g_ctrl = atomisp_g_ctrl,
+       .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls,
+       .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls,
+       .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap,
+       .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap,
+       .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap,
+       .vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap,
+       .vidioc_s_fmt_type_private = atomisp_s_fmt_cap,
+       .vidioc_reqbufs = atomisp_reqbufs,
+       .vidioc_querybuf = atomisp_querybuf,
+       .vidioc_qbuf = atomisp_qbuf,
+       .vidioc_dqbuf = atomisp_dqbuf,
+       .vidioc_streamon = atomisp_streamon,
+       .vidioc_streamoff = atomisp_streamoff,
+       .vidioc_default = atomisp_vidioc_default,
+       .vidioc_cropcap = atomisp_cropcap,
+       .vidioc_enum_framesizes = atomisp_enum_framesizes,
+       .vidioc_enum_frameintervals = atomisp_enum_frameintervals,
+       .vidioc_s_parm = atomisp_s_parm,
+       .vidioc_g_parm = atomisp_g_parm,
+       .vidioc_g_std = atomisp_g_std,
+       .vidioc_s_std = atomisp_s_std,
+       .vidioc_g_crop = atomisp_g_crop,
+       .vidioc_s_crop = atomisp_s_crop,
+};
+
+const struct v4l2_ioctl_ops atomisp_file_ioctl_ops = {
+       .vidioc_querycap = atomisp_querycap,
+       .vidioc_g_fmt_vid_out = atomisp_g_fmt_file,
+       .vidioc_s_fmt_vid_out = atomisp_s_fmt_file,
+       .vidioc_s_parm = atomisp_s_parm_file,
+       .vidioc_reqbufs = atomisp_reqbufs_file,
+       .vidioc_querybuf = atomisp_querybuf_file,
+       .vidioc_qbuf = atomisp_qbuf_file,
+       /* .vidioc_streamon = atomisp_streamon_out, */
+};
diff --git a/drivers/media/video/atomisp/atomisp_ioctl.h b/drivers/media/video/atomisp/atomisp_ioctl.h
new file mode 100644 (file)
index 0000000..6a7e1bd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __ATOMISP_CTRL_H__
+#define        __ATOMISP_CTRL_H__
+
+#include "atomisp_common.h"
+
+/*
+ * v4l2 ioctls
+ */
+int atomisp_streamoff(struct file *file, void *fh,
+                             enum v4l2_buf_type type);
+
+int atomisp_reqbufs(struct file *file, void *fh,
+                       struct v4l2_requestbuffers *req);
+
+extern const struct v4l2_file_operations atomisp_fops;
+
+extern const struct v4l2_file_operations atomisp_file_fops;
+
+extern const struct v4l2_ioctl_ops atomisp_ioctl_ops;
+
+extern const struct v4l2_ioctl_ops atomisp_file_ioctl_ops;
+
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_subdev.c b/drivers/media/video/atomisp/atomisp_subdev.c
new file mode 100644 (file)
index 0000000..c41fb46
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include "atomisp_internal.h"
+
+static const unsigned int isp_subdev_input_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+};
+
+static const unsigned int isp_subdev_vf_output_fmts[] = {
+       /* yuv420, nv12, yv12, nv21, rgb565 */
+       V4L2_MBUS_FMT_UYVY8_1X16,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+       V4L2_PIX_FMT_YUV420,
+       V4L2_PIX_FMT_YVU420,
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_RGB565,
+       V4L2_PIX_FMT_NV21,
+};
+
+static const unsigned int isp_subdev_mo_output_fmts[] = {
+       /* yuv420, nv12, yv12, nv21, rgb565, nv11, yuv422, nv16, yv16, yuy2 */
+       /* rgb565, rgb888 */
+       V4L2_MBUS_FMT_UYVY8_1X16,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+       V4L2_PIX_FMT_YUV420,
+       V4L2_PIX_FMT_YVU420,
+       V4L2_PIX_FMT_YUV422P,
+       V4L2_PIX_FMT_YUV444,
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_NV21,
+       V4L2_PIX_FMT_NV16,
+       V4L2_PIX_FMT_NV61,
+       V4L2_PIX_FMT_YUYV,
+       V4L2_PIX_FMT_UYVY,
+       V4L2_PIX_FMT_RGB565,
+       V4L2_PIX_FMT_RGB32
+};
+
+/*
+* V4L2 subdev operations
+*/
+
+/*
+ * isp_subdev_get_ctrl - V4L2 control get handler
+ * @sd: ISP V4L2 subdevice
+ * @ctrl: V4L2 control
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+static int isp_subdev_get_ctrl(struct v4l2_subdev *sd,
+       struct v4l2_control *ctrl)
+{
+       return -EINVAL;
+}
+
+/*
+ * isp_subdev_set_ctrl - V4L2 control set handler
+ * @sd: ISP CCDC V4L2 subdevice
+ * @ctrl: V4L2 control
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+static int isp_subdev_set_ctrl(struct v4l2_subdev *sd,
+       struct v4l2_control *ctrl)
+{
+       return -EINVAL;
+}
+
+/*
+ * isp_subdev_ioctl - CCDC module private ioctl's
+ * @sd: ISP V4L2 subdevice
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+static long isp_subdev_ioctl(struct v4l2_subdev *sd,
+       unsigned int cmd, void *arg)
+{
+       int ret = 0;
+
+       return ret;
+}
+
+/*
+ * isp_subdev_set_power - Power on/off the CCDC module
+ * @sd: ISP V4L2 subdevice
+ * @on: power on/off
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
+{
+       return 0;
+}
+
+static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
+       struct v4l2_fh *fh,
+       struct v4l2_event_subscription *sub)
+{
+
+       /* TBD
+       return v4l2_event_subscribe(fh, sub);
+       */
+       return 0;
+}
+
+static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
+       struct v4l2_fh *fh,
+       struct v4l2_event_subscription *sub)
+{
+       return v4l2_event_unsubscribe(fh, sub);
+}
+
+/*
+* isp_subdev_set_stream - Enable/Disable streaming on the isp sub module
+* @sd: ISP V4L2 subdevice
+* @enable: Enable/disable stream
+*/
+static int isp_subdev_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       int ret = 0;
+
+       /* handle continuous, single shot or stopped state */
+       return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__isp_subdev_get_format(struct atomisp_sub_device *isp_subdev,
+       struct v4l2_subdev_fh *fh, unsigned int pad,
+       enum v4l2_subdev_format_whence which)
+{
+
+       switch (which) {
+       case V4L2_SUBDEV_FORMAT_TRY:
+               return v4l2_subdev_get_try_format(fh, pad);
+       case V4L2_SUBDEV_FORMAT_ACTIVE:
+               if (pad == ATOMISP_SUBDEV_PAD_SINK ||
+                       pad == ATOMISP_SUBDEV_PAD_SOURCE_VF ||
+                       pad == ATOMISP_SUBDEV_PAD_SOURCE_MO)
+                       return &isp_subdev->formats[pad];
+               else
+                       return NULL;
+       default:
+               return NULL;
+       }
+}
+
+/*
+ * isp_subdev_try_format - Try video format on a pad
+ * @isp_subdev: ISP v4l2 sub device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+*/
+static void
+isp_subdev_try_format(struct atomisp_sub_device *isp_subdev,
+       struct v4l2_subdev_fh *fh,
+       unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+       enum v4l2_subdev_format_whence which)
+{
+       struct v4l2_mbus_framefmt *format;
+       unsigned int width = fmt->width;
+       unsigned int height = fmt->height;
+       enum v4l2_mbus_pixelcode pixelcode;
+       unsigned int i;
+
+       switch (pad) {
+       case ATOMISP_SUBDEV_PAD_SINK:
+               if (isp_subdev->input == ATOMISP_SUBDEV_INPUT_MEMORY) {
+                       fmt->width = clamp_t(u32, fmt->width,
+                               ATOM_ISP_MIN_WIDTH, ATOM_ISP_MAX_WIDTH);
+                       fmt->height = clamp_t(u32, fmt->height,
+                               ATOM_ISP_MIN_HEIGHT, ATOM_ISP_MAX_HEIGHT);
+               }
+
+               fmt->colorspace = V4L2_COLORSPACE_SRGB;
+               for (i = 0; i < ARRAY_SIZE(isp_subdev_input_fmts); i++) {
+                       if (fmt->code == isp_subdev_input_fmts[i])
+                               break;
+               }
+
+               /* If not found, use SGRBG10 as default */
+               if (i >= ARRAY_SIZE(isp_subdev_input_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SBGGR10_1X10;
+
+               /* Clamp the input size. */
+               fmt->width = clamp_t(u32, width, 32, 4096);
+               fmt->height = clamp_t(u32, height, 32, 4096);
+
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SOURCE_VF:
+               pixelcode = fmt->code;
+               format = __isp_subdev_get_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               switch (pixelcode) {
+               /* yuv420, nv12, yv12, nv21, rgb565 */
+               case V4L2_MBUS_FMT_YUYV8_1X16:
+               case V4L2_MBUS_FMT_UYVY8_1X16:
+               case V4L2_MBUS_FMT_RGB565_2X8_LE:
+               case V4L2_MBUS_FMT_YUYV8_1_5X8:
+                       fmt->code = pixelcode;
+                       break;
+               default:
+                       fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+                       break;
+               }
+
+               /* The data formatter truncates the number of horizontal output
+               * pixels to a multiple of 16. To avoid clipping data, allow
+               * callers to request an output size bigger than the input size
+               * up to the nearest multiple of 16.
+               */
+               fmt->width = clamp_t(u32, width, 256, 1920);
+               fmt->height = clamp_t(u32, height, 0, 1080);
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SOURCE_MO:
+               pixelcode = fmt->code;
+               format = __isp_subdev_get_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+               switch (pixelcode) {
+               /* yuv420, nv12, yv12, nv21, rgb565, nv11, yuv422 */
+               /* nv16, yv16, yuy2 */
+               /* rgb565, rgb888 */
+               case V4L2_MBUS_FMT_YUYV8_1X16:
+               case V4L2_MBUS_FMT_UYVY8_1X16:
+               case V4L2_MBUS_FMT_RGB565_2X8_LE:
+               case V4L2_MBUS_FMT_YUYV8_1_5X8:
+                       fmt->code = pixelcode;
+                       break;
+               default:
+                       fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+                       break;
+               }
+
+               /* The number of lines that can be clocked out from the video
+               * port output must be at least one line less than the number
+               * of input lines.
+               */
+               fmt->width = clamp_t(u32, width, 256, 4608);
+               fmt->height = clamp_t(u32, height, 0, fmt->height - 1);
+               break;
+       }
+
+       /* Data is written to memory unpacked, each 10-bit pixel is stored on
+       * 2 bytes.
+       */
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * isp_subdev_enum_mbus_code - Handle pixel format enumeration
+ * @sd: pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
+ * return -EINVAL or zero on success
+*/
+static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh,
+       struct v4l2_subdev_mbus_code_enum *code)
+{
+       switch (code->pad) {
+       case ATOMISP_SUBDEV_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(isp_subdev_input_fmts))
+                       return -EINVAL;
+
+               code->code = isp_subdev_input_fmts[code->index];
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SOURCE_VF:
+               /* format conversion inside isp subdev */
+               if (code->index >= ARRAY_SIZE(isp_subdev_vf_output_fmts))
+                       return -EINVAL;
+
+               code->code = isp_subdev_vf_output_fmts[code->index];
+               break;
+       case ATOMISP_SUBDEV_PAD_SOURCE_MO:
+               /* format conversion inside isp subdev */
+               if (code->index >= ARRAY_SIZE(isp_subdev_mo_output_fmts))
+                       return -EINVAL;
+
+               code->code = isp_subdev_mo_output_fmts[code->index];
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int isp_subdev_enum_frame_size(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh,
+       struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct atomisp_sub_device *isp_subdev = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       isp_subdev_try_format(isp_subdev, fh, fse->pad,
+               &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       isp_subdev_try_format(isp_subdev, fh, fse->pad,
+               &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * isp_subdev_get_format - Retrieve the video format on a pad
+ * @sd : ISP V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+*/
+static int isp_subdev_get_format(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt)
+{
+       struct atomisp_sub_device *isp_subdev = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __isp_subdev_get_format(isp_subdev, fh, fmt->pad, fmt->which);
+       if (format == NULL) {
+               v4l2_err(&atomisp_dev, "no format available\n");
+               return -EINVAL;
+       }
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * isp_subdev_set_format - Set the video format on a pad
+ * @sd : ISP subdev V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+*/
+static int isp_subdev_set_format(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt)
+{
+       struct atomisp_sub_device *isp_subdev = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __isp_subdev_get_format(isp_subdev, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       isp_subdev_try_format(isp_subdev, fh, fmt->pad,
+               &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == ATOMISP_SUBDEV_PAD_SINK) {
+               format = __isp_subdev_get_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SOURCE_VF, fmt->which);
+               *format = fmt->format;
+               isp_subdev_try_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SOURCE_VF, format, fmt->which);
+
+               format = __isp_subdev_get_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SOURCE_MO, fmt->which);
+               *format = fmt->format;
+               isp_subdev_try_format(isp_subdev, fh,
+                       ATOMISP_SUBDEV_PAD_SOURCE_MO, format, fmt->which);
+       }
+
+       return 0;
+}
+
+ /* V4L2 subdev core operations */
+ static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
+        .g_ctrl = isp_subdev_get_ctrl,
+        .s_ctrl = isp_subdev_set_ctrl,
+        .ioctl = isp_subdev_ioctl,
+        .s_power = isp_subdev_set_power,
+        .subscribe_event = isp_subdev_subscribe_event,
+        .unsubscribe_event = isp_subdev_unsubscribe_event,
+ };
+
+ /* V4L2 subdev video operations */
+ static const struct v4l2_subdev_video_ops isp_subdev_v4l2_video_ops = {
+        .s_stream = isp_subdev_set_stream,
+ };
+
+ /* V4L2 subdev pad operations */
+ static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
+        .enum_mbus_code = isp_subdev_enum_mbus_code,
+        .enum_frame_size = isp_subdev_enum_frame_size,
+        .get_fmt = isp_subdev_get_format,
+        .set_fmt = isp_subdev_set_format,
+ };
+
+ /* V4L2 subdev operations */
+ static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
+        .core = &isp_subdev_v4l2_core_ops,
+        .video = &isp_subdev_v4l2_video_ops,
+        .pad = &isp_subdev_v4l2_pad_ops,
+ };
+
+static void isp_subdev_init_params(struct atomisp_sub_device *isp_subdev)
+{
+       /* parameters initialization */
+
+}
+
+/*
+* isp_subdev_link_setup - Setup isp subdev connections
+* @entity: ispsubdev media entity
+* @local: Pad at the local end of the link
+* @remote: Pad at the remote end of the link
+* @flags: Link flags
+*
+* return -EINVAL or zero on success
+*/
+static int isp_subdev_link_setup(struct media_entity *entity,
+       const struct media_pad *local,
+       const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
+       struct atomisp_device *isp = isp_sd->isp;
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENTITY_TYPE_V4L2_SUBDEV:
+               /* Read from the sensor CSI2-4p or CSI2-1p. */
+               if (!(flags & MEDIA_LINK_FLAG_ENABLED)) {
+                       isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
+                       break;
+               }
+
+               if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE)
+                       return -EBUSY;
+
+               if (remote->entity == &isp->csi2_4p.subdev.entity)
+                       isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_4P;
+               else if (remote->entity == &isp->csi2_1p.subdev.entity)
+                       isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_1P;
+               else
+                       isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_4P;
+
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENTITY_TYPE_DEVNODE:
+               /* read from memory */
+               if (flags & MEDIA_LINK_FLAG_ENABLED) {
+                       if (isp_sd->input == ATOMISP_SUBDEV_INPUT_CSI2_4P
+                       || isp_sd->input == ATOMISP_SUBDEV_INPUT_CSI2_1P)
+                               return -EBUSY;
+                       isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY;
+               } else {
+                       if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY)
+                               isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
+               }
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENTITY_TYPE_DEVNODE:
+               /* always write to memory */
+               break;
+
+       case ATOMISP_SUBDEV_PAD_SOURCE_MO | MEDIA_ENTITY_TYPE_DEVNODE:
+               /* always write to memory */
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+ /* media operations */
+ static const struct media_entity_operations isp_subdev_media_ops = {
+        .link_setup = isp_subdev_link_setup,
+        .set_power = v4l2_subdev_set_power,
+ };
+
+/*
+ * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
+ * @isp_subdev: ISP CCDC module
+ *
+ * Return 0 on success and a negative error code on failure.
+*/
+static int isp_subdev_init_entities(struct atomisp_sub_device *isp_subdev)
+{
+       struct v4l2_subdev *sd = &isp_subdev->subdev;
+       struct media_pad *pads = isp_subdev->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       isp_subdev->input = ATOMISP_SUBDEV_INPUT_NONE;
+
+       v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
+       strlcpy(sd->name, "ATOM ISP SUBDEV", sizeof(sd->name));
+       v4l2_set_subdevdata(sd, isp_subdev);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+       sd->nevents = 16; /* TBD */
+
+       pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FLAG_INPUT;
+       pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FLAG_OUTPUT;
+       pads[ATOMISP_SUBDEV_PAD_SOURCE_MO].flags = MEDIA_PAD_FLAG_OUTPUT;
+
+       isp_subdev->formats[ATOMISP_SUBDEV_PAD_SINK].code =
+               V4L2_MBUS_FMT_SBGGR10_1X10;
+       isp_subdev->formats[ATOMISP_SUBDEV_PAD_SOURCE_VF].code =
+               V4L2_MBUS_FMT_SBGGR10_1X10;
+       isp_subdev->formats[ATOMISP_SUBDEV_PAD_SOURCE_MO].code =
+               V4L2_MBUS_FMT_SBGGR10_1X10;
+
+       me->ops = &isp_subdev_media_ops;
+       me->type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
+       ret = media_entity_init(me, ATOMISP_SUBDEV_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       isp_subdev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       isp_subdev->video_in.isp = isp_subdev->isp;
+
+       isp_subdev->video_out_vf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       isp_subdev->video_out_vf.isp = isp_subdev->isp;
+       isp_subdev->video_out_vf.is_main = false;
+
+       isp_subdev->video_out_mo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       isp_subdev->video_out_mo.isp = isp_subdev->isp;
+       isp_subdev->video_out_mo.is_main = true;
+
+
+       ret = atomisp_video_init(&isp_subdev->video_in, "MEMORY");
+       if (ret < 0)
+               return ret;
+
+       ret = atomisp_video_init(&isp_subdev->video_out_mo, "MAINOUTPUT");
+       if (ret < 0)
+               return ret;
+
+       ret = atomisp_video_init(&isp_subdev->video_out_vf, "VIEWFINDER");
+       if (ret < 0)
+               return ret;
+
+       /* Connect the isp subdev to the video node. */
+       ret = media_entity_create_link(&isp_subdev->video_in.vdev.entity,
+               0, &isp_subdev->subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0);
+       if (ret < 0)
+               return ret;
+       ret = media_entity_create_link(&isp_subdev->subdev.entity,
+               ATOMISP_SUBDEV_PAD_SOURCE_VF,
+               &isp_subdev->video_out_vf.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = media_entity_create_link(&isp_subdev->subdev.entity,
+               ATOMISP_SUBDEV_PAD_SOURCE_MO,
+               &isp_subdev->video_out_mo.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+void atomisp_subdev_unregister_entities(struct atomisp_sub_device *isp_subdev)
+{
+       media_entity_cleanup(&isp_subdev->subdev.entity);
+
+       v4l2_device_unregister_subdev(&isp_subdev->subdev);
+       atomisp_video_unregister(&isp_subdev->video_in);
+       atomisp_video_unregister(&isp_subdev->video_out_vf);
+       atomisp_video_unregister(&isp_subdev->video_out_mo);
+}
+
+int atomisp_subdev_register_entities(struct atomisp_sub_device *isp_subdev,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video node. */
+       ret = v4l2_device_register_subdev(vdev, &isp_subdev->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = atomisp_video_register(&isp_subdev->video_out_mo, vdev);
+       if (ret < 0)
+               goto error;
+
+       ret = atomisp_video_register(&isp_subdev->video_out_vf, vdev);
+       if (ret < 0)
+               goto error;
+
+       ret = atomisp_video_register(&isp_subdev->video_in, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       atomisp_subdev_unregister_entities(isp_subdev);
+       return ret;
+}
+
+
+/*
+ * atomisp_subdev_init - ISP Subdevice  initialization.
+ * @dev: Device pointer specific to the ATOM ISP.
+ *
+ * TODO: Get the initialisation values from platform data.
+ *
+ * Return 0 on success or a negative error code otherwise.
+*/
+int atomisp_subdev_init(struct atomisp_device *isp)
+{
+       struct atomisp_sub_device *isp_subdev = &isp->isp_subdev;
+       int ret;
+
+       spin_lock_init(&isp_subdev->lock);
+       isp_subdev->isp = isp;
+       isp_subdev_init_params(isp_subdev);
+       ret = isp_subdev_init_entities(isp_subdev);
+       if (ret < 0)
+               atomisp_subdev_cleanup(isp);
+
+       return ret;
+}
+
+void atomisp_subdev_cleanup(struct atomisp_device *isp)
+{
+
+}
+
diff --git a/drivers/media/video/atomisp/atomisp_subdev.h b/drivers/media/video/atomisp/atomisp_subdev.h
new file mode 100644 (file)
index 0000000..a35cb0c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef ATOMISP_SUBDEV_H_
+#define ATOMISP_SUBDEV_H_
+
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+enum atomisp_subdev_input_entity {
+       ATOMISP_SUBDEV_INPUT_NONE,
+       ATOMISP_SUBDEV_INPUT_MEMORY,
+       ATOMISP_SUBDEV_INPUT_CSI2,
+       ATOMISP_SUBDEV_INPUT_CSI2_4P,
+       ATOMISP_SUBDEV_INPUT_CSI2_1P
+};
+
+#define ATOMISP_SUBDEV_PAD_SINK                        0
+#define ATOMISP_SUBDEV_PAD_SOURCE_VF           1 /* viewfinder output*/
+#define ATOMISP_SUBDEV_PAD_SOURCE_MO           2 /* regular output */
+#define ATOMISP_SUBDEV_PADS_NUM                        3
+
+struct atomisp_video_pipe {
+       struct video_device vdev;
+       enum v4l2_buf_type type;
+       struct media_pad pad;
+       struct videobuf_queue capq;
+       struct videobuf_queue outq;
+       struct list_head activeq;
+       struct list_head activeq_out;
+       struct mutex mutex;
+
+       spinlock_t irq_lock;
+       bool opened;
+       bool is_main;
+
+       struct atomisp_device *isp;
+       struct atomisp_fmt *out_fmt;
+       struct atomisp_video_pipe_format *format;
+};
+
+struct atomisp_sub_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[ATOMISP_SUBDEV_PADS_NUM];
+
+       enum atomisp_subdev_input_entity input;
+       unsigned int output;
+       struct atomisp_video_pipe video_in;
+       struct atomisp_video_pipe video_out_vf; /* view finder */
+       struct atomisp_video_pipe video_out_mo; /* main output */
+       /* struct isp_subdev_params params; */
+       spinlock_t lock;
+       struct atomisp_device *isp;
+};
+
+void atomisp_subdev_unregister_entities(struct atomisp_sub_device *isp_subdev);
+int atomisp_subdev_register_entities(struct atomisp_sub_device *isp_subdev,
+       struct v4l2_device *vdev);
+int atomisp_subdev_init(struct atomisp_device *isp);
+void atomisp_subdev_cleanup(struct atomisp_device *isp);
+
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_tpg.c b/drivers/media/video/atomisp/atomisp_tpg.c
new file mode 100644 (file)
index 0000000..7d98c82
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <css/sh_css.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include "atomisp_internal.h"
+#include "atomisp_tpg.h"
+
+static int tpg_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       return 0;
+}
+
+static int tpg_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmtdesc)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+static int tpg_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+static int tpg_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_enum_framesizes(struct v4l2_subdev *sd,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_enum_frameintervals(struct v4l2_subdev *sd,
+                                     struct v4l2_frmivalenum *fival)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+                               enum v4l2_mbus_pixelcode *code)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_try_mbus_fmt(struct v4l2_subdev *sd,
+                              struct v4l2_mbus_framefmt *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_g_mbus_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_mbus_framefmt *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_s_mbus_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_mbus_framefmt *fmt)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_g_chip_ident(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_chip_ident *chip)
+{
+       struct atomisp_tpg_device *dev;
+       dev = container_of(sd, struct atomisp_tpg_device, sd);
+
+       if (!chip)
+               return -EINVAL;
+       return 0;
+}
+
+static int tpg_log_status(struct v4l2_subdev *sd)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_s_config(struct v4l2_subdev *sd, int irq, void *platform_data)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+       /*to fake*/
+       return -EINVAL;
+}
+
+static int tpg_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       /*to fake*/
+       return -EINVAL;
+}
+
+static int tpg_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_s_power(struct v4l2_subdev *sd, int on)
+{
+       int x_delta = -2;
+       int y_delta = 3;
+       unsigned int x_mask  = (1 << 4) - 1;
+       unsigned int y_mask  = (1 << 4) - 1;
+       unsigned int xy_mask = (1 << 8) - 1;
+
+       sh_css_tpg_configure(x_mask, x_delta, y_mask, y_delta, xy_mask);
+       sh_css_input_set_mode(SH_CSS_INPUT_MODE_TPG);
+       return 0;
+}
+
+static int tpg_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_enum_frame_size(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_frame_size_enum *fse)
+{
+       /*to fake*/
+       return 0;
+}
+
+static int tpg_enum_frame_ival(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_frame_interval_enum *fie)
+{
+       /*to fake*/
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops tpg_video_ops = {
+       .s_stream = tpg_s_stream,
+       .enum_fmt = tpg_enum_fmt,
+       .try_fmt = tpg_try_fmt,
+       .g_fmt = tpg_g_fmt,
+       .s_fmt = tpg_s_fmt,
+       .g_parm = tpg_g_parm,
+       .s_parm = tpg_s_parm,
+       .enum_framesizes = tpg_enum_framesizes,
+       .enum_frameintervals = tpg_enum_frameintervals,
+       .enum_mbus_fmt = tpg_enum_mbus_fmt,
+       .try_mbus_fmt = tpg_try_mbus_fmt,
+       .g_mbus_fmt = tpg_g_mbus_fmt,
+       .s_mbus_fmt = tpg_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_core_ops tpg_core_ops = {
+       .g_chip_ident = tpg_g_chip_ident,
+       .log_status = tpg_log_status,
+       .s_config = tpg_s_config,
+       .queryctrl = tpg_queryctrl,
+       .g_ctrl = tpg_g_ctrl,
+       .s_ctrl = tpg_s_ctrl,
+       .s_power = tpg_s_power,
+};
+
+static const struct v4l2_subdev_pad_ops tpg_pad_ops = {
+       .enum_mbus_code = tpg_enum_mbus_code,
+       .enum_frame_size = tpg_enum_frame_size,
+       .enum_frame_interval = tpg_enum_frame_ival,
+};
+
+static const struct v4l2_subdev_ops tpg_ops = {
+       .core = &tpg_core_ops,
+       .video = &tpg_video_ops,
+       .pad = &tpg_pad_ops,
+};
+
+static const struct media_entity_operations tpg_entity_ops = {
+       .set_power = v4l2_subdev_set_power,
+};
+
+void atomisp_tpg_unregister_entities(struct atomisp_tpg_device *tpg)
+{
+       v4l2_device_unregister_subdev(&tpg->sd);
+}
+
+int atomisp_tpg_register_entities(struct atomisp_tpg_device *tpg,
+                       struct v4l2_device *vdev)
+{
+       int ret;
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &tpg->sd);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       atomisp_tpg_unregister_entities(tpg);
+       return ret;
+}
+
+void atomisp_tpg_cleanup(struct atomisp_device *isp)
+{
+
+}
+
+int atomisp_tpg_init(struct atomisp_device *isp)
+{
+       struct atomisp_tpg_device *tpg = &isp->tpg;
+       struct v4l2_subdev *sd = &tpg->sd;
+       struct media_pad *pads = tpg->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       tpg->isp = isp;
+       v4l2_subdev_init(sd, &tpg_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       strcpy(sd->name, "tpg_subdev");
+       v4l2_set_subdevdata(sd, tpg);
+
+       pads[0].flags = MEDIA_PAD_FLAG_INPUT;
+       me->type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
+
+       ret = media_entity_init(me, 1, pads, 0);
+       if (ret < 0)
+               goto fail;
+       return 0;
+fail:
+       atomisp_tpg_cleanup(isp);
+       return ret;
+}
diff --git a/drivers/media/video/atomisp/atomisp_tpg.h b/drivers/media/video/atomisp/atomisp_tpg.h
new file mode 100644 (file)
index 0000000..65740af
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __TPG_H__
+#define __TPG_H__
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+struct atomisp_tpg_device {
+       struct v4l2_subdev sd;
+       struct atomisp_device *isp;
+       struct media_pad pads[1];
+};
+
+void atomisp_tpg_cleanup(struct atomisp_device *isp);
+int atomisp_tpg_init(struct atomisp_device *isp);
+void atomisp_tpg_unregister_entities(struct atomisp_tpg_device *tpg);
+int atomisp_tpg_register_entities(struct atomisp_tpg_device *tpg,
+                       struct v4l2_device *vdev);
+
+#endif
diff --git a/drivers/media/video/atomisp/atomisp_v4l2.c b/drivers/media/video/atomisp/atomisp_v4l2.c
new file mode 100644 (file)
index 0000000..44c9742
--- /dev/null
@@ -0,0 +1,957 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/async.h>
+#include "atomisp_ioctl.h"
+#include "atomisp_cmd.h"
+#include "atomisp_fops.h"
+#include "atomisp_file.h"
+
+/* cross componnet debug message flag */
+int dbg_level;
+module_param(dbg_level, int, 0644);
+MODULE_PARM_DESC(dbg_level, "debug message on/off (default:off)");
+
+int mipicsi_flag;
+module_param(mipicsi_flag, int, 0644);
+MODULE_PARM_DESC(mipicsi_flag, "mipi csi compression predictor algorithm");
+
+int pad_w = 8;
+module_param(pad_w, int, 0644);
+MODULE_PARM_DESC(pad_w, "extra data for ISP processing");
+
+int pad_h = 10;
+module_param(pad_h, int, 0644);
+MODULE_PARM_DESC(pad_h, "extra data for ISP processing");
+
+struct v4l2_device atomisp_dev = {
+       .name = "atomisp",
+};
+
+void __iomem *atomisp_io_base;
+
+/*
+ * supported V4L2 fmts and resolutions
+ */
+const struct atomisp_format_bridge atomisp_output_fmts[] = {
+       {
+               .pixelformat = V4L2_PIX_FMT_YUV420,
+               .depth = 12,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_YUV420,
+               .description = "YUV420, planner"},
+       {
+               .pixelformat = V4L2_PIX_FMT_YVU420,
+               .depth = 12,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_YV12,
+               .description = "YVU420, planner"},
+       {
+               .pixelformat = V4L2_PIX_FMT_YUV422P,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_YUV422,
+               .description = "YUV422, planner"},
+       {
+               .pixelformat = V4L2_PIX_FMT_YUV444,
+               .depth = 24,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_YUV444,
+               .description = "YUV444"},
+       {
+               .pixelformat = V4L2_PIX_FMT_NV12,
+               .depth = 12,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_NV12,
+               .description = "NV12, interleaved"},
+       {
+               .pixelformat = V4L2_PIX_FMT_NV21,
+               .depth = 12,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_NV21,
+               .description = "NV21, interleaved"},
+       {
+               .pixelformat = V4L2_PIX_FMT_NV16,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_NV16,
+               .description = "NV16, interleaved"},
+       {
+               .pixelformat = V4L2_PIX_FMT_YUYV,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_YUYV,
+               .description = "YUYV, interleaved"},
+       {
+               .pixelformat = V4L2_PIX_FMT_UYVY,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_UYVY,
+               .description = "UYVY, interleaved"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SBGGR16,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 16"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .depth = 8,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 8"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGBRG8,
+               .depth = 8,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 8"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGRBG8,
+               .depth = 8,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 8"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SRGGB8,
+               .depth = 8,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 8"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SBGGR10,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 10"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGBRG10,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 10"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGRBG10,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 10"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SRGGB10,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 10"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SBGGR12,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 12"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGBRG12,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 12"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SGRBG12,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 12"},
+       {
+               .pixelformat = V4L2_PIX_FMT_SRGGB12,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RAW,
+               .description = "Bayer 12"},
+       {
+               .pixelformat = V4L2_PIX_FMT_RGB32,
+               .depth = 32,
+               .mbus_code = V4L2_MBUS_FMT_FIXED,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RGBA888,
+               .description = "32 RGB 8-8-8-8"},
+       {
+               .pixelformat = V4L2_PIX_FMT_RGB565,
+               .depth = 16,
+               .mbus_code = V4L2_MBUS_FMT_BGR565_2X8_LE,
+               .sh_fmt = SH_CSS_FRAME_FORMAT_RGB565,
+               .description = "16 RGB 5-6-5"}
+};
+
+const u32 atomisp_output_fmts_num = ARRAY_SIZE(atomisp_output_fmts);
+
+static struct atomisp_tvnorm tvnorms[] = {
+       {
+               .name = "atomisp format",
+               .id = V4L2_STD_NTSC_M,
+               .cxiformat = 0,
+               .cxoformat = 0x181f0008,
+       },
+       {
+               .name = "atomisp format NULL",
+               .id = V4L2_STD_NTSC_M_JP,
+               .cxiformat = 1,
+               .cxoformat = 0x181f0008,
+       }
+};
+
+static const struct video_device atomisp_video_dev = {
+       .name = "atomisp",
+       .minor = -1,
+       .fops = &atomisp_fops,
+       .release = video_device_release_empty,
+       .ioctl_ops = &atomisp_ioctl_ops
+};
+
+int atomisp_video_init(struct atomisp_video_pipe *video, const char *name)
+{
+       int ret;
+       const char *direction;
+
+       switch (video->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               direction = "output";
+               video->pad.flags = MEDIA_PAD_FLAG_INPUT;
+               video->vdev.fops = &atomisp_fops;
+               video->vdev.ioctl_ops = &atomisp_ioctl_ops;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               direction = "input";
+               video->pad.flags = MEDIA_PAD_FLAG_OUTPUT;
+               video->vdev.fops = &atomisp_file_fops;
+               video->vdev.ioctl_ops = &atomisp_file_ioctl_ops;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = media_entity_init(&video->vdev.entity, 1, &video->pad, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Initialize the video device. */
+       snprintf(video->vdev.name, sizeof(video->vdev.name),
+                "ATOMISP ISP %s %s", name, direction);
+       video->vdev.vfl_type = VFL_TYPE_GRABBER;
+       video->vdev.release = video_device_release;
+       video_set_drvdata(&video->vdev, video->isp);
+       video->opened = false;
+
+       return 0;
+}
+
+int atomisp_video_register(struct atomisp_video_pipe *video,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       video->vdev.v4l2_dev = vdev;
+
+       ret = video_register_device(&video->vdev, VFL_TYPE_GRABBER, -1);
+       if (ret < 0)
+               v4l2_err(&atomisp_dev,
+                       "%s: could not register video device (%d)\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+void atomisp_video_unregister(struct atomisp_video_pipe *video)
+{
+       if (video_is_registered(&video->vdev)) {
+               media_entity_cleanup(&video->vdev.entity);
+               video_unregister_device(&video->vdev);
+       }
+}
+
+#ifdef CONFIG_PM
+static int atomisp_runtime_suspend(struct device *dev)
+{
+       struct atomisp_device *isp = (struct atomisp_device *)
+               dev_get_drvdata(dev);
+       int ret;
+
+       /* save IUnit context */
+       atomisp_save_iunit_reg(isp);
+
+       /*Turn off the ISP power island*/
+       ret = atomisp_ospm_power_island_down(isp);
+
+       return ret;
+}
+
+static int atomisp_runtime_resume(struct device *dev)
+{
+       struct atomisp_device *isp = (struct atomisp_device *)
+               dev_get_drvdata(dev);
+       int ret;
+
+       if (isp->sw_contex.power_state == ATOM_ISP_POWER_DOWN) {
+               /*Turn on ISP power island*/
+               ret = atomisp_ospm_power_island_up(isp);
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                   "Failed to power up ISP!.\n");
+                       return -EINVAL;
+               }
+       }
+
+       /*restore register values for iUnit and iUnitPHY registers*/
+       if (isp->hw_contex.pcicmdsts)
+               atomisp_restore_iunit_reg(isp);
+       atomisp_save_iunit_reg(isp);
+
+       return 0;
+}
+
+static int atomisp_suspend(struct device *dev)
+{
+       struct atomisp_device *isp = (struct atomisp_device *)
+               dev_get_drvdata(dev);
+       int ret;
+
+       /*
+        * FIXME: Suspend is not supported by sensors. Abort if any video
+        * node was opened.
+        */
+       if (isp->sw_contex.init == true)
+               return -EBUSY;
+
+       if (isp->sw_contex.isp_streaming) {
+               v4l2_err(&atomisp_dev,
+                           "atomisp cannot suspend at this time.\n");
+               return -EINVAL;
+       }
+
+       /* save IUnit context */
+       atomisp_save_iunit_reg(isp);
+
+       /*Turn off the ISP power island*/
+       ret = atomisp_ospm_power_island_down(isp);
+       if (ret)
+               v4l2_err(&atomisp_dev,
+                           "fail to power off ISP\n");
+
+       return ret;
+}
+
+static int atomisp_resume(struct device *dev)
+{
+       struct atomisp_device *isp = (struct atomisp_device *)
+               dev_get_drvdata(dev);
+       int ret;
+
+       /*Turn on ISP power island*/
+       ret = atomisp_ospm_power_island_up(isp);
+       if (ret) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to power up ISP!.\n");
+               return -EINVAL;
+       }
+
+       /*restore register values for iUnit and iUnitPHY registers*/
+       if (isp->hw_contex.pcicmdsts)
+               atomisp_restore_iunit_reg(isp);
+       atomisp_save_iunit_reg(isp);
+
+       return 0;
+}
+#endif
+
+static int atomisp_subdev_probe(struct atomisp_device *isp)
+{
+       struct atomisp_platform_data *pdata = NULL;
+       struct intel_v4l2_subdev_table *subdevs;
+       struct v4l2_subdev *subdev = NULL;
+       struct i2c_adapter *adapter = NULL;
+       struct i2c_board_info *board_info;
+
+       pdata = (struct atomisp_platform_data *)intel_get_v4l2_subdev_table();
+       if (pdata == NULL) {
+               v4l2_err(&atomisp_dev, "no platform data available\n");
+               return -ENODEV;
+       }
+
+       for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
+               board_info = &subdevs->v4l2_subdev.board_info;
+               v4l2_info(&atomisp_dev, "name %s, addr %d, id %d\n",
+                         board_info->type,
+                         board_info->addr,
+                         subdevs->v4l2_subdev.i2c_adapter_id);
+
+               adapter = i2c_get_adapter(subdevs->v4l2_subdev.i2c_adapter_id);
+               if (adapter == NULL) {
+                       v4l2_err(&atomisp_dev,
+                                   "Failed to find i2c adapter for subdev %s\n"
+                                   , board_info->type);
+                       break;
+               }
+               v4l2_info(&atomisp_dev, "Found adapter %s for subdev %s\n",
+                        adapter->name, board_info->type);
+
+               subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
+                               board_info, NULL, 1);
+
+               if (subdev == NULL) {
+                       v4l2_info(&atomisp_dev,
+                                   "Subdev %s detection fail\n",
+                                   board_info->type);
+                       continue;
+               }
+
+               v4l2_info(&atomisp_dev,
+                           "Subdev %s successfully register\n",
+                         board_info->type);
+
+               switch (subdevs->type) {
+               case RAW_CAMERA:
+               case SOC_CAMERA:
+                       if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
+                               v4l2_warn(&atomisp_dev,
+                                       "too many atomisp inputs, ignored\n");
+                               break;
+                       }
+
+                       v4l2_info(&atomisp_dev,
+                               "still camera sensor detected\n");
+                       isp->inputs[isp->input_cnt].type = subdevs->type;
+                       isp->inputs[isp->input_cnt].port = subdevs->port;
+                       isp->inputs[isp->input_cnt].camera = subdev;
+                       isp->inputs[isp->input_cnt].shading_table = NULL;
+                       isp->inputs[isp->input_cnt].morph_table = NULL;
+                       isp->input_cnt++;
+                       break;
+               case CAMERA_MOTOR:
+                       v4l2_info(&atomisp_dev, "lens/motor probed\n");
+                       isp->motor = subdev;
+                       break;
+               case LED_FLASH:
+               case XENON_FLASH:
+                       v4l2_info(&atomisp_dev, "flash probed\n");
+                       isp->flash = subdev;
+                       break;
+               default:
+                       v4l2_info(&atomisp_dev, "unkonw subdev probed\n");
+                       break;
+               }
+
+       }
+
+       /*Check camera for at least one subdev in it */
+       if (!isp->inputs[0].camera) {
+               v4l2_info(&atomisp_dev, "atomisp: "
+                      "no camera attached or fail to detect\n");
+               return -ENODEV;
+       }
+       v4l2_info(&atomisp_dev, "%d camera(s) detect\n", isp->input_cnt);
+       return 0;
+}
+
+static void atomisp_unregister_entities(struct atomisp_device *isp)
+{
+       atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p);
+       atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p);
+       atomisp_tpg_unregister_entities(&isp->tpg);
+       atomisp_subdev_unregister_entities(&isp->isp_subdev);
+
+       v4l2_device_unregister(&isp->v4l2_dev);
+       media_device_unregister(&isp->media_dev);
+}
+
+static int atomisp_register_entities(struct atomisp_device *isp)
+{
+       int ret = 0;
+       int i = 0;
+       struct v4l2_subdev *subdev = NULL;
+       struct media_entity *input = NULL;
+       unsigned int flags;
+       unsigned int pad;
+
+       isp->media_dev.dev = isp->dev;
+
+       strlcpy(isp->media_dev.model, "Intel Atom ISP",
+               sizeof(isp->media_dev.model));
+
+       ret = media_device_register(&isp->media_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev, "%s: Media device registration "
+                        "failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       isp->v4l2_dev.mdev = &isp->media_dev;
+       ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "%s: V4L2 device registration failed (%d)\n",
+                       __func__, ret);
+               goto v4l2_device_failed;
+       }
+
+       ret = atomisp_subdev_probe(isp);
+       if (ret < 0)
+               goto lane4_and_subdev_probe_failed;
+
+       /* Register internal entities */
+       ret =
+       atomisp_mipi_csi2_register_entities(&isp->csi2_4p, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "atomisp_mipi_csi2_register_entities 4p\n");
+               goto lane4_and_subdev_probe_failed;
+       }
+
+       ret =
+       atomisp_mipi_csi2_register_entities(&isp->csi2_1p, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "atomisp_mipi_csi2_register_entities 1p\n");
+               goto lane1_failed;
+       }
+
+       ret =
+       atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "atomisp_file_input_register_entities\n");
+               goto file_input_register_failed;
+       }
+
+       ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n");
+               goto tpg_register_failed;
+       }
+
+       ret =
+       atomisp_subdev_register_entities(&isp->isp_subdev, &isp->v4l2_dev);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "atomisp_subdev_register_entities fail\n");
+               goto subdev_register_failed;
+       }
+
+       for (i = 0; i < isp->input_cnt; i++) {
+               subdev = isp->inputs[i].camera;
+               switch (isp->inputs[i].port) {
+               case ATOMISP_CAMERA_PORT_PRIMARY:
+                       input = &isp->csi2_4p.subdev.entity;
+                       pad = CSI2_PAD_SINK;
+                       flags = 0;
+                       break;
+               case ATOMISP_CAMERA_PORT_SECONDARY:
+                       input = &isp->csi2_1p.subdev.entity;
+                       pad = CSI2_PAD_SINK;
+                       flags = 0;
+                       break;
+               default:
+                       v4l2_info(&atomisp_dev,
+                                 "isp->inputs type not supported\n");
+                       break;
+               }
+               ret = media_entity_create_link(&subdev->entity, 0,
+                       input, pad, flags);
+               if (ret < 0) {
+                       v4l2_err(&atomisp_dev,
+                               "snr to mipi csi link failed\n");
+                       goto link_failed;
+               }
+       }
+
+       v4l2_info(&atomisp_dev,
+               "FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt);
+       isp->inputs[isp->input_cnt].type = FILE_INPUT;
+       isp->inputs[isp->input_cnt].port = -1;
+       isp->inputs[isp->input_cnt].shading_table = NULL;
+       isp->inputs[isp->input_cnt].morph_table = NULL;
+       isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd;
+
+       if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
+               v4l2_info(&atomisp_dev,
+                       "TPG detected, camera_cnt: %d\n", isp->input_cnt);
+               isp->inputs[isp->input_cnt].type = TEST_PATTERN;
+               isp->inputs[isp->input_cnt].port = -1;
+               isp->inputs[isp->input_cnt].shading_table = NULL;
+               isp->inputs[isp->input_cnt].morph_table = NULL;
+               isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
+       } else {
+               v4l2_warn(&atomisp_dev,
+                       "too many atomisp inputs, TPG ignored.\n");
+       }
+
+       return ret;
+
+link_failed:
+       atomisp_subdev_unregister_entities(&isp->isp_subdev);
+subdev_register_failed:
+       atomisp_tpg_unregister_entities(&isp->tpg);
+tpg_register_failed:
+       atomisp_file_input_unregister_entities(&isp->file_dev);
+file_input_register_failed:
+       atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p);
+lane1_failed:
+       atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p);
+lane4_and_subdev_probe_failed:
+       v4l2_device_unregister(&isp->v4l2_dev);
+v4l2_device_failed:
+       media_device_unregister(&isp->media_dev);
+       return ret;
+}
+
+static int atomisp_initialize_modules(struct atomisp_device *isp)
+{
+       int ret;
+
+       ret = atomisp_mipi_csi2_init(isp);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev, "mipi csi2 initialization failed\n");
+               goto error_mipi_csi2;
+       }
+
+       ret = atomisp_file_input_init(isp);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev,
+                       "file input device initialization failed\n");
+               goto error_file_input;
+       }
+
+       ret = atomisp_tpg_init(isp);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev, "tpg initialization failed\n");
+               goto error_tpg;
+       }
+
+       ret = atomisp_subdev_init(isp);
+       if (ret < 0) {
+               v4l2_err(&atomisp_dev, "ISP subdev initialization failed\n");
+               goto error_isp_subdev;
+       }
+
+       /* connet submoduels */
+       ret = media_entity_create_link(
+                       &isp->csi2_4p.subdev.entity,
+                       CSI2_PAD_SOURCE,
+                       &isp->isp_subdev.subdev.entity,
+                       ATOMISP_SUBDEV_PAD_SINK,
+                       0);
+       if (ret < 0)
+               goto error_link;
+       ret = media_entity_create_link(
+                       &isp->csi2_1p.subdev.entity,
+                       CSI2_PAD_SOURCE,
+                       &isp->isp_subdev.subdev.entity,
+                       ATOMISP_SUBDEV_PAD_SINK,
+                       0);
+       if (ret < 0)
+               goto error_link;
+       return 0;
+
+error_link:
+error_isp_subdev:
+       atomisp_subdev_cleanup(isp);
+error_tpg:
+       atomisp_tpg_cleanup(isp);
+error_file_input:
+       atomisp_file_input_cleanup(isp);
+error_mipi_csi2:
+       atomisp_mipi_csi2_cleanup(isp);
+       return ret;
+}
+
+static const struct firmware *
+load_firmware(struct device *dev)
+{
+       const struct firmware *fw;
+       int rc;
+
+       v4l2_info(&atomisp_dev, "loading ISP firmware ...\n");
+
+       rc = request_firmware(&fw, FW_PATH, dev);
+       if (rc) {
+               if (rc == -ENOENT)
+                       v4l2_info(&atomisp_dev,
+                                   "Error ISP firmware %s not found.\n",
+                                   FW_PATH);
+               else
+                       v4l2_info(&atomisp_dev,
+                                   "atomisp: Error %d while requesting"
+                                   " firmware %s\n", rc, FW_PATH);
+               return NULL;
+       }
+
+       if (fw->data != NULL) {
+               v4l2_info(&atomisp_dev,
+                           "isp_fw_file info: file:%p, size:%x\n",
+                           fw->data, fw->size);
+       } else {
+               return NULL;
+       }
+
+       v4l2_info(&atomisp_dev, "loading isp firmware ... done\n");
+       return fw;
+}
+
+static struct pci_driver atomisp_pci_driver;
+static int __devinit atomisp_pci_probe(struct pci_dev *dev,
+                                       const struct pci_device_id *id)
+{
+       struct atomisp_device *isp = NULL;
+       unsigned int start, len;
+       void __iomem *base = NULL;
+       int err;
+       uint32_t ispmmadr;
+
+       if (!dev) {
+               v4l2_err(&atomisp_dev, "atomisp: erorr device ptr\n");
+               return -EINVAL;
+       }
+
+       err = pci_enable_device(dev);
+       if (err) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to enable CI ISP device\n");
+               return err;
+       }
+
+       start = pci_resource_start(dev, 0);
+       len = pci_resource_len(dev, 0);
+
+       /*
+        * Read ISP memory base address from Iunit register ISPMMADR  message
+        * bus port 0x08, offset 0x04
+        */
+       ispmmadr = atomisp_msg_read32(isp, IUNIT_PORT, ISPMMADR);
+       ispmmadr &= 0xFFC00000;
+       if (start != ispmmadr) {
+               start = ispmmadr;
+               len = 0x400000;
+       }
+       v4l2_info(&atomisp_dev,
+                   "ATOM ISP resource start 0x%x, len %d\n",
+                   start, len);
+
+       err = pci_request_region(dev, 0, atomisp_pci_driver.name);
+       if (err) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to request region 0x%1x-0x%Lx\n",
+                           start, (unsigned long long)pci_resource_end(dev,
+                               0));
+               goto request_region_fail;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to I/O memory remapping\n");
+               err = -ENOMEM;
+               goto ioremap_fail;
+       }
+
+       isp = kzalloc(sizeof(struct atomisp_device), GFP_KERNEL);
+       if (!isp) {
+               v4l2_err(&atomisp_dev, "Failed to alloc CI ISP structure\n");
+               goto kzalloc_fail;
+       }
+       isp->sw_contex.probed = false;
+       isp->sw_contex.init = false;
+       isp->pdev = dev;
+       isp->dev = &dev->dev;
+       isp->sw_contex.power_state = ATOM_ISP_POWER_UP;
+       isp->hw_contex.pci_dev = pci_get_bus_and_slot(0, 0);
+
+       /* Load isp firmware from user space */
+       isp->firmware = load_firmware(&dev->dev);
+       if (!isp->firmware) {
+               v4l2_err(&atomisp_dev, "Load firmwares failed\n");
+               goto load_fw_fail;
+       }
+
+       err = atomisp_initialize_modules(isp);
+       if (err < 0) {
+               v4l2_err(&atomisp_dev, "atomisp_initialize_modules\n");
+               goto init_mod_fail;
+       }
+
+       err = atomisp_register_entities(isp);
+       if (err < 0) {
+               v4l2_err(&atomisp_dev, "atomisp_register_entities failed\n");
+               goto init_mod_fail;
+       }
+
+       init_completion(&isp->wq_frame_complete);
+       init_completion(&isp->dis_state_complete);
+       spin_lock_init(&isp->irq_lock);
+
+       isp->work_queue = create_singlethread_workqueue(isp->v4l2_dev.name);
+       if (isp->work_queue == NULL) {
+               v4l2_err(&atomisp_dev, "Failed to initialize work queue\n");
+               goto work_queue_fail;
+       }
+       INIT_WORK(&isp->work, atomisp_work);
+
+       isp->hw_contex.ispmmadr = ispmmadr;
+       v4l2_info(&atomisp_dev, "isp memory address = %x\n",
+                   isp->hw_contex.ispmmadr);
+
+       pci_set_master(dev);
+       atomisp_io_base = base;
+       v4l2_info(&atomisp_dev, "ATOM ISP base address %p\n", base);
+
+       isp->tvnorm = tvnorms;
+       mutex_init(&isp->input_lock);
+       /* isp_lock is to protect race access of css functions */
+       mutex_init(&isp->isp_lock);
+       mutex_init(&isp->isp3a_lock);
+       isp->sw_contex.updating_uptr = false;
+       isp->isp3a_stat_ready = false;
+
+       pci_set_drvdata(dev, isp);
+
+       err = pci_enable_msi(dev);
+       if (err) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to enable msi\n");
+               goto enable_msi_fail;
+       }
+       err = request_irq(dev->irq, atomisp_isr,
+                         IRQF_SHARED, "isp_irq", isp);
+       if (err) {
+               v4l2_err(&atomisp_dev,
+                           "Failed to request irq\n");
+               goto request_irq_fail;
+       }
+       atomisp_msi_irq_init(isp, dev);
+
+#ifdef CONFIG_PM
+       pm_runtime_set_active(&dev->dev);
+       pm_runtime_enable(&dev->dev);
+       pm_runtime_put_sync(&dev->dev);
+#endif
+       isp->sw_contex.probed = true;
+
+       return 0;
+
+request_irq_fail:
+       pci_disable_msi(dev);
+enable_msi_fail:
+       pci_set_drvdata(dev, NULL);
+       destroy_workqueue(isp->work_queue);
+work_queue_fail:
+       atomisp_unregister_entities(isp);
+init_mod_fail:
+       release_firmware(isp->firmware);
+load_fw_fail:
+       kfree(isp);
+kzalloc_fail:
+       iounmap(base);
+ioremap_fail:
+       pci_release_region(dev, 0);
+request_region_fail:
+       pci_disable_device(dev);
+       return err;
+}
+
+static void __devexit atomisp_pci_remove(struct pci_dev *dev)
+{
+       struct atomisp_device *isp = (struct atomisp_device *)
+               pci_get_drvdata(dev);
+
+       atomisp_msi_irq_uninit(isp, dev);
+       free_irq(dev->irq, isp);
+       pci_disable_msi(dev);
+       pci_dev_put(isp->hw_contex.pci_dev);
+
+       atomisp_unregister_entities(isp);
+
+       flush_workqueue(isp->work_queue);
+       destroy_workqueue(isp->work_queue);
+
+       iounmap(atomisp_io_base);
+       pci_set_drvdata(dev, NULL);
+       pci_release_region(dev, 0);
+       pci_disable_device(dev);
+
+       /* in case user forget to close */
+       release_firmware(isp->firmware);
+       isp->pdev = NULL;
+       kfree(isp);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(atomisp_pci_tbl) = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0148)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0149)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014A)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014B)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014C)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014D)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014E)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x014F)},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, atomisp_pci_tbl);
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops atomisp_pm_ops = {
+       .runtime_suspend = atomisp_runtime_suspend,
+       .runtime_resume = atomisp_runtime_resume,
+       .suspend = atomisp_suspend,
+       .resume = atomisp_resume,
+};
+
+#define DEV_PM_OPS (&atomisp_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+static struct pci_driver atomisp_pci_driver = {
+       .driver = {
+               .pm = DEV_PM_OPS,
+       },
+       .name = "atomisp",
+       .id_table = atomisp_pci_tbl,
+       .probe = atomisp_pci_probe,
+       .remove = atomisp_pci_remove,
+};
+
+static int __init atomisp_init(void)
+{
+       v4l2_info(&atomisp_dev, "Init ATOM ISP device driver,"
+                   " version: %s-%x\n", DRIVER_VERSION_STR, MAGIC_NUMBER);
+       return pci_register_driver(&atomisp_pci_driver);
+}
+
+static void __exit atomisp_exit(void)
+{
+       v4l2_info(&atomisp_dev, "Exit ATOM ISP device driver\n");
+       pci_unregister_driver(&atomisp_pci_driver);
+}
+
+late_initcall_async(atomisp_init);
+module_exit(atomisp_exit);
+
+MODULE_AUTHOR("Wen Wang <wen.w.wang@intel.com>");
+MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel ATOM Platform ISP Driver");
diff --git a/drivers/media/video/atomisp/css/hrt/bits.h b/drivers/media/video/atomisp/css/hrt/bits.h
new file mode 100644 (file)
index 0000000..321dff8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HRT_BITS_H_
+#define _HRT_BITS_H_
+
+#include "defs.h"
+
+#define _hrt_ones(n) HRTCAT(_hrt_ones_, n)
+#define _hrt_ones_0x0  0x00000000U
+#define _hrt_ones_0x1  0x00000001U
+#define _hrt_ones_0x2  0x00000003U
+#define _hrt_ones_0x3  0x00000007U
+#define _hrt_ones_0x4  0x0000000FU
+#define _hrt_ones_0x5  0x0000001FU
+#define _hrt_ones_0x6  0x0000003FU
+#define _hrt_ones_0x7  0x0000007FU
+#define _hrt_ones_0x8  0x000000FFU
+#define _hrt_ones_0x9  0x000001FFU
+#define _hrt_ones_0xA  0x000003FFU
+#define _hrt_ones_0xB  0x000007FFU
+#define _hrt_ones_0xC  0x00000FFFU
+#define _hrt_ones_0xD  0x00001FFFU
+#define _hrt_ones_0xE  0x00003FFFU
+#define _hrt_ones_0xF  0x00007FFFU
+#define _hrt_ones_0x10 0x0000FFFFU
+#define _hrt_ones_0x11 0x0001FFFFU
+#define _hrt_ones_0x12 0x0003FFFFU
+#define _hrt_ones_0x13 0x0007FFFFU
+#define _hrt_ones_0x14 0x000FFFFFU
+#define _hrt_ones_0x15 0x001FFFFFU
+#define _hrt_ones_0x16 0x003FFFFFU
+#define _hrt_ones_0x17 0x007FFFFFU
+#define _hrt_ones_0x18 0x00FFFFFFU
+#define _hrt_ones_0x19 0x01FFFFFFU
+#define _hrt_ones_0x1A 0x03FFFFFFU
+#define _hrt_ones_0x1B 0x07FFFFFFU
+#define _hrt_ones_0x1C 0x0FFFFFFFU
+#define _hrt_ones_0x1D 0x1FFFFFFFU
+#define _hrt_ones_0x1E 0x3FFFFFFFU
+#define _hrt_ones_0x1F 0x7FFFFFFFU
+#define _hrt_ones_0x20 0xFFFFFFFFU
+
+#define _hrt_ones_0  _hrt_ones_0x0
+#define _hrt_ones_1  _hrt_ones_0x1
+#define _hrt_ones_2  _hrt_ones_0x2
+#define _hrt_ones_3  _hrt_ones_0x3
+#define _hrt_ones_4  _hrt_ones_0x4
+#define _hrt_ones_5  _hrt_ones_0x5
+#define _hrt_ones_6  _hrt_ones_0x6
+#define _hrt_ones_7  _hrt_ones_0x7
+#define _hrt_ones_8  _hrt_ones_0x8
+#define _hrt_ones_9  _hrt_ones_0x9
+#define _hrt_ones_10 _hrt_ones_0xA
+#define _hrt_ones_11 _hrt_ones_0xB
+#define _hrt_ones_12 _hrt_ones_0xC
+#define _hrt_ones_13 _hrt_ones_0xD
+#define _hrt_ones_14 _hrt_ones_0xE
+#define _hrt_ones_15 _hrt_ones_0xF
+#define _hrt_ones_16 _hrt_ones_0x10
+#define _hrt_ones_17 _hrt_ones_0x11
+#define _hrt_ones_18 _hrt_ones_0x12
+#define _hrt_ones_19 _hrt_ones_0x13
+#define _hrt_ones_20 _hrt_ones_0x14
+#define _hrt_ones_21 _hrt_ones_0x15
+#define _hrt_ones_22 _hrt_ones_0x16
+#define _hrt_ones_23 _hrt_ones_0x17
+#define _hrt_ones_24 _hrt_ones_0x18
+#define _hrt_ones_25 _hrt_ones_0x19
+#define _hrt_ones_26 _hrt_ones_0x1A
+#define _hrt_ones_27 _hrt_ones_0x1B
+#define _hrt_ones_28 _hrt_ones_0x1C
+#define _hrt_ones_29 _hrt_ones_0x1D
+#define _hrt_ones_30 _hrt_ones_0x1E
+#define _hrt_ones_31 _hrt_ones_0x1F
+#define _hrt_ones_32 _hrt_ones_0x20
+
+#define _hrt_mask(b, n) \
+       (_hrt_ones(n) << (b))
+#define _hrt_get_bits(w, b, n) \
+       (((w) >> (b)) & _hrt_ones(n))
+#define _hrt_set_bits(w, b, n, v) \
+       (((w) & ~_hrt_mask(b, n)) | (((v) & _hrt_ones(n)) << (b)))
+#define _hrt_get_bit(w, b) \
+       (((w) >> (b)) & 1)
+#define _hrt_set_bit(w, b, v) \
+       (((w) & (~(1 << (b)))) | (((v)&1) << (b)))
+#define _hrt_set_lower_half(w, v) \
+       _hrt_set_bits(w, 0, 16, v)
+#define _hrt_set_upper_half(w, v) \
+       _hrt_set_bits(w, 16, 16, v)
+
+#endif /* _HRT_BITS_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/cell_params.h b/drivers/media/video/atomisp/css/hrt/cell_params.h
new file mode 100644 (file)
index 0000000..eabfc9f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _cell_params_h
+#define _cell_params_h
+
+#define SP_PMEM_LOG_WIDTH_BITS           6  /*Width of PC, 64 bits, 8 bytes*/
+#define SP_ICACHE_TAG_BITS               4  /*size of tag*/
+#define SP_ICACHE_SET_BITS               8  /* 256 sets*/
+#define SP_ICACHE_BLOCKS_PER_SET_BITS    1  /* 2 way associative*/
+#define SP_ICACHE_BLOCK_ADDRESS_BITS     11 /* 2048 lines capacity*/
+
+#define SP_ICACHE_ADDRESS_BITS \
+                       (SP_ICACHE_TAG_BITS+SP_ICACHE_BLOCK_ADDRESS_BITS)
+
+#define SP_PMEM_DEPTH        (1<<SP_ICACHE_ADDRESS_BITS)
+
+#define SP_FIFO_0_DEPTH      0
+#define SP_FIFO_1_DEPTH      0
+#define SP_FIFO_2_DEPTH      0
+#define SP_FIFO_3_DEPTH      0
+#define SP_FIFO_4_DEPTH      0
+#define SP_FIFO_5_DEPTH      0
+#define SP_FIFO_6_DEPTH      0
+#define SP_FIFO_7_DEPTH      0
+
+
+#define SP_SLV_BUS_MAXBURSTSIZE        1
+
+#endif /* _cell_params_h */
+
diff --git a/drivers/media/video/atomisp/css/hrt/css_receiver_ahb_defs.h b/drivers/media/video/atomisp/css/hrt/css_receiver_ahb_defs.h
new file mode 100644 (file)
index 0000000..5235e89
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _css_receiver_ahb_defs_h_
+#define _css_receiver_ahb_defs_h_
+
+#define CSS_RECEIVER_DATA_WIDTH                8
+#define CSS_RECEIVER_RX_TRIG                   4
+#define CSS_RECEIVER_RF_WORD                  32
+#define CSS_RECEIVER_IMG_PROC_RF_ADDR         10
+#define CSS_RECEIVER_CSI_RF_ADDR               4
+#define CSS_RECEIVER_DATA_OUT                 12
+#define CSS_RECEIVER_CHN_NO                    2
+#define CSS_RECEIVER_DWORD_CNT                11
+#define CSS_RECEIVER_FORMAT_TYP                5
+#define CSS_RECEIVER_HRESPONSE                 2
+#define CSS_RECEIVER_STATE_WIDTH               3
+#define CSS_RECEIVER_FIFO_DAT                 32
+#define CSS_RECEIVER_CNT_VAL                   2
+#define CSS_RECEIVER_PRED10_VAL               10
+#define CSS_RECEIVER_PRED12_VAL               12
+#define CSS_RECEIVER_CNT_WIDTH                 8
+#define CSS_RECEIVER_WORD_CNT                 16
+#define CSS_RECEIVER_PIXEL_LEN                 6
+#define CSS_RECEIVER_PIXEL_CNT                 5
+#define CSS_RECEIVER_COMP_8_BIT                8
+#define CSS_RECEIVER_COMP_7_BIT                7
+#define CSS_RECEIVER_COMP_6_BIT                6
+#define CSS_RECEIVER_GEN_SHORT_DATA_WIDTH     16
+#define CSS_RECEIVER_GEN_SHORT_CH_ID_WIDTH     2
+#define CSS_RECEIVER_GEN_SHORT_FMT_TYPE_WIDTH  3
+#define CSS_RECEIVER_GEN_SHORT_STR_REAL_WIDTH \
+       (CSS_RECEIVER_GEN_SHORT_DATA_WIDTH + \
+        CSS_RECEIVER_GEN_SHORT_CH_ID_WIDTH + \
+        CSS_RECEIVER_GEN_SHORT_FMT_TYPE_WIDTH)
+/* use 32 to be compatible with streaming monitor!
+ * MSB's of interface are tied to '0'.
+ */
+#define CSS_RECEIVER_GEN_SHORT_STR_WIDTH      32
+
+/* division of gen_short data, ch_id and fmt_type over
+ * streaming data interface.
+ */
+#define CSS_RECEIVER_GEN_SHORT_STR_DATA_BIT_LSB     0
+#define CSS_RECEIVER_GEN_SHORT_STR_FMT_TYPE_BIT_LSB \
+       (CSS_RECEIVER_GEN_SHORT_STR_DATA_BIT_LSB + \
+        CSS_RECEIVER_GEN_SHORT_DATA_WIDTH)
+#define CSS_RECEIVER_GEN_SHORT_STR_CH_ID_BIT_LSB \
+       (CSS_RECEIVER_GEN_SHORT_STR_FMT_TYPE_BIT_LSB + \
+        CSS_RECEIVER_GEN_SHORT_FMT_TYPE_WIDTH)
+#define CSS_RECEIVER_GEN_SHORT_STR_DATA_BIT_MSB \
+       (CSS_RECEIVER_GEN_SHORT_STR_FMT_TYPE_BIT_LSB - 1)
+#define CSS_RECEIVER_GEN_SHORT_STR_FMT_TYPE_BIT_MSB \
+       (CSS_RECEIVER_GEN_SHORT_STR_CH_ID_BIT_LSB - 1)
+#define CSS_RECEIVER_GEN_SHORT_STR_CH_ID_BIT_MSB \
+       (CSS_RECEIVER_GEN_SHORT_STR_REAL_WIDTH - 1)
+
+#define _HRT_CSS_RECEIVER_AHB_REG_ALIGN 4
+
+#define hrt_css_receiver_ahb_4_lane_port_offset 0x100
+#define hrt_css_receiver_ahb_1_lane_port_offset 0x200
+
+#define _HRT_CSS_RECEIVER_AHB_DEVICE_READY_REG_IDX      0
+#define _HRT_CSS_RECEIVER_AHB_IRQ_STATUS_REG_IDX        1
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ENABLE_REG_IDX        2
+#define _HRT_CSS_RECEIVER_AHB_CSI2_FUNC_PROG_REG_IDX    3
+#define _HRT_CSS_RECEIVER_AHB_INIT_COUNT_REG_IDX        4
+#define _HRT_CSS_RECEIVER_AHB_COMP_FORMAT_REG_IDX       5
+#define _HRT_CSS_RECEIVER_AHB_COMP_PREDICT_REG_IDX      6
+#define _HRT_CSS_RECEIVER_AHB_FS_TO_LS_DELAY_REG_IDX    7
+#define _HRT_CSS_RECEIVER_AHB_LS_TO_DATA_DELAY_REG_IDX  8
+#define _HRT_CSS_RECEIVER_AHB_DATA_TO_LE_DELAY_REG_IDX  9
+#define _HRT_CSS_RECEIVER_AHB_LE_TO_FE_DELAY_REG_IDX   10
+#define _HRT_CSS_RECEIVER_AHB_FE_TO_FS_DELAY_REG_IDX   11
+#define _HRT_CSS_RECEIVER_AHB_LE_TO_LS_DELAY_REG_IDX   12
+#define _HRT_CSS_RECEIVER_AHB_TWO_PIXEL_EN_REG_IDX     13
+
+/* Interrupt bits for IRQ_STATUS and IRQ_ENABLE registers */
+#define _HRT_CSS_RECEIVER_AHB_IRQ_OVERRUN_BIT                0
+#define _HRT_CSS_RECEIVER_AHB_IRQ_RESERVED_BIT               1
+#define _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_ENTRY_BIT       2
+#define _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_EXIT_BIT        3
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_HS_BIT             4
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_SYNC_HS_BIT        5
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CONTROL_BIT            6
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_DOUBLE_BIT         7
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_CORRECTED_BIT      8
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_NO_CORRECTION_BIT  9
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CRC_BIT               10
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ID_BIT                11
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_SYNC_BIT        12
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_DATA_BIT        13
+#define _HRT_CSS_RECEIVER_AHB_IRQ_DATA_TIMEOUT_BIT          14
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ESCAPE_BIT            15
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_LINE_SYNC_BIT         16
+
+#define _HRT_CSS_RECEIVER_AHB_IRQ_OVERRUN_CAUSE_\
+       "Fifo Overrun"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_RESERVED_CAUSE_ \
+       "Reserved"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_ENTRY_CAUSE_ \
+       "Sleep mode entry"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_EXIT_CAUSE_ \
+       "Sleep mode exit"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_HS_CAUSE_ \
+       "Error high speed SOT"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_SYNC_HS_CAUSE_ \
+       "Error high speed sync SOT"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CONTROL_CAUSE_ \
+       "Error control"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_DOUBLE_CAUSE_ \
+       "Error correction double bit"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_CORRECTED_CAUSE_ \
+       "Error correction single bit"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_NO_CORRECTION_CAUSE_ \
+       "No error"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CRC_CAUSE_ \
+       "Error cyclic redundancy check"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ID_CAUSE_ \
+       "Error id"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_SYNC_CAUSE_ \
+       "Error frame sync"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_DATA_CAUSE_ \
+       "Error frame data"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_DATA_TIMEOUT_CAUSE_ \
+       "Data time-out"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ESCAPE_CAUSE_ \
+       "Error escape"
+#define _HRT_CSS_RECEIVER_AHB_IRQ_ERR_LINE_SYNC_CAUSE_ \
+       "Error line sync"
+
+/* Bits for CSI2_FUNC_PROG register */
+#define _HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_IDX  0
+#define _HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_BITS 3
+#define _HRT_CSS_RECEIVER_AHB_CSI2_DATA_TIMEOUT_IDX  \
+       (_HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_IDX + \
+        _HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_BITS)
+#define _HRT_CSS_RECEIVER_AHB_CSI2_DATA_TIMEOUT_BITS   29
+
+/* Bits for INIT_COUNT register */
+#define _HRT_CSS_RECEIVER_AHB_INIT_TIMER_IDX  0
+#define _HRT_CSS_RECEIVER_AHB_INIT_TIMER_BITS 16
+
+/* Bits for COMP_FORMAT register, this selects the compression data format */
+#define _HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_IDX  0
+#define _HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_BITS 8
+#define _HRT_CSS_RECEIVER_AHB_COMP_NUM_BITS_IDX \
+       (_HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_IDX + \
+        _HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_BITS)
+#define _HRT_CSS_RECEIVER_AHB_COMP_NUM_BITS_BITS 8
+
+/* Bits for COMP_PREDICT register, this selects the predictor algorithm */
+#define _HRT_CSS_RECEIVER_AHB_PREDICT_NO_COMP 0
+#define _HRT_CSS_RECEIVER_AHB_PREDICT_1       1
+#define _HRT_CSS_RECEIVER_AHB_PREDICT_2       2
+
+/* Number of bits used for the delay registers */
+#define _HRT_CSS_RECEIVER_AHB_DELAY_BITS 8
+
+/* These hsync and vsync values are for HSS simulation only */
+#define _HRT_CSS_RECEIVER_AHB_HSYNC_VAL (1<<16)
+#define _HRT_CSS_RECEIVER_AHB_VSYNC_VAL (1<<17)
+
+/* Definition of format_types */
+/* !! Changes here should be copied to
+ * systems/isp/isp_css/bin/conv_transmitter_cmd.tcl !!
+ */
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RGB888           0
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RGB555           1
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RGB444           2
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RGB565           3
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RGB666           4
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW8             5
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW10            6
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW6             7
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW7             8
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW12            9
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_RAW14           10
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV420_8        11
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV420_10       12
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV422_8        13
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV422_10       14
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_1       15
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV420_8L       16
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_Emb             17
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_2       18
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_3       19
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_4       20
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_5       21
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_6       22
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_7       23
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_USR_DEF_8       24
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV420_8_CSPS   25
+#define _HRT_CSS_RECEIVER_AHB_FMT_TYPE_YUV420_10_CSPS  26
+
+#endif /* _css_receiver_ahb_defs_h_ */
diff --git a/drivers/media/video/atomisp/css/hrt/defs.h b/drivers/media/video/atomisp/css/hrt/defs.h
new file mode 100644 (file)
index 0000000..f95c33e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HRT_DEFS_H_
+#define _HRT_DEFS_H_
+
+#ifndef HRTCAT
+#define _HRTCAT(m, n)     m##n
+#define HRTCAT(m, n)      _HRTCAT(m, n)
+#endif
+
+#ifndef HRTSTR
+#define _HRTSTR(x)   #x
+#define HRTSTR(x)    _HRTSTR(x)
+#endif
+
+#ifndef HRTMIN
+#define HRTMIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef HRTMAX
+#define HRTMAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#endif /* _HRT_DEFS_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/dma_v1_defs.h b/drivers/media/video/atomisp/css/hrt/dma_v1_defs.h
new file mode 100644 (file)
index 0000000..ba7b7ea
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _dma_v1_defs_h
+#define _dma_v1_defs_h
+
+/* if this file is included from a C source file, you need to include
+ * <hrt/bits.h> first. We cannot include that here because this file is
+ * also included from CHDL sources which do not have access to HRT.
+ */
+#define _DMA_V1_NUM_CHANNELS_ID               MaxNumChannels
+#define _DMA_V1_CONNECTIONS_ID                Connections
+#define _DMA_V1_DEV_ELEM_WIDTHS_ID            DevElemWidths
+#define _DMA_V1_DEV_FIFO_DEPTH_ID             DevFifoDepth
+#define _DMA_V1_DEV_FIFO_RD_LAT_ID            DevFifoRdLat
+#define _DMA_V1_DEV_FIFO_LAT_BYPASS_ID        DevFifoRdLatBypass
+#define _DMA_V1_DEV_2_CIO_ID                  DevConnectedToCIO
+#define _DMA_V1_DEV_HAS_CRUN_ID               CRunMasters
+#define _DMA_V1_CONN_GROUPS_ID                ConnectionGroups
+#define _DMA_V1_CONN_GROUP_FIFO_DEPTH_ID      ConnectionGroupFifoDepth
+#define _DMA_V1_CONN_GROUP_FIFO_RD_LAT_ID     ConnectionGroupFifoRdLat
+#define _DMA_V1_CONN_GROUP_FIFO_LAT_BYPASS_ID ConnectionGroupFifoRdLatBypass
+
+#define _DMA_V1_REG_ALIGN                4
+#define _DMA_V1_REG_ADDR_BITS            2
+
+/* Command word */
+#define _DMA_CMD_IDX         0
+#define _DMA_CMD_BITS        4
+#define _DMA_CHANNEL_IDX     (_DMA_CMD_IDX + _DMA_CMD_BITS)
+#define _DMA_CHANNEL_BITS    8
+#define _DMA_PARAM_IDX       (_DMA_CHANNEL_IDX + _DMA_CHANNEL_BITS)
+#define _DMA_PARAM_BITS      4
+#define _DMA_CRUN_IDX        (_DMA_PARAM_IDX + _DMA_PARAM_BITS)
+#define _DMA_CRUN_BITS       1
+
+/* Packing setup word */
+#define _DMA_CONNECTION_IDX  0
+#define _DMA_CONNECTION_BITS 8
+#define _DMA_EXTENSION_IDX   (_DMA_CONNECTION_IDX + _DMA_CONNECTION_BITS)
+#define _DMA_EXTENSION_BITS  4
+#define _DMA_ELEM_ORDER_IDX  (_DMA_EXTENSION_IDX + _DMA_EXTENSION_BITS)
+#define _DMA_ELEM_ORDER_BITS 4
+
+/* Elements packing word */
+#define _DMA_ELEMENTS_IDX        0
+#define _DMA_ELEMENTS_BITS      12
+#define _DMA_LEFT_CROPPING_IDX  (_DMA_ELEMENTS_IDX + _DMA_ELEMENTS_BITS)
+#define _DMA_LEFT_CROPPING_BITS 12
+
+#define _DMA_WIDTH_IDX   0
+#define _DMA_WIDTH_BITS 16
+
+#define _DMA_HEIGHT_IDX   0
+#define _DMA_HEIGHT_BITS 16
+
+#define _DMA_STRIDE_IDX   0
+#define _DMA_STRIDE_BITS 32
+
+/* Command IDs */
+#define _DMA_READ_COMMAND              0
+#define _DMA_WRITE_COMMAND             1
+#define _DMA_CONFIG_CHANNEL_COMMAND    2
+#define _DMA_SET_CHANNEL_PARAM_COMMAND 3
+#define _DMA_INIT_COMMAND              8
+#define _DMA_RESET_COMMAND            15
+
+/* Channel Parameter IDs */
+#define _DMA_PACKING_SETUP_PARAM   0
+#define _DMA_STRIDE_A_PARAM        1
+#define _DMA_ELEM_CROPPING_A_PARAM 2
+#define _DMA_WIDTH_A_PARAM         3
+#define _DMA_STRIDE_B_PARAM        4
+#define _DMA_ELEM_CROPPING_B_PARAM 5
+#define _DMA_WIDTH_B_PARAM         6
+#define _DMA_HEIGHT_PARAM          7
+
+/* Parameter Constants */
+#define _DMA_ZERO_EXTEND     0
+#define _DMA_SIGN_EXTEND     1
+#define _DMA_REVERSE_ELEMS   1
+#define _DMA_KEEP_ELEM_ORDER 0
+
+  /* SLAVE address map */
+#define _DMA_SEL_FSM_CMD                           0
+#define _DMA_SEL_CH_REG                            1
+#define _DMA_SEL_CONN_GROUP                        2
+#define _DMA_SEL_DEV_INTERF                        3
+#define _DMA_SEL_RESET                             15
+
+#define _DMA_RESET_TOKEN                  0xDEADCAFE
+
+#define _DMA_SEL_CONN_CMD                          0
+#define _DMA_SEL_CONN_ADDRESS_A                    1
+#define _DMA_SEL_CONN_ADDRESS_B                    2
+#define _DMA_SEL_FSM_CONN_CTRL                     3
+#define _DMA_SEL_FSM_PACK                          4
+#define _DMA_SEL_FSM_REQ                           5
+#define _DMA_SEL_FSM_WR                            6
+
+#define _DMA_ADDR_SEL_COMP_IDX                    12
+#define _DMA_ADDR_SEL_COMP_BITS                    4
+#define _DMA_ADDR_SEL_CH_REG_IDX                   2
+#define _DMA_ADDR_SEL_CH_REG_BITS                  6
+#define _DMA_ADDR_SEL_PARAM_IDX                    8
+#define _DMA_ADDR_SEL_PARAM_BITS                   4
+
+#define _DMA_ADDR_SEL_GROUP_IDX                    2
+#define _DMA_ADDR_SEL_GROUP_BITS                   3
+#define _DMA_ADDR_SEL_GROUP_COMP_IDX               5
+#define _DMA_ADDR_SEL_GROUP_COMP_BITS              3
+#define _DMA_ADDR_SEL_GROUP_COMP_INFO_IDX          8
+#define _DMA_ADDR_SEL_GROUP_COMP_INFO_BITS         4
+
+#define _DMA_ADDR_SEL_DEV_INTERF_IDX_IDX           2
+#define _DMA_ADDR_SEL_DEV_INTERF_IDX_BITS          6
+#define _DMA_ADDR_SEL_DEV_INTERF_INFO_IDX          8
+#define _DMA_ADDR_SEL_DEV_INTERF_INFO_BITS         4
+
+#define _DMA_FSM_GROUP_CMD_IDX                     0
+#define _DMA_FSM_GROUP_ADDR_A_IDX                  1
+#define _DMA_FSM_GROUP_ADDR_B_IDX                  2
+#define _DMA_FSM_GROUP_FSM_CTRL_IDX                3
+#define _DMA_FSM_GROUP_FSM_PACK_IDX                4
+#define _DMA_FSM_GROUP_FSM_REQ_IDX                 5
+#define _DMA_FSM_GROUP_FSM_WR_IDX                  6
+
+#define _DMA_FSM_GROUP_FSM_CTRL_STATE_IDX          0
+#define _DMA_FSM_GROUP_FSM_CTRL_REQ_DEV_IDX        1
+#define _DMA_FSM_GROUP_FSM_CTRL_REQ_ADDR_IDX       2
+#define _DMA_FSM_GROUP_FSM_CTRL_REQ_STRIDE_IDX     3
+#define _DMA_FSM_GROUP_FSM_CTRL_REQ_XB_IDX         4
+#define _DMA_FSM_GROUP_FSM_CTRL_REQ_YB_IDX         5
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_REQ_DEV_IDX   6
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_WR_DEV_IDX    7
+#define _DMA_FSM_GROUP_FSM_CTRL_WR_ADDR_IDX        8
+#define _DMA_FSM_GROUP_FSM_CTRL_WR_STRIDE_IDX      9
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_REQ_XB_IDX   10
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_WR_YB_IDX    11
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_WR_XB_IDX    12
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_ELEM_REQ_IDX 13
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_ELEM_WR_IDX  14
+#define _DMA_FSM_GROUP_FSM_CTRL_PACK_S_Z_REV_IDX  15
+
+#define _DMA_FSM_GROUP_FSM_PACK_STATE_IDX          0
+#define _DMA_FSM_GROUP_FSM_PACK_CNT_YB_IDX         1
+#define _DMA_FSM_GROUP_FSM_PACK_CNT_XB_REQ_IDX     2
+#define _DMA_FSM_GROUP_FSM_PACK_CNT_XB_WR_IDX      3
+
+#define _DMA_FSM_GROUP_FSM_REQ_STATE_IDX           0
+#define _DMA_FSM_GROUP_FSM_REQ_CNT_YB_IDX          1
+#define _DMA_FSM_GROUP_FSM_REQ_CNT_XB_IDX          2
+
+#define _DMA_FSM_GROUP_FSM_WR_STATE_IDX            0
+#define _DMA_FSM_GROUP_FSM_WR_CNT_YB_IDX           1
+#define _DMA_FSM_GROUP_FSM_WR_CNT_XB_IDX           2
+
+#define _DMA_DEV_INTERF_REQ_SIDE_STATUS_IDX        0
+#define _DMA_DEV_INTERF_SEND_SIDE_STATUS_IDX       1
+#define _DMA_DEV_INTERF_FIFO_STATUS_IDX            2
+#define _DMA_DEV_INTERF_MAX_BURST_IDX              3
+#define _DMA_DEV_INTERF_CHK_ADDR_ALIGN             4
+
+/* constants */
+#define hrt_dma_v1_zero_extension     _DMA_ZERO_EXTEND
+#define hrt_dma_v1_sign_extension     _DMA_SIGN_EXTEND
+#define hrt_dma_v1_reverse_elements   _DMA_REVERSE_ELEMS
+#define hrt_dma_v1_keep_element_order _DMA_KEEP_ELEM_ORDER
+
+/* Construct address from field type */
+#define _hrt_dma_v1_sel_comp(comp) \
+       (((comp) & _hrt_ones(_DMA_ADDR_SEL_COMP_BITS)) << \
+        _DMA_ADDR_SEL_COMP_IDX)
+#define _hrt_dma_v1_sel_ch(ch) \
+       (((ch) & _hrt_ones(_DMA_ADDR_SEL_CH_REG_BITS)) << \
+        _DMA_ADDR_SEL_CH_REG_IDX)
+#define _hrt_dma_v1_sel_param(param) \
+       (((param) & _hrt_ones(_DMA_ADDR_SEL_PARAM_BITS)) << \
+        _DMA_ADDR_SEL_PARAM_IDX)
+#define _hrt_dma_v1_sel_cg_info(info) \
+       (((info) & _hrt_ones(_DMA_ADDR_SEL_GROUP_COMP_INFO_BITS)) << \
+        _DMA_ADDR_SEL_GROUP_COMP_INFO_IDX)
+#define _hrt_dma_v1_sel_cg_comp(comp) \
+       (((comp) & _hrt_ones(_DMA_ADDR_SEL_GROUP_COMP_BITS)) << \
+        _DMA_ADDR_SEL_GROUP_COMP_IDX)
+#define _hrt_dma_v1_sel_cg_id(gr) \
+       (((gr) & _hrt_ones(_DMA_ADDR_SEL_GROUP_BITS)) << \
+        _DMA_ADDR_SEL_GROUP_IDX)
+#define _hrt_dma_v1_sel_dev_info(info) \
+       (((info) & _hrt_ones(_DMA_ADDR_SEL_DEV_INTERF_INFO_BITS)) << \
+        _DMA_ADDR_SEL_DEV_INTERF_INFO_IDX)
+#define _hrt_dma_v1_sel_dev_id(dev) \
+       (((dev) & _hrt_ones(_DMA_ADDR_SEL_DEV_INTERF_IDX_BITS))  << \
+        _DMA_ADDR_SEL_DEV_INTERF_IDX_IDX)
+
+/* Retrieve return values from packed fields */
+#define _hrt_dma_v1_get_connection(val) \
+       _hrt_get_bits(val, _DMA_CONNECTION_IDX, _DMA_CONNECTION_BITS)
+#define _hrt_dma_v1_get_extension(val) \
+       _hrt_get_bits(val, _DMA_EXTENSION_IDX, _DMA_EXTENSION_BITS)
+#define _hrt_dma_v1_get_element_order(val) \
+       _hrt_get_bits(val, _DMA_ELEM_ORDER_IDX, _DMA_ELEM_ORDER_BITS)
+#define _hrt_dma_v1_get_elements(val) \
+       _hrt_get_bits(val, _DMA_ELEMENTS_IDX, _DMA_ELEMENTS_BITS)
+#define _hrt_dma_v1_get_cropping(val) \
+       _hrt_get_bits(val, _DMA_LEFT_CROPPING_IDX, _DMA_LEFT_CROPPING_BITS)
+
+#define hrt_dma_v1_command_fsm_register_address \
+       _hrt_dma_v1_sel_comp(_DMA_SEL_FSM_CMD)
+#define hrt_dma_v1_channel_parameter_register_address(ch, param) \
+       (_hrt_dma_v1_sel_comp(_DMA_SEL_CH_REG) | _hrt_dma_v1_sel_ch(ch) | \
+        _hrt_dma_v1_sel_param(param))
+#define hrt_dma_v1_conn_group_info_register_address(info_id, comp_id, gr_id) \
+       (_hrt_dma_v1_sel_comp(_DMA_SEL_CONN_GROUP) | \
+        _hrt_dma_v1_sel_cg_info(info_id) | \
+        _hrt_dma_v1_sel_cg_comp(comp_id) | \
+        _hrt_dma_v1_sel_cg_id(gr_id))
+#define hrt_dma_v1_device_interface_info_register_address(info_id, dev_id) \
+       (_hrt_dma_v1_sel_comp(_DMA_SEL_DEV_INTERF) | \
+        _hrt_dma_v1_sel_dev_info(info_id) | \
+        _hrt_dma_v1_sel_dev_id(dev_id))
+#define hrt_dma_v1_reset_register_address \
+       _hrt_dma_v1_sel_comp(_DMA_SEL_RESET)
+
+#endif /* _dma_v1_defs_h */
diff --git a/drivers/media/video/atomisp/css/hrt/embed.h b/drivers/media/video/atomisp/css/hrt/embed.h
new file mode 100644 (file)
index 0000000..a63d2bb
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HRT_EMBED_H_
+#define _HRT_EMBED_H_
+
+#define _hrt_cell_dummy_use_blob(prog) \
+       HRTCAT(_hrt_dummy_use_blob_, prog)()
+#define _hrt_program_transfer_func(prog) \
+       HRTCAT(_hrt_transfer_embedded_, prog)
+#define _hrt_program_blob(prog) \
+       (HRTCAT(_hrt_blob_, prog).data)
+#define hrt_embedded_program_size(prog) \
+       HRTCAT(_hrt_size_of_, prog)
+#define hrt_embedded_program_text_size(prog) \
+       HRTCAT(_hrt_text_size_of_, prog)
+
+#endif /* _HRT_EMBED_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/gdc_defs.h b/drivers/media/video/atomisp/css/hrt/gdc_defs.h
new file mode 100644 (file)
index 0000000..864dacf
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _GDC_DEFS_H_
+#define _GDC_DEFS_H_
+
+/* This file contains the settings for both the gdc (64-way fixed)
+   and the gdc_param (variable nway) devices. */
+
+#define HRT_GDC_N_BITS               6
+#define HRT_GDC_N                    64
+
+/* GDC lookup tables entries are 10 bits values, but they're
+   stored 2 by 2 as 32 bit values, yielding 16 bits per entry.
+   A GDC lookup table contains 64 * 4 elements */
+#define HRT_GDC_LUT_BYTES            ((HRT_GDC_N * 4) * 2)
+
+#define HRT_GDC_BLI_COEF_BITS        5
+#define HRT_GDC_BLI_COEF_SHIFT       (HRT_GDC_BLI_COEF_BITS - 1)
+#define HRT_GDC_BLI_COEF_ONE         (1 << HRT_GDC_BLI_COEF_SHIFT)
+
+#define HRT_GDC_BCI_COEF_BITS        10
+#define HRT_GDC_BCI_COEF_MASK        ((1 << HRT_GDC_BCI_COEF_BITS) - 1)
+#define HRT_GDC_BCI_COEF_SHIFT       (HRT_GDC_BCI_COEF_BITS - 2)
+#define HRT_GDC_BCI_COEF_ONE         (1 << HRT_GDC_BCI_COEF_SHIFT)
+
+#define HRT_GDC_GDCAC_BITS           (6 + 4)
+#define HRT_GDC_GDCAC_ONE            (1 << (HRT_GDC_GDCAC_BITS-1))
+
+#define HRT_GDC_COORD_FRAC_BITS      4
+#define HRT_GDC_COORD_ONE            (1 << HRT_GDC_COORD_FRAC_BITS)
+
+#define HRT_GDC_MAX_GDC_IPY_16NWAY   (15*HRT_GDC_COORD_ONE - 1)
+#define HRT_GDC_MAX_GDC_IPY_64NWAY   (49*HRT_GDC_COORD_ONE - 1)
+
+#define _HRT_GDC_REG_ALIGN           4
+
+#define HRT_GDC_NND_CMD              4
+#define HRT_GDC_BLI_CMD              5
+#define HRT_GDC_BCI_CMD              6
+#define HRT_GDC_GD_CAC_CMD           7
+#define HRT_GDC_CONFIG_CMD           8
+
+/* This is how commands are packed into one fifo token */
+#define HRT_GDC_CMD_DATA_POS         16
+#define HRT_GDC_CMD_DATA_BITS        16
+#define HRT_GDC_CMD_BITS             4
+#define HRT_GDC_REG_ID_BITS          8
+#define HRT_GDC_CRUN_BIT             (HRT_GDC_CMD_BITS + HRT_GDC_REG_ID_BITS)
+
+#define HRT_GDC_MODE_IDX             0
+#define HRT_GDC_BPP_IDX              1
+#define HRT_GDC_END_IDX              2
+#define HRT_GDC_WOIX_IDX             3
+#define HRT_GDC_WOIY_IDX             4
+#define HRT_GDC_STX_IDX              5
+#define HRT_GDC_STY_IDX              6
+#define HRT_GDC_OXDIM_IDX            7
+#define HRT_GDC_OYDIM_IDX            8
+#define HRT_GDC_SRC_ADDR_IDX         9
+#define HRT_GDC_SRC_END_ADDR_IDX     10
+#define HRT_GDC_SRC_WRAP_ADDR_IDX    11
+#define HRT_GDC_SRC_STRIDE_IDX       12
+#define HRT_GDC_DST_ADDR_IDX         13
+#define HRT_GDC_DST_STRIDE_IDX       14
+#define HRT_GDC_DX_IDX               15
+#define HRT_GDC_DY_IDX               16
+#define HRT_GDC_P0X_IDX              17
+#define HRT_GDC_P1X_IDX              18
+#define HRT_GDC_P2X_IDX              19
+#define HRT_GDC_P3X_IDX              20
+#define HRT_GDC_P0Y_IDX              21
+#define HRT_GDC_P1Y_IDX              22
+#define HRT_GDC_P2Y_IDX              23
+#define HRT_GDC_P3Y_IDX              24
+#define HRT_GDC_SOFT_RST_IDX         25
+#ifndef __HIVECC
+#define HRT_GDC_ELEM_WIDTH_IDX       26 /* Only for csim */
+#define HRT_GDC_ELEMS_PER_WORD_IDX   27 /* Only for csim */
+#define HRT_GDC_BYTES_PER_WORD_IDX   28 /* Only for csim */
+#define HRT_GDC_CRUN_IDX             29 /* Only for csim */
+#endif
+#define HRT_GDC_LUT_IDX                     32
+
+#ifdef __HIVECC
+#define HRT_GDC_PACK_CMD(cmd) (cmd)
+#else
+#define HRT_GDC_PACK_CMD(cmd) ((cmd) | (1 << HRT_GDC_CRUN_BIT))
+#endif
+
+#endif /* _GDC_DEFS_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/gp_regs_defs.h b/drivers/media/video/atomisp/css/hrt/gp_regs_defs.h
new file mode 100644 (file)
index 0000000..fd4a124
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _gp_regs_defs_h
+#define _gp_regs_defs_h
+
+#define _HRT_GP_REGS_IS_FWD_REG_IDX 0
+#define _HRT_GP_REGS_REG_ALIGN 4
+
+#endif /* _gp_regs_defs_h */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_defs.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_defs.h
new file mode 100644 (file)
index 0000000..7af93b4
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _hive_isp_css_defs_h
+#define _hive_isp_css_defs_h
+
+#define HIVE_ISP_CTRL_DATA_WIDTH     32
+#define HIVE_ISP_CTRL_ADDRESS_WIDTH  32
+#define HIVE_ISP_CTRL_MAX_BURST_SIZE  1
+#define HIVE_ISP_NUM_GPIO_PINS       10
+
+/* This list of vector num_elems/elem_bits pairs is valid both
+   in C as initializer and in the DMA parameter list */
+#define HIVE_ISP_DDR_DMA_SPECS { {32,  8}, {16, 16}, {18, 14}, \
+                                {25, 10}, {21, 12} }
+#define HIVE_ISP_DDR_WORD_BITS 256
+#define HIVE_ISP_DDR_BYTES     (256 * 1024 * 1024)
+#define HIVE_ISP_PAGE_SHIFT    12
+#define HIVE_ISP_PAGE_SIZE     (1<<HIVE_ISP_PAGE_SHIFT)
+
+/* If HIVE_ISP_DDR_BASE_OFFSET is set to a non-zero value,
+ * the wide bus just before the DDRAM gets an extra dummy port where
+ * address range 0 .. HIVE_ISP_DDR_BASE_OFFSET-1 maps onto.
+ * This effectively creates an offset for the DDRAM from system perspective.
+ */
+#define HIVE_ISP_DDR_BASE_OFFSET 0 /* 0x200000 */
+
+#define HIVE_DMA_ISP_BUS_CONN 0
+#define HIVE_DMA_ISP_DDR_CONN 1
+#define HIVE_DMA_BUS_DDR_CONN 2
+#define HIVE_DMA_ISP_MASTER master_port0
+#define HIVE_DMA_BUS_MASTER master_port1
+#define HIVE_DMA_DDR_MASTER master_port2
+#define HIVE_DMA_NUM_CHANNELS       8
+
+#define HIVE_IF_PIXEL_WIDTH 12
+
+#define HIVE_MMU_TLB_SETS           16
+#define HIVE_MMU_TLB_SET_BLOCKS     8
+#define HIVE_MMU_TLB_BLOCK_ELEMENTS 8
+#define HIVE_MMU_PAGE_TABLE_LEVELS  2
+#define HIVE_MMU_PAGE_BYTES         HIVE_ISP_PAGE_SIZE
+
+#define HIVE_ISP_CH_ID_BITS    2
+#define HIVE_ISP_FMT_TYPE_BITS 5
+#define HIVE_ISP_ISEL_SEL_BITS 2
+
+/* gp_register register id's   */
+#define HIVE_GP_REGS_SWITCH_IF_IDX                              0
+#define HIVE_GP_REGS_SWITCH_DMA_IDX                             1
+#define HIVE_GP_REGS_SWITCH_GDC_IDX                             2
+
+#define HIVE_GP_REGS_SYNCGEN_ENABLE_IDX                         3
+#define HIVE_GP_REGS_SYNCGEN_NR_PIX_IDX                         4
+#define HIVE_GP_REGS_SYNCGEN_NR_LINES_IDX                       5
+#define HIVE_GP_REGS_SYNCGEN_HBLANK_CYCLES_IDX                  6
+#define HIVE_GP_REGS_SYNCGEN_VBLANK_CYCLES_IDX                  7
+
+#define HIVE_GP_REGS_ISEL_SOF_IDX                               8
+#define HIVE_GP_REGS_ISEL_EOF_IDX                               9
+#define HIVE_GP_REGS_ISEL_SOL_IDX                              10
+#define HIVE_GP_REGS_ISEL_EOL_IDX                              11
+
+#define HIVE_GP_REGS_PRBS_ENABLE                               12
+#define HIVE_GP_REGS_PRBS_ENABLE_PORT_B                        13
+#define HIVE_GP_REGS_PRBS_LFSR_RESET_VALUE                     14
+
+#define HIVE_GP_REGS_TPG_ENABLE                                15
+#define HIVE_GP_REGS_TPG_ENABLE_PORT_B                         16
+#define HIVE_GP_REGS_TPG_HOR_CNT_MASK_IDX                      17
+#define HIVE_GP_REGS_TPG_VER_CNT_MASK_IDX                      18
+#define HIVE_GP_REGS_TPG_XY_CNT_MASK_IDX                       19
+#define HIVE_GP_REGS_TPG_HOR_CNT_DELTA_IDX                     20
+#define HIVE_GP_REGS_TPG_VER_CNT_DELTA_IDX                     21
+
+#define HIVE_GP_REGS_ISEL_CH_ID_IDX                            22
+#define HIVE_GP_REGS_ISEL_FMT_TYPE_IDX                         23
+#define HIVE_GP_REGS_ISEL_DATA_SEL_IDX                         24
+#define HIVE_GP_REGS_ISEL_SBAND_SEL_IDX                        25
+#define HIVE_GP_REGS_ISEL_SYNC_SEL_IDX                         26
+
+/* HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_? have to be sequential ! */
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_0                    27
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_1                    28
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_2                    29
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_3                    30
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_4                    31
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_5                    32
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_6                    33
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_7                    34
+
+#define HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_BASE \
+       HIVE_GP_REGS_INPUT_SWITCH_LUT_REG_0
+#define HIVE_GP_REGS_INPUT_SWITCH_FSYNC_LUT_REG                35
+
+#define HIVE_GP_REGS_SDRAM_WAKEUP_IDX                          36
+#define HIVE_GP_REGS_IDLE_IDX                                  37
+#define HIVE_GP_REGS_IRQ_IDX                                   38
+
+#define HIVE_GP_REGS_MIPI_FIFO_FULL                            39
+#define HIVE_GP_REGS_MIPI_USED_DWORD                           40
+
+#define HIVE_GP_REGS_SP_STREAM_STAT                            41
+#define HIVE_GP_REGS_MOD_STREAM_STAT                           42
+#define HIVE_GP_REGS_ISP_STREAM_STAT                           43
+
+#define HIVE_GP_REGS_CH_ID_FMT_TYPE_IDX                        44
+
+/* order of the input bits for the irq controller */
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_0_BIT_ID             0
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_1_BIT_ID             1
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_2_BIT_ID             2
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_3_BIT_ID             3
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_4_BIT_ID             4
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_5_BIT_ID             5
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_6_BIT_ID             6
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_7_BIT_ID             7
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_8_BIT_ID             8
+#define HIVE_TESTBENCH_IRQ_SOURCE_GPIO_PIN_9_BIT_ID             9
+#define HIVE_TESTBENCH_IRQ_SOURCE_SP_BIT_ID                    10
+#define HIVE_TESTBENCH_IRQ_SOURCE_ISP_BIT_ID                   11
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_BIT_ID                  12
+#define HIVE_TESTBENCH_IRQ_SOURCE_PRIM_IF_BIT_ID               13
+#define HIVE_TESTBENCH_IRQ_SOURCE_PRIM_B_IF_BIT_ID             14
+#define HIVE_TESTBENCH_IRQ_SOURCE_SEC_IF_BIT_ID                15
+#define HIVE_TESTBENCH_IRQ_SOURCE_MEM_COPY_BIT_ID              16
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_FIFO_FULL_BIT_ID        17
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_SOF_BIT_ID              18
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_EOF_BIT_ID              19
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_SOL_BIT_ID              20
+#define HIVE_TESTBENCH_IRQ_SOURCE_MIPI_EOL_BIT_ID              21
+#define HIVE_TESTBENCH_IRQ_SOURCE_SYNC_GEN_SOF_BIT_ID          22
+#define HIVE_TESTBENCH_IRQ_SOURCE_SYNC_GEN_EOF_BIT_ID          23
+#define HIVE_TESTBENCH_IRQ_SOURCE_SYNC_GEN_SOL_BIT_ID          24
+#define HIVE_TESTBENCH_IRQ_SOURCE_SYNC_GEN_EOL_BIT_ID          25
+#define HIVE_TESTBENCH_IRQ_SOURCE_CSS_GEN_SHORT_VALID_BIT_ID   26
+#define HIVE_TESTBENCH_IRQ_SOURCE_CSS_GEN_SHORT_ACCEPT_BIT_ID  27
+#define HIVE_TESTBENCH_IRQ_SOURCE_SIDEBAND_CHANGED_BIT_ID      28
+
+#define HIVE_TESTBENCH_IRQ_SOURCE_SW_PIN_0_BIT_ID              29
+#define HIVE_TESTBENCH_IRQ_SOURCE_SW_PIN_1_BIT_ID              30
+#define HIVE_TESTBENCH_IRQ_SOURCE_SW_PIN_2_BIT_ID              31
+
+#define HIVE_ISP_NUM_USED_IRQ_INPUTS \
+       (HIVE_TESTBENCH_IRQ_SOURCE_SW_PIN_0_BIT_ID - \
+        HIVE_TESTBENCH_IRQ_SOURCE_SP_BIT_ID)
+
+#define HIVE_GP_REGS_IRQ_REG_WIDTH \
+       (HIVE_ISP_CTRL_DATA_WIDTH - \
+        HIVE_TESTBENCH_IRQ_SOURCE_SW_PIN_0_BIT_ID)
+
+/* testbench signals:       */
+
+/* GP adapter register ids  */
+#define HIVE_TESTBENCH_GPIO_DATA_OUT_REG_IDX                    0
+#define HIVE_TESTBENCH_GPIO_DIR_OUT_REG_IDX                     1
+#define HIVE_TESTBENCH_IRQ_REG_IDX                              2
+#define HIVE_TESTBENCH_SDRAM_WAKEUP_REG_IDX                     3
+#define HIVE_TESTBENCH_IDLE_REG_IDX                             4
+#define HIVE_TESTBENCH_GPIO_DATA_IN_REG_IDX                     5
+
+/* Signal monitor input bit ids */
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_O_BIT_ID         0
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_1_BIT_ID         1
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_2_BIT_ID         2
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_3_BIT_ID         3
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_4_BIT_ID         4
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_5_BIT_ID         5
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_6_BIT_ID         6
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_7_BIT_ID         7
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_8_BIT_ID         8
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_GPIO_PIN_9_BIT_ID         9
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_IRQ_PIN_BIT_ID           10
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_SDRAM_WAKEUP_PIN_BIT_ID  11
+#define HIVE_TESTBENCH_SIG_MON_SOURCE_IDLE_PIN_BIT_ID          12
+
+#endif /* _hive_isp_css_defs_h */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_host_ids_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_host_ids_hrt.h
new file mode 100644 (file)
index 0000000..581aa0f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _hive_isp_css_host_ids_hrt_h_
+#define _hive_isp_css_host_ids_hrt_h_
+
+/* ISP_CSS identifiers */
+#define ISP           testbench_isp_isp
+#define SP            testbench_isp_scp
+#define IF_PRIM       testbench_isp_ift_prim
+#define IF_PRIM_B     testbench_isp_ift_prim_b
+#define IF_SEC        testbench_isp_ift_sec
+#define STR_TO_MEM    testbench_isp_mem_cpy
+#define CSS_RECEIVER  testbench_isp_css_receiver
+#define TC            testbench_isp_gpd_tc
+#define DMA           testbench_isp_isp_dma
+#define GDC           testbench_isp_gdc
+#define IRQ_CTRL      testbench_isp_gpd_irq_ctrl
+#define GPIO          testbench_isp_gpd_c_gpio
+#define GP_REGS       testbench_isp_gpd_gp_reg
+#define MMU           testbench_isp_c_mmu
+#define ISEL_FA       testbench_isp_gpd_fa_isel
+/* next is actually not FIFO but FIFO adapter, or slave to streaming adapter */
+#define ISP_SP_FIFO   testbench_isp_gpd_fa_sp_isp
+#define GP_FIFO       testbench_isp_gpd_sf_2isel_in
+#define FIFO_GPF_ISEL testbench_isp_gpd_sf_2isel_in
+#define FIFO_GPF_SP   testbench_isp_gpd_sf_gpf2sp_in
+#define FIFO_GPF_ISP  testbench_isp_gpd_sf_gpf2isp_in
+#define FIFO_SP_GPF   testbench_isp_gpd_sf_sp2gpf_in
+#define FIFO_ISP_GPF  testbench_isp_gpd_sf_isp2gpf_in
+#define OCP_MASTER    testbench_isp_cio2ocp_wide_data_out_mt
+#define IF_SEC_MASTER testbench_isp_ift_sec_mt_out
+#define SP_IN_FIFO    testbench_isp_gpd_sf_gpf2sp_in
+#define SP_OUT_FIFO   testbench_isp_gpd_sf_sp2gpf_out
+#define ISP_IN_FIFO   testbench_isp_gpd_sf_gpf2isp_in
+#define ISP_OUT_FIFO  testbench_isp_gpd_sf_isp2gpf_out
+#define GEN_SHORT_PACK_PORT testbench_isp_ModStrMon_out10
+
+/* Testbench identifiers */
+#define DDR           testbench_ddram
+#define XMEM          DDR
+#define GPIO_ADAPTER  testbench_gp_adapter
+#define SIG_MONITOR   testbench_sig_mon
+#define DDR_SLAVE     testbench_ddram_ip0
+#define HOST_MASTER   host_op0
+
+#endif /* _hive_isp_css_host_ids_hrt_h_ */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_if_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_if_hrt.h
new file mode 100644 (file)
index 0000000..a7d3ace
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HIVE_ISP_CSS_IF_HRT_H_
+#define _HIVE_ISP_CSS_IF_HRT_H_
+
+#ifdef _HIVE_ISP_CSS_FPGA_SYSTEM
+#define dev_sys_isp_clus_ift_prim_vector_alignment   ISP_VEC_ALIGN
+#define dev_sys_isp_clus_ift_prim_b_vector_alignment ISP_VEC_ALIGN
+#define dev_sys_isp_clus_ift_sec_vector_alignment \
+       (dev_sys_isp_clus_ift_sec_mt_out_data_width / 8)
+#define dev_sys_isp_clus_mem_cpy_vector_alignment \
+       (dev_sys_isp_clus_mem_cpy_mt_out_data_width / 8)
+#else
+#define testbench_isp_ift_prim_vector_alignment   ISP_VEC_ALIGN
+#define testbench_isp_ift_prim_b_vector_alignment ISP_VEC_ALIGN
+#define testbench_isp_ift_sec_vector_alignment \
+       (testbench_isp_ift_sec_mt_out_data_width / 8)
+#define testbench_isp_mem_cpy_vector_alignment \
+       (testbench_isp_mem_cpy_mt_out_data_width / 8)
+#endif
+
+#endif /* _HIVE_ISP_CSS_IF_HRT_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_irq_types_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_irq_types_hrt.h
new file mode 100644 (file)
index 0000000..ed97422
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HIVE_ISP_CSS_IRQ_TYPES_HRT_H_
+#define _HIVE_ISP_CSS_IRQ_TYPES_HRT_H_
+
+/* these are the indices of each interrupt in the
+ * interrupt controller's registers. these can be used
+ * as the irq_id argument to the hrt functions irq_controller.h.
+ */
+enum hrt_isp_css_irq {
+       hrt_isp_css_irq_gpio_0,
+       hrt_isp_css_irq_gpio_1,
+       hrt_isp_css_irq_gpio_2,
+       hrt_isp_css_irq_gpio_3,
+       hrt_isp_css_irq_gpio_4,
+       hrt_isp_css_irq_gpio_5,
+       hrt_isp_css_irq_gpio_6,
+       hrt_isp_css_irq_gpio_7,
+       hrt_isp_css_irq_gpio_8,
+       hrt_isp_css_irq_gpio_9,
+       hrt_isp_css_irq_sp,
+       hrt_isp_css_irq_isp,
+       hrt_isp_css_irq_mipi,
+       hrt_isp_css_irq_ift_prim,
+       hrt_isp_css_irq_ift_prim_b,
+       hrt_isp_css_irq_ift_sec,
+       hrt_isp_css_irq_ift_mem_cpy,
+       hrt_isp_css_irq_mipi_fifo_full,
+       hrt_isp_css_irq_mipi_sof,
+       hrt_isp_css_irq_mipi_eof,
+       hrt_isp_css_irq_mipi_sol,
+       hrt_isp_css_irq_mipi_eol,
+       hrt_isp_css_irq_syncgen_sof,
+       hrt_isp_css_irq_syncgen_eof,
+       hrt_isp_css_irq_syncgen_sol,
+       hrt_isp_css_irq_syncgen_eol,
+#ifdef CSS_RECEIVER
+       hrt_isp_css_irq_css_gen_short_0,
+       hrt_isp_css_irq_css_gen_short_1,
+       hrt_isp_css_irq_sideband_changed,
+#endif
+       /* The ASIC system has only 3 SW interrupts,
+        * so the FPGA system is limited
+        * by this to 3 as well. */
+       hrt_isp_css_irq_sw_0,
+       hrt_isp_css_irq_sw_1,
+       hrt_isp_css_irq_sw_2,
+       /* this must (obviously) be the last on in the enum */
+       hrt_isp_css_irq_num_irqs
+};
+
+enum hrt_isp_css_irq_status {
+       hrt_isp_css_irq_status_error,
+       hrt_isp_css_irq_status_more_irqs,
+       hrt_isp_css_irq_status_success
+};
+
+#endif /* _HIVE_ISP_CSS_IRQ_TYPES_HRT_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h
new file mode 100644 (file)
index 0000000..58cf772
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _hive_isp_css_mm_hrt_h_
+#define _hive_isp_css_mm_hrt_h_
+
+#ifndef HRT_KERNEL
+/* size_t is defined already in kernel mode */
+#include <stdlib.h>
+#endif
+#include <hmm/hmm.h>
+
+int hrt_isp_css_mm_set(void *virt_addr, int c, size_t bytes);
+
+/* Allocate memory, returns a virtual address */
+void *hrt_isp_css_mm_alloc(size_t bytes);
+void *hrt_isp_css_mm_alloc_cached(size_t bytes);
+
+/* allocate memory and initialize with zeros,
+   returns a virtual address */
+void *hrt_isp_css_mm_calloc(size_t bytes);
+void *hrt_isp_css_mm_calloc_cached(size_t bytes);
+
+/* Free memory, given a virtual address */
+void hrt_isp_css_mm_free(void *virt_addr);
+
+/* Store data to a virtual address */
+int hrt_isp_css_mm_load(void *virt_addr, void *data, size_t bytes);
+
+/* Load data from a virtual address */
+int hrt_isp_css_mm_store(void *virt_addr, const void *data, size_t bytes);
+
+int hrt_isp_css_mm_load_int(void *virt_addr, int *data);
+int hrt_isp_css_mm_load_short(void *virt_addr, short *data);
+int hrt_isp_css_mm_load_char(void *virt_addr, char *data);
+
+int hrt_isp_css_mm_store_char(void *virt_addr, char data);
+int hrt_isp_css_mm_store_short(void *virt_addr, short data);
+int hrt_isp_css_mm_store_int(void *virt_addr, int data);
+
+/* translate a virtual to a physical address, used to program
+   the display driver on  the FPGA system */
+void *hrt_isp_css_virt_to_phys(void *virt_addr);
+
+void *hrt_isp_css_mm_alloc_contiguous(size_t bytes);
+void *hrt_isp_css_mm_calloc_contiguous(size_t bytes);
+
+void hrt_isp_css_mm_clear(void);
+#endif /* _hive_isp_css_mm_hrt_h_ */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_monitors_types_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_monitors_types_hrt.h
new file mode 100644 (file)
index 0000000..1d21beb
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _hive_isp_css_streaming_monitors_types_hrt_h
+#define _hive_isp_css_streaming_monitors_types_hrt_h
+
+#define _hive_str_mon_valid_offset   0
+#define _hive_str_mon_accept_offset  1
+
+#define SP_STR_MON_PORT_SND_PIF_A         0
+#define SP_STR_MON_PORT_RCV_PIF_A         1
+#define SP_STR_MON_PORT_SND_SIF           2
+#define SP_STR_MON_PORT_RCV_SIF           3
+#define SP_STR_MON_PORT_SND_MC            4
+#define SP_STR_MON_PORT_RCV_MC            5
+#define SP_STR_MON_PORT_SND_DMA           6
+#define SP_STR_MON_PORT_RCV_DMA           7
+#define SP_STR_MON_PORT_SND_GDC           8
+#define SP_STR_MON_PORT_RCV_GDC           9
+#define SP_STR_MON_PORT_SND_ISP          10
+#define SP_STR_MON_PORT_RCV_ISP          11
+#define SP_STR_MON_PORT_SND_GPD          12
+#define SP_STR_MON_PORT_RCV_GPD          13
+#define SP_STR_MON_PORT_SND_PIF_B        14
+#define SP_STR_MON_PORT_RCV_PIF_B        15
+
+#define MOD_STR_MON_PORT_SND_PIF_A        0
+#define MOD_STR_MON_PORT_RCV_PIF_A        1
+#define MOD_STR_MON_PORT_SND_SIF          2
+#define MOD_STR_MON_PORT_RCV_SIF          3
+#define MOD_STR_MON_PORT_SND_MC           4
+#define MOD_STR_MON_PORT_RCV_MC           5
+#define MOD_STR_MON_PORT_SND_DMA          6
+#define MOD_STR_MON_PORT_RCV_DMA          7
+#define MOD_STR_MON_PORT_SND_GDC          8
+#define MOD_STR_MON_PORT_RCV_GDC          9
+#define MOD_STR_MON_PORT_SND_CSS_REC     10
+
+#define ISP_STR_MON_PORT_SND_PIF_A        0
+#define ISP_STR_MON_PORT_RCV_PIF_A        1
+#define ISP_STR_MON_PORT_SND_PIF_B        2
+#define ISP_STR_MON_PORT_RCV_PIF_B        3
+#define ISP_STR_MON_PORT_SND_DMA          4
+#define ISP_STR_MON_PORT_RCV_DMA          5
+#define ISP_STR_MON_PORT_SND_GDC          6
+#define ISP_STR_MON_PORT_RCV_GDC          7
+#define ISP_STR_MON_PORT_SND_GPD          8
+#define ISP_STR_MON_PORT_RCV_GPD          9
+#define ISP_STR_MON_PORT_SND_SP          10
+#define ISP_STR_MON_PORT_RCV_SP          11
+
+#endif /* _hive_isp_css_streaming_monitors_types_hrt_h */
diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_to_mipi_types_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_streaming_to_mipi_types_hrt.h
new file mode 100644 (file)
index 0000000..47750f0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _hive_isp_css_streaming_to_mipi_types_hrt_h_
+#define _hive_isp_css_streaming_to_mipi_types_hrt_h_
+
+#include <streaming_to_mipi_defs.h>
+
+#define _HIVE_ISP_CH_ID_MASK    ((1U << HIVE_ISP_CH_ID_BITS)-1)
+#define _HIVE_ISP_FMT_TYPE_MASK ((1U << HIVE_ISP_FMT_TYPE_BITS)-1)
+
+#define _HIVE_STR_TO_MIPI_FMT_TYPE_LSB \
+       (HIVE_STR_TO_MIPI_CH_ID_LSB + HIVE_ISP_CH_ID_BITS)
+#define _HIVE_STR_TO_MIPI_DATA_B_LSB \
+       (HIVE_STR_TO_MIPI_DATA_A_LSB + HIVE_IF_PIXEL_WIDTH)
+
+#endif /* _hive_isp_css_streaming_to_mipi_types_hrt_h_ */
diff --git a/drivers/media/video/atomisp/css/hrt/if_defs.h b/drivers/media/video/atomisp/css/hrt/if_defs.h
new file mode 100644 (file)
index 0000000..9641e31
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _IF_DEFS_H
+#define _IF_DEFS_H
+
+/* Hardware registers */
+#define HIVE_IF_RESET_ADDRESS                   0x000
+#define HIVE_IF_START_LINE_ADDRESS              0x004
+#define HIVE_IF_START_COLUMN_ADDRESS            0x008
+#define HIVE_IF_CROPPED_HEIGHT_ADDRESS          0x00C
+#define HIVE_IF_CROPPED_WIDTH_ADDRESS           0x010
+#define HIVE_IF_VERTICAL_DECIMATION_ADDRESS     0x014
+#define HIVE_IF_HORIZONTAL_DECIMATION_ADDRESS   0x018
+#define HIVE_IF_H_DEINTERLEAVING_ADDRESS        0x01C
+#define HIVE_IF_LEFTPADDING_WIDTH_ADDRESS       0x020
+#define HIVE_IF_END_OF_LINE_OFFSET_ADDRESS      0x024
+#define HIVE_IF_VMEM_START_ADDRESS_ADDRESS      0x028
+#define HIVE_IF_VMEM_END_ADDRESS_ADDRESS        0x02C
+#define HIVE_IF_VMEM_INCREMENT_ADDRESS          0x030
+#define HIVE_IF_YUV_420_FORMAT_ADDRESS          0x034
+#define HIVE_IF_VSYNCK_ACTIVE_LOW_ADDRESS       0x038
+#define HIVE_IF_HSYNCK_ACTIVE_LOW_ADDRESS       0x03C
+#define HIVE_IF_ALLOW_FIFO_OVERFLOW_ADDRESS     0x040
+#define HIVE_IF_BLOCK_FIFO_NO_REQ_ADDRESS       0x044
+#define HIVE_IF_V_DEINTERLEAVING_ADDRESS        0x048
+#define HIVE_IF_FSM_SYNC_STATUS                 0x100
+#define HIVE_IF_FSM_SYNC_COUNTER                0x104
+#define HIVE_IF_FSM_CROP_STATUS                 0x108
+#define HIVE_IF_FSM_CROP_LINE_COUNTER           0x10C
+#define HIVE_IF_FSM_CROP_PIXEL_COUNTER          0x110
+#define HIVE_IF_FSM_DEINTERLEAVING_IDX          0x114
+#define HIVE_IF_FSM_DECIMATION_H_COUNTER        0x118
+#define HIVE_IF_FSM_DECIMATION_V_COUNTER        0x11C
+#define HIVE_IF_FSM_DECIMATION_BLOCK_V_COUNTER  0x120
+#define HIVE_IF_FSM_PADDING_STATUS              0x124
+#define HIVE_IF_FSM_PADDING_ELEMENT_COUNTER     0x128
+#define HIVE_IF_FSM_VECTOR_SUPPORT_ERROR        0x12C
+#define HIVE_IF_FSM_VECTOR_SUPPORT_BUFF_FULL    0x130
+#define HIVE_IF_FSM_VECTOR_SUPPORT              0x134
+#define HIVE_IF_FIFO_SENSOR_DATA_LOST           0x138
+
+/* Registers only for simulation */
+#define HIVE_IF_CRUN_MODE_ADDRESS               0x04C
+#define HIVE_IF_DUMP_OUTPUT_ADDRESS             0x050
+
+#define HIVE_IF_FRAME_REQUEST        0xA000
+#define HIVE_IF_LINES_REQUEST        0xB000
+#define HIVE_IF_VECTORS_REQUEST      0xC000
+
+#define _HRT_IF_VEC_ALIGN(if_id) HRTCAT(if_id, _vector_alignment)
+
+#endif /* _IF_DEFS_H */
diff --git a/drivers/media/video/atomisp/css/hrt/irq_controller_defs.h b/drivers/media/video/atomisp/css/hrt/irq_controller_defs.h
new file mode 100644 (file)
index 0000000..2287a29
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _irq_controller_defs_h
+#define _irq_controller_defs_h
+
+#define _HRT_IRQ_CONTROLLER_EDGE_REG_IDX           0
+#define _HRT_IRQ_CONTROLLER_MASK_REG_IDX           1
+#define _HRT_IRQ_CONTROLLER_STATUS_REG_IDX         2
+#define _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX          3
+#define _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX         4
+#define _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX 5
+
+#define _HRT_IRQ_CONTROLLER_REG_ALIGN 4
+
+#endif /* _irq_controller_defs_h */
diff --git a/drivers/media/video/atomisp/css/hrt/isp2300_medfield_params.h b/drivers/media/video/atomisp/css/hrt/isp2300_medfield_params.h
new file mode 100644 (file)
index 0000000..a02d0c2
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/* Version */
+#define ISP_VERSION RTL_VERSION
+
+/* Cell name  */
+
+#define ISP_CELL_TYPE         isp2300_medfield
+#define ISP_VMEM              simd_vmem
+#define _HRT_ISP_VMEM         isp2300_medfield_simd_vmem
+
+/* instruction pipeline depth */
+#define ISP_BRANCHDELAY       3
+
+/* bus */
+#define ISP_BUS_PROT          CIO
+#define ISP_BUS_WIDTH         32
+#define ISP_BUS_ADDR_WIDTH    32
+#define ISP_BUS_BURST_SIZE    1
+
+/* data-path */
+#define ISP_SCALAR_WIDTH      32
+#define ISP_SLICE_NELEMS      4
+#define ISP_VEC_NELEMS        64
+#define ISP_VEC_ELEMBITS      14
+#define ISP_VEC_ELEM8BITS     16
+#define ISP_ALPHA_BLEND_SHIFT 13
+
+/* memories */
+#define ISP_DMEM_DEPTH            4096
+#define ISP_VMEM_DEPTH            2048
+#define ISP_VMEM_ELEMBITS         14
+#define ISP_VMEM_ELEM_PRECISION   14
+#define ISP_PMEM_DEPTH            2048
+#define ISP_PMEM_WIDTH            448
+#define ISP_VAMEM_ADDRESS_BITS    13
+#define ISP_VAMEM_ELEMBITS        12
+#define ISP_VAMEM_DEPTH           4096
+#define ISP_VAMEM_ALIGNMENT       2
+#define ISP_VA_ADDRESS_WIDTH      896
+#define ISP_VEC_VALSU_LATENCY     ISP_VEC_NELEMS
+
+/* program counter */
+#define ISP_PC_WIDTH          12
+
+/* RSN pipelining */
+#define ISP_RSN_PIPE          0
+
+/* shrink instruction set */
+#define ISP_SHRINK_IS         0
+
+/* Template experiments */
+#define ISP_HAS_VARU_SIMD_IS1 0
+#define ISP_HAS_SIMD_IS5      1
+#define ISP_HAS_SIMD6_FLGU    0
+#define ISP_HAS_VALSU         1
+#define ISP_SRU_GUARDING      1
+#define ISP_VRF_RAM           1
+#define ISP_SRF_RAM           1
+#define ISP_REDUCE_VARUS      0
+#define ISP_COMBINE_MAC_SHIFT 0
+#define ISP_COMBINE_MAC_VARU  1
+#define ISP_COMBINE_SHIFT_VARU 0
+#define ISP_SLICE_LATENCY     1
+#define ISP_RFSPLIT_EXP       0
+#define ISP_SPILL_MEM_EXP     0
+#define ISP_VHSU_NO_WIDE      0
+#define ISP_NO_SLICE          0
+#define ISP_BLOCK_SLICE       0
+#define ISP_IF                1
+#define ISP_IF_B              1
+#define ISP_DMA               0
+#define ISP_OF                0
+#define ISP_SYS_OF            1
+#define ISP_GDC               1
+#define ISP_GPIO              1
+#define ISP_SP                1
+#define ISP_HAS_IRQ           1
+
+/* derived values */
+#define ISP_VEC_WIDTH         896
+#define ISP_SLICE_WIDTH       56
+#define ISP_VMEM_WIDTH        896
+#define ISP_SIMDLSU           1
+#define ISP_LSU_IMM_BITS      12
+
+/* convenient shortcuts for software*/
+#define ISP_NWAY              ISP_VEC_NELEMS
+#define NBITS                       ISP_VEC_ELEMBITS
+
+#define _isp_ceil_div(a, b)         (((a)+(b)-1)/(b))
+
+#ifdef C_RUN
+#define ISP_VEC_ALIGN         (_isp_ceil_div(ISP_VEC_WIDTH, 64)*8)
+#define ISP_VMEM_ALIGN        (_isp_ceil_div(ISP_VMEM_WIDTH, 64)*8)
+#else
+#define ISP_VEC_ALIGN         128
+#define ISP_VMEM_ALIGN        ISP_VEC_ALIGN
+#endif
+
+/* HRT specific vector support */
+#define isp2300_medfield_vector_alignment      ISP_VEC_ALIGN
+#define isp2300_medfield_vector_elem_bits      ISP_VMEM_ELEMBITS
+#define isp2300_medfield_vector_elem_precision ISP_VMEM_ELEM_PRECISION
+#define isp2300_medfield_vector_num_elems      ISP_VEC_NELEMS
+
+/* register file sizes */
+#define ISP_RF0_SIZE        64
+#define ISP_RF1_SIZE        8
+#define ISP_RF2_SIZE        64
+#define ISP_RF3_SIZE        32
+#define ISP_RF4_SIZE        32
+#define ISP_RF5_SIZE        32
+#define ISP_RF6_SIZE        16
+#define ISP_VRF0_SIZE       16
+#define ISP_VRF1_SIZE       16
+#define ISP_VRF2_SIZE       16
+#define ISP_VRF3_SIZE       16
+#define ISP_VRF4_SIZE       16
+#define ISP_VRF5_SIZE       16
+#define ISP_VRF6_SIZE       16
+#define ISP_VRF7_SIZE       16
+#define ISP_VRF8_SIZE       16
+#define ISP_SRF0_SIZE       64
+#define ISP_SRF1_SIZE       64
+#define ISP_FRF0_SIZE       16
+#define ISP_FRF1_SIZE       16
+/* register file read latency */
+#define ISP_VRF0_READ_LAT       0
+#define ISP_VRF1_READ_LAT       0
+#define ISP_VRF2_READ_LAT       0
+#define ISP_VRF3_READ_LAT       0
+#define ISP_VRF4_READ_LAT       0
+#define ISP_VRF5_READ_LAT       0
+#define ISP_VRF6_READ_LAT       0
+#define ISP_VRF7_READ_LAT       0
+#define ISP_VRF8_READ_LAT       0
+#define ISP_SRF0_READ_LAT       0
+#define ISP_SRF1_READ_LAT       0
+/* immediate sizes */
+#define ISP_IS1_IMM_BITS        13
+#define ISP_IS2_IMM_BITS        10
+#define ISP_IS3_IMM_BITS        7
+#define ISP_IS4_IMM_BITS        7
+#define ISP_IS5_IMM_BITS        13
+#define ISP_IS6_IMM_BITS        7
+#define ISP_IS7_IMM_BITS        7
+#define ISP_IS8_IMM_BITS        7
+#define ISP_IS9_IMM_BITS        7
+/* fifo depths */
+#define ISP_IF_FIFO_DEPTH         0
+#define ISP_IF_B_FIFO_DEPTH       0
+#define ISP_DMA_FIFO_DEPTH        0
+#define ISP_OF_FIFO_DEPTH         0
+#define ISP_GDC_FIFO_DEPTH        0
+#define ISP_GPIO_FIFO_DEPTH       0
+#define ISP_SP_FIFO_DEPTH         0
diff --git a/drivers/media/video/atomisp/css/hrt/master_port.h b/drivers/media/video/atomisp/css/hrt/master_port.h
new file mode 100644 (file)
index 0000000..0823774
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _HRT_MASTER_PORT_H_
+#define _HRT_MASTER_PORT_H_
+
+/* This file contains the end of the HRT.
+ * Here we split between the hardware implementation (memcpy / assignments)
+ * and the software backends (_hrt_master_port_load / _hrt_master_port_store)
+ */
+
+/* If HRT_USE_VIR_ADDRS is defined, the OS needs to implement the following
+   functions for us:
+   _hrt_master_port_store_8(addr,data)
+   _hrt_master_port_store_16(addr,data)
+   _hrt_master_port_store_32(addr,data)
+   _hrt_master_port_load_8(addr)
+   _hrt_master_port_uload_8(addr)
+   _hrt_master_port_load_16(addr)
+   _hrt_master_port_uload_16(addr)
+   _hrt_master_port_load_32(addr)
+   _hrt_master_port_uload_32(addr)
+   _hrt_master_port_store_8_volatile(addr,data)
+   _hrt_master_port_load_8_volatile(addr)
+   _hrt_master_port_uload_8_volatile(addr)
+   _hrt_master_port_store_16_volatile(addr,data)
+   _hrt_master_port_load_16_volatile(addr)
+   _hrt_master_port_uload_16_volatile(addr)
+   _hrt_master_port_store_32_volatile(addr,data)
+   _hrt_master_port_load_32_volatile(addr)
+   _hrt_master_port_uload_32_volatile(addr)
+   _hrt_mem_store(addr,data,size)
+   _hrt_mem_load(addr,data,size)
+   _hrt_mem_set(addr,val,size)
+*/
+
+#define hrt_master_port_store_8(addr, data) \
+       _hrt_master_port_store_8(addr, data)
+#define hrt_master_port_store_16(addr, data) \
+       _hrt_master_port_store_16(addr, data)
+#define hrt_master_port_store_32(addr, data) \
+       _hrt_master_port_store_32(addr, data)
+#define hrt_master_port_load_8(addr) \
+       _hrt_master_port_load_8(addr)
+#define hrt_master_port_load_16(addr) \
+       _hrt_master_port_load_16(addr)
+#define hrt_master_port_load_32(addr) \
+       _hrt_master_port_load_32(addr)
+#define hrt_master_port_uload_8(addr) \
+       _hrt_master_port_uload_8(addr)
+#define hrt_master_port_uload_16(addr) \
+       _hrt_master_port_uload_16(addr)
+#define hrt_master_port_uload_32(addr) \
+       _hrt_master_port_uload_32(addr)
+
+#define hrt_master_port_store(addr, data, bytes) \
+       _hrt_master_port_unaligned_store((void *)(addr), \
+                                       (const void *)(data), bytes)
+#define hrt_master_port_load(addr, data, bytes) \
+       _hrt_master_port_unaligned_load((const void *)(addr), \
+                                       (void *)(data), bytes)
+#define hrt_master_port_set(addr, data, bytes) \
+       _hrt_master_port_unaligned_set((void *)(addr), \
+                                       (int)(data), bytes)
+
+#ifdef HRT_HW
+/* on real hardware, we cannot print messages, so we get rid of them here. */
+#define _hrt_master_port_unaligned_store_msg(a, d, s, m) \
+       _hrt_master_port_unaligned_store(a, d, s)
+#define _hrt_master_port_unaligned_load_msg(a, d, s, m) \
+       _hrt_master_port_unaligned_load(a, d, s)
+#define _hrt_master_port_unaligned_set_msg(a, d, s, m) \
+       _hrt_master_port_unaligned_set(a, d, s)
+#define _hrt_master_port_store_8_msg(a, d, m) \
+       _hrt_master_port_store_8(a, d)
+#define _hrt_master_port_store_16_msg(a, d, m) \
+       _hrt_master_port_store_16(a, d)
+#define _hrt_master_port_store_32_msg(a, d, m) \
+       _hrt_master_port_store_32(a, d)
+#define _hrt_master_port_load_8_msg(a, m) \
+       _hrt_master_port_load_8(a)
+#define _hrt_master_port_load_16_msg(a, m) \
+       _hrt_master_port_load_16(a)
+#define _hrt_master_port_load_32_msg(a, m) \
+       _hrt_master_port_load_32(a)
+#define _hrt_master_port_uload_8_msg(a, m) \
+       _hrt_master_port_uload_8(a)
+#define _hrt_master_port_uload_16_msg(a, m) \
+       _hrt_master_port_uload_16(a)
+#define _hrt_master_port_uload_32_msg(a, m) \
+       _hrt_master_port_uload_32(a)
+#define _hrt_master_port_store_8_volatile_msg(a, d, m) \
+       _hrt_master_port_store_8_volatile(a, d)
+#define _hrt_master_port_load_8_volatile_msg(a, m) \
+       _hrt_master_port_load_8_volatile(a)
+#define _hrt_master_port_uload_8_volatile_msg(a, m) \
+       _hrt_master_port_uload_8_volatile(a)
+#define _hrt_master_port_store_16_volatile_msg(a, d, m) \
+       _hrt_master_port_store_16_volatile(a, d)
+#define _hrt_master_port_load_16_volatile_msg(a, m) \
+       _hrt_master_port_load_16_volatile(a)
+#define _hrt_master_port_uload_16_volatile_msg(a, m) \
+       _hrt_master_port_uload_16_volatile(a)
+#define _hrt_master_port_store_32_volatile_msg(a, d, m) \
+       _hrt_master_port_store_32_volatile(a, d)
+#define _hrt_master_port_load_32_volatile_msg(a, m) \
+       _hrt_master_port_load_32_volatile(a)
+#define _hrt_master_port_uload_32_volatile_msg(a, m) \
+       _hrt_master_port_uload_32_volatile(a)
+/* reduce number of functions */
+#define _hrt_master_port_unaligned_store(address, data, size) \
+       _hrt_mem_store(address, data, size)
+#define _hrt_master_port_unaligned_load(address, data, size) \
+       _hrt_mem_load(address, data, size)
+#define _hrt_master_port_unaligned_set(address, data, size) \
+       _hrt_mem_set(address, data, size)
+#endif /* HRT_HW */
+
+#if defined(__HIVECC)
+#include "master_port_hivecc.h"
+#elif defined(HRT_USE_VIR_ADDRS)
+/* do nothing, hrt backend is already included */
+#elif defined(HRT_HW)
+#include "master_port_hw.h"
+#else
+#include "master_port_sim.h"
+#endif
+
+#endif /* _HRT_MASTER_PORT_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/mmu_defs.h b/drivers/media/video/atomisp/css/hrt/mmu_defs.h
new file mode 100644 (file)
index 0000000..6aa8ed5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _mmu_defs_h
+#define _mmu_defs_h
+
+#define _HRT_MMU_INVALIDATE_TLB_REG_IDX          0
+#define _HRT_MMU_PAGE_TABLE_BASE_ADDRESS_REG_IDX 1
+
+#define _HRT_MMU_REG_ALIGN 4
+
+#endif /* _mmu_defs_h */
diff --git a/drivers/media/video/atomisp/css/hrt/scalar_processor_params.h b/drivers/media/video/atomisp/css/hrt/scalar_processor_params.h
new file mode 100644 (file)
index 0000000..2eb5166
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _scalar_processor_params_h
+#define _scalar_processor_params_h
+
+#include "cell_params.h"
+
+#endif /* _scalar_processor_params_h */
diff --git a/drivers/media/video/atomisp/css/hrt/sp.map.h b/drivers/media/video/atomisp/css/hrt/sp.map.h
new file mode 100644 (file)
index 0000000..7b1821f
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _SP_MAP_H_
+#define _SP_MAP_H_
+
+
+#ifndef _hrt_dummy_use_blob_sp
+#define _hrt_dummy_use_blob_sp()
+#endif
+
+#define _hrt_cell_load_program_sp(proc) \
+       _hrt_cell_load_program_from_elf_file(proc, "sp")
+
+#define HIVE_MEM_isp_vectors_per_input_line  scalar_processor_dmem
+#define HIVE_ADDR_isp_vectors_per_input_line 0xF38
+#define HIVE_SIZE_isp_vectors_per_input_line 4
+#define HIVE_MEM_sp_raw_copy_thread  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_thread 0xA8
+#define HIVE_SIZE_sp_raw_copy_thread 4
+#define HIVE_MEM_sp_input_v_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_input_v_addr 0xF3C
+#define HIVE_SIZE_sp_input_v_addr 4
+#define HIVE_MEM_dma_proxy_status  scalar_processor_dmem
+#define HIVE_ADDR_dma_proxy_status 0xCC
+#define HIVE_SIZE_dma_proxy_status 4
+#define HIVE_MEM_sp_bin_copy_bytes_available  scalar_processor_dmem
+#define HIVE_ADDR_sp_bin_copy_bytes_available 0x3914
+#define HIVE_SIZE_sp_bin_copy_bytes_available 4
+#define HIVE_MEM_sp_error  scalar_processor_dmem
+#define HIVE_ADDR_sp_error 0x39C0
+#define HIVE_SIZE_sp_error 4
+#define HIVE_MEM_sp_read_sp_group_from_ddr  scalar_processor_dmem
+#define HIVE_ADDR_sp_read_sp_group_from_ddr 0xF40
+#define HIVE_SIZE_sp_read_sp_group_from_ddr 4
+#define HIVE_MEM_sp_raw_copy_width  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_width 0x3990
+#define HIVE_SIZE_sp_raw_copy_width 4
+#define HIVE_MEM_sp_if_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_if_a 0x3928
+#define HIVE_SIZE_sp_if_a 48
+#define HIVE_MEM_sp_no_side_band  scalar_processor_dmem
+#define HIVE_ADDR_sp_no_side_band 0xF44
+#define HIVE_SIZE_sp_no_side_band 4
+#define HIVE_MEM_sp_raw_copy_max_input_width  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_max_input_width 0x3994
+#define HIVE_SIZE_sp_raw_copy_max_input_width 4
+#define HIVE_MEM_sp_ch_id  scalar_processor_dmem
+#define HIVE_ADDR_sp_ch_id 0xF48
+#define HIVE_SIZE_sp_ch_id 4
+#define HIVE_MEM_sp_sync_gen_vblank_cycles  scalar_processor_dmem
+#define HIVE_ADDR_sp_sync_gen_vblank_cycles 0xF4C
+#define HIVE_SIZE_sp_sync_gen_vblank_cycles 4
+#define HIVE_MEM_sp_prbs_seed  scalar_processor_dmem
+#define HIVE_ADDR_sp_prbs_seed 0xF50
+#define HIVE_SIZE_sp_prbs_seed 4
+#define HIVE_MEM_sp_tpg_x_mask  scalar_processor_dmem
+#define HIVE_ADDR_sp_tpg_x_mask 0xF54
+#define HIVE_SIZE_sp_tpg_x_mask 4
+#define HIVE_MEM_xmem_bin_addr  scalar_processor_dmem
+#define HIVE_ADDR_xmem_bin_addr 0xF58
+#define HIVE_SIZE_xmem_bin_addr 4
+#define HIVE_MEM_sp_fmt_type  scalar_processor_dmem
+#define HIVE_ADDR_sp_fmt_type 0xF5C
+#define HIVE_SIZE_sp_fmt_type 4
+#define HIVE_MEM_sp_uds_config  scalar_processor_dmem
+#define HIVE_ADDR_sp_uds_config 0x39B0
+#define HIVE_SIZE_sp_uds_config 16
+#define HIVE_MEM_sp_isp_started  scalar_processor_dmem
+#define HIVE_ADDR_sp_isp_started 0xF60
+#define HIVE_SIZE_sp_isp_started 4
+#define HIVE_MEM_sp_obarea_start_bq  scalar_processor_dmem
+#define HIVE_ADDR_sp_obarea_start_bq 0xF64
+#define HIVE_SIZE_sp_obarea_start_bq 4
+#define HIVE_MEM_sp_start_isp_thread  scalar_processor_dmem
+#define HIVE_ADDR_sp_start_isp_thread 0x188
+#define HIVE_SIZE_sp_start_isp_thread 4
+#define HIVE_MEM_sp_proxy_thread  scalar_processor_dmem
+#define HIVE_ADDR_sp_proxy_thread 0xD4
+#define HIVE_SIZE_sp_proxy_thread 4
+#define HIVE_MEM_sp_bin_copy_bytes_copied  scalar_processor_dmem
+#define HIVE_ADDR_sp_bin_copy_bytes_copied 0x3918
+#define HIVE_SIZE_sp_bin_copy_bytes_copied 4
+#define HIVE_MEM_sp_raw_copy_height  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_height 0x3998
+#define HIVE_SIZE_sp_raw_copy_height 4
+#define HIVE_MEM_sp_raw_copy_out  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_out 0x399C
+#define HIVE_SIZE_sp_raw_copy_out 4
+#define HIVE_MEM_isp_sh_dma_cmd_buffer  scalar_processor_dmem
+#define HIVE_ADDR_isp_sh_dma_cmd_buffer 0x39C4
+#define HIVE_SIZE_isp_sh_dma_cmd_buffer 4
+#define HIVE_MEM_sp_overlay_bg_u  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_bg_u 0xF68
+#define HIVE_SIZE_sp_overlay_bg_u 4
+#define HIVE_MEM_vf_pp_args  scalar_processor_dmem
+#define HIVE_ADDR_vf_pp_args 0x3B20
+#define HIVE_SIZE_vf_pp_args 76
+#define HIVE_MEM_sp_sync_gen_width  scalar_processor_dmem
+#define HIVE_ADDR_sp_sync_gen_width 0xF6C
+#define HIVE_SIZE_sp_sync_gen_width 4
+#define HIVE_ADDR_vf_pp_dynamic_entry 0x16C7
+#define HIVE_MEM_current_thread  scalar_processor_dmem
+#define HIVE_ADDR_current_thread 0x39A8
+#define HIVE_SIZE_current_thread 4
+#define HIVE_MEM_sp_dma_output_block_width_b  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_output_block_width_b 0x3A08
+#define HIVE_SIZE_sp_dma_output_block_width_b 4
+#define HIVE_ADDR_sp_raw_copy_entry 0x486
+#define HIVE_MEM_sp_tpg_x_delta  scalar_processor_dmem
+#define HIVE_ADDR_sp_tpg_x_delta 0xF70
+#define HIVE_SIZE_sp_tpg_x_delta 4
+#define HIVE_ADDR_sp_init_dmem_entry 0x77
+#define HIVE_MEM_sp_overlay_v_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_v_addr 0xF74
+#define HIVE_SIZE_sp_overlay_v_addr 4
+#define HIVE_MEM_sp_obarea_length_bq  scalar_processor_dmem
+#define HIVE_ADDR_sp_obarea_length_bq 0xF78
+#define HIVE_SIZE_sp_obarea_length_bq 4
+#define HIVE_MEM_capture_pp_args  scalar_processor_dmem
+#define HIVE_ADDR_capture_pp_args 0x3B6C
+#define HIVE_SIZE_capture_pp_args 12
+#define HIVE_MEM_vtmp4  scalar_processor_dmem
+#define HIVE_ADDR_vtmp4 0xF7C
+#define HIVE_SIZE_vtmp4 512
+#define HIVE_MEM_sp_bin_copy_out  scalar_processor_dmem
+#define HIVE_ADDR_sp_bin_copy_out 0x391C
+#define HIVE_SIZE_sp_bin_copy_out 4
+#define HIVE_MEM_sp_dma_crop_block_width_b  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_crop_block_width_b 0x3A0C
+#define HIVE_SIZE_sp_dma_crop_block_width_b 4
+#define HIVE_MEM_sp_overlay_start_x  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_start_x 0x117C
+#define HIVE_SIZE_sp_overlay_start_x 4
+#define HIVE_MEM_sp_output_v_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_output_v_addr 0x1180
+#define HIVE_SIZE_sp_output_v_addr 4
+#define HIVE_ADDR_sp_start_isp_entry 0x0
+#define HIVE_MEM_sp_no_dma_proxy  scalar_processor_dmem
+#define HIVE_ADDR_sp_no_dma_proxy 0x440
+#define HIVE_SIZE_sp_no_dma_proxy 4
+#define HIVE_MEM_sp_raw_copy_padded_width  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_padded_width 0x39A0
+#define HIVE_SIZE_sp_raw_copy_padded_width 4
+#define HIVE_MEM_sp_current_isp_program  scalar_processor_dmem
+#define HIVE_ADDR_sp_current_isp_program 0xF34
+#define HIVE_SIZE_sp_current_isp_program 4
+#define HIVE_MEM_sp_dma_crop_block_width_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_crop_block_width_a 0x3A10
+#define HIVE_SIZE_sp_dma_crop_block_width_a 4
+#define HIVE_MEM_sp_dma_c_block_width_b  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_c_block_width_b 0x3A14
+#define HIVE_SIZE_sp_dma_c_block_width_b 4
+#define HIVE_MEM_isp_vectors_per_line  scalar_processor_dmem
+#define HIVE_ADDR_isp_vectors_per_line 0x1184
+#define HIVE_SIZE_isp_vectors_per_line 4
+#define HIVE_MEM_sp_ddr_data_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_ddr_data_addr 0x1188
+#define HIVE_SIZE_sp_ddr_data_addr 4
+#define HIVE_ADDR_sp_gen_histogram_entry 0x353
+#define HIVE_MEM_sp_group  scalar_processor_dmem
+#define HIVE_ADDR_sp_group 0x118C
+#define HIVE_SIZE_sp_group 1160
+#define HIVE_MEM_isp_uv_internal_width_vecs  scalar_processor_dmem
+#define HIVE_ADDR_isp_uv_internal_width_vecs 0x1614
+#define HIVE_SIZE_isp_uv_internal_width_vecs 4
+#define HIVE_MEM_sp_input_y_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_input_y_addr 0x1618
+#define HIVE_SIZE_sp_input_y_addr 4
+#define HIVE_MEM_sp_dmem_data_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_dmem_data_addr 0x161C
+#define HIVE_SIZE_sp_dmem_data_addr 4
+#define HIVE_MEM_sp_sw_interrupt_value  scalar_processor_dmem
+#define HIVE_ADDR_sp_sw_interrupt_value 0x1620
+#define HIVE_SIZE_sp_sw_interrupt_value 4
+#define HIVE_MEM_histogram_args  scalar_processor_dmem
+#define HIVE_ADDR_histogram_args 0x3920
+#define HIVE_SIZE_histogram_args 4
+#define HIVE_MEM_sp_bss_size  scalar_processor_dmem
+#define HIVE_ADDR_sp_bss_size 0x1624
+#define HIVE_SIZE_sp_bss_size 4
+#define HIVE_ADDR_capture_pp_dynamic_entry 0x37F7
+#define HIVE_MEM_sp_tpg_y_delta  scalar_processor_dmem
+#define HIVE_ADDR_sp_tpg_y_delta 0x1628
+#define HIVE_SIZE_sp_tpg_y_delta 4
+#define HIVE_MEM_sp_overlay_width  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_width 0x162C
+#define HIVE_SIZE_sp_overlay_width 4
+#define HIVE_MEM_isp_sdis_horiproj_num  scalar_processor_dmem
+#define HIVE_ADDR_isp_sdis_horiproj_num 0x1630
+#define HIVE_SIZE_isp_sdis_horiproj_num 4
+#define HIVE_MEM_sp_dma_output_block_width_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_output_block_width_a 0x3A18
+#define HIVE_SIZE_sp_dma_output_block_width_a 4
+#define HIVE_MEM_sp_input_mode  scalar_processor_dmem
+#define HIVE_ADDR_sp_input_mode 0x1634
+#define HIVE_SIZE_sp_input_mode 4
+#define HIVE_MEM_sp_tpg_xy_mask  scalar_processor_dmem
+#define HIVE_ADDR_sp_tpg_xy_mask 0x1638
+#define HIVE_SIZE_sp_tpg_xy_mask 4
+#define HIVE_MEM_sp_overlay_start_y  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_start_y 0x163C
+#define HIVE_SIZE_sp_overlay_start_y 4
+#define HIVE_MEM_sp_sp_group_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_sp_group_addr 0x1640
+#define HIVE_SIZE_sp_sp_group_addr 4
+#define HIVE_MEM_sp_data_size  scalar_processor_dmem
+#define HIVE_ADDR_sp_data_size 0x1644
+#define HIVE_SIZE_sp_data_size 4
+#define HIVE_MEM_num_sp_threads  scalar_processor_dmem
+#define HIVE_ADDR_num_sp_threads 0x39AC
+#define HIVE_SIZE_num_sp_threads 4
+#define HIVE_MEM_sp_output_y_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_output_y_addr 0x1648
+#define HIVE_SIZE_sp_output_y_addr 4
+#define HIVE_MEM_bayer_conf  scalar_processor_dmem
+#define HIVE_ADDR_bayer_conf 0x18C
+#define HIVE_SIZE_bayer_conf 56
+#define HIVE_MEM_sp_proxy_busy_wait  scalar_processor_dmem
+#define HIVE_ADDR_sp_proxy_busy_wait 0x528
+#define HIVE_SIZE_sp_proxy_busy_wait 4
+#define HIVE_MEM_sp_sync_gen_hblank_cycles  scalar_processor_dmem
+#define HIVE_ADDR_sp_sync_gen_hblank_cycles 0x164C
+#define HIVE_SIZE_sp_sync_gen_hblank_cycles 4
+#define HIVE_MEM_isp_sdis_vertproj_num  scalar_processor_dmem
+#define HIVE_ADDR_isp_sdis_vertproj_num 0x1650
+#define HIVE_SIZE_isp_sdis_vertproj_num 4
+#define HIVE_MEM_sp_sync_gen_height  scalar_processor_dmem
+#define HIVE_ADDR_sp_sync_gen_height 0x1654
+#define HIVE_SIZE_sp_sync_gen_height 4
+#define HIVE_MEM_sp_program_input_circuit  scalar_processor_dmem
+#define HIVE_ADDR_sp_program_input_circuit 0x1658
+#define HIVE_SIZE_sp_program_input_circuit 4
+#define HIVE_MEM_sp_if_b_changed  scalar_processor_dmem
+#define HIVE_ADDR_sp_if_b_changed 0x3958
+#define HIVE_SIZE_sp_if_b_changed 4
+#define HIVE_MEM_sp_dma_c_block_width_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_c_block_width_a 0x3A1C
+#define HIVE_SIZE_sp_dma_c_block_width_a 4
+#define HIVE_MEM_sp_dma_crop_cropping_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_crop_cropping_a 0x3A20
+#define HIVE_SIZE_sp_dma_crop_cropping_a 4
+#define HIVE_MEM_sp_dma_output_skip_vecs  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_output_skip_vecs 0x3A24
+#define HIVE_SIZE_sp_dma_output_skip_vecs 4
+#define HIVE_MEM_sp_vf_downscale_bits  scalar_processor_dmem
+#define HIVE_ADDR_sp_vf_downscale_bits 0x165C
+#define HIVE_SIZE_sp_vf_downscale_bits 4
+#define HIVE_MEM_isp_sdis_vertcoef_vectors  scalar_processor_dmem
+#define HIVE_ADDR_isp_sdis_vertcoef_vectors 0x1660
+#define HIVE_SIZE_isp_sdis_vertcoef_vectors 4
+#define HIVE_MEM_sp_overlay_bg_v  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_bg_v 0x1664
+#define HIVE_SIZE_sp_overlay_bg_v 4
+#define HIVE_MEM_sp_output_u_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_output_u_addr 0x1668
+#define HIVE_SIZE_sp_output_u_addr 4
+#define HIVE_MEM_output_dma_info_descr  scalar_processor_dmem
+#define HIVE_ADDR_output_dma_info_descr 0x3AD8
+#define HIVE_SIZE_output_dma_info_descr 72
+#define HIVE_MEM_sp_isp_input_stream_format  scalar_processor_dmem
+#define HIVE_ADDR_sp_isp_input_stream_format 0x166C
+#define HIVE_SIZE_sp_isp_input_stream_format 4
+#define HIVE_MEM_curr_binary_id  scalar_processor_dmem
+#define HIVE_ADDR_curr_binary_id 0x0
+#define HIVE_SIZE_curr_binary_id 4
+#define HIVE_MEM_sp_dma_c_skip_vecs  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_c_skip_vecs 0x3A28
+#define HIVE_SIZE_sp_dma_c_skip_vecs 4
+#define HIVE_MEM_sp_dma_vfout_cropping_a  scalar_processor_dmem
+#define HIVE_ADDR_sp_dma_vfout_cropping_a 0x3A2C
+#define HIVE_SIZE_sp_dma_vfout_cropping_a 4
+#define HIVE_MEM_sp_overlay_bg_y  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_bg_y 0x1670
+#define HIVE_SIZE_sp_overlay_bg_y 4
+#define HIVE_MEM_sp_histo_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_histo_addr 0x3924
+#define HIVE_SIZE_sp_histo_addr 4
+#define HIVE_MEM_sp_overlay_u_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_u_addr 0x1674
+#define HIVE_SIZE_sp_overlay_u_addr 4
+#define HIVE_MEM_sp_input_u_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_input_u_addr 0x1678
+#define HIVE_SIZE_sp_input_u_addr 4
+#define HIVE_MEM_sp_tpg_y_mask  scalar_processor_dmem
+#define HIVE_ADDR_sp_tpg_y_mask 0x167C
+#define HIVE_SIZE_sp_tpg_y_mask 4
+#define HIVE_MEM_sp_si  scalar_processor_dmem
+#define HIVE_ADDR_sp_si 0x3A30
+#define HIVE_SIZE_sp_si 68
+#define HIVE_MEM_sp_debug  scalar_processor_dmem
+#define HIVE_ADDR_sp_debug 0x39C8
+#define HIVE_SIZE_sp_debug 64
+#define HIVE_MEM_sp_raw_copy_raw_bit_depth  scalar_processor_dmem
+#define HIVE_ADDR_sp_raw_copy_raw_bit_depth 0x39A4
+#define HIVE_SIZE_sp_raw_copy_raw_bit_depth 4
+#define HIVE_MEM_sp_overlay_y_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_y_addr 0x1680
+#define HIVE_SIZE_sp_overlay_y_addr 4
+#define HIVE_MEM_isp_sdis_horicoef_vectors  scalar_processor_dmem
+#define HIVE_ADDR_isp_sdis_horicoef_vectors 0x1684
+#define HIVE_SIZE_isp_sdis_horicoef_vectors 4
+#define HIVE_MEM_sp_if_b  scalar_processor_dmem
+#define HIVE_ADDR_sp_if_b 0x395C
+#define HIVE_SIZE_sp_if_b 48
+#define HIVE_MEM_sp_dmem_bss_addr  scalar_processor_dmem
+#define HIVE_ADDR_sp_dmem_bss_addr 0x1688
+#define HIVE_SIZE_sp_dmem_bss_addr 4
+#define HIVE_MEM_sp_data  scalar_processor_dmem
+#define HIVE_ADDR_sp_data 0x168C
+#define HIVE_SIZE_sp_data 8704
+#define HIVE_MEM_sp_overlay_height  scalar_processor_dmem
+#define HIVE_ADDR_sp_overlay_height 0x388C
+#define HIVE_SIZE_sp_overlay_height 4
+#define HIVE_MEM_dma_proxy_kill_req  scalar_processor_dmem
+#define HIVE_ADDR_dma_proxy_kill_req 0x524
+#define HIVE_SIZE_dma_proxy_kill_req 1
+#define HIVE_MEM_mem_map  scalar_processor_dmem
+#define HIVE_ADDR_mem_map 0x3A74
+#define HIVE_SIZE_mem_map 100
+#define HIVE_MEM_sp_proxy_running  scalar_processor_dmem
+#define HIVE_ADDR_sp_proxy_running 0x52C
+#define HIVE_SIZE_sp_proxy_running 4
+#define HIVE_MEM_sp_if_a_changed  scalar_processor_dmem
+#define HIVE_ADDR_sp_if_a_changed 0x398C
+#define HIVE_SIZE_sp_if_a_changed 4
+#define HIVE_MEM_vtmp1  scalar_processor_dmem
+#define HIVE_ADDR_vtmp1 0x3890
+#define HIVE_SIZE_vtmp1 128
+#define HIVE_MEM_isp_vf_output_width_vecs  scalar_processor_dmem
+#define HIVE_ADDR_isp_vf_output_width_vecs 0x3910
+#define HIVE_SIZE_isp_vf_output_width_vecs 4
+#define HIVE_ADDR_sp_bin_copy_entry 0x2D8
+
+#endif /* _SP_MAP_H_ */
diff --git a/drivers/media/video/atomisp/css/hrt/sp_hrt.h b/drivers/media/video/atomisp/css/hrt/sp_hrt.h
new file mode 100644 (file)
index 0000000..809e9a3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _sp_hrt_h_
+#define _sp_hrt_h_
+
+#define hrt_sp_dmem(cell) HRT_PROC_TYPE_PROP(cell, _dmem)
+
+#define hrt_sp_dmem_master_port_address(cell) \
+       hrt_mem_master_port_address(cell, hrt_sp_dmem(cell))
+
+#endif /* _sp_hrt_h_ */
diff --git a/drivers/media/video/atomisp/css/hrt/streaming_to_mipi_defs.h b/drivers/media/video/atomisp/css/hrt/streaming_to_mipi_defs.h
new file mode 100644 (file)
index 0000000..2826ce8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _streaming_to_mipi_defs_h
+#define _streaming_to_mipi_defs_h
+
+#define HIVE_STR_TO_MIPI_VALID_A_BIT 0
+#define HIVE_STR_TO_MIPI_VALID_B_BIT 1
+#define HIVE_STR_TO_MIPI_SOL_BIT     2
+#define HIVE_STR_TO_MIPI_EOL_BIT     3
+#define HIVE_STR_TO_MIPI_SOF_BIT     4
+#define HIVE_STR_TO_MIPI_EOF_BIT     5
+#define HIVE_STR_TO_MIPI_CH_ID_LSB   6
+
+#define HIVE_STR_TO_MIPI_DATA_A_LSB  (HIVE_STR_TO_MIPI_VALID_B_BIT + 1)
+
+#endif /* _streaming_to_mipi_defs_h */
diff --git a/drivers/media/video/atomisp/css/sh_css.c b/drivers/media/video/atomisp/css/sh_css.c
new file mode 100644 (file)
index 0000000..b0b68ff
--- /dev/null
@@ -0,0 +1,4699 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css.h"
+#include "sh_css_hrt.h"
+#include "sh_css_binary.h"
+#include "sh_css_internal.h"
+#include "sh_css_sp.h"
+#include "sh_css_hw.h"
+#include "sh_css_rx.h"
+#include "sh_css_defs.h"
+#include "sh_css_firmware.h"
+#include "sh_css_binary_info.h"
+#include "sh_css_accelerate.h"
+
+#define WITH_PC_MONITORING  0
+
+#if WITH_PC_MONITORING
+#define MULTIPLE_SAMPLES 1
+#define NOF_SAMPLES      60
+#include "linux/kthread.h"
+#include "linux/sched.h"
+#include "linux/delay.h"
+#include "sh_css_metrics.h"
+
+static int thread_alive;
+#endif
+
+/* Name of the sp program: should not be built-in */
+#define SP_PROG_NAME "sp"
+
+/* for JPEG, we don't know the length of the image upfront,
+ * but since we support sensor upto 16MP, we take this as
+ * upper limit.
+ */
+#define JPEG_BYTES (16 * 1024 * 1024)
+
+#define NUM_REF_FRAMES         2
+#define NUM_CONTINUOUS_FRAMES  2
+#define NUM_TNR_FRAMES         2
+
+#define IS_ODD(a)              ((a) & 0x1)
+
+#define DEFAULT_FRAME_INFO \
+{ \
+       .width           = 0, \
+       .height          = 0, \
+       .format          = SH_CSS_FRAME_FORMAT_YUV420, \
+       .raw_bit_depth   = 0, \
+       .raw_bayer_order = sh_css_bayer_order_grbg, \
+}
+
+#define DEFAULT_IF_CONFIG \
+{ \
+       .start_line      = 0, \
+       .start_column    = 0, \
+       .left_padding    = 0, \
+       .cropped_height  = 0, \
+       .cropped_width   = 0, \
+       .deinterleaving  = 0, \
+       .buf_vecs        = 0, \
+       .buf_start_index = 0, \
+       .buf_increment   = 0, \
+       .buf_eol_offset  = 0, \
+       .yuv420          = false, \
+       .block_no_reqs   = false, \
+}
+
+enum sh_css_mode {
+       sh_css_mode_preview,
+       sh_css_mode_video,
+       sh_css_mode_capture
+};
+
+enum sh_css_state {
+       sh_css_state_idle,
+       sh_css_state_executing_isp,
+       sh_css_state_executing_sp_bin_copy,
+};
+
+struct sh_css_pipeline_stage {
+       struct sh_css_binary        *binary;      /* built-in binary */
+       struct sh_css_binary_args    args;
+       const struct sh_css_acc_fw  *firmware; /* acceleration binary */
+       int                          mode;
+       bool                         out_frame_allocated;
+       bool                         vf_frame_allocated;
+       struct sh_css_pipeline_stage *next;
+};
+
+struct sh_css_pipeline {
+       unsigned int length;
+       struct sh_css_pipeline_stage *stages;
+       bool reload;
+       struct sh_css_pipeline_stage *current_stage;
+};
+
+struct sh_css_preview_settings {
+       struct sh_css_frame_info output_info;
+       /* resolution before yuv downscaling */
+       struct sh_css_frame_info pp_input_info;
+       struct sh_css_pipeline pipeline;
+       struct sh_css_binary copy_binary;
+       struct sh_css_binary preview_binary;
+       struct sh_css_binary vf_pp_binary;
+       struct sh_css_frame *ref_frames[NUM_REF_FRAMES];
+       unsigned int prev_ref_frame;
+       struct sh_css_frame *continuous_frames[NUM_CONTINUOUS_FRAMES];
+       unsigned int continuous_frame;
+       bool online;
+       struct sh_css_shading_table *shading_table;
+       bool zoom_changed;
+};
+
+#define DEFAULT_PREVIEW_SETTINGS \
+{ \
+       .output_info       = DEFAULT_FRAME_INFO, \
+       .pp_input_info     = DEFAULT_FRAME_INFO, \
+       .online            = true, \
+}
+
+struct sh_css_capture_settings {
+       enum sh_css_capture_mode mode;
+       bool xnr;
+       bool bayer_ds;
+       struct sh_css_binary copy_binary;
+       struct sh_css_binary primary_binary;
+       struct sh_css_binary pre_gdc_binary;
+       struct sh_css_binary gdc_binary;
+       struct sh_css_binary post_gdc_binary;
+       struct sh_css_binary pre_anr_binary;
+       struct sh_css_binary anr_binary;
+       struct sh_css_binary post_anr_binary;
+       struct sh_css_binary capture_pp_binary;
+       struct sh_css_binary vf_pp_binary;
+       /* resolution before yuv downscaling */
+       struct sh_css_frame_info pp_input_info;
+       struct sh_css_frame_info output_info;
+       struct sh_css_frame_info vf_info;
+       struct sh_css_pipeline pipeline;
+       struct sh_css_frame *capture_pp_frame;
+       struct sh_css_frame *output_frame;
+       bool online;
+       bool need_pp;
+       struct sh_css_shading_table *shading_table;
+       bool zoom_changed;
+};
+
+#define DEFAULT_CAPTURE_SETTINGS \
+{ \
+       .mode              = SH_CSS_CAPTURE_MODE_PRIMARY, \
+       .xnr               = false, \
+       .bayer_ds          = false, \
+       .pp_input_info     = DEFAULT_FRAME_INFO, \
+       .output_info       = DEFAULT_FRAME_INFO, \
+       .vf_info           = DEFAULT_FRAME_INFO, \
+       .online            = true, \
+       .need_pp           = false, \
+}
+
+#define NUM_VIDEO_REF_FRAMES 2
+#define NUM_VIDEO_TNR_FRAMES 2
+
+struct sh_css_video_settings {
+       struct sh_css_binary video_binary;
+       struct sh_css_binary vf_pp_binary;
+       struct sh_css_frame_info output_info;
+       struct sh_css_frame_info vf_info;
+       struct sh_css_frame *ref_frames[NUM_VIDEO_REF_FRAMES];
+       unsigned int         prev_ref_frame;
+       struct sh_css_frame *tnr_frames[NUM_VIDEO_TNR_FRAMES];
+       unsigned int         prev_tnr_frame;
+       int dvs_vector_x;
+       int dvs_vector_y;
+       unsigned int dvs_envelope_width;
+       unsigned int dvs_envelope_height;
+       struct sh_css_frame *vf_pp_in_frame;
+       struct sh_css_pipeline pipeline;
+       struct sh_css_shading_table *shading_table;
+       bool zoom_changed;
+};
+
+#define DEFAULT_VIDEO_SETTINGS \
+{ \
+       .output_info         = DEFAULT_FRAME_INFO, \
+       .vf_info             = DEFAULT_FRAME_INFO, \
+}
+
+struct sh_css {
+       struct sh_css_preview_settings preview_settings;
+       struct sh_css_capture_settings capture_settings;
+       struct sh_css_video_settings   video_settings;
+       unsigned int                   ch_id;
+       unsigned int                   input_width;
+       unsigned int                   input_height;
+       struct sh_css_frame_info       input_effective_info;
+       enum sh_css_input_format       input_format;
+       enum sh_css_mode               mode;
+       struct sh_css_mipi_config      mipi_config;
+       bool                           reconfigure_css_rx;
+       bool                           invalidate;
+       void *(*malloc) (size_t size);
+       void (*free) (void *ptr);
+       enum sh_css_state              state;
+       bool                           two_ppc;
+       enum sh_css_bayer_order        bayer_order;
+       unsigned int                   sensor_binning;
+       bool                           irq_edge;
+       const struct sh_css_overlay   *vf_overlay;
+       bool                           vf_overlay_changed;
+       struct sh_css_if_config        curr_if_a_config;
+       struct sh_css_if_config        curr_if_b_config;
+       unsigned int                   curr_fmt_type;
+       unsigned int                   curr_ch_id;
+       enum sh_css_input_mode         curr_input_mode;
+       enum sh_css_input_mode         input_mode;
+       bool                           check_system_idle;
+       unsigned int                   curr_dx;
+       unsigned int                   curr_dy;
+       bool                           continuous;
+       bool                           start_sp_copy;
+       bool                           disable_vf_pp;
+       bool                           disable_capture_pp;
+       const struct sh_css_shading_table *shading_table;
+       void                          *sp_bin_addr;
+       struct sh_css_acc_fw          *output_stage;    /* extra output stage */
+       struct sh_css_acc_fw          *vf_stage;        /* extra vf stage */
+       void                          *page_table_base_address;
+       bool capture_zoom_update;
+       bool preview_zoom_update;
+       bool video_zoom_update;
+};
+
+#define DEFAULT_MIPI_CONFIG \
+{ \
+       .port            = SH_CSS_MIPI_PORT_1LANE, \
+       .num_lanes       = 1, \
+       .timeout         = 0xffff4, \
+       .comp_bpp        = 0, \
+       .uncomp_bpp      = 0, \
+       .comp            = SH_CSS_MIPI_COMPRESSION_NONE, \
+       .two_ppc         = false, \
+}
+
+#define DEFAULT_CSS \
+{ \
+       .preview_settings     = DEFAULT_PREVIEW_SETTINGS, \
+       .capture_settings     = DEFAULT_CAPTURE_SETTINGS, \
+       .video_settings       = DEFAULT_VIDEO_SETTINGS, \
+       .ch_id                = 0, \
+       .input_width          = 0, \
+       .input_height         = 0, \
+       .input_effective_info = DEFAULT_FRAME_INFO, \
+       .input_format         = SH_CSS_INPUT_FORMAT_RAW_10, \
+       .mode                 = -1, \
+       .mipi_config          = DEFAULT_MIPI_CONFIG, \
+       .reconfigure_css_rx   = true, \
+       .invalidate           = false, \
+       .malloc               = NULL, \
+       .free                 = NULL, \
+       .state                = sh_css_state_idle, \
+       .two_ppc              = false, \
+       .bayer_order          = sh_css_bayer_order_grbg, \
+       .sensor_binning       = 0, \
+       .vf_overlay           = NULL, \
+       .vf_overlay_changed   = false, \
+       .curr_if_a_config     = DEFAULT_IF_CONFIG, \
+       .curr_if_b_config     = DEFAULT_IF_CONFIG, \
+       .curr_fmt_type        = -1, /* trigger first configuration */ \
+       .curr_ch_id           = 0, \
+       .curr_input_mode      = SH_CSS_INPUT_MODE_SENSOR, \
+       .input_mode           = SH_CSS_INPUT_MODE_SENSOR, \
+       .check_system_idle    = true, \
+       .curr_dx              = 64, \
+       .curr_dy              = 64, \
+       .continuous           = false, \
+       .start_sp_copy        = false, \
+       .disable_vf_pp        = false, \
+       .disable_capture_pp   = false, \
+       .shading_table        = NULL, \
+       .sp_bin_addr          = NULL, \
+       .page_table_base_address = NULL, \
+       .capture_zoom_update = false, \
+       .preview_zoom_update = false, \
+       .video_zoom_update = false, \
+}
+
+int (*sh_css_printf) (const char *fmt, ...) = NULL;
+
+static struct sh_css my_css;
+/* static variables, temporarily used in load_<mode>_binaries.
+   Declaring these inside the functions increases the size of the
+   stack frames beyond the acceptable 128 bytes. */
+static struct sh_css_binary_descr preview_descr,
+                                 vf_pp_descr,
+                                 copy_descr,
+                                 prim_descr,
+                                 pre_gdc_descr,
+                                 gdc_descr,
+                                 post_gdc_descr,
+                                 pre_anr_descr,
+                                 anr_descr,
+                                 post_anr_descr,
+                                 video_descr,
+                                 capture_pp_descr;
+
+static enum sh_css_err
+check_frame_info(struct sh_css_frame_info *info)
+{
+       if (info->width == 0 || info->height == 0)
+               return sh_css_err_illegal_resolution;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+check_vf_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+       err = check_frame_info(info);
+       if (err != sh_css_success)
+               return err;
+       if (info->width > ISP_VF_PP_MAX_OUTPUT_WIDTH*2)
+               return sh_css_err_viewfinder_resolution_too_wide;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+check_vf_out_info(struct sh_css_frame_info *out_info,
+                 struct sh_css_frame_info *vf_info)
+{
+       enum sh_css_err err;
+       err = check_frame_info(out_info);
+       if (err != sh_css_success)
+               return err;
+       err = check_vf_info(vf_info);
+       if (err != sh_css_success)
+               return err;
+       if (vf_info->width > out_info->width ||
+           vf_info->height > out_info->height)
+               return sh_css_err_viewfinder_resolution_exceeds_output;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+check_res(unsigned int width, unsigned int height)
+{
+       if (width  == 0   ||
+           height == 0   ||
+           IS_ODD(width) ||
+           IS_ODD(height)) {
+               return sh_css_err_illegal_resolution;
+       }
+       return sh_css_success;
+}
+
+static enum sh_css_err
+check_null_res(unsigned int width, unsigned int height)
+{
+       if (IS_ODD(width) || IS_ODD(height))
+               return sh_css_err_illegal_resolution;
+
+       return sh_css_success;
+}
+
+static bool
+input_format_is_raw(enum sh_css_input_format format)
+{
+       return format == SH_CSS_INPUT_FORMAT_RAW_6 ||
+           format == SH_CSS_INPUT_FORMAT_RAW_7 ||
+           format == SH_CSS_INPUT_FORMAT_RAW_8 ||
+           format == SH_CSS_INPUT_FORMAT_RAW_10 ||
+           format == SH_CSS_INPUT_FORMAT_RAW_12;
+       /* raw_14 and raw_16 are not supported as input formats to the ISP.
+        * They can only be copied to a frame in memory using the
+        * copy binary.
+        */
+}
+
+static bool
+input_format_is_yuv(enum sh_css_input_format format)
+{
+       return format == SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY ||
+           format == SH_CSS_INPUT_FORMAT_YUV420_8 ||
+           format == SH_CSS_INPUT_FORMAT_YUV420_10 ||
+           format == SH_CSS_INPUT_FORMAT_YUV422_8 ||
+           format == SH_CSS_INPUT_FORMAT_YUV422_10;
+}
+
+static enum sh_css_err
+check_input(bool must_be_raw)
+{
+       if (my_css.input_effective_info.width == 0 ||
+           my_css.input_effective_info.height == 0) {
+               return sh_css_err_effective_input_resolution_not_set;
+       }
+       if (must_be_raw &&
+           !input_format_is_raw(my_css.input_format)) {
+               return sh_css_err_unsupported_input_format;
+       }
+       return sh_css_success;
+}
+
+/* we don't compare the height here since the output frame is usually
+   a couple of lines bigger than the height of the binary info.
+   For the padded width however, we do check equility because this is
+   not expected to differ. A difference there would indicate an erroneous
+   situation. */
+static bool
+check_infos_match(struct sh_css_frame_info *frame_info,
+                 struct sh_css_frame_info *binary_info)
+{
+       if (frame_info->padded_width != binary_info->padded_width ||
+           frame_info->height       <  binary_info->height       ||
+           frame_info->format       != binary_info->format) {
+               return sh_css_err_frames_mismatch;
+       }
+       return sh_css_success;
+}
+
+/* Input network configuration functions */
+static void
+get_copy_out_frame_format(enum sh_css_frame_format *format)
+{
+       switch (my_css.input_format) {
+       case SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY:
+       case SH_CSS_INPUT_FORMAT_YUV420_8:
+               *format = SH_CSS_FRAME_FORMAT_YUV420;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV420_10:
+               *format = SH_CSS_FRAME_FORMAT_YUV420_16;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV422_8:
+               *format = SH_CSS_FRAME_FORMAT_YUV422;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV422_10:
+               *format = SH_CSS_FRAME_FORMAT_YUV422_16;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_444:
+       case SH_CSS_INPUT_FORMAT_RGB_555:
+       case SH_CSS_INPUT_FORMAT_RGB_565:
+               if (*format != SH_CSS_FRAME_FORMAT_RGBA888)
+                       *format = SH_CSS_FRAME_FORMAT_RGB565;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_666:
+       case SH_CSS_INPUT_FORMAT_RGB_888:
+               *format = SH_CSS_FRAME_FORMAT_RGBA888;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_6:
+       case SH_CSS_INPUT_FORMAT_RAW_7:
+       case SH_CSS_INPUT_FORMAT_RAW_8:
+       case SH_CSS_INPUT_FORMAT_RAW_10:
+       case SH_CSS_INPUT_FORMAT_RAW_12:
+       case SH_CSS_INPUT_FORMAT_RAW_14:
+       case SH_CSS_INPUT_FORMAT_RAW_16:
+               if (*format != SH_CSS_FRAME_FORMAT_RAW)
+                       *format = SH_CSS_FRAME_FORMAT_RAW;
+               break;
+       case SH_CSS_INPUT_FORMAT_BINARY_8:
+               *format = SH_CSS_FRAME_FORMAT_BINARY_8;
+               break;
+       }
+}
+
+unsigned int
+sh_css_input_format_bits_per_pixel(enum sh_css_input_format format,
+                                  bool two_ppc)
+{
+       switch (format) {
+       case SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY:
+       case SH_CSS_INPUT_FORMAT_YUV420_8:
+       case SH_CSS_INPUT_FORMAT_YUV422_8:
+       case SH_CSS_INPUT_FORMAT_RGB_888:
+       case SH_CSS_INPUT_FORMAT_RAW_8:
+       case SH_CSS_INPUT_FORMAT_BINARY_8:
+               return 8;
+       case SH_CSS_INPUT_FORMAT_YUV420_10:
+       case SH_CSS_INPUT_FORMAT_YUV422_10:
+       case SH_CSS_INPUT_FORMAT_RAW_10:
+               return 10;
+       case SH_CSS_INPUT_FORMAT_RGB_444:
+               return 4;
+       case SH_CSS_INPUT_FORMAT_RGB_555:
+               return 5;
+       case SH_CSS_INPUT_FORMAT_RGB_565:
+               return 565;
+       case SH_CSS_INPUT_FORMAT_RGB_666:
+       case SH_CSS_INPUT_FORMAT_RAW_6:
+               return 6;
+       case SH_CSS_INPUT_FORMAT_RAW_7:
+               return 7;
+       case SH_CSS_INPUT_FORMAT_RAW_12:
+               return 12;
+       case SH_CSS_INPUT_FORMAT_RAW_14:
+               if (two_ppc)
+                       return 14;
+               else
+                       return 12;
+       case SH_CSS_INPUT_FORMAT_RAW_16:
+               if (two_ppc)
+                       return 16;
+               else
+                       return 12;
+       }
+       return 0;
+}
+
+/* compute the log2 of the downscale factor needed to get closest
+ * to the requested viewfinder resolution on the upper side. The output cannot
+ * be smaller than the requested viewfinder resolution.
+ */
+enum sh_css_err
+sh_css_vf_downscale_log2(const struct sh_css_frame_info *out_info,
+                        const struct sh_css_frame_info *vf_info,
+                        unsigned int *downscale_log2)
+{
+       unsigned int ds_log2 = 0, out_width = out_info->padded_width;
+
+       if (out_width == 0)
+               return 0;
+
+       /* downscale until width smaller than the viewfinder width. We don't
+        * test for the height since the vmem buffers only put restrictions on
+        * the width of a line, not on the number of lines in a frame.
+        */
+       while (out_width >= vf_info->width) {
+               ds_log2++;
+               out_width /= 2;
+       }
+       /* now width is smaller, so we go up one step */
+       if ((ds_log2 > 0) && (out_width < ISP_VF_PP_MAX_OUTPUT_WIDTH))
+               ds_log2--;
+       /* TODO: use actual max input resolution of vf_pp binary */
+       if ((out_info->width >> ds_log2) >= 2*ISP_VF_PP_MAX_OUTPUT_WIDTH)
+               return sh_css_err_viewfinder_resolution_too_wide;
+       *downscale_log2 = ds_log2;
+       return sh_css_success;
+}
+
+/* ISP expects GRBG bayer order, we skip one line and/or one row
+ * to correct in case the input bayer order is different.
+ */
+static unsigned int
+lines_needed_for_bayer_order(void)
+{
+       if (my_css.bayer_order == sh_css_bayer_order_bggr ||
+           my_css.bayer_order == sh_css_bayer_order_gbrg) {
+               return 1;
+       }
+       return 0;
+}
+
+static unsigned int
+columns_needed_for_bayer_order(void)
+{
+       if (my_css.bayer_order == sh_css_bayer_order_rggb ||
+           my_css.bayer_order == sh_css_bayer_order_gbrg) {
+               return 1;
+       }
+       return 0;
+}
+
+static enum sh_css_err
+input_start_column(unsigned int bin_in,
+                  unsigned int *start_column)
+{
+       unsigned int in = my_css.input_width,
+           for_bayer = columns_needed_for_bayer_order(), start;
+
+       if (bin_in + 2 * for_bayer > in)
+               return sh_css_err_not_enough_input_columns;
+
+       /* On the hardware, we want to use the middle of the input, so we
+        * divide the start column by 2. */
+       start = (in - bin_in) / 2;
+       /* in case the number of extra columns is 2 or odd, we round the start
+        * column down */
+       start &= ~0x1;
+
+       /* now we add the one column (if needed) to correct for the bayer
+        * order).
+        */
+       start += for_bayer;
+       *start_column = start;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+input_start_line(unsigned int bin_in, unsigned int *start_line)
+{
+       unsigned int in = my_css.input_height,
+           for_bayer = lines_needed_for_bayer_order(), start;
+
+       if (bin_in + 2 * for_bayer > in)
+               return sh_css_err_not_enough_input_lines;
+
+       /* On the hardware, we want to use the middle of the input, so we
+        * divide the start line by 2. On the simulator, we cannot handle extra
+        * lines at the end of the frame.
+        */
+       start = (in - bin_in) / 2;
+       /* in case the number of extra lines is 2 or odd, we round the start
+        * line down.
+        */
+       start &= ~0x1;
+
+       /* now we add the one line (if needed) to correct for the bayer order*/
+       start += for_bayer;
+       *start_line = start;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+program_input_formatter(struct sh_css_binary *binary)
+{
+       unsigned int start_line, start_column = 0,
+                    cropped_height = binary->in_frame_info.height,
+                    cropped_width  = binary->in_frame_info.width,
+                    left_padding = binary->left_padding,
+                    num_vectors,
+                    buffer_height = 2,
+                    buffer_width = binary->info->max_input_width,
+                    two_ppc = my_css.two_ppc,
+                    vmem_increment = 0,
+                    deinterleaving = 0,
+                    deinterleaving_b = 0,
+                    width_a = 0,
+                    width_b = 0,
+                    bits_per_pixel,
+                    vectors_per_buffer,
+                    vectors_per_line = 0,
+                    buffers_per_line = 0,
+                    buf_offset_b = 0,
+                    line_width = 0,
+                    width_b_factor = 1,
+                    start_column_b;
+       struct sh_css_if_config if_a_config, if_b_config;
+       enum sh_css_input_format input_format = binary->input_format;
+       enum sh_css_err err = sh_css_success;
+
+       /* TODO: check to see if input is RAW and if current mode interprets
+        * RAW data in any particular bayer order. copy binary with output
+        * format other than raw should not result in dropping lines and/or
+        * columns.
+        */
+       err = input_start_line(cropped_height, &start_line);
+       if (err != sh_css_success)
+               return err;
+
+       if (left_padding) {
+               num_vectors = CEIL_DIV(cropped_width + left_padding,
+                                      ISP_VEC_NELEMS);
+       } else {
+               err = input_start_column(cropped_width, &start_column);
+               if (err != sh_css_success)
+                       return err;
+               num_vectors = CEIL_DIV(cropped_width, ISP_VEC_NELEMS);
+               num_vectors *= buffer_height;
+               /* todo: in case of left padding,
+                  num_vectors is vectors per line,
+                  otherwise vectors per line * buffer_height. */
+       }
+
+       start_column_b = start_column;
+
+       bits_per_pixel = sh_css_hrt_if_prim_vec_align()*8 / ISP_VEC_NELEMS;
+       switch (input_format) {
+       case SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY:
+               if (two_ppc) {
+                       vmem_increment = 1;
+                       deinterleaving = 1;
+                       deinterleaving_b = 1;
+                       /* half lines */
+                       width_a = cropped_width * deinterleaving / 2;
+                       width_b_factor = 2;
+                       /* full lines */
+                       width_b = width_a * width_b_factor;
+                       buffer_width *= deinterleaving * 2;
+                       /* Patch from bayer to yuv */
+                       num_vectors *= deinterleaving;
+                       buf_offset_b = buffer_width / 2 / ISP_VEC_NELEMS;
+                       vectors_per_line = num_vectors / buffer_height;
+                       /* Even lines are half size */
+                       line_width =
+                           vectors_per_line * sh_css_hrt_if_prim_vec_align() /
+                           2;
+                       start_column /= 2;
+               } else {
+                       vmem_increment = 1;
+                       deinterleaving = 3;
+                       width_a = cropped_width * deinterleaving / 2;
+                       buffer_width = buffer_width * deinterleaving / 2;
+                       /* Patch from bayer to yuv */
+                       num_vectors = num_vectors / 2 * deinterleaving;
+                       start_column = start_column * deinterleaving / 2;
+               }
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV420_8:
+       case SH_CSS_INPUT_FORMAT_YUV420_10:
+               if (two_ppc) {
+                       vmem_increment = 1;
+                       deinterleaving = 1;
+                       width_a = width_b = cropped_width * deinterleaving / 2;
+                       buffer_width *= deinterleaving * 2;
+                       num_vectors *= deinterleaving;
+                       buf_offset_b = buffer_width / 2 / ISP_VEC_NELEMS;
+                       vectors_per_line = num_vectors / buffer_height;
+                       /* Even lines are half size */
+                       line_width =
+                           vectors_per_line * sh_css_hrt_if_prim_vec_align() /
+                           2;
+                       start_column *= deinterleaving;
+                       start_column /= 2;
+                       start_column_b = start_column;
+               } else {
+                       vmem_increment = 1;
+                       deinterleaving = 1;
+                       width_a = cropped_width * deinterleaving;
+                       buffer_width  *= deinterleaving * 2;
+                       num_vectors  *= deinterleaving;
+                       start_column *= deinterleaving;
+               }
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV422_8:
+       case SH_CSS_INPUT_FORMAT_YUV422_10:
+               if (two_ppc) {
+                       vmem_increment = 1;
+                       deinterleaving = 1;
+                       width_a = width_b = cropped_width * deinterleaving;
+                       buffer_width *= deinterleaving * 2;
+                       num_vectors  *= deinterleaving;
+                       start_column *= deinterleaving;
+                       buf_offset_b   = buffer_width / 2 / ISP_VEC_NELEMS;
+                       start_column_b = start_column;
+               } else {
+                       vmem_increment = 1;
+                       deinterleaving = 2;
+                       width_a = cropped_width * deinterleaving;
+                       buffer_width *= deinterleaving;
+                       num_vectors  *= deinterleaving;
+                       start_column *= deinterleaving;
+               }
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_444:
+       case SH_CSS_INPUT_FORMAT_RGB_555:
+       case SH_CSS_INPUT_FORMAT_RGB_565:
+       case SH_CSS_INPUT_FORMAT_RGB_666:
+       case SH_CSS_INPUT_FORMAT_RGB_888:
+               num_vectors *= 2;
+               if (two_ppc) {
+                       deinterleaving = 2;     /* BR in if_a, G in if_b */
+                       deinterleaving_b = 1;   /* BR in if_a, G in if_b */
+                       buffers_per_line = 4;
+                       start_column_b = start_column;
+                       start_column *= deinterleaving;
+                       start_column_b *= deinterleaving_b;
+               } else {
+                       deinterleaving = 3;     /* BGR */
+                       buffers_per_line = 3;
+                       start_column *= deinterleaving;
+               }
+               vmem_increment = 1;
+               width_a = cropped_width * deinterleaving;
+               width_b = cropped_width * deinterleaving_b;
+               buffer_width *= buffers_per_line;
+               /* Patch from bayer to rgb */
+               num_vectors = num_vectors / 2 * deinterleaving;
+               buf_offset_b = buffer_width / 2 / ISP_VEC_NELEMS;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_6:
+       case SH_CSS_INPUT_FORMAT_RAW_7:
+       case SH_CSS_INPUT_FORMAT_RAW_8:
+       case SH_CSS_INPUT_FORMAT_RAW_10:
+       case SH_CSS_INPUT_FORMAT_RAW_12:
+               if (two_ppc) {
+                       vmem_increment = 2;
+                       deinterleaving = 1;
+                       width_a = width_b = cropped_width / 2;
+                       start_column /= 2;
+                       start_column_b = start_column;
+                       buf_offset_b = 1;
+               } else {
+                       vmem_increment = 1;
+                       deinterleaving = 2;
+                       if (my_css.continuous &&
+                           binary->info->mode == SH_CSS_BINARY_MODE_COPY) {
+                               /* No deinterleaving for sp copy */
+                               deinterleaving = 1;
+                       }
+                       width_a = cropped_width;
+                       /* Must be multiple of deinterleaving */
+                       num_vectors = CEIL_MUL(num_vectors, deinterleaving);
+               }
+               buffer_height *= 2;
+               vectors_per_line = CEIL_DIV(cropped_width, ISP_VEC_NELEMS);
+               vectors_per_line = CEIL_MUL(vectors_per_line, deinterleaving);
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_14:
+       case SH_CSS_INPUT_FORMAT_RAW_16:
+               if (two_ppc) {
+                       num_vectors *= 2;
+                       vmem_increment = 1;
+                       deinterleaving = 2;
+                       width_a = width_b = cropped_width;
+                       /* B buffer is one line further */
+                       buf_offset_b = buffer_width / ISP_VEC_NELEMS;
+                       bits_per_pixel *= 2;
+               } else {
+                       vmem_increment = 1;
+                       deinterleaving = 2;
+                       width_a = cropped_width;
+                       start_column /= deinterleaving;
+               }
+               buffer_height *= 2;
+               break;
+       case SH_CSS_INPUT_FORMAT_BINARY_8:
+               break;
+       }
+       if (width_a == 0)
+               return sh_css_err_unsupported_input_mode;
+
+       if (two_ppc)
+               left_padding /= 2;
+
+       /* Default values */
+       if (left_padding)
+               vectors_per_line = num_vectors;
+       if (!vectors_per_line) {
+               vectors_per_line = CEIL_MUL(num_vectors / buffer_height,
+                                           deinterleaving);
+               line_width = 0;
+       }
+       if (!line_width)
+               line_width = vectors_per_line * sh_css_hrt_if_prim_vec_align();
+       if (!buffers_per_line)
+               buffers_per_line = deinterleaving;
+       line_width = CEIL_MUL(line_width,
+                             sh_css_hrt_if_prim_vec_align()*vmem_increment);
+
+       vectors_per_buffer = buffer_height * buffer_width / ISP_VEC_NELEMS;
+
+       if (my_css.input_mode == SH_CSS_INPUT_MODE_TPG &&
+           binary->info->mode == SH_CSS_BINARY_MODE_VIDEO) {
+               /* workaround for TPG in video mode*/
+               start_line = 0;
+               start_column = 0;
+               cropped_height -= start_line;
+               width_a -= start_column;
+       }
+
+       if_a_config.start_line = start_line;
+       if_a_config.start_column = start_column;
+       if_a_config.left_padding = left_padding / deinterleaving;
+       if_a_config.cropped_height = cropped_height;
+       if_a_config.cropped_width = width_a;
+       if_a_config.deinterleaving = deinterleaving;
+       if_a_config.buf_vecs = vectors_per_buffer;
+       if_a_config.buf_start_index = 0;
+       if_a_config.buf_increment = vmem_increment;
+       if_a_config.buf_eol_offset =
+           buffer_width * bits_per_pixel/8 - line_width;
+       if_a_config.yuv420 = input_format == SH_CSS_INPUT_FORMAT_YUV420_8 ||
+                            input_format == SH_CSS_INPUT_FORMAT_YUV420_10;
+       if_a_config.block_no_reqs =
+               my_css.input_mode != SH_CSS_INPUT_MODE_SENSOR;
+
+       if (two_ppc) {
+               if (deinterleaving_b) {
+                       deinterleaving = deinterleaving_b;
+                       width_b = cropped_width * deinterleaving;
+                       buffer_width *= deinterleaving;
+                       /* Patch from bayer to rgb */
+                       num_vectors =
+                           num_vectors / 2 * deinterleaving * width_b_factor;
+                       vectors_per_line = num_vectors / buffer_height;
+                       line_width =
+                           vectors_per_line * sh_css_hrt_if_prim_vec_align();
+               }
+               if_b_config.start_line = start_line;
+               if_b_config.start_column = start_column_b;
+               if_b_config.left_padding = left_padding / deinterleaving;
+               if_b_config.cropped_height = cropped_height;
+               if_b_config.cropped_width = width_b;
+               if_b_config.deinterleaving = deinterleaving;
+               if_b_config.buf_vecs = vectors_per_buffer;
+               if_b_config.buf_start_index = buf_offset_b;
+               if_b_config.buf_increment = vmem_increment;
+               if_b_config.buf_eol_offset =
+                   buffer_width * bits_per_pixel/8 - line_width;
+               if_b_config.yuv420 =
+                   input_format == SH_CSS_INPUT_FORMAT_YUV420_8
+                   || input_format == SH_CSS_INPUT_FORMAT_YUV420_10;
+               if_b_config.block_no_reqs =
+                       my_css.input_mode != SH_CSS_INPUT_MODE_SENSOR;
+               if (memcmp(&if_a_config, &my_css.curr_if_a_config,
+                          sizeof(if_a_config)) ||
+                   memcmp(&if_b_config, &my_css.curr_if_b_config,
+                          sizeof(if_b_config))) {
+                       my_css.curr_if_a_config = if_a_config;
+                       my_css.curr_if_b_config = if_b_config;
+                       sh_css_sp_set_if_configs(&if_a_config, &if_b_config);
+               }
+       } else {
+               if (memcmp(&if_a_config, &my_css.curr_if_a_config,
+                          sizeof(if_a_config))) {
+                       my_css.curr_if_a_config = if_a_config;
+                       sh_css_sp_set_if_configs(&if_a_config, NULL);
+               }
+       }
+       return sh_css_success;
+}
+
+static enum sh_css_err
+sh_css_config_input_network(struct sh_css_pipeline *pipeline,
+                           struct sh_css_binary *binary)
+{
+       unsigned int fmt_type;
+       enum sh_css_err err = sh_css_success;
+
+       if (pipeline && pipeline->stages)
+               binary = pipeline->stages->binary;
+
+       err = sh_css_input_format_type(my_css.input_format,
+                                      my_css.mipi_config.comp,
+                                      &fmt_type);
+       if (err != sh_css_success)
+               return err;
+       if (fmt_type != my_css.curr_fmt_type ||
+           my_css.ch_id != my_css.curr_ch_id ||
+           my_css.input_mode != my_css.curr_input_mode) {
+               my_css.curr_fmt_type = fmt_type;
+               my_css.curr_ch_id = my_css.ch_id;
+               my_css.curr_input_mode = my_css.input_mode;
+               sh_css_sp_program_input_circuit(fmt_type,
+                                               my_css.ch_id,
+                                               my_css.input_mode);
+       }
+
+       if (binary && (binary->online || my_css.continuous)) {
+               if (my_css.continuous)
+                       my_css.start_sp_copy = true;
+               err = program_input_formatter(binary);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       if (my_css.input_mode == SH_CSS_INPUT_MODE_TPG ||
+           my_css.input_mode == SH_CSS_INPUT_MODE_PRBS) {
+               unsigned int hblank_cycles = 100,
+                            vblank_lines = 6,
+                            width,
+                            height,
+                            vblank_cycles;
+               width  = binary->in_frame_info.width;
+               height = binary->in_frame_info.height;
+               vblank_cycles = vblank_lines * (width + hblank_cycles);
+               sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
+                                            vblank_cycles);
+       }
+       return sh_css_success;
+}
+
+#if WITH_PC_MONITORING
+struct task_struct *my_kthread;    /* Handle for the monitoring thread */
+int sh_binary_running;         /* Enable sampling in the thread */
+
+static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
+{
+       unsigned i;
+       unsigned cnt_run = 0;
+       unsigned cnt_stall = 0;
+       sh_css_print("%s histogram length = %d\n", core_name, hist->length);
+       sh_css_print("%s PC\trun\tstall\n", core_name);
+
+       for (i = 0; i < hist->length; i++) {
+               if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
+                       continue;
+               sh_css_print("%s %d\t%d\t%d\n",
+                               core_name, i, hist->run[i], hist->stall[i]);
+               cnt_run += hist->run[i];
+               cnt_stall += hist->stall[i];
+       }
+
+       sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, "
+              "hist->length = %d\n",
+                       core_name, cnt_run, cnt_stall, hist->length);
+}
+
+static void print_pc_histogram(void)
+{
+       struct sh_css_binary_metrics *metrics;
+
+       for (metrics = sh_css_metrics.binary_metrics;
+            metrics;
+            metrics = metrics->next) {
+               if (metrics->mode == SH_CSS_BINARY_ID_PREVIEW_DZ ||
+                   metrics->mode == SH_CSS_BINARY_ID_VF_PP) {
+                       sh_css_print("pc_histogram for binary %d is SKIPPED\n",
+                               metrics->mode);
+                       continue;
+               }
+
+               sh_css_print(" pc_histogram for binary %d\n", metrics->mode);
+               print_pc_histo("  ISP", &metrics->isp_histogram);
+               print_pc_histo("  SP",   &metrics->sp_histogram);
+               sh_css_print("print_pc_histogram() done for binay->id = %d, "
+                            "done.\n", metrics->mode);
+       }
+
+       sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
+}
+
+static int pc_monitoring(void *data)
+{
+       int i = 0;
+
+       while (true) {
+               if (sh_binary_running) {
+                       sh_css_metrics_sample_pcs();
+#if MULTIPLE_SAMPLES
+                       for (i = 0; i < NOF_SAMPLES; i++)
+                               sh_css_metrics_sample_pcs();
+#endif
+               }
+               usleep_range(10, 50);
+       }
+       return 0;
+}
+
+static void spying_thread_create(void)
+{
+       my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
+       sh_css_metrics_enable_pc_histogram(1);
+}
+
+static void input_frame_info(struct sh_css_frame_info frame_info)
+{
+       sh_css_print("SH_CSS:input_frame_info() -- frame->info.width = %d, "
+              "frame->info.height = %d, format = %d\n",
+                       frame_info.width, frame_info.height, frame_info.format);
+}
+#endif /* WITH_PC_MONITORING */
+
+static enum sh_css_err
+start_binary(struct sh_css_binary *binary,
+            struct sh_css_binary_args *args,
+            bool preview_mode)
+{
+       enum sh_css_err err = sh_css_success;
+
+       if (my_css.reconfigure_css_rx)
+               sh_css_rx_disable();
+
+       sh_css_metrics_start_binary(&binary->metrics);
+
+#if WITH_PC_MONITORING
+       sh_css_print("PC_MONITORING: %s() -- binary id = %d , "
+                    "enable_dvs_envelope = %d\n",
+                    __func__, binary->info->id,
+                    binary->info->enable_dvs_envelope);
+       input_frame_info(binary->in_frame_info);
+
+       if (binary->info->id == SH_CSS_BINARY_ID_VIDEO_DZ)
+               sh_binary_running = 1;
+#endif
+
+       if (binary->info->mode == SH_CSS_BINARY_MODE_VF_PP &&
+           my_css.vf_overlay_changed) {
+               sh_css_sp_set_overlay(my_css.vf_overlay);
+               my_css.vf_overlay_changed = false;
+       }
+
+       if (my_css.continuous && binary->info->mode ==
+           SH_CSS_BINARY_MODE_PREVIEW) {
+               sh_css_sp_start_raw_copy(binary, args->cc_frame,
+                                        my_css.two_ppc, false);
+       }
+       my_css.state = sh_css_state_executing_isp;
+       err = sh_css_sp_start_isp(binary, args, preview_mode);
+       if (err != sh_css_success)
+               return err;
+
+       if (my_css.reconfigure_css_rx) {
+               my_css.mipi_config.two_ppc = my_css.two_ppc;
+               sh_css_rx_configure(&my_css.mipi_config);
+               my_css.reconfigure_css_rx = false;
+       }
+       return sh_css_success;
+}
+
+static enum sh_css_err
+start_firmware(const struct sh_css_acc_fw *fw,
+              struct sh_css_binary_args *args)
+{
+       enum sh_css_err err;
+       struct sh_css_acc_fw *firmware = (struct sh_css_acc_fw *)fw;
+       my_css.state = sh_css_state_executing_isp;
+       err = sh_css_acc_start(firmware, args);
+       return err;
+}
+
+static void
+sh_css_frame_zero(struct sh_css_frame *frame)
+{
+       unsigned int i, words = frame->data_bytes / sizeof(int);
+       int *ptr = frame->data;
+
+       for (i = 0; i < words; i++)
+               hrt_isp_css_mm_store_int(ptr + i, 0);
+}
+
+/* start the copy function on the SP */
+static enum sh_css_err
+start_copy_on_sp(struct sh_css_binary *binary,
+                struct sh_css_frame *out_frame)
+{
+       my_css.capture_settings.output_frame = out_frame;
+
+       if (my_css.reconfigure_css_rx)
+               sh_css_rx_disable();
+
+       sh_css_hrt_irq_enable(hrt_isp_css_irq_sw_0, true, false);
+       sh_css_hrt_irq_enable(hrt_isp_css_irq_sw_1, true, false);
+       sh_css_hrt_irq_enable(hrt_isp_css_irq_sw_2, true, false);
+       if (my_css.input_format == SH_CSS_INPUT_FORMAT_BINARY_8) {
+               sh_css_sp_start_binary_copy(out_frame, my_css.two_ppc);
+       } else {
+               sh_css_sp_start_raw_copy(binary, out_frame,
+                                        my_css.two_ppc, true);
+       }
+
+       if (my_css.reconfigure_css_rx) {
+               /* do we need to wait for the IF do be ready? */
+               my_css.mipi_config.two_ppc = my_css.two_ppc;
+               sh_css_rx_configure(&my_css.mipi_config);
+               my_css.reconfigure_css_rx = false;
+       }
+
+       return sh_css_success;
+}
+
+/* Pipeline:
+ * To organize the several different binaries for each type of mode,
+ * we use a pipeline. A pipeline contains a number of stages, each with
+ * their own binary and frame pointers.
+ * When stages are added to a pipeline, output frames that are not passed
+ * from outside are automatically allocated.
+ * When input frames are not passed from outside, each stage will use the
+ * output frame of the previous stage as input (the full resolution output,
+ * not the viewfinder output).
+ * Pipelines must be cleaned and re-created when settings of the binaries
+ * change.
+ */
+static void
+sh_css_pipeline_stage_destroy(struct sh_css_pipeline_stage *me)
+{
+       if (me->out_frame_allocated)
+               sh_css_frame_free(me->args.out_frame);
+       if (me->vf_frame_allocated)
+               sh_css_frame_free(me->args.out_vf_frame);
+       sh_css_free(me);
+}
+
+static void
+sh_css_binary_args_reset(struct sh_css_binary_args *args)
+{
+       args->in_frame      = NULL;
+       args->out_frame     = NULL;
+       args->in_ref_frame  = NULL;
+       args->out_ref_frame = NULL;
+       args->in_tnr_frame  = NULL;
+       args->out_tnr_frame = NULL;
+       args->extra_frame   = NULL;
+       args->out_vf_frame  = NULL;
+       args->dvs_vector_x  = 0;
+       args->dvs_vector_y  = 0;
+       args->enable_xnr    = my_css.capture_settings.xnr;
+       args->two_ppc       = my_css.two_ppc;
+       args->copy_vf       = false;
+       args->copy_output   = true;
+       args->vf_downscale_log2 = 0;
+}
+
+static enum sh_css_err
+sh_css_pipeline_stage_create(struct sh_css_pipeline_stage **me,
+                            struct sh_css_binary *binary,
+                            const struct sh_css_acc_fw *firmware,
+                            int    mode,
+                            struct sh_css_frame *cc_frame,
+                            struct sh_css_frame *in_frame,
+                            struct sh_css_frame *out_frame,
+                            struct sh_css_frame *vf_frame)
+{
+       struct sh_css_pipeline_stage *stage = sh_css_malloc(sizeof(*stage));
+       if (!stage)
+               return sh_css_err_cannot_allocate_memory;
+       stage->binary = firmware ? NULL : binary;
+       stage->firmware = firmware;
+       stage->mode = mode;
+       stage->out_frame_allocated = false;
+       stage->vf_frame_allocated = false;
+       stage->next = NULL;
+       sh_css_binary_args_reset(&stage->args);
+
+       if (!in_frame && !firmware && !binary->online)
+               return sh_css_err_internal_error;
+
+       if (!out_frame && !firmware) {
+               enum sh_css_err ret =
+                   sh_css_frame_allocate_from_info(&out_frame,
+                                                   &binary->out_frame_info);
+               if (ret != sh_css_success) {
+                       sh_css_free(stage);
+                       return ret;
+               }
+               stage->out_frame_allocated = true;
+       }
+       /* VF frame is not needed in case of my_css.capture_settings.need_pp
+          However, the capture binary needs a vf frame to write to.
+       */
+       if (!vf_frame) {
+               if ((binary && binary->vf_frame_info.width) ||
+                   (firmware && firmware->header.sp.out_vf)) {
+                       enum sh_css_err ret =
+                           sh_css_frame_allocate_from_info(&vf_frame,
+                                                   &binary->vf_frame_info);
+                       if (ret != sh_css_success) {
+                               if (stage->out_frame_allocated)
+                                       sh_css_frame_free(out_frame);
+                               sh_css_free(stage);
+                               return ret;
+                       }
+                       stage->vf_frame_allocated = true;
+               }
+       } else if (vf_frame && binary && binary->vf_frame_info.width)
+               stage->vf_frame_allocated = true;
+
+       stage->args.cc_frame = cc_frame;
+       stage->args.in_frame = in_frame;
+       stage->args.out_frame = out_frame;
+       stage->args.out_vf_frame = vf_frame;
+       *me = stage;
+       return sh_css_success;
+}
+
+static void
+sh_css_pipeline_init(struct sh_css_pipeline *me)
+{
+       me->length = 0;
+       me->stages = NULL;
+       me->reload = true;
+       me->current_stage = NULL;
+}
+
+static enum sh_css_err
+sh_css_pipeline_add_stage(struct sh_css_pipeline *me,
+                         struct sh_css_binary *binary,
+                         const struct sh_css_acc_fw *firmware,
+                         int    mode,
+                         struct sh_css_frame *cc_frame,
+                         struct sh_css_frame *in_frame,
+                         struct sh_css_frame *out_frame,
+                         struct sh_css_frame *vf_frame,
+                         struct sh_css_pipeline_stage **stage)
+{
+       struct sh_css_pipeline_stage *last = me->stages, *new_stage = NULL;
+       enum sh_css_err err;
+
+       if (!binary && !firmware)
+               return sh_css_err_internal_error;
+
+       while (last && last->next)
+               last = last->next;
+
+       /* if in_frame is not set, we use the out_frame from the previous
+        * stage, if no previous stage, it's an error.
+        */
+       if (!in_frame && !firmware && !binary->online) {
+               if (last)
+                       in_frame = last->args.out_frame;
+               if (!in_frame)
+                       return sh_css_err_internal_error;
+       }
+       err = sh_css_pipeline_stage_create(&new_stage, binary, firmware,
+                                          mode, cc_frame,
+                                          in_frame, out_frame, vf_frame);
+       if (err != sh_css_success)
+               return err;
+       if (last)
+               last->next = new_stage;
+       else
+               me->stages = new_stage;
+       me->length++;
+       if (stage)
+               *stage = new_stage;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+sh_css_pipeline_get_stage(struct sh_css_pipeline *me,
+                         int mode,
+                         struct sh_css_pipeline_stage **stage)
+{
+       struct sh_css_pipeline_stage *s;
+       for (s = me->stages; s; s = s->next) {
+               if (s->mode == mode) {
+                       *stage = s;
+                       return sh_css_success;
+               }
+       }
+       return sh_css_err_internal_error;
+}
+
+static enum sh_css_err
+sh_css_pipeline_get_output_stage(struct sh_css_pipeline *me,
+                                int mode,
+                                struct sh_css_pipeline_stage **stage)
+{
+       struct sh_css_pipeline_stage *s;
+
+       *stage = NULL;
+       /* First find acceleration firmware at end of pipe */
+       for (s = me->stages; s; s = s->next) {
+               if (s->firmware && s->mode == mode &&
+                   s->firmware->header.sp.output)
+                       *stage = s;
+       }
+       if (*stage)
+               return sh_css_success;
+       /* If no firmware, find binary in pipe */
+       return sh_css_pipeline_get_stage(me, mode, stage);
+}
+
+static void
+sh_css_pipeline_restart(struct sh_css_pipeline *me)
+{
+       me->current_stage = NULL;
+}
+
+static void
+sh_css_pipeline_clean(struct sh_css_pipeline *me)
+{
+       struct sh_css_pipeline_stage *s = me->stages;
+
+       while (s) {
+               struct sh_css_pipeline_stage *next = s->next;
+               sh_css_pipeline_stage_destroy(s);
+               s = next;
+       }
+       sh_css_pipeline_init(me);
+}
+
+static bool
+sh_css_pipeline_done(struct sh_css_pipeline *me)
+{
+       return me->current_stage && !me->current_stage->next;
+}
+
+static struct sh_css_pipeline *
+get_current_pipeline(void)
+{
+       if (my_css.mode == sh_css_mode_preview)
+               return &my_css.preview_settings.pipeline;
+       else if (my_css.mode == sh_css_mode_video)
+               return &my_css.video_settings.pipeline;
+       else
+               return &my_css.capture_settings.pipeline;
+}
+
+void
+sh_css_terminate_firmware(void)
+{
+       struct sh_css_pipeline *me = get_current_pipeline();
+       struct sh_css_acc_fw *firmware;
+
+       if (!me->current_stage)
+               return;
+       firmware = (struct sh_css_acc_fw *)me->current_stage->firmware;
+       if (!firmware)
+               return;
+
+       sh_css_acceleration_done(firmware);
+       /* reload SP firmmware */
+       my_css.sp_bin_addr = sh_css_sp_load_program(&sh_css_sp_fw,
+                                                   SP_PROG_NAME);
+       /* restore SP state */
+       if (my_css.two_ppc) {
+               sh_css_sp_set_if_configs(&my_css.curr_if_a_config,
+                                        &my_css.curr_if_b_config);
+       } else {
+               sh_css_sp_set_if_configs(&my_css.curr_if_a_config, NULL);
+       }
+}
+
+static enum sh_css_err
+sh_css_pipeline_start_next_stage(struct sh_css_pipeline *me)
+{
+       struct sh_css_pipeline_stage *stage;
+       enum sh_css_err err;
+
+       if (me->current_stage)
+               stage = me->current_stage->next;
+       else
+               stage = me->stages;
+       if (!stage)
+               return sh_css_success;
+
+       me->current_stage = stage;
+
+       if (stage->firmware)
+               err = start_firmware(stage->firmware, &stage->args);
+       else
+               err = start_binary(stage->binary, &stage->args,
+                                  me == &my_css.preview_settings.pipeline);
+       return err;
+}
+
+void
+sh_css_frame_info_set_width(struct sh_css_frame_info *info,
+                           unsigned int width)
+{
+       info->width = width;
+       /* frames with a U and V plane of 8 bits per pixel need to have
+          all planes aligned, this means double the alignment for the
+          Y plane if the horizontal decimation is 2. */
+       if (info->format == SH_CSS_FRAME_FORMAT_YUV420 ||
+           info->format == SH_CSS_FRAME_FORMAT_YV12)
+               info->padded_width = CEIL_MUL(width, 2*HIVE_ISP_DDR_WORD_BYTES);
+       else if (info->format == SH_CSS_FRAME_FORMAT_YUV_LINE)
+               info->padded_width = CEIL_MUL(width, 2*ISP_VEC_NELEMS);
+       else
+               info->padded_width = CEIL_MUL(width, HIVE_ISP_DDR_WORD_BYTES);
+}
+
+static void
+sh_css_frame_info_set_format(struct sh_css_frame_info *info,
+                            enum sh_css_frame_format format)
+{
+       /* yuv_line has 2*NWAY alignment */
+       info->format = format;
+       /* HACK: this resets the padded width incorrectly.
+          Lex needs to fix this in the vf_veceven module. */
+       info->padded_width =  CEIL_MUL(info->padded_width, 2*ISP_VEC_NELEMS);
+}
+
+static void
+sh_css_frame_info_init(struct sh_css_frame_info *info,
+                      unsigned int width,
+                      unsigned int height,
+                      enum sh_css_frame_format format)
+{
+       info->height = height;
+       info->format = format;
+       sh_css_frame_info_set_width(info, width);
+}
+
+static void
+invalidate_video_binaries(void)
+{
+       my_css.video_settings.pipeline.reload   = true;
+       my_css.video_settings.video_binary.info = NULL;
+       my_css.video_settings.vf_pp_binary.info = NULL;
+       if (my_css.video_settings.shading_table) {
+               sh_css_shading_table_free(my_css.video_settings.shading_table);
+               my_css.video_settings.shading_table = NULL;
+       }
+}
+
+void
+sh_css_overlay_set_for_viewfinder(const struct sh_css_overlay *overlay)
+{
+       my_css.vf_overlay = overlay;
+       my_css.vf_overlay_changed = true;
+}
+
+void
+sh_css_set_shading_table(const struct sh_css_shading_table *table)
+{
+       my_css.shading_table = table;
+}
+
+/* CSS receiver programming */
+enum sh_css_err
+sh_css_input_configure_port(enum sh_css_mipi_port port,
+                           unsigned int num_lanes,
+                           unsigned int timeout)
+{
+       if (port == SH_CSS_MIPI_PORT_1LANE && num_lanes > 1)
+               return sh_css_err_conflicting_mipi_settings;
+       if (num_lanes > 4)
+               return sh_css_err_conflicting_mipi_settings;
+       my_css.mipi_config.port = port;
+       my_css.mipi_config.num_lanes = num_lanes;
+       my_css.mipi_config.timeout = timeout;
+       my_css.reconfigure_css_rx = true;
+
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_input_set_compression(enum sh_css_mipi_compression comp,
+                            unsigned int compressed_bits_per_pixel,
+                            unsigned int uncompressed_bits_per_pixel)
+{
+       if (comp == SH_CSS_MIPI_COMPRESSION_NONE) {
+               if (compressed_bits_per_pixel || uncompressed_bits_per_pixel)
+                       return sh_css_err_conflicting_mipi_settings;
+       } else {
+               if (compressed_bits_per_pixel < 6 ||
+                   compressed_bits_per_pixel > 8)
+                       return sh_css_err_conflicting_mipi_settings;
+               if (uncompressed_bits_per_pixel != 10 &&
+                   uncompressed_bits_per_pixel != 12)
+                       return sh_css_err_conflicting_mipi_settings;
+       }
+       my_css.mipi_config.comp = comp;
+       my_css.mipi_config.comp_bpp = compressed_bits_per_pixel;
+       my_css.mipi_config.uncomp_bpp = uncompressed_bits_per_pixel;
+       my_css.reconfigure_css_rx = true;
+       return sh_css_success;
+}
+
+void
+sh_css_tpg_configure(unsigned int x_mask,
+                    int x_delta,
+                    unsigned int y_mask,
+                    int y_delta,
+                    unsigned int xy_mask)
+{
+       sh_css_sp_configure_tpg(x_mask, y_mask, x_delta, y_delta, xy_mask);
+}
+
+void
+sh_css_prbs_set_seed(int seed)
+{
+       sh_css_sp_configure_prbs(seed);
+}
+
+/* currently, the capture pp binary requires an internal frame. This will
+   be removed in the future. */
+static enum sh_css_err
+alloc_capture_pp_frame(const struct sh_css_binary *binary)
+{
+
+       struct sh_css_frame_info cpp_info;
+       enum sh_css_err err = sh_css_success;
+
+       cpp_info = binary->internal_frame_info;
+       cpp_info.format = SH_CSS_FRAME_FORMAT_YUV420;
+       if (my_css.capture_settings.capture_pp_frame)
+               sh_css_frame_free(my_css.capture_settings.capture_pp_frame);
+       err = sh_css_frame_allocate_from_info(
+                       &my_css.capture_settings.capture_pp_frame, &cpp_info);
+       return err;
+}
+
+static void
+invalidate_preview_binaries(void)
+{
+       my_css.preview_settings.pipeline.reload     = true;
+       my_css.preview_settings.preview_binary.info = NULL;
+       my_css.preview_settings.vf_pp_binary.info   = NULL;
+       my_css.preview_settings.copy_binary.info    = NULL;
+       if (my_css.preview_settings.shading_table) {
+               sh_css_shading_table_free(
+                               my_css.preview_settings.shading_table);
+               my_css.preview_settings.shading_table = NULL;
+       }
+}
+
+static void
+invalidate_capture_binaries(void)
+{
+       my_css.capture_settings.pipeline.reload        = true;
+       my_css.capture_settings.copy_binary.info       = NULL;
+       my_css.capture_settings.primary_binary.info    = NULL;
+       my_css.capture_settings.pre_gdc_binary.info    = NULL;
+       my_css.capture_settings.gdc_binary.info        = NULL;
+       my_css.capture_settings.post_gdc_binary.info   = NULL;
+       my_css.capture_settings.capture_pp_binary.info = NULL;
+       my_css.capture_settings.vf_pp_binary.info      = NULL;
+       my_css.capture_settings.need_pp = false;
+       if (my_css.capture_settings.shading_table) {
+               sh_css_shading_table_free(
+                               my_css.capture_settings.shading_table);
+               my_css.capture_settings.shading_table = NULL;
+       }
+}
+
+static void
+enable_interrupts(void)
+{
+       /* Enable IRQ when SP goes to idle */
+       sh_css_hrt_irq_enable_sp(true);
+       /* Enabling this triggers an interrupt immediately, clear it */
+       sh_css_hrt_irq_clear_sp();
+
+       sh_css_hrt_irq_enable(hrt_isp_css_irq_sp, true, my_css.irq_edge);
+       sh_css_hrt_irq_clear_all();
+       sh_css_rx_enable_all_interrupts();
+}
+
+enum sh_css_err
+sh_css_init(void *(*malloc_func) (size_t size),
+           void (*free_func) (void *ptr),
+           enum sh_css_interrupt_setting irq_setting,
+           const char *fw_data,
+           unsigned int fw_size)
+{
+       static struct sh_css default_css = DEFAULT_CSS;
+       enum sh_css_err err;
+
+       if (malloc_func == NULL || free_func == NULL)
+               return sh_css_err_invalid_arguments;
+
+       memcpy(&my_css, &default_css, sizeof(my_css));
+
+       my_css.malloc = malloc_func;
+       my_css.free = free_func;
+       my_css.irq_edge = (irq_setting == SH_CSS_INTERRUPT_SETTING_EDGE);
+
+       /* In case this has been programmed already, update internal
+          data structure */
+       my_css.page_table_base_address =
+               sh_css_mmu_get_page_table_base_address();
+
+       enable_interrupts();
+
+       err = sh_css_params_init();
+       if (err != sh_css_success)
+               return err;
+       err = sh_css_load_firmware(fw_data, fw_size);
+       if (err != sh_css_success)
+               return err;
+       sh_css_init_binary_infos();
+       my_css.sp_bin_addr = sh_css_sp_load_program(&sh_css_sp_fw,
+                                                   SP_PROG_NAME);
+       if (!my_css.sp_bin_addr)
+               return sh_css_err_cannot_allocate_memory;
+       sh_css_pipeline_init(&my_css.preview_settings.pipeline);
+       sh_css_pipeline_init(&my_css.video_settings.pipeline);
+       sh_css_pipeline_init(&my_css.capture_settings.pipeline);
+
+#if WITH_PC_MONITORING
+       if (!thread_alive) {
+               thread_alive++;
+               sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
+                            __func__);
+               spying_thread_create();
+       }
+       sh_css_printf = printk;
+#endif
+
+       return err;
+}
+
+/* Suspend does not need to do anything for now, this may change
+   in the future though. */
+void
+sh_css_suspend(void)
+{
+}
+
+void
+sh_css_resume(void)
+{
+       /* trigger reconfiguration of necessary hardware */
+       my_css.reconfigure_css_rx = true;
+       my_css.curr_if_a_config.cropped_width  = 0;
+       my_css.curr_if_a_config.cropped_height = 0;
+       my_css.curr_if_b_config.cropped_width  = 0;
+       my_css.curr_if_b_config.cropped_height = 0;
+       my_css.curr_fmt_type = -1;
+       /* reload the SP binary. ISP binaries are automatically
+          reloaded by the ISP upon execution. */
+       sh_css_hrt_mmu_set_page_table_base_address(
+                       my_css.page_table_base_address);
+       sh_css_params_reconfigure_gdc_lut();
+
+       sh_css_sp_activate_program(&sh_css_sp_fw, my_css.sp_bin_addr,
+                                  SP_PROG_NAME);
+
+       enable_interrupts();
+}
+
+void *
+sh_css_malloc(size_t size)
+{
+       if (size > 0 && my_css.malloc)
+               return my_css.malloc(size);
+       return NULL;
+}
+
+void
+sh_css_free(void *ptr)
+{
+       if (ptr && my_css.free)
+               my_css.free(ptr);
+}
+
+void
+sh_css_set_print_function(int (*func) (const char *fmt, ...))
+{
+       sh_css_printf = func;
+}
+
+void
+sh_css_uninit(void)
+{
+       int i;
+
+#if WITH_PC_MONITORING
+       sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
+       print_pc_histogram();
+#endif
+
+       /* cleanup generic data */
+       sh_css_params_uninit();
+       sh_css_binary_uninit();
+       if (my_css.sp_bin_addr) {
+               hrt_isp_css_mm_free(my_css.sp_bin_addr);
+               my_css.sp_bin_addr = NULL;
+       }
+
+       /* cleanup preview data */
+       invalidate_preview_binaries();
+       sh_css_pipeline_clean(&my_css.preview_settings.pipeline);
+       for (i = 0; i < NUM_REF_FRAMES; i++) {
+               if (my_css.preview_settings.ref_frames[i]) {
+                       sh_css_frame_free(
+                                       my_css.preview_settings.ref_frames[i]);
+                       my_css.preview_settings.ref_frames[i] = NULL;
+               }
+       }
+       for (i = 0; i < NUM_CONTINUOUS_FRAMES; i++) {
+               if (my_css.preview_settings.continuous_frames[i]) {
+                       sh_css_frame_free(
+                               my_css.preview_settings.continuous_frames[i]);
+                       my_css.preview_settings.continuous_frames[i] = NULL;
+               }
+       }
+
+       /* cleanup video data */
+       invalidate_video_binaries();
+       sh_css_pipeline_clean(&my_css.video_settings.pipeline);
+       for (i = 0; i < NUM_TNR_FRAMES; i++) {
+               if (my_css.video_settings.tnr_frames[i])
+                       sh_css_frame_free(my_css.video_settings.tnr_frames[i]);
+               my_css.video_settings.tnr_frames[i] = NULL;
+       }
+       for (i = 0; i < NUM_REF_FRAMES; i++) {
+               if (my_css.video_settings.ref_frames[i])
+                       sh_css_frame_free(my_css.video_settings.ref_frames[i]);
+               my_css.video_settings.ref_frames[i] = NULL;
+       }
+
+       /* cleanup capture data */
+       invalidate_capture_binaries();
+       sh_css_pipeline_clean(&my_css.capture_settings.pipeline);
+       if (my_css.capture_settings.capture_pp_frame) {
+               sh_css_frame_free(my_css.capture_settings.capture_pp_frame);
+               my_css.capture_settings.capture_pp_frame = NULL;
+       }
+}
+
+enum sh_css_err
+sh_css_start_next_stage(void)
+{
+       struct sh_css_pipeline *pipeline = NULL;
+       enum sh_css_err err = sh_css_success;
+
+       /* LA: to be removed, now only first binary can run it */
+       my_css.start_sp_copy = false;
+
+       if (my_css.state != sh_css_state_idle)
+               return sh_css_err_system_not_idle;
+
+       if (my_css.check_system_idle && !sh_css_hrt_system_is_idle())
+               return sh_css_err_system_not_idle;
+
+       if (my_css.mode == sh_css_mode_preview)
+               pipeline = &my_css.preview_settings.pipeline;
+       else if (my_css.mode == sh_css_mode_video)
+               pipeline = &my_css.video_settings.pipeline;
+       else
+               pipeline = &my_css.capture_settings.pipeline;
+       err = sh_css_pipeline_start_next_stage(pipeline);
+       return err;
+}
+
+static bool
+sh_css_frame_done(void)
+{
+       bool done = true;
+       if (my_css.state == sh_css_state_executing_isp)
+               done = sh_css_pipeline_done(get_current_pipeline());
+       else if (my_css.state == sh_css_state_executing_sp_bin_copy) {
+               my_css.capture_settings.output_frame->planes.binary.size =
+                       sh_css_sp_get_binary_copy_size();
+       }
+       return done;
+}
+
+static bool
+sh_css_statistics_ready(void)
+{
+       struct sh_css_pipeline *pipeline = NULL;
+
+       if (my_css.state != sh_css_state_executing_isp)
+               return false;
+
+       pipeline = get_current_pipeline();
+       if (pipeline->current_stage->binary)
+               return pipeline->current_stage->binary->info->enable_s3a;
+       return false;
+}
+
+static bool
+acceleration_done(void)
+{
+       struct sh_css_pipeline *pipeline = get_current_pipeline();
+       return pipeline &&
+              pipeline->current_stage &&
+              pipeline->current_stage->firmware;
+}
+
+enum sh_css_err
+sh_css_translate_interrupt(unsigned int *irq_infos)
+{
+       enum hrt_isp_css_irq irq;
+       enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
+       unsigned int infos = 0;
+
+       while (status == hrt_isp_css_irq_status_more_irqs) {
+               status = sh_css_hrt_irq_get_id(&irq);
+               if (status == hrt_isp_css_irq_status_error)
+                       return sh_css_err_interrupt_error;
+
+#if WITH_PC_MONITORING
+               sh_css_print("PC_MONITORING: %s() irq = %d, "
+                            "sh_binary_running set to 0\n", __func__, irq);
+               sh_binary_running = 0 ;
+#endif
+
+               switch (irq) {
+               case hrt_isp_css_irq_sp:
+                       sh_css_hrt_irq_clear_sp();
+                       if (sh_css_frame_done())
+                               infos |= SH_CSS_IRQ_INFO_FRAME_DONE;
+                       else
+                               infos |= SH_CSS_IRQ_INFO_START_NEXT_STAGE;
+                       if (sh_css_statistics_ready())
+                               infos |= SH_CSS_IRQ_INFO_STATISTICS_READY;
+                       if (acceleration_done())
+                               infos |= SH_CSS_IRQ_INFO_FW_ACC_DONE;
+                       my_css.state = sh_css_state_idle;
+                       break;
+               case hrt_isp_css_irq_isp:
+                       /* nothing */
+                       break;
+               case hrt_isp_css_irq_mipi:
+                       /* css rx interrupt, read error bits from css rx */
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_ERROR;
+                       break;
+               case hrt_isp_css_irq_mipi_fifo_full:
+                       infos |=
+                           SH_CSS_IRQ_INFO_CSS_RECEIVER_FIFO_OVERFLOW;
+                       break;
+               case hrt_isp_css_irq_mipi_sof:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
+                       break;
+               case hrt_isp_css_irq_mipi_eof:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
+                       break;
+               case hrt_isp_css_irq_mipi_sol:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_SOL;
+                       break;
+               case hrt_isp_css_irq_mipi_eol:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_EOL;
+                       break;
+               case hrt_isp_css_irq_sideband_changed:
+                       infos |=
+                           SH_CSS_IRQ_INFO_CSS_RECEIVER_SIDEBAND_CHANGED;
+                       break;
+               case hrt_isp_css_irq_css_gen_short_0:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_0;
+                       break;
+               case hrt_isp_css_irq_css_gen_short_1:
+                       infos |= SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_1;
+                       break;
+               case hrt_isp_css_irq_ift_prim:
+                       infos |= SH_CSS_IRQ_INFO_IF_PRIM_ERROR;
+                       break;
+               case hrt_isp_css_irq_ift_prim_b:
+                       infos |= SH_CSS_IRQ_INFO_IF_PRIM_B_ERROR;
+                       break;
+               case hrt_isp_css_irq_ift_sec:
+                       infos |= SH_CSS_IRQ_INFO_IF_SEC_ERROR;
+                       break;
+               case hrt_isp_css_irq_ift_mem_cpy:
+                       infos |= SH_CSS_IRQ_INFO_STREAM_TO_MEM_ERROR;
+                       break;
+               case hrt_isp_css_irq_sw_0:
+                       infos |= SH_CSS_IRQ_INFO_SW_0;
+                       break;
+               case hrt_isp_css_irq_sw_1:
+                       infos |= SH_CSS_IRQ_INFO_SW_1;
+                       break;
+               case hrt_isp_css_irq_sw_2:
+                       infos |= SH_CSS_IRQ_INFO_SW_2;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (irq_infos)
+               *irq_infos = infos;
+       return sh_css_success;
+}
+
+void
+sh_css_mmu_set_page_table_base_address(void *base_address)
+{
+       my_css.page_table_base_address = base_address;
+       sh_css_hrt_mmu_set_page_table_base_address(base_address);
+       sh_css_mmu_invalidate_cache();
+}
+
+void *
+sh_css_mmu_get_page_table_base_address(void)
+{
+       return sh_css_hrt_mmu_get_page_table_base_address();
+}
+
+void
+sh_css_mmu_invalidate_cache(void)
+{
+       sh_css_sp_invalidate_mmu();
+}
+
+enum sh_css_err
+sh_css_enable_interrupt(enum sh_css_interrupt_info info,
+                       bool enable)
+{
+       enum hrt_isp_css_irq irq = -1;
+       bool edge = my_css.irq_edge;
+
+       switch (info) {
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_ERROR:
+               irq = hrt_isp_css_irq_mipi;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_FIFO_OVERFLOW:
+               irq = hrt_isp_css_irq_mipi_fifo_full;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
+               irq = hrt_isp_css_irq_mipi_sof;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
+               irq = hrt_isp_css_irq_mipi_eof;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_SOL:
+               irq = hrt_isp_css_irq_mipi_sol;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_EOL:
+               irq = hrt_isp_css_irq_mipi_eol;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_SIDEBAND_CHANGED:
+               irq = hrt_isp_css_irq_sideband_changed;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_0:
+               irq = hrt_isp_css_irq_css_gen_short_0;
+               break;
+       case SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_1:
+               irq = hrt_isp_css_irq_css_gen_short_1;
+               break;
+       case SH_CSS_IRQ_INFO_IF_PRIM_ERROR:
+               irq = hrt_isp_css_irq_ift_prim;
+               break;
+       case SH_CSS_IRQ_INFO_IF_PRIM_B_ERROR:
+               irq = hrt_isp_css_irq_ift_prim_b;
+               break;
+       case SH_CSS_IRQ_INFO_IF_SEC_ERROR:
+               irq = hrt_isp_css_irq_ift_sec;
+               break;
+       case SH_CSS_IRQ_INFO_STREAM_TO_MEM_ERROR:
+               irq = hrt_isp_css_irq_ift_mem_cpy;
+               break;
+       case SH_CSS_IRQ_INFO_SW_0:
+               irq = hrt_isp_css_irq_sw_0;
+               edge = false;
+               break;
+       case SH_CSS_IRQ_INFO_SW_1:
+               irq = hrt_isp_css_irq_sw_1;
+               edge = false;
+               break;
+       case SH_CSS_IRQ_INFO_SW_2:
+               irq = hrt_isp_css_irq_sw_2;
+               edge = false;
+               break;
+       default:
+               return sh_css_err_invalid_arguments;
+       }
+
+       if (enable)
+               sh_css_hrt_irq_enable(irq, true, edge);
+       else
+               sh_css_hrt_irq_disable(irq);
+
+       return sh_css_success;
+}
+
+unsigned int
+sh_css_get_sw_interrupt_value(void)
+{
+       return sh_css_sp_get_sw_interrupt_value();
+}
+
+enum sh_css_err
+sh_css_wait_for_completion(void)
+{
+       enum sh_css_err err;
+       unsigned int irq_infos = 0;
+
+       while (true) {
+               err = sh_css_hrt_sp_wait();
+               if (err != sh_css_success)
+                       return err;
+               /* just in case we're not using interrupts */
+               sh_css_translate_interrupt(&irq_infos);
+               if (irq_infos & SH_CSS_IRQ_INFO_START_NEXT_STAGE) {
+                       err = sh_css_start_next_stage();
+                       if (err != sh_css_success)
+                               return err;
+               } else {
+                       break;
+               }
+       }
+       return sh_css_success;
+}
+
+void
+sh_css_uv_offset_is_zero(bool *uv_offset_is_zero)
+{
+       if (uv_offset_is_zero)
+               *uv_offset_is_zero = SH_CSS_UV_OFFSET_IS_0;
+}
+
+enum sh_css_err
+sh_css_input_set_resolution(unsigned int width, unsigned int height)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       my_css.input_width = width;
+       my_css.input_height = height;
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_input_set_effective_resolution(unsigned int width, unsigned int height)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       my_css.input_effective_info.width = width;
+       my_css.input_effective_info.padded_width = width;
+       my_css.input_effective_info.height = height;
+       return sh_css_success;
+}
+
+void
+sh_css_input_set_format(enum sh_css_input_format format)
+{
+       my_css.input_format = format;
+}
+
+void
+sh_css_input_set_binning_factor(unsigned int binning_factor)
+{
+       my_css.sensor_binning = binning_factor;
+}
+
+void
+sh_css_input_set_two_pixels_per_clock(bool two_ppc)
+{
+       if (my_css.two_ppc != two_ppc) {
+               my_css.two_ppc = two_ppc;
+               my_css.reconfigure_css_rx = true;
+       }
+}
+
+void
+sh_css_input_set_bayer_order(enum sh_css_bayer_order bayer_order)
+{
+       my_css.bayer_order = bayer_order;
+}
+
+int
+sh_css_get_extra_pixels_count(int *extra_rows, int *extra_cols)
+{
+       int rows = SH_CSS_MAX_LEFT_CROPPING,
+           cols = SH_CSS_MAX_LEFT_CROPPING;
+
+       if (lines_needed_for_bayer_order())
+               rows += 2;
+
+       if (columns_needed_for_bayer_order())
+               cols  += 2;
+
+       *extra_rows = rows;
+       *extra_cols = cols;
+
+       return 0;
+}
+
+
+void
+sh_css_input_set_channel(unsigned int channel_id)
+{
+       my_css.ch_id = channel_id;
+}
+
+void
+sh_css_input_set_mode(enum sh_css_input_mode mode)
+{
+       enum sh_css_input_mode prev = my_css.input_mode;
+
+       if (prev != mode) {
+               if (mode == SH_CSS_INPUT_MODE_MEMORY
+                   || prev == SH_CSS_INPUT_MODE_MEMORY) {
+                       /* if we switch from online to offline, we need to
+                          reload the binary */
+                       invalidate_video_binaries();
+               }
+       }
+       my_css.input_mode = mode;
+}
+
+static void
+init_copy_descr(struct sh_css_frame_info *in_info,
+               struct sh_css_frame_info *out_info)
+{
+       *in_info = *out_info;
+
+       copy_descr.mode          = SH_CSS_BINARY_MODE_COPY;
+       copy_descr.online        = true;
+       copy_descr.stream_format = my_css.input_format;
+       copy_descr.two_ppc       = my_css.two_ppc;
+       copy_descr.in_info       = in_info;
+       copy_descr.out_info      = out_info;
+       copy_descr.vf_info       = NULL;
+}
+
+/* Bilinear interpolation on shading tables:
+ * For each target point T, we calculate the 4 surrounding source points:
+ * ul (upper left), ur (upper right), ll (lower left) and lr (lower right).
+ * We then calculate the distances from the T to the source points: x0, x1,
+ * y0 and y1.
+ * We then calculate the value of T:
+ *   dx0*dy0*Slr + dx0*dy1*Sur + dx1*dy0*Sll + dx1*dy1*Sul.
+ * We choose a grid size of 1x1 which means:
+ *   dx1 = 1-dx0
+ *   dy1 = 1-dy0
+ *
+ *   Sul dx0         dx1      Sur
+ *    .<----->|<------------->.
+ *    ^
+ * dy0|
+ *    v        T
+ *    -        .
+ *    ^
+ *    |
+ * dy1|
+ *    v
+ *    .                        .
+ *   Sll                      Slr
+ *
+ * Padding:
+ * The area that the ISP operates on can include padding both on the left
+ * and the right. We need to padd the shading table such that the shading
+ * values end up on the correct pixel values. This means we must padd the
+ * shading table to match the ISP padding.
+ * We can have 5 cases:
+ * 1. All 4 points fall in the left padding.
+ * 2. The left 2 points fall in the left padding.
+ * 3. All 4 points fall in the cropped (target) region.
+ * 4. The right 2 points fall in the right padding.
+ * 5. All 4 points fall in the right padding.
+ * Cases 1 and 5 are easy to handle: we simply use the
+ * value 1 in the shading table.
+ * Cases 2 and 4 require interpolation that takes into
+ * account how far into the padding area the pixels
+ * fall. We extrapolate the shading table into the
+ * padded area and then interpolate.
+ */
+static void
+crop_and_interpolate(unsigned int cropped_width,
+                    unsigned int cropped_height,
+                    unsigned int left_padding,
+                    unsigned int right_padding,
+                    struct sh_css_shading_table *out_table,
+                    enum sh_css_sc_color color)
+{
+       unsigned int i, j,
+                    sensor_width  = my_css.shading_table->sensor_width,
+                    sensor_height = my_css.shading_table->sensor_height,
+                    table_width   = my_css.shading_table->width,
+                    table_height  = my_css.shading_table->height,
+                    out_cell_size,
+                    in_cell_size,
+                    out_start_row,
+                    padded_width;
+       int out_start_col; /* can be negative to indicate padded space */
+       unsigned short *in_ptr = my_css.shading_table->data[color],
+                      *out_ptr = out_table->data[color];
+
+       padded_width = cropped_width + left_padding + right_padding;
+       out_cell_size = CEIL_DIV(padded_width, out_table->width - 1);
+       in_cell_size  = CEIL_DIV(sensor_width, table_width - 1);
+
+       out_start_col = (sensor_width - cropped_width)/2 - left_padding;
+       out_start_row = (sensor_height - cropped_height)/2;
+
+       for (i = 0; i < out_table->height; i++) {
+               unsigned int ty, src_y0, src_y1, sy0, sy1, dy0, dy1, divy;
+
+               /* calculate target point and make sure it falls within
+                  the table */
+               ty = out_start_row + i * out_cell_size;
+               ty = min(ty, sensor_height);
+               /* calculate closest source points in shading table and
+                  make sure they fall within the table */
+               src_y0 = ty / in_cell_size;
+               if (in_cell_size < out_cell_size)
+                       src_y1 = (ty + out_cell_size) / in_cell_size;
+               else
+                       src_y1 = src_y0 + 1;
+               src_y0 = min(src_y0, table_height-1);
+               src_y1 = min(src_y1, table_height-1);
+               /* calculate closest source points for distance computation */
+               sy0 = min(src_y0 * in_cell_size, sensor_height-1);
+               sy1 = min(src_y1 * in_cell_size, sensor_height-1);
+               /* calculate distance between source and target pixels */
+               dy0 = ty - sy0;
+               dy1 = sy1 - ty;
+               divy = sy1 - sy0;
+               if (divy == 0) {
+                       dy0 = 1;
+                       divy = 1;
+               }
+
+               for (j = 0; j < out_table->width; j++, out_ptr++) {
+                       int tx, src_x0, src_x1;
+                       unsigned int sx0, sx1, dx0, dx1, divx;
+                       unsigned short s_ul, s_ur, s_ll, s_lr;
+
+                       /* calculate target point */
+                       tx = out_start_col + j * out_cell_size;
+                       /* calculate closest source points. */
+                       src_x0 = tx / (int)in_cell_size;
+                       if (in_cell_size < out_cell_size) {
+                               src_x1 = (tx + out_cell_size) /
+                                        (int)in_cell_size;
+                       } else {
+                               src_x1 = src_x0 + 1;
+                       }
+                       /* if src points fall in padding, select closest ones.*/
+                       src_x0 = clamp(src_x0, 0, (int)table_width-1);
+                       src_x1 = clamp(src_x1, 0, (int)table_width-1);
+                       tx = clamp(tx, 0, (int)sensor_width-1);
+                       /* calculate closest source points for distance
+                          computation */
+                       sx0 = min(src_x0 * in_cell_size, sensor_width-1);
+                       sx1 = min(src_x1 * in_cell_size, sensor_width-1);
+                       /* calculate distances between source and target
+                          pixels */
+                       dx0 = tx - sx0;
+                       dx1 = sx1 - tx;
+                       divx = sx1 - sx0;
+                       /* if we're at the edge, we just use the closest
+                          point still in the grid. We make up for the divider
+                          in this case by setting the distance to
+                          out_cell_size, since it's actually 0. */
+                       if (divx == 0) {
+                               dx0 = 1;
+                               divx = 1;
+                       }
+
+                       /* get source pixel values */
+                       s_ul = in_ptr[(table_width*src_y0)+src_x0];
+                       s_ur = in_ptr[(table_width*src_y0)+src_x1];
+                       s_ll = in_ptr[(table_width*src_y1)+src_x0];
+                       s_lr = in_ptr[(table_width*src_y1)+src_x1];
+
+                       *out_ptr = (dx0*dy0*s_lr +
+                                   dx0*dy1*s_ur +
+                                   dx1*dy0*s_ll +
+                                   dx1*dy1*s_ul) / (divx*divy);
+               }
+       }
+}
+
+static void
+generate_id_shading_table(struct sh_css_shading_table **target_table,
+                         const struct sh_css_binary *binary)
+{
+       /* initialize table with ones, shift becomes zero */
+       unsigned int i, j, table_width, table_height;
+       struct sh_css_shading_table *result;
+
+       table_width  = binary->sctbl_width_per_color;
+       table_height = binary->sctbl_height;
+       result = sh_css_shading_table_alloc(table_width, table_height);
+       if (result == NULL) {
+               *target_table = NULL;
+               return;
+       }
+
+       for (i = 0; i < SH_CSS_SC_NUM_COLORS; i++) {
+               for (j = 0; j < table_height * table_width; j++)
+                       result->data[i][j] = 1;
+       }
+       result->fraction_bits = 0;
+       *target_table = result;
+}
+
+static void
+prepare_shading_table(struct sh_css_shading_table **target_table,
+                     const struct sh_css_binary *binary)
+{
+       unsigned int input_width,
+                    input_height,
+                    table_width,
+                    table_height,
+                    left_padding,
+                    right_padding,
+                    i;
+       struct sh_css_shading_table *result;
+
+       if (!my_css.shading_table) {
+               generate_id_shading_table(target_table, binary);
+               return;
+       }
+
+       left_padding = my_css.curr_if_a_config.left_padding;
+       if (my_css.two_ppc)
+               left_padding += my_css.curr_if_a_config.left_padding;
+       /* We use the ISP input resolution for the shading table because
+          shading correction is performed in the bayer domain (before bayer
+          down scaling). */
+       input_height  = binary->in_frame_info.height;
+       input_width   = binary->in_frame_info.width;
+       left_padding  = binary->left_padding;
+       right_padding = binary->in_frame_info.padded_width -
+                       (input_width + left_padding);
+
+       /* We take into account the binning done by the sensor. We do this
+          by cropping the non-binned part of the shading table and then
+          increasing the size of a grid cell with this same binning factor. */
+       input_width  <<= my_css.sensor_binning;
+       input_height <<= my_css.sensor_binning;
+       /* We also scale the padding by the same binning factor. This will
+          make it much easier later on to calculate the padding of the
+          shading table. */
+       left_padding  <<= my_css.sensor_binning;
+       right_padding <<= my_css.sensor_binning;
+
+       /* during simulation, the used resolution can exceed the sensor
+          resolution, so we clip it. */
+       input_width  = min(input_width,  my_css.shading_table->sensor_width);
+       input_height = min(input_height, my_css.shading_table->sensor_height);
+
+       table_width  = binary->sctbl_width_per_color;
+       table_height = binary->sctbl_height;
+
+       result = sh_css_shading_table_alloc(table_width, table_height);
+       if (result == NULL) {
+               *target_table = NULL;
+               return;
+       }
+       result->sensor_width  = my_css.shading_table->sensor_width;
+       result->sensor_height = my_css.shading_table->sensor_height;
+       result->fraction_bits = my_css.shading_table->fraction_bits;
+
+       /* now we crop the original shading table and then interpolate to the
+          requested resolution and decimation factor. */
+       for (i = 0; i < SH_CSS_SC_NUM_COLORS; i++) {
+               crop_and_interpolate(input_width, input_height,
+                                    left_padding, right_padding, result, i);
+       }
+       *target_table = result;
+}
+
+static void
+init_offline_descr(struct sh_css_binary_descr *descr,
+                  int mode,
+                  struct sh_css_frame_info *in_info,
+                  struct sh_css_frame_info *out_info,
+                  struct sh_css_frame_info *vf_info)
+{
+       descr->mode          = mode;
+       descr->online        = false;
+       descr->stream_format = my_css.input_format;
+       descr->two_ppc       = false;
+       descr->in_info       = in_info;
+       descr->out_info      = out_info;
+       descr->vf_info       = vf_info;
+}
+
+static void
+init_vf_pp_descr(struct sh_css_frame_info *in_info,
+                struct sh_css_frame_info *out_info)
+{
+       in_info->raw_bit_depth = 0;
+       init_offline_descr(&vf_pp_descr, SH_CSS_BINARY_MODE_VF_PP,
+                          in_info, out_info, NULL);
+}
+
+static void
+init_preview_descr(struct sh_css_frame_info *in_info,
+                  struct sh_css_frame_info *out_info)
+{
+       int mode = SH_CSS_BINARY_MODE_PREVIEW;
+
+       *in_info = my_css.input_effective_info;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       if (input_format_is_yuv(my_css.input_format))
+               mode = SH_CSS_BINARY_MODE_COPY;
+       else
+               in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+
+       init_offline_descr(&preview_descr, mode,
+                          in_info, out_info, NULL);
+       preview_descr.online        = my_css.preview_settings.online;
+       preview_descr.stream_format = my_css.input_format;
+}
+
+/* configure and load the copy binary, the next binary is used to
+   determine whether the copy binary needs to do left padding. */
+static enum sh_css_err
+load_copy_binary(struct sh_css_binary *copy_binary,
+                struct sh_css_binary *next_binary)
+{
+       struct sh_css_frame_info copy_out_info, copy_in_info;
+       unsigned int left_padding;
+       enum sh_css_err err;
+       int mode = SH_CSS_BINARY_MODE_COPY;
+
+       if (next_binary) {
+               copy_out_info = next_binary->in_frame_info;
+               left_padding = next_binary->left_padding;
+       } else {
+               copy_out_info = my_css.capture_settings.output_info;
+               left_padding = 0;
+               if (my_css.capture_settings.bayer_ds)
+                       mode = SH_CSS_BINARY_MODE_BAYER_DS;
+       }
+
+       init_copy_descr(&copy_in_info, &copy_out_info);
+       copy_descr.mode = mode;
+       err = sh_css_binary_find(&copy_descr, copy_binary);
+       if (err != sh_css_success)
+               return err;
+       copy_binary->left_padding = left_padding;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+load_preview_binaries(void)
+{
+       struct sh_css_frame_info prev_in_info,
+                                prev_out_info,
+                                ref_info;
+       enum sh_css_err err = sh_css_success;
+       bool online = my_css.preview_settings.online;
+       bool continuous = my_css.continuous;
+       unsigned int i;
+
+       if (my_css.preview_settings.preview_binary.info &&
+           my_css.preview_settings.vf_pp_binary.info)
+               return sh_css_success;
+
+       err = check_input(false);
+       if (err != sh_css_success)
+               return err;
+       err = check_frame_info(&my_css.preview_settings.output_info);
+       if (err != sh_css_success)
+               return err;
+
+       /* Preview */
+       if (my_css.preview_settings.pp_input_info.width)
+               prev_out_info = my_css.preview_settings.pp_input_info;
+       else
+               prev_out_info = my_css.preview_settings.output_info;
+       sh_css_frame_info_set_format(&prev_out_info,
+                                    SH_CSS_FRAME_FORMAT_YUV_LINE);
+       init_preview_descr(&prev_in_info, &prev_out_info);
+       err = sh_css_binary_find(&preview_descr,
+                                &my_css.preview_settings.preview_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Viewfinder post-processing */
+       init_vf_pp_descr(
+                       &my_css.preview_settings.preview_binary.out_frame_info,
+                       &my_css.preview_settings.output_info);
+       err = sh_css_binary_find(&vf_pp_descr,
+                                &my_css.preview_settings.vf_pp_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Copy */
+       if (!online && !continuous) {
+               err = load_copy_binary(&my_css.preview_settings.copy_binary,
+                                      &my_css.preview_settings.preview_binary);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       ref_info = my_css.preview_settings.preview_binary.internal_frame_info;
+       ref_info.format = SH_CSS_FRAME_FORMAT_YUV420;
+
+       for (i = 0; i < NUM_REF_FRAMES; i++) {
+               if (my_css.preview_settings.ref_frames[i]) {
+                       sh_css_frame_free(
+                               my_css.preview_settings.ref_frames[i]);
+               }
+               err = sh_css_frame_allocate_from_info(
+                               &my_css.preview_settings.ref_frames[i],
+                               &ref_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       my_css.preview_settings.prev_ref_frame = 0;
+       if (SH_CSS_PREVENT_UNINIT_READS)
+               sh_css_frame_zero(my_css.preview_settings.ref_frames[0]);
+
+       if (!continuous)
+               ref_info = my_css.preview_settings.preview_binary.in_frame_info;
+       else
+               ref_info =
+                 my_css.preview_settings.preview_binary.internal_frame_info;
+       ref_info.format = SH_CSS_FRAME_FORMAT_RAW;
+
+       for (i = 0; i < NUM_CONTINUOUS_FRAMES; i++) {
+               if (my_css.preview_settings.continuous_frames[i])
+                       sh_css_frame_free(
+                               my_css.preview_settings.continuous_frames[i]);
+               err = sh_css_frame_allocate_from_info(
+                       &my_css.preview_settings.continuous_frames[i],
+                       &ref_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       my_css.preview_settings.continuous_frame = 0;
+       if (SH_CSS_PREVENT_UNINIT_READS)
+               sh_css_frame_zero(my_css.preview_settings.continuous_frames[0]);
+
+       if (my_css.preview_settings.shading_table) {
+               sh_css_shading_table_free(
+                               my_css.preview_settings.shading_table);
+               my_css.preview_settings.shading_table = NULL;
+       }
+       return sh_css_success;
+}
+
+static const struct sh_css_acc_fw *
+last_output_firmware(const struct sh_css_acc_fw *fw)
+{
+       const struct sh_css_acc_fw *last_fw = NULL;
+       for (; fw; fw = fw->next) {
+               if (fw->header.sp.output)
+                       last_fw = fw;
+       }
+       return last_fw;
+}
+
+static enum sh_css_err
+add_firmwares(struct sh_css_pipeline *me,
+             struct sh_css_binary *binary,
+             const struct sh_css_acc_fw *fw,
+             const struct sh_css_acc_fw *last_fw,
+             unsigned int binary_mode,
+             struct sh_css_frame *in_frame,
+             struct sh_css_frame *out_frame,
+             struct sh_css_frame *vf_frame,
+             struct sh_css_pipeline_stage **my_stage,
+             struct sh_css_pipeline_stage **vf_stage)
+{
+       enum sh_css_err err = sh_css_success;
+       struct sh_css_pipeline_stage *extra_stage = NULL;
+       for (; fw; fw = fw->next) {
+               struct sh_css_frame *out = NULL;
+               if (fw == last_fw)
+                       out = out_frame;
+               err = sh_css_pipeline_add_stage(me, binary, fw,
+                               binary_mode, NULL,
+                               in_frame, out,
+                               vf_frame, &extra_stage);
+               if (err != sh_css_success)
+                       return err;
+               if (fw->header.sp.output)
+                       in_frame = extra_stage->args.out_frame;
+               if (my_stage && !*my_stage && extra_stage)
+                       *my_stage = extra_stage;
+               if (vf_stage && !*vf_stage && extra_stage &&
+                   fw->header.sp.out_vf)
+                       *vf_stage = extra_stage;
+       }
+       return err;
+}
+
+static enum sh_css_err
+add_vf_pp_stage(struct sh_css_pipeline *me,
+               struct sh_css_frame *out_frame,
+               struct sh_css_binary *vf_pp_binary,
+               struct sh_css_pipeline_stage *post_stage,
+               struct sh_css_pipeline_stage **vf_pp_stage)
+{
+       const struct sh_css_acc_fw *last_fw;
+       enum sh_css_err err = sh_css_success;
+       struct sh_css_frame *in_frame = post_stage->args.out_vf_frame;
+
+       *vf_pp_stage = NULL;
+
+       if (!in_frame)
+               in_frame = post_stage->args.out_frame;
+
+       last_fw = last_output_firmware(my_css.vf_stage);
+       if (!my_css.disable_vf_pp) {
+               err = sh_css_pipeline_add_stage(me, vf_pp_binary, NULL,
+                               vf_pp_binary->info->mode, NULL,
+                               in_frame,
+                               last_fw ? NULL : out_frame,
+                               NULL, vf_pp_stage);
+               if (err != sh_css_success)
+                       return err;
+               in_frame = (*vf_pp_stage)->args.out_frame;
+       }
+       err = add_firmwares(me, vf_pp_binary, my_css.vf_stage, last_fw,
+                           SH_CSS_BINARY_MODE_VF_PP,
+                           in_frame, out_frame, NULL,
+                           vf_pp_stage, NULL);
+       return err;
+}
+
+static enum sh_css_err
+add_capture_pp_stage(struct sh_css_pipeline *me,
+                    struct sh_css_frame *out_frame,
+                    struct sh_css_binary *capture_pp_binary,
+                    struct sh_css_pipeline_stage *capture_stage,
+                    struct sh_css_pipeline_stage **pre_vf_pp_stage)
+{
+       const struct sh_css_acc_fw *last_fw;
+       enum sh_css_err err = sh_css_success;
+       struct sh_css_frame *in_frame = capture_stage->args.out_frame;
+       struct sh_css_frame *vf_frame = NULL;
+
+       *pre_vf_pp_stage = NULL;
+
+       if (!in_frame)
+               in_frame = capture_stage->args.out_frame;
+
+       last_fw = last_output_firmware(my_css.output_stage);
+       if (!my_css.disable_capture_pp && my_css.capture_settings.need_pp) {
+               err = sh_css_frame_allocate_from_info(&vf_frame,
+                                           &capture_pp_binary->vf_frame_info);
+               if (err != sh_css_success)
+                       return err;
+               err = sh_css_pipeline_add_stage(me, capture_pp_binary, NULL,
+                               capture_pp_binary->info->mode, NULL,
+                               NULL,
+                               last_fw ? NULL : out_frame,
+                               vf_frame, pre_vf_pp_stage);
+               if (err != sh_css_success)
+                       return err;
+               in_frame = (*pre_vf_pp_stage)->args.out_frame;
+       }
+       err = add_firmwares(me, capture_pp_binary, my_css.output_stage, last_fw,
+                           SH_CSS_BINARY_MODE_CAPTURE_PP,
+                           in_frame, out_frame, vf_frame,
+                           NULL, pre_vf_pp_stage);
+       /* If a firmware produce vf_pp output, we set that as vf_pp input */
+       if (*pre_vf_pp_stage) {
+               (*pre_vf_pp_stage)->args.extra_frame =
+                 my_css.capture_settings.capture_pp_frame;
+               (*pre_vf_pp_stage)->args.vf_downscale_log2 =
+                 capture_pp_binary->vf_downscale_log2;
+       } else {
+               *pre_vf_pp_stage = capture_stage;
+       }
+       return err;
+}
+
+
+enum sh_css_err
+sh_css_preview_start(struct sh_css_frame *raw_out_frame,
+                    struct sh_css_frame *out_frame)
+{
+       struct sh_css_pipeline *me = &my_css.preview_settings.pipeline;
+       struct sh_css_pipeline_stage *preview_stage, *copy_stage;
+       struct sh_css_pipeline_stage *vf_pp_stage;
+       struct sh_css_frame *in_frame = NULL, *in_ref_frame, *cc_frame = NULL;
+       struct sh_css_binary *copy_binary, *preview_binary, *vf_pp_binary;
+       enum sh_css_err err = sh_css_success;
+
+       if (!out_frame)
+               return sh_css_err_invalid_arguments;
+       copy_stage = NULL;
+
+       if (my_css.invalidate || my_css.preview_settings.zoom_changed) {
+               invalidate_preview_binaries();
+               my_css.preview_settings.zoom_changed = false;
+               my_css.invalidate = false;
+       }
+
+       err = load_preview_binaries();
+       if (err != sh_css_success)
+               return err;
+
+       err = check_infos_match(&out_frame->info,
+                       &my_css.preview_settings.vf_pp_binary.out_frame_info);
+       if (err != sh_css_success)
+               return err;
+
+       copy_binary    = &my_css.preview_settings.copy_binary;
+       preview_binary = &my_css.preview_settings.preview_binary;
+       vf_pp_binary   = &my_css.preview_settings.vf_pp_binary;
+
+       sh_css_metrics_start_frame();
+
+       if (me->reload) {
+               struct sh_css_pipeline_stage *post_stage;
+               sh_css_pipeline_clean(me);
+               if (my_css.preview_settings.copy_binary.info) {
+                       err = sh_css_pipeline_add_stage(me, copy_binary, NULL,
+                                       copy_binary->info->mode,
+                                       NULL, NULL, raw_out_frame, NULL,
+                                       &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+                       in_frame = me->stages->args.out_frame;
+               } else {
+                       in_frame = my_css.preview_settings.continuous_frames
+                               [my_css.preview_settings.continuous_frame];
+               }
+               err = sh_css_pipeline_add_stage(me, preview_binary, NULL,
+                                               preview_binary->info->mode,
+                                               cc_frame, in_frame, NULL, NULL,
+                                               &post_stage);
+               if (err != sh_css_success)
+                       return err;
+               /* If we use copy iso preview, the input must be yuv iso raw */
+               post_stage->args.copy_vf =
+                       preview_binary->info->mode == SH_CSS_BINARY_MODE_COPY;
+               post_stage->args.copy_output = !post_stage->args.copy_vf;
+               if (post_stage->args.copy_vf) {
+                       /* in case of copy, use the vf frame as output frame */
+                       post_stage->args.out_vf_frame =
+                               post_stage->args.out_frame;
+               }
+
+               err = add_vf_pp_stage(me, out_frame, vf_pp_binary,
+                                     post_stage, &vf_pp_stage);
+               if (err != sh_css_success)
+                       return err;
+               me->reload = false;
+       } else {
+               sh_css_pipeline_restart(me);
+       }
+       err = sh_css_config_input_network(me, copy_binary);
+       if (err != sh_css_success)
+               return err;
+       if (!my_css.preview_settings.shading_table) {
+               prepare_shading_table(
+                               &my_css.preview_settings.shading_table,
+                               preview_binary);
+       }
+       sh_css_params_set_shading_table(my_css.preview_settings.shading_table);
+
+       err = sh_css_pipeline_get_output_stage(me, SH_CSS_BINARY_MODE_VF_PP,
+                                              &vf_pp_stage);
+
+       if (err != sh_css_success)
+               return err;
+       err = sh_css_pipeline_get_stage(me, preview_binary->info->mode,
+                                       &preview_stage);
+       if (err != sh_css_success)
+               return err;
+
+       vf_pp_stage->args.out_frame = out_frame;
+
+       in_ref_frame = my_css.preview_settings.ref_frames
+               [my_css.preview_settings.prev_ref_frame];
+
+       /* switch the reference frame buffers */
+       my_css.preview_settings.prev_ref_frame++;
+       if (my_css.preview_settings.prev_ref_frame == NUM_REF_FRAMES)
+               my_css.preview_settings.prev_ref_frame = 0;
+
+       if (my_css.continuous) {
+               in_frame = my_css.preview_settings.continuous_frames
+                       [my_css.preview_settings.continuous_frame];
+               my_css.preview_settings.continuous_frame++;
+               if (my_css.preview_settings.continuous_frame ==
+                   NUM_CONTINUOUS_FRAMES) {
+                       my_css.preview_settings.continuous_frame = 0;
+               }
+               cc_frame = my_css.preview_settings.continuous_frames
+                       [my_css.preview_settings.continuous_frame];
+               preview_stage->args.cc_frame = cc_frame;
+               preview_stage->args.in_frame = in_frame;
+       }
+       /* update the arguments with the latest info */
+       preview_stage->args.in_ref_frame = in_ref_frame;
+       preview_stage->args.out_ref_frame =
+               my_css.preview_settings.ref_frames
+                       [my_css.preview_settings.prev_ref_frame];
+
+       my_css.mode = sh_css_mode_preview;
+       return sh_css_pipeline_start_next_stage(me);
+}
+
+enum sh_css_err
+sh_css_preview_get_output_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+       err = load_preview_binaries();
+       if (err == sh_css_success)
+               *info = my_css.preview_settings.output_info;
+       return err;
+}
+
+enum sh_css_err
+sh_css_preview_configure_pp_input(unsigned int width, unsigned int height)
+{
+       enum sh_css_err err = sh_css_success;
+
+       err = check_null_res(width, height);
+       if (err != sh_css_success)
+               return err;
+
+       if (my_css.preview_settings.pp_input_info.width != width ||
+           my_css.preview_settings.pp_input_info.height != height) {
+               sh_css_frame_info_init(&my_css.preview_settings.pp_input_info,
+                                      width, height,
+                                      SH_CSS_FRAME_FORMAT_YUV_LINE);
+               invalidate_preview_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_preview_get_input_resolution(unsigned int *width,
+                                   unsigned int *height)
+{
+       enum sh_css_err err;
+       err = load_preview_binaries();
+       if (err == sh_css_success) {
+               const struct sh_css_binary *binary;
+               if (my_css.preview_settings.copy_binary.info)
+                       binary = &my_css.preview_settings.copy_binary;
+               else
+                       binary = &my_css.preview_settings.preview_binary;
+               *width  = binary->in_frame_info.width +
+                         columns_needed_for_bayer_order();
+               *height = binary->in_frame_info.height +
+                         lines_needed_for_bayer_order();
+       }
+       return err;
+}
+
+void
+sh_css_preview_enable_online(bool enable)
+{
+       my_css.preview_settings.online = enable;
+}
+
+void
+sh_css_enable_continuous(bool enable)
+{
+       my_css.continuous = enable;
+}
+
+bool
+sh_css_continuous_is_enabled(void)
+{
+       return my_css.continuous;
+}
+
+bool
+sh_css_continuous_start_sp_copy(void)
+{
+       return my_css.start_sp_copy;
+}
+
+void
+sh_css_disable_vf_pp(bool disable)
+{
+       my_css.disable_vf_pp = disable;
+}
+
+void
+sh_css_disable_capture_pp(bool disable)
+{
+       my_css.disable_capture_pp = disable;
+}
+
+enum sh_css_err
+sh_css_preview_configure_output(unsigned int width,
+                               unsigned int height,
+                               enum sh_css_frame_format format)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.preview_settings.output_info.width != width ||
+           my_css.preview_settings.output_info.height != height ||
+           my_css.preview_settings.output_info.format != format) {
+               sh_css_frame_info_init(&my_css.preview_settings.output_info,
+                                      width, height, format);
+               invalidate_preview_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_preview_get_grid_info(struct sh_css_grid_info *info)
+{
+       enum sh_css_err err;
+       err = load_preview_binaries();
+       if (err == sh_css_success) {
+               err = sh_css_binary_grid_info(
+                               &my_css.preview_settings.preview_binary,
+                               info);
+       }
+       return err;
+}
+
+static void
+init_video_descr(struct sh_css_frame_info *in_info,
+                struct sh_css_frame_info *vf_info)
+{
+       int mode = SH_CSS_BINARY_MODE_VIDEO;
+
+       if (input_format_is_yuv(my_css.input_format))
+               mode = SH_CSS_BINARY_MODE_COPY;
+       *in_info = my_css.input_effective_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&video_descr, mode,
+                          in_info, &my_css.video_settings.output_info,
+                          vf_info);
+       video_descr.online = my_css.input_mode != SH_CSS_INPUT_MODE_MEMORY;
+}
+
+static enum sh_css_err
+load_video_binaries(void)
+{
+       struct sh_css_frame_info video_in_info, ref_info, tnr_info,
+                                *video_vf_info;
+       bool online;
+       enum sh_css_err err = sh_css_success;
+       int i;
+
+       /* we only test the video_binary because offline video doesn't need a
+        * vf_pp binary. Both are always reset together anyway.
+        */
+       if (my_css.video_settings.video_binary.info)
+               return sh_css_success;
+       online = my_css.input_mode != SH_CSS_INPUT_MODE_MEMORY;
+       err = check_input(!online);
+       if (err != sh_css_success)
+               return err;
+       if (online) {
+               err = check_vf_out_info(&my_css.video_settings.output_info,
+                                       &my_css.video_settings.vf_info);
+       } else {
+               err = check_frame_info(&my_css.video_settings.output_info);
+       }
+       if (err != sh_css_success)
+               return err;
+
+       /* Video */
+       if (online)
+               video_vf_info = &my_css.video_settings.vf_info;
+       else
+               video_vf_info = NULL;
+       init_video_descr(&video_in_info, video_vf_info);
+       err = sh_css_binary_find(&video_descr,
+                                &my_css.video_settings.video_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Viewfinder post-processing */
+       if (online) {
+               init_vf_pp_descr(
+                       &my_css.video_settings.video_binary.vf_frame_info,
+                       &my_css.video_settings.vf_info);
+               err = sh_css_binary_find(&vf_pp_descr,
+                               &my_css.video_settings.vf_pp_binary);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       /* yuv copy does not use reference frames */
+       if (input_format_is_yuv(my_css.input_format))
+               return sh_css_success;
+
+       ref_info = my_css.video_settings.video_binary.internal_frame_info;
+       ref_info.format = SH_CSS_FRAME_FORMAT_YUV420;
+
+       for (i = 0; i < NUM_REF_FRAMES; i++) {
+               if (my_css.video_settings.ref_frames[i])
+                       sh_css_frame_free(my_css.video_settings.ref_frames[i]);
+               err = sh_css_frame_allocate_from_info(
+                               &my_css.video_settings.ref_frames[i],
+                               &ref_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+       my_css.video_settings.prev_ref_frame = 0;
+       if (SH_CSS_PREVENT_UNINIT_READS)
+               sh_css_frame_zero(my_css.video_settings.ref_frames[0]);
+
+       tnr_info = my_css.video_settings.video_binary.internal_frame_info;
+       tnr_info.format = SH_CSS_FRAME_FORMAT_YUV420;
+
+       for (i = 0; i < NUM_TNR_FRAMES; i++) {
+               if (my_css.video_settings.tnr_frames[i])
+                       sh_css_frame_free(my_css.video_settings.tnr_frames[i]);
+               err = sh_css_frame_allocate_from_info(
+                               &my_css.video_settings.tnr_frames[i],
+                               &tnr_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+       my_css.video_settings.prev_tnr_frame = 0;
+       if (SH_CSS_PREVENT_UNINIT_READS) {
+               sh_css_frame_zero(my_css.video_settings.tnr_frames[0]);
+               sh_css_frame_zero(my_css.video_settings.tnr_frames[1]);
+       }
+
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_video_start(struct sh_css_frame *in_frame,
+                  struct sh_css_frame *out_frame,
+                  struct sh_css_frame *vf_frame)
+{
+       struct sh_css_pipeline *me = &my_css.video_settings.pipeline;
+       struct sh_css_pipeline_stage *video_stage, *vf_pp_stage;
+       struct sh_css_frame *in_ref_frame, *in_tnr_frame;
+       struct sh_css_binary *video_binary, *vf_pp_binary;
+       enum sh_css_err err = sh_css_success;
+
+       if (!out_frame)
+               return sh_css_err_invalid_arguments;
+       if (my_css.invalidate || my_css.video_settings.zoom_changed) {
+               invalidate_video_binaries();
+               my_css.video_settings.zoom_changed = false;
+               my_css.invalidate = false;
+       }
+
+       err = load_video_binaries();
+       if (err != sh_css_success)
+               return err;
+       video_binary = &my_css.video_settings.video_binary;
+       vf_pp_binary = &my_css.video_settings.vf_pp_binary;
+       if (in_frame) {
+               if (vf_frame)
+                       return sh_css_err_mode_does_not_have_viewfinder;
+       } else {
+               if (!vf_frame)
+                       return sh_css_err_invalid_arguments;
+               err = check_infos_match(&vf_frame->info,
+                       &my_css.video_settings.vf_pp_binary.out_frame_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+       err = check_infos_match(&out_frame->info,
+                       &my_css.video_settings.video_binary.out_frame_info);
+       if (err != sh_css_success)
+               return err;
+
+       sh_css_metrics_start_frame();
+
+       if (me->reload) {
+               sh_css_pipeline_clean(me);
+               err = sh_css_pipeline_add_stage(me, video_binary, NULL,
+                                               video_binary->info->mode, NULL,
+                                               in_frame, out_frame, NULL,
+                                               &video_stage);
+               if (err != sh_css_success)
+                       return err;
+               /* If we use copy iso video, the input must be yuv iso raw */
+               video_stage->args.copy_vf =
+                       video_binary->info->mode == SH_CSS_BINARY_MODE_COPY;
+               video_stage->args.copy_output = video_stage->args.copy_vf;
+               if (!in_frame) {
+                       err = add_vf_pp_stage(me, vf_frame, vf_pp_binary,
+                                             video_stage, &vf_pp_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               me->reload = false;
+       } else {
+               sh_css_pipeline_restart(me);
+       }
+       err = sh_css_config_input_network(me, NULL);
+       if (err != sh_css_success)
+               return err;
+       if (!my_css.video_settings.shading_table) {
+               prepare_shading_table(
+                               &my_css.video_settings.shading_table,
+                               video_binary);
+       }
+       sh_css_params_set_shading_table(my_css.video_settings.shading_table);
+
+       err = sh_css_pipeline_get_stage(me, video_binary->info->mode,
+                                       &video_stage);
+       if (err != sh_css_success)
+               return err;
+       if (!in_frame) {
+               err = sh_css_pipeline_get_output_stage(me,
+                                                      vf_pp_binary->info->mode,
+                                                      &vf_pp_stage);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       in_ref_frame = my_css.video_settings.ref_frames
+               [my_css.video_settings.prev_ref_frame];
+       /* switch the reference frame buffers */
+       my_css.video_settings.prev_ref_frame++;
+       if (my_css.video_settings.prev_ref_frame == NUM_VIDEO_REF_FRAMES)
+               my_css.video_settings.prev_ref_frame = 0;
+
+       in_tnr_frame = my_css.video_settings.tnr_frames
+               [my_css.video_settings.prev_tnr_frame];
+       /* switch the tnr frame buffers */
+       my_css.video_settings.prev_tnr_frame++;
+       if (my_css.video_settings.prev_tnr_frame == NUM_VIDEO_TNR_FRAMES)
+               my_css.video_settings.prev_tnr_frame = 0;
+
+       /* update the arguments with the latest info */
+       video_stage->args.in_ref_frame = in_ref_frame;
+       video_stage->args.in_tnr_frame = in_tnr_frame;
+       video_stage->args.out_frame = out_frame;
+       video_stage->args.out_ref_frame =
+               my_css.video_settings.ref_frames
+                       [my_css.video_settings.prev_ref_frame];
+       video_stage->args.out_tnr_frame =
+               my_css.video_settings.tnr_frames
+                       [my_css.video_settings.prev_tnr_frame];
+       video_stage->args.dvs_vector_x = my_css.video_settings.dvs_vector_x;
+       video_stage->args.dvs_vector_y = my_css.video_settings.dvs_vector_y;
+       if (!in_frame)
+               vf_pp_stage->args.out_frame = vf_frame;
+
+       my_css.mode = sh_css_mode_video;
+       return sh_css_pipeline_start_next_stage(me);
+}
+
+enum sh_css_err
+sh_css_video_get_output_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+
+       err = load_video_binaries();
+       if (err == sh_css_success)
+               *info = my_css.video_settings.output_info;
+       return err;
+}
+
+enum sh_css_err
+sh_css_video_get_viewfinder_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+
+       err = load_video_binaries();
+       if (err != sh_css_success)
+               return err;
+       /* offline video does not generate viewfinder output */
+       if (my_css.input_mode == SH_CSS_INPUT_MODE_MEMORY)
+               return sh_css_err_mode_does_not_have_viewfinder;
+       else
+               *info = my_css.video_settings.vf_info;
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_video_get_grid_info(struct sh_css_grid_info *info)
+{
+       enum sh_css_err err;
+
+       err = load_video_binaries();
+       if (err != sh_css_success)
+               return err;
+       err = sh_css_binary_grid_info(&my_css.video_settings.video_binary,
+                                     info);
+       return err;
+}
+
+enum sh_css_err
+sh_css_video_get_input_resolution(unsigned int *width, unsigned int *height)
+{
+       enum sh_css_err err;
+
+       err = load_video_binaries();
+       if (err == sh_css_success) {
+               const struct sh_css_binary *binary;
+               binary = &my_css.video_settings.video_binary;
+               *width  = binary->in_frame_info.width +
+                         columns_needed_for_bayer_order();
+               *height = binary->in_frame_info.height +
+                         lines_needed_for_bayer_order();
+       }
+
+       return err;
+}
+
+enum sh_css_err
+sh_css_video_configure_output(unsigned int width,
+                             unsigned int height,
+                             enum sh_css_frame_format format)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.video_settings.output_info.width != width ||
+           my_css.video_settings.output_info.height != height ||
+           my_css.video_settings.output_info.format != format) {
+               sh_css_frame_info_init(&my_css.video_settings.output_info,
+                                      width, height, format);
+               invalidate_video_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_video_configure_viewfinder(unsigned int width,
+                                 unsigned int height,
+                                 enum sh_css_frame_format format)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.video_settings.vf_info.width != width ||
+           my_css.video_settings.vf_info.height != height ||
+           my_css.video_settings.vf_info.format != format) {
+               sh_css_frame_info_init(&my_css.video_settings.vf_info,
+                                      width, height, format);
+               invalidate_video_binaries();
+       }
+       return sh_css_success;
+}
+
+void
+sh_css_video_set_dis_vector(int x, int y)
+{
+       my_css.video_settings.dvs_vector_x = x;
+       my_css.video_settings.dvs_vector_y = y;
+}
+
+/* Specify the envelope to be used for DIS. */
+void
+sh_css_video_set_dis_envelope(unsigned int width, unsigned int height)
+{
+       if (width != my_css.video_settings.dvs_envelope_width ||
+           height != my_css.video_settings.dvs_envelope_height) {
+               my_css.video_settings.dvs_envelope_width = width;
+               my_css.video_settings.dvs_envelope_height = height;
+               invalidate_video_binaries();
+       }
+}
+
+void
+sh_css_video_get_dis_envelope(unsigned int *width, unsigned int *height)
+{
+       *width = my_css.video_settings.dvs_envelope_width;
+       *height = my_css.video_settings.dvs_envelope_height;
+}
+
+void
+sh_css_set_zoom_factor(unsigned int dx, unsigned int dy)
+{
+       bool is_zoomed = (dx < 64) || (dy < 64);
+       bool was_zoomed = (my_css.curr_dx < 64) || (my_css.curr_dy < 64);
+
+       if (is_zoomed != was_zoomed) {
+               /* for with/without zoom, we use different binaries */
+               my_css.video_settings.zoom_changed   = true;
+               my_css.preview_settings.zoom_changed = true;
+               my_css.capture_settings.zoom_changed = true;
+       }
+       my_css.curr_dx = dx;
+       my_css.curr_dy = dy;
+}
+
+void
+sh_css_get_zoom_factor(unsigned int *dx, unsigned int *dy)
+{
+       *dx = my_css.curr_dx;
+       *dy = my_css.curr_dy;
+}
+
+static enum sh_css_err
+load_copy_binaries(void)
+{
+       enum sh_css_err err = sh_css_success;
+
+       if (my_css.capture_settings.copy_binary.info)
+               return sh_css_success;
+
+       err = check_frame_info(&my_css.capture_settings.output_info);
+       if (err != sh_css_success)
+               return err;
+
+       get_copy_out_frame_format(&my_css.capture_settings.output_info.format);
+       return load_copy_binary(&my_css.capture_settings.copy_binary, NULL);
+}
+
+static bool
+need_capture_pp(void)
+{
+       /* determine whether we need to use the capture_pp binary.
+        * This is needed for:
+        *   1. XNR or
+        *   2. Digital Zoom or
+        *   3. YUV downscaling
+        */
+       if (my_css.capture_settings.pp_input_info.width &&
+           ((my_css.capture_settings.pp_input_info.width !=
+             my_css.capture_settings.output_info.width) ||
+            (my_css.capture_settings.pp_input_info.height !=
+             my_css.capture_settings.output_info.height)))
+               return true;
+       if (my_css.capture_settings.xnr)
+               return true;
+       if (my_css.curr_dx < 64 || my_css.curr_dy < 64)
+               return true;
+       return false;
+}
+
+static void
+init_capture_pp_descr(struct sh_css_frame_info *in_info,
+                     struct sh_css_frame_info *vf_info)
+{
+       /* the in_info is only used for resolution to enable
+          bayer down scaling. */
+       if (my_css.capture_settings.pp_input_info.width)
+               *in_info = my_css.capture_settings.pp_input_info;
+       else
+               *in_info = my_css.capture_settings.output_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_YUV420;
+       in_info->raw_bit_depth = 0;
+       sh_css_frame_info_set_width(in_info, in_info->width);
+       init_offline_descr(&capture_pp_descr, SH_CSS_BINARY_MODE_CAPTURE_PP,
+                          in_info, &my_css.capture_settings.output_info,
+                          vf_info);
+}
+
+static void
+init_primary_descr(struct sh_css_frame_info *in_info,
+                  struct sh_css_frame_info *out_info,
+                  struct sh_css_frame_info *vf_info)
+{
+       int mode = SH_CSS_BINARY_MODE_PRIMARY;
+
+       if (input_format_is_yuv(my_css.input_format))
+               mode = SH_CSS_BINARY_MODE_COPY;
+
+       *in_info = my_css.input_effective_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&prim_descr, mode,
+                          in_info, out_info, vf_info);
+       if (my_css.capture_settings.online) {
+               prim_descr.online        = true;
+               prim_descr.stream_format = my_css.input_format;
+       }
+}
+
+static void
+init_pre_gdc_descr(struct sh_css_frame_info *in_info,
+                  struct sh_css_frame_info *out_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&pre_gdc_descr, SH_CSS_BINARY_MODE_PRE_GDC,
+                          in_info, out_info, NULL);
+}
+
+static void
+init_gdc_descr(struct sh_css_frame_info *in_info,
+              struct sh_css_frame_info *out_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_QPLANE6;
+       init_offline_descr(&gdc_descr, SH_CSS_BINARY_MODE_GDC,
+                          in_info, out_info, NULL);
+}
+
+static void
+init_post_gdc_descr(struct sh_css_frame_info *in_info,
+                   struct sh_css_frame_info *out_info,
+                   struct sh_css_frame_info *vf_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_YUV420_16;
+       init_offline_descr(&post_gdc_descr, SH_CSS_BINARY_MODE_POST_GDC,
+                          in_info, out_info, vf_info);
+}
+
+static void
+init_pre_anr_descr(struct sh_css_frame_info *in_info,
+                  struct sh_css_frame_info *out_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&pre_anr_descr, SH_CSS_BINARY_MODE_PRE_ANR,
+                          in_info, out_info, NULL);
+}
+
+static void
+init_anr_descr(struct sh_css_frame_info *in_info,
+              struct sh_css_frame_info *out_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&anr_descr, SH_CSS_BINARY_MODE_ANR,
+                          in_info, out_info, NULL);
+}
+
+static void
+init_post_anr_descr(struct sh_css_frame_info *in_info,
+                   struct sh_css_frame_info *out_info,
+                   struct sh_css_frame_info *vf_info)
+{
+       *in_info = *out_info;
+       in_info->format = SH_CSS_FRAME_FORMAT_RAW;
+       in_info->raw_bit_depth =
+               sh_css_input_format_bits_per_pixel(my_css.input_format,
+                                                  my_css.two_ppc);
+       init_offline_descr(&post_anr_descr, SH_CSS_BINARY_MODE_POST_ANR,
+                          in_info, out_info, vf_info);
+}
+
+static enum sh_css_err
+load_primary_binaries(void)
+{
+       bool online = my_css.capture_settings.online;
+       bool continuous = my_css.continuous;
+       bool need_pp = false;
+       struct sh_css_frame_info prim_in_info,
+                                prim_out_info, vf_info,
+                                *vf_pp_in_info;
+       enum sh_css_err err = sh_css_success;
+
+       if (my_css.capture_settings.primary_binary.info)
+               return sh_css_success;
+
+       err = check_vf_out_info(&my_css.capture_settings.output_info,
+                               &my_css.capture_settings.vf_info);
+       if (err != sh_css_success)
+               return err;
+       need_pp = need_capture_pp();
+
+       /* we use the vf output info to get the primary/capture_pp binary
+          configured for vf_veceven. It will select the closest downscaling
+          factor. */
+       vf_info = my_css.capture_settings.vf_info;
+       sh_css_frame_info_set_format(&vf_info,
+                                    SH_CSS_FRAME_FORMAT_YUV_LINE);
+
+       /* we build up the pipeline starting at the end */
+       /* Capture post-processing */
+       my_css.capture_settings.need_pp = need_pp;
+       if (need_pp) {
+               init_capture_pp_descr(&prim_out_info, &vf_info);
+               err = sh_css_binary_find(&capture_pp_descr,
+                               &my_css.capture_settings.capture_pp_binary);
+               if (err != sh_css_success)
+                       return err;
+       } else {
+               prim_out_info = my_css.capture_settings.output_info;
+       }
+
+       /* Primary */
+       init_primary_descr(&prim_in_info, &prim_out_info, &vf_info);
+       err = sh_css_binary_find(&prim_descr,
+                                &my_css.capture_settings.primary_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Viewfinder post-processing */
+       if (need_pp) {
+               vf_pp_in_info =
+                   &my_css.capture_settings.capture_pp_binary.vf_frame_info;
+       } else {
+               vf_pp_in_info =
+                   &my_css.capture_settings.primary_binary.vf_frame_info;
+       }
+
+       init_vf_pp_descr(vf_pp_in_info, &my_css.capture_settings.vf_info);
+       err = sh_css_binary_find(&vf_pp_descr,
+                                &my_css.capture_settings.vf_pp_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Copy */
+       if (!online && !continuous) {
+               err = load_copy_binary(&my_css.capture_settings.copy_binary,
+                                      &my_css.capture_settings.primary_binary);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       if (need_pp)
+               return alloc_capture_pp_frame(
+                               &my_css.capture_settings.capture_pp_binary);
+       else
+               return sh_css_success;
+}
+
+static enum sh_css_err
+load_advanced_binaries(void)
+{
+       struct sh_css_frame_info pre_in_info, gdc_in_info,
+                                post_in_info, post_out_info,
+                                vf_info, *vf_pp_in_info;
+       bool need_pp;
+       enum sh_css_err err = sh_css_success;
+
+       if (my_css.capture_settings.pre_gdc_binary.info)
+               return sh_css_success;
+
+       err = check_vf_out_info(&my_css.capture_settings.output_info,
+                               &my_css.capture_settings.vf_info);
+       if (err != sh_css_success)
+               return err;
+       need_pp = need_capture_pp();
+
+       vf_info = my_css.capture_settings.vf_info;
+       sh_css_frame_info_set_format(&vf_info,
+                                    SH_CSS_FRAME_FORMAT_YUV_LINE);
+
+       /* we build up the pipeline starting at the end */
+       /* Capture post-processing */
+       my_css.capture_settings.need_pp = need_pp;
+       if (need_pp) {
+               init_capture_pp_descr(&post_out_info, &vf_info);
+               err = sh_css_binary_find(&capture_pp_descr,
+                               &my_css.capture_settings.capture_pp_binary);
+               if (err != sh_css_success)
+                       return err;
+       } else {
+               post_out_info = my_css.capture_settings.output_info;
+       }
+
+       /* Post-gdc */
+       init_post_gdc_descr(&post_in_info, &post_out_info, &vf_info);
+       err = sh_css_binary_find(&post_gdc_descr,
+                                &my_css.capture_settings.post_gdc_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Gdc */
+       init_gdc_descr(&gdc_in_info,
+                      &my_css.capture_settings.post_gdc_binary.in_frame_info);
+       err = sh_css_binary_find(&gdc_descr,
+                                &my_css.capture_settings.gdc_binary);
+       if (err != sh_css_success)
+               return err;
+       my_css.capture_settings.gdc_binary.left_padding =
+               my_css.capture_settings.post_gdc_binary.left_padding;
+
+       /* Pre-gdc */
+       init_pre_gdc_descr(&pre_in_info,
+                          &my_css.capture_settings.gdc_binary.in_frame_info);
+       err = sh_css_binary_find(&pre_gdc_descr,
+                                &my_css.capture_settings.pre_gdc_binary);
+       if (err != sh_css_success)
+               return err;
+       my_css.capture_settings.pre_gdc_binary.left_padding =
+               my_css.capture_settings.gdc_binary.left_padding;
+
+       /* Viewfinder post-processing */
+       if (need_pp) {
+               vf_pp_in_info =
+                   &my_css.capture_settings.capture_pp_binary.vf_frame_info;
+       } else {
+               vf_pp_in_info =
+                   &my_css.capture_settings.post_gdc_binary.vf_frame_info;
+       }
+
+       init_vf_pp_descr(vf_pp_in_info, &my_css.capture_settings.vf_info);
+       err = sh_css_binary_find(&vf_pp_descr,
+                                &my_css.capture_settings.vf_pp_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Copy */
+       err = load_copy_binary(&my_css.capture_settings.copy_binary,
+                              &my_css.capture_settings.pre_gdc_binary);
+       if (err != sh_css_success)
+               return err;
+
+       if (need_pp)
+               return alloc_capture_pp_frame(
+                               &my_css.capture_settings.capture_pp_binary);
+       else
+               return sh_css_success;
+}
+
+static enum sh_css_err
+load_low_light_binaries(void)
+{
+       struct sh_css_frame_info pre_in_info, anr_in_info,
+                                post_in_info, post_out_info,
+                                vf_info, *vf_pp_in_info;
+       bool need_pp;
+       enum sh_css_err err = sh_css_success;
+
+       if (my_css.capture_settings.pre_anr_binary.info)
+               return sh_css_success;
+
+       err = check_vf_out_info(&my_css.capture_settings.output_info,
+                               &my_css.capture_settings.vf_info);
+       if (err != sh_css_success)
+               return err;
+       need_pp = need_capture_pp();
+
+       vf_info = my_css.capture_settings.vf_info;
+       sh_css_frame_info_set_format(&vf_info,
+                                    SH_CSS_FRAME_FORMAT_YUV_LINE);
+
+       /* we build up the pipeline starting at the end */
+       /* Capture post-processing */
+       my_css.capture_settings.need_pp = need_pp;
+       if (need_pp) {
+               init_capture_pp_descr(&post_out_info, &vf_info);
+               err = sh_css_binary_find(&capture_pp_descr,
+                               &my_css.capture_settings.capture_pp_binary);
+               if (err != sh_css_success)
+                       return err;
+       } else {
+               post_out_info = my_css.capture_settings.output_info;
+       }
+
+       /* Post-anr */
+       init_post_anr_descr(&post_in_info, &post_out_info, &vf_info);
+       err = sh_css_binary_find(&post_anr_descr,
+                                &my_css.capture_settings.post_anr_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Anr */
+       init_anr_descr(&anr_in_info,
+                      &my_css.capture_settings.post_anr_binary.in_frame_info);
+       err = sh_css_binary_find(&anr_descr,
+                                &my_css.capture_settings.anr_binary);
+       if (err != sh_css_success)
+               return err;
+       my_css.capture_settings.anr_binary.left_padding =
+               my_css.capture_settings.post_anr_binary.left_padding;
+
+       /* Pre-anr */
+       init_pre_anr_descr(&pre_in_info,
+                          &my_css.capture_settings.anr_binary.in_frame_info);
+       err = sh_css_binary_find(&pre_anr_descr,
+                                &my_css.capture_settings.pre_anr_binary);
+       if (err != sh_css_success)
+               return err;
+       my_css.capture_settings.pre_anr_binary.left_padding =
+               my_css.capture_settings.anr_binary.left_padding;
+
+       /* Viewfinder post-processing */
+       if (need_pp) {
+               vf_pp_in_info =
+                   &my_css.capture_settings.capture_pp_binary.vf_frame_info;
+       } else {
+               vf_pp_in_info =
+                   &my_css.capture_settings.post_anr_binary.vf_frame_info;
+       }
+
+       init_vf_pp_descr(vf_pp_in_info, &my_css.capture_settings.vf_info);
+       err = sh_css_binary_find(&vf_pp_descr,
+                                &my_css.capture_settings.vf_pp_binary);
+       if (err != sh_css_success)
+               return err;
+
+       /* Copy */
+       err = load_copy_binary(&my_css.capture_settings.copy_binary,
+                              &my_css.capture_settings.pre_anr_binary);
+       if (err != sh_css_success)
+               return err;
+
+       if (need_pp)
+               return alloc_capture_pp_frame(
+                               &my_css.capture_settings.capture_pp_binary);
+       else
+               return sh_css_success;
+}
+
+static bool
+copy_on_sp(void)
+{
+       if (my_css.capture_settings.mode != SH_CSS_CAPTURE_MODE_RAW)
+               return false;
+       return my_css.continuous ||
+               my_css.input_format == SH_CSS_INPUT_FORMAT_BINARY_8;
+}
+
+static enum sh_css_err
+load_capture_binaries(void)
+{
+       enum sh_css_err err = sh_css_success;
+       bool must_be_raw;
+
+       /* in primary, advanced or low light, the input format must be raw */
+       must_be_raw =
+               my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_ADVANCED ||
+               my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_LOW_LIGHT;
+       err = check_input(must_be_raw);
+       if (err != sh_css_success)
+               return err;
+       if (copy_on_sp()) {
+               /* this is handled by the SP, no ISP binaries needed. */
+               if (my_css.input_format == SH_CSS_INPUT_FORMAT_BINARY_8) {
+                       sh_css_frame_info_init(
+                               &my_css.capture_settings.output_info,
+                               JPEG_BYTES, 1, SH_CSS_FRAME_FORMAT_BINARY_8);
+                       return sh_css_success;
+               }
+       }
+
+       switch (my_css.capture_settings.mode) {
+       case SH_CSS_CAPTURE_MODE_RAW:
+               return load_copy_binaries();
+       case SH_CSS_CAPTURE_MODE_PRIMARY:
+               return load_primary_binaries();
+       case SH_CSS_CAPTURE_MODE_ADVANCED:
+               return load_advanced_binaries();
+       case SH_CSS_CAPTURE_MODE_LOW_LIGHT:
+               return load_low_light_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_capture_start(struct sh_css_frame *raw_out_frame,
+                    struct sh_css_frame *out_frame,
+                    struct sh_css_frame *vf_frame)
+{
+       bool raw = my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW;
+       struct sh_css_pipeline *me = &my_css.capture_settings.pipeline;
+       struct sh_css_pipeline_stage *out_stage, *vf_pp_stage, *copy_stage;
+       struct sh_css_binary *copy_binary,
+                            *primary_binary,
+                            *vf_pp_binary,
+                            *pre_gdc_binary,
+                            *gdc_binary,
+                            *post_gdc_binary,
+                            *pre_anr_binary,
+                            *anr_binary,
+                            *post_anr_binary,
+                            *capture_pp_binary,
+                            *sc_binary = NULL;
+       bool need_pp = false;
+       enum sh_css_err err = sh_css_success;
+       bool raw_copy = my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW
+                       && copy_on_sp();
+
+       if (!out_frame)
+               return sh_css_err_invalid_arguments;
+       copy_stage = NULL;
+
+       if (my_css.invalidate || my_css.capture_settings.zoom_changed) {
+               invalidate_capture_binaries();
+               my_css.capture_settings.zoom_changed = false;
+               my_css.invalidate = false;
+       }
+
+       err = load_capture_binaries();
+       if (err != sh_css_success)
+               return err;
+
+       err = check_infos_match(&out_frame->info,
+                       &my_css.capture_settings.output_info);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW && vf_frame)
+               return sh_css_err_mode_does_not_have_viewfinder;
+
+       if (vf_frame) {
+               err = check_infos_match(&vf_frame->info,
+                                       &my_css.capture_settings.vf_info);
+               if (err != sh_css_success)
+                       return err;
+       }
+
+       copy_binary       = &my_css.capture_settings.copy_binary;
+       primary_binary    = &my_css.capture_settings.primary_binary;
+       vf_pp_binary      = &my_css.capture_settings.vf_pp_binary;
+       pre_gdc_binary    = &my_css.capture_settings.pre_gdc_binary;
+       gdc_binary        = &my_css.capture_settings.gdc_binary;
+       post_gdc_binary   = &my_css.capture_settings.post_gdc_binary;
+       pre_anr_binary    = &my_css.capture_settings.pre_anr_binary;
+       anr_binary        = &my_css.capture_settings.anr_binary;
+       post_anr_binary   = &my_css.capture_settings.post_anr_binary;
+       capture_pp_binary = &my_css.capture_settings.capture_pp_binary;
+       need_pp = my_css.capture_settings.need_pp || my_css.output_stage;
+
+       sh_css_metrics_start_frame();
+
+       if (me->reload) {
+               struct sh_css_pipeline_stage *post_stage;
+               sh_css_pipeline_clean(me);
+               if (my_css.capture_settings.copy_binary.info && !raw_copy) {
+                       err = sh_css_pipeline_add_stage(me, copy_binary, NULL,
+                                       copy_binary->info->mode, NULL, NULL,
+                                       raw ? out_frame : raw_out_frame,
+                                       NULL, &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               if (my_css.capture_settings.mode ==
+                   SH_CSS_CAPTURE_MODE_PRIMARY) {
+                       err = sh_css_pipeline_add_stage(me, primary_binary,
+                                       NULL, primary_binary->info->mode,
+                                       NULL, NULL,
+                                       need_pp ? NULL : out_frame,
+                                       NULL, &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+                       /* If we use copy iso primary,
+                          the input must be yuv iso raw */
+                       post_stage->args.copy_vf =
+                               primary_binary->info->mode ==
+                               SH_CSS_BINARY_MODE_COPY;
+                       post_stage->args.copy_output = post_stage->args.copy_vf;
+                       sc_binary = primary_binary;
+               } else if (my_css.capture_settings.mode ==
+                          SH_CSS_CAPTURE_MODE_ADVANCED) {
+                       err = sh_css_pipeline_add_stage(me, pre_gdc_binary,
+                                       NULL, pre_gdc_binary->info->mode,
+                                       NULL, NULL, NULL, NULL, NULL);
+                       if (err != sh_css_success)
+                               return err;
+                       err = sh_css_pipeline_add_stage(me, gdc_binary,
+                                       NULL, gdc_binary->info->mode,
+                                       NULL, NULL, NULL, NULL, NULL);
+                       if (err != sh_css_success)
+                               return err;
+                       err = sh_css_pipeline_add_stage(me, post_gdc_binary,
+                                       NULL, post_gdc_binary->info->mode,
+                                       NULL, NULL,
+                                       need_pp ? NULL : out_frame,
+                                       NULL, &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+                       sc_binary = pre_gdc_binary;
+               } else if (my_css.capture_settings.mode ==
+                          SH_CSS_CAPTURE_MODE_LOW_LIGHT) {
+                       err = sh_css_pipeline_add_stage(me, pre_anr_binary,
+                                       NULL, pre_anr_binary->info->mode,
+                                       NULL, NULL, NULL, NULL, NULL);
+                       if (err != sh_css_success)
+                               return err;
+                       err = sh_css_pipeline_add_stage(me, anr_binary,
+                                       NULL, anr_binary->info->mode,
+                                       NULL, NULL, NULL, NULL, NULL);
+                       if (err != sh_css_success)
+                               return err;
+                       err = sh_css_pipeline_add_stage(me, post_anr_binary,
+                                       NULL, post_anr_binary->info->mode,
+                                       NULL, NULL,
+                                       need_pp ? NULL : out_frame,
+                                       NULL, &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+                       sc_binary = pre_anr_binary;
+               }
+
+               if (need_pp) {
+                       err = add_capture_pp_stage(me, out_frame,
+                                                  capture_pp_binary,
+                                                  post_stage, &post_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               if (my_css.capture_settings.mode != SH_CSS_CAPTURE_MODE_RAW) {
+                       err = add_vf_pp_stage(me, vf_frame, vf_pp_binary,
+                                             post_stage, &vf_pp_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               me->reload = false;
+       } else {
+               sh_css_pipeline_restart(me);
+       }
+
+       err = sh_css_config_input_network(me, copy_binary);
+       if (err != sh_css_success)
+               return err;
+       if (!my_css.capture_settings.shading_table && sc_binary) {
+               prepare_shading_table(
+                               &my_css.capture_settings.shading_table,
+                               sc_binary);
+       }
+       sh_css_params_set_shading_table(my_css.capture_settings.shading_table);
+
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW) {
+               if (copy_on_sp()) {
+                       my_css.mode = sh_css_mode_capture;
+                       my_css.state = sh_css_state_executing_sp_bin_copy;
+                       return start_copy_on_sp(copy_binary, out_frame);
+               }
+       } else {
+               if (!vf_frame)
+                       return sh_css_err_invalid_arguments;
+       }
+       if (err != sh_css_success)
+               return err;
+
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW) {
+               err = sh_css_pipeline_get_stage(me, copy_binary->info->mode,
+                                               &out_stage);
+               if (err != sh_css_success)
+                       return err;
+               copy_stage = out_stage;
+       } else {
+               if (copy_binary->info) {
+                       err = sh_css_pipeline_get_stage(me,
+                                                       copy_binary->info->mode,
+                                                       &copy_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               if (capture_pp_binary->info) {
+                       err = sh_css_pipeline_get_stage(me,
+                                       capture_pp_binary->info->mode,
+                                       &out_stage);
+                       if (err != sh_css_success)
+                               return err;
+               } else if (my_css.capture_settings.mode ==
+                          SH_CSS_CAPTURE_MODE_PRIMARY) {
+                       err = sh_css_pipeline_get_stage(me,
+                                       primary_binary->info->mode, &out_stage);
+                       if (err != sh_css_success)
+                               return err;
+               } else if (my_css.capture_settings.mode ==
+                          SH_CSS_CAPTURE_MODE_LOW_LIGHT) {
+                       err = sh_css_pipeline_get_stage(me,
+                                       post_anr_binary->info->mode,
+                                       &out_stage);
+                       if (err != sh_css_success)
+                               return err;
+               } else {
+                       err = sh_css_pipeline_get_stage(me,
+                                       post_gdc_binary->info->mode,
+                                       &out_stage);
+                       if (err != sh_css_success)
+                               return err;
+               }
+               err = sh_css_pipeline_get_output_stage(me,
+                                                      vf_pp_binary->info->mode,
+                                                      &vf_pp_stage);
+               if (err != sh_css_success)
+                       return err;
+       }
+       if (my_css.capture_settings.mode != SH_CSS_CAPTURE_MODE_RAW)
+               vf_pp_stage->args.out_frame = vf_frame;
+
+       if (!my_css.output_stage)
+               out_stage->args.out_frame = out_frame;
+
+       if (copy_stage && raw_out_frame)
+               copy_stage->args.out_frame = raw_out_frame;
+       my_css.mode = sh_css_mode_capture;
+       return sh_css_pipeline_start_next_stage(me);
+}
+
+enum sh_css_err
+sh_css_capture_get_output_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+
+       err = load_capture_binaries();
+       if (err != sh_css_success)
+               return err;
+
+       if (copy_on_sp() &&
+           my_css.input_format == SH_CSS_INPUT_FORMAT_BINARY_8) {
+               sh_css_frame_info_init(info, JPEG_BYTES, 1,
+                                      SH_CSS_FRAME_FORMAT_BINARY_8);
+       } else {
+               *info = my_css.capture_settings.output_info;
+               if (info->format == SH_CSS_FRAME_FORMAT_RAW)
+                       info->raw_bit_depth =
+                               sh_css_input_format_bits_per_pixel(
+                                       my_css.input_format,
+                                       my_css.two_ppc);
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_capture_get_viewfinder_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW)
+               return sh_css_err_mode_does_not_have_viewfinder;
+       err = load_capture_binaries();
+       if (err == sh_css_success)
+               *info = my_css.capture_settings.vf_info;
+       return err;
+}
+
+enum sh_css_err
+sh_css_capture_get_output_raw_frame_info(struct sh_css_frame_info *info)
+{
+       enum sh_css_err err;
+
+       if (my_css.capture_settings.online ||
+           copy_on_sp()) {
+               return sh_css_err_mode_does_not_have_raw_output;
+       }
+       err = load_capture_binaries();
+       if (err == sh_css_success)
+               *info = my_css.capture_settings.copy_binary.out_frame_info;
+       return err;
+}
+
+enum sh_css_err
+sh_css_capture_get_grid_info(struct sh_css_grid_info *info)
+{
+       enum sh_css_err err;
+
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_RAW)
+               return sh_css_err_mode_does_not_have_grid;
+       err = load_capture_binaries();
+       if (err != sh_css_success)
+               return err;
+       if (my_css.capture_settings.mode == SH_CSS_CAPTURE_MODE_PRIMARY) {
+               err = sh_css_binary_grid_info(
+                               &my_css.capture_settings.primary_binary, info);
+       } else {
+               err = sh_css_binary_grid_info(
+                               &my_css.capture_settings.pre_gdc_binary, info);
+       }
+       return err;
+}
+
+enum sh_css_err
+sh_css_capture_get_input_resolution(unsigned int *width, unsigned int *height)
+{
+       enum sh_css_err err;
+
+       if (copy_on_sp() &&
+           my_css.input_format == SH_CSS_INPUT_FORMAT_BINARY_8) {
+               *width = JPEG_BYTES;
+               *height = 1;
+               return sh_css_success;
+       }
+
+       err = load_capture_binaries();
+       if (err == sh_css_success) {
+               const struct sh_css_binary *binary;
+               if (my_css.capture_settings.copy_binary.info)
+                       binary = &my_css.capture_settings.copy_binary;
+               else
+                       binary = &my_css.capture_settings.primary_binary;
+               *width  = binary->in_frame_info.width +
+                         columns_needed_for_bayer_order();
+               *height = binary->in_frame_info.height +
+                         lines_needed_for_bayer_order();
+       }
+       return err;
+}
+
+void
+sh_css_capture_set_mode(enum sh_css_capture_mode mode)
+{
+       if (mode != my_css.capture_settings.mode) {
+               my_css.capture_settings.mode = mode;
+               invalidate_capture_binaries();
+       }
+}
+
+void
+sh_css_capture_enable_xnr(bool enable)
+{
+       if (my_css.capture_settings.xnr != enable) {
+               invalidate_capture_binaries();
+               my_css.capture_settings.xnr = enable;
+       }
+}
+
+void
+sh_css_capture_enable_bayer_downscaling(bool enable)
+{
+       if (my_css.capture_settings.bayer_ds != enable) {
+               invalidate_capture_binaries();
+               my_css.capture_settings.bayer_ds = enable;
+       }
+}
+
+enum sh_css_err
+sh_css_capture_configure_output(unsigned int width,
+                               unsigned int height,
+                               enum sh_css_frame_format format)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.capture_settings.output_info.width != width ||
+           my_css.capture_settings.output_info.height != height ||
+           my_css.capture_settings.output_info.format != format) {
+               sh_css_frame_info_init(&my_css.capture_settings.output_info,
+                                      width, height, format);
+               invalidate_capture_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_capture_configure_viewfinder(unsigned int width,
+                                   unsigned int height,
+                                   enum sh_css_frame_format format)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.capture_settings.vf_info.width != width ||
+           my_css.capture_settings.vf_info.height != height ||
+           my_css.capture_settings.vf_info.format != format) {
+               sh_css_frame_info_init(&my_css.capture_settings.vf_info,
+                                      width, height, format);
+               invalidate_capture_binaries();
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_capture_configure_pp_input(unsigned int width,
+                                 unsigned int height)
+{
+       enum sh_css_err err = sh_css_success;
+       err = check_null_res(width, height);
+       if (err != sh_css_success)
+               return err;
+       if (my_css.capture_settings.pp_input_info.width != width ||
+           my_css.capture_settings.pp_input_info.height != height) {
+               sh_css_frame_info_init(&my_css.capture_settings.pp_input_info,
+                                      width, height,
+                                      SH_CSS_FRAME_FORMAT_YUV420);
+               invalidate_capture_binaries();
+       }
+       return sh_css_success;
+}
+
+void
+sh_css_capture_enable_online(bool enable)
+{
+       my_css.capture_settings.online = enable;
+}
+
+enum sh_css_err
+sh_css_histogram_allocate(unsigned int num_elements,
+                         struct sh_css_histogram **histogram)
+{
+       struct sh_css_histogram *me = sh_css_malloc(sizeof(*me));
+
+       if (me == NULL)
+               return sh_css_err_cannot_allocate_memory;
+       me->num_elements = num_elements;
+       me->data = hrt_isp_css_mm_alloc(num_elements * sizeof(unsigned int));
+       if (me->data == NULL) {
+               sh_css_free(me);
+               return sh_css_err_cannot_allocate_memory;
+       }
+       *histogram = me;
+       return sh_css_success;
+}
+
+void
+sh_css_histogram_free(struct sh_css_histogram *me)
+{
+       if (me->data)
+               hrt_isp_css_mm_free(me->data);
+       sh_css_free(me);
+}
+
+enum sh_css_err
+sh_css_histogram_start(const struct sh_css_frame *input_frame,
+                      struct sh_css_histogram *histogram)
+{
+       if (my_css.state != sh_css_state_idle)
+               return sh_css_err_system_not_idle;
+       if (input_frame->info.padded_width > SH_CSS_SP_MAX_WIDTH)
+               return sh_css_err_overlay_frames_too_big;
+       if (input_frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_frames_mismatch;
+       sh_css_sp_start_histogram(histogram, input_frame);
+       return sh_css_success;
+}
+
+void
+sh_css_send_input_frame(unsigned short *data,
+                       unsigned int width,
+                       unsigned int height)
+{
+       sh_css_hrt_send_input_frame(data, width, height, my_css.ch_id,
+                                   my_css.input_format,
+                                   my_css.two_ppc);
+}
+
+static enum sh_css_err
+allocate_frame_data(struct sh_css_frame *frame, unsigned int bytes)
+{
+#ifndef __KERNEL__
+       /* Physically contiguous memory allocation only for FPGA. */
+       if (frame->contiguous)
+               frame->data = hrt_isp_css_mm_alloc_contiguous(bytes);
+       else
+#endif
+               frame->data = hrt_isp_css_mm_alloc(bytes);
+       if (frame->data == NULL)
+               return sh_css_err_cannot_allocate_memory;
+       frame->data_bytes = bytes;
+       return sh_css_success;
+}
+
+static void
+init_plane(struct sh_css_frame_plane *plane,
+          unsigned int width,
+          unsigned int stride,
+          unsigned int height,
+          void *data)
+{
+       plane->height = height;
+       plane->width = width;
+       plane->stride = stride;
+       plane->data = data;
+}
+
+static enum sh_css_err
+allocate_single_plane(struct sh_css_frame *frame,
+                     struct sh_css_frame_plane *plane,
+                     unsigned int height,
+                     unsigned int subpixels_per_line,
+                     unsigned int bytes_per_pixel)
+{
+       enum sh_css_err err;
+       unsigned int stride;
+
+       stride = subpixels_per_line * bytes_per_pixel;
+       err = allocate_frame_data(frame, stride * height);
+       if (err == sh_css_success) {
+               init_plane(plane, subpixels_per_line, stride,
+                          height, frame->data);
+       }
+       return err;
+}
+
+static enum sh_css_err
+allocate_nv_planes(struct sh_css_frame *frame,
+                  unsigned int horizontal_decimation,
+                  unsigned int vertical_decimation)
+{
+       enum sh_css_err err;
+       unsigned int y_width = frame->info.padded_width,
+                    y_height = frame->info.height,
+                    uv_width = 2 * (y_width / horizontal_decimation),
+                    uv_height = y_height / vertical_decimation,
+                    y_bytes, uv_bytes;
+
+       y_bytes   = y_width * y_height;
+       uv_bytes  = uv_width * uv_height;
+
+       err = allocate_frame_data(frame, y_bytes + uv_bytes);
+       if (err == sh_css_success) {
+               init_plane(&frame->planes.nv.y, y_width, y_width,
+                          y_height, frame->data);
+               init_plane(&frame->planes.nv.uv, uv_width, uv_width,
+                          uv_height, frame->data + y_bytes);
+       }
+       return err;
+}
+
+static enum sh_css_err
+allocate_yuv_planes(struct sh_css_frame *frame,
+                   unsigned int horizontal_decimation,
+                   unsigned int vertical_decimation,
+                   bool swap_uv,
+                   unsigned int bytes_per_element)
+{
+       enum sh_css_err err;
+       unsigned int y_width = frame->info.padded_width,
+                    y_height = frame->info.height,
+                    uv_width = y_width / horizontal_decimation,
+                    uv_height = y_height / vertical_decimation,
+                    y_stride, y_bytes, uv_bytes, uv_stride;
+
+       y_stride  = y_width * bytes_per_element;
+       uv_stride = uv_width * bytes_per_element;
+       y_bytes   = y_stride * y_height;
+       uv_bytes  = uv_stride * uv_height;
+
+       err = allocate_frame_data(frame, y_bytes + 2 * uv_bytes);
+       if (err == sh_css_success) {
+               init_plane(&frame->planes.yuv.y, y_width, y_stride, y_height,
+                               frame->data);
+               if (swap_uv) {
+                       init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
+                                  uv_height, frame->data + y_bytes);
+                       init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
+                                  uv_height, frame->data + y_bytes + uv_bytes);
+               } else {
+                       init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
+                                  uv_height, frame->data + y_bytes);
+                       init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
+                                  uv_height, frame->data + y_bytes + uv_bytes);
+               }
+       }
+       return err;
+}
+
+static enum sh_css_err
+allocate_rgb_planes(struct sh_css_frame *frame, unsigned int bytes_per_element)
+{
+       enum sh_css_err err;
+       unsigned int width = frame->info.width,
+                    height = frame->info.height, stride, bytes;
+
+       stride = width * bytes_per_element;
+       bytes  = stride * height;
+       err = allocate_frame_data(frame, 3 * bytes);
+       if (err == sh_css_success) {
+               init_plane(&frame->planes.planar_rgb.r, width, stride,
+                          height, frame->data);
+               init_plane(&frame->planes.planar_rgb.g, width, stride,
+                          height, frame->data + 1 * bytes);
+               init_plane(&frame->planes.planar_rgb.b, width, stride,
+                          height, frame->data + 2 * bytes);
+       }
+       return err;
+}
+
+static enum sh_css_err
+allocate_qplane6_planes(struct sh_css_frame *frame)
+{
+       enum sh_css_err err;
+       unsigned int width = frame->info.padded_width / 2,
+                    height = frame->info.height / 2,
+                    bytes, stride;
+
+       stride = width * 2;
+       bytes  = stride * height;
+
+       err = allocate_frame_data(frame, 6 * bytes);
+       if (err == sh_css_success) {
+               init_plane(&frame->planes.plane6.r, width, stride,
+                          height, frame->data + 0 * bytes);
+               init_plane(&frame->planes.plane6.r_at_b, width, stride,
+                          height, frame->data + 1 * bytes);
+               init_plane(&frame->planes.plane6.gr, width, stride,
+                          height, frame->data + 2 * bytes);
+               init_plane(&frame->planes.plane6.gb, width, stride,
+                          height, frame->data + 3 * bytes);
+               init_plane(&frame->planes.plane6.b, width, stride,
+                          height, frame->data + 4 * bytes);
+               init_plane(&frame->planes.plane6.b_at_r, width, stride,
+                          height, frame->data + 5 * bytes);
+       }
+       return err;
+}
+
+static enum sh_css_err
+allocate_frame(struct sh_css_frame **frame,
+              unsigned int width,
+              unsigned int height,
+              enum sh_css_frame_format format,
+              unsigned int padded_width,
+              unsigned int raw_bit_depth,
+              bool contiguous)
+{
+       enum sh_css_err err;
+       struct sh_css_frame *me = sh_css_malloc(sizeof(*me));
+       unsigned int bytes_per_pixel = raw_bit_depth <= 8 ? 1 : 2;
+
+       if (!me)
+               return sh_css_err_cannot_allocate_memory;
+       me->info.width = width;
+       me->info.height = height;
+       me->info.format = format;
+       me->info.padded_width = padded_width;
+       me->info.raw_bit_depth = raw_bit_depth;
+       me->contiguous = contiguous;
+
+       switch (me->info.format) {
+       case SH_CSS_FRAME_FORMAT_RAW:
+               err = allocate_single_plane(me, &me->planes.raw,
+                                           me->info.height,
+                                           padded_width,
+                                           bytes_per_pixel);
+               break;
+       case SH_CSS_FRAME_FORMAT_RGB565:
+               err = allocate_single_plane(me, &me->planes.rgb,
+                                           me->info.height,
+                                           padded_width, 2);
+               break;
+       case SH_CSS_FRAME_FORMAT_RGBA888:
+               err = allocate_single_plane(me, &me->planes.rgb,
+                                           me->info.height,
+                                           padded_width * 4, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_PLANAR_RGB888:
+               err = allocate_rgb_planes(me, 1);
+               break;
+               /* yuyv and uyvu have the same frame layout, only the data
+                * positioning differs.
+                */
+       case SH_CSS_FRAME_FORMAT_YUYV:
+       case SH_CSS_FRAME_FORMAT_UYVY:
+               err = allocate_single_plane(me, &me->planes.yuyv,
+                                           me->info.height,
+                                           padded_width * 2, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV_LINE:
+               /* Needs 3 extra lines to allow vf_pp prefetching */
+               err = allocate_single_plane(me, &me->planes.yuyv,
+                                           me->info.height * 3/2 + 3,
+                                           padded_width, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_NV11:
+               err = allocate_nv_planes(me, 4, 1);
+               break;
+               /* nv12 and nv21 have the same frame layout, only the data
+                * positioning differs.
+                */
+       case SH_CSS_FRAME_FORMAT_NV12:
+       case SH_CSS_FRAME_FORMAT_NV21:
+               err = allocate_nv_planes(me, 2, 2);
+               break;
+               /* nv16 and nv61 have the same frame layout, only the data
+                * positioning differs.
+                */
+       case SH_CSS_FRAME_FORMAT_NV16:
+       case SH_CSS_FRAME_FORMAT_NV61:
+               err = allocate_nv_planes(me, 2, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV420:
+               err = allocate_yuv_planes(me, 2, 2, false, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV422:
+               err = allocate_yuv_planes(me, 2, 1, false, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV444:
+               err = allocate_yuv_planes(me, 1, 1, false, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV420_16:
+               err = allocate_yuv_planes(me, 2, 2, false, 2);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV422_16:
+               err = allocate_yuv_planes(me, 2, 1, false, 2);
+               break;
+       case SH_CSS_FRAME_FORMAT_YV12:
+               err = allocate_yuv_planes(me, 2, 2, true, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_YV16:
+               err = allocate_yuv_planes(me, 2, 1, true, 1);
+               break;
+       case SH_CSS_FRAME_FORMAT_QPLANE6:
+               err = allocate_qplane6_planes(me);
+               break;
+       case SH_CSS_FRAME_FORMAT_BINARY_8:
+               err = allocate_single_plane(me, &me->planes.binary.data,
+                                           me->info.height,
+                                           padded_width, 1);
+               me->planes.binary.size = 0;
+               break;
+       default:
+               sh_css_free(me);
+               return sh_css_err_invalid_frame_format;
+       }
+       if (err == sh_css_success)
+               *frame = me;
+       return err;
+}
+
+enum sh_css_err
+sh_css_frame_allocate(struct sh_css_frame **frame,
+                     unsigned int width,
+                     unsigned int height,
+                     enum sh_css_frame_format format,
+                     unsigned int padded_width,
+                     unsigned int raw_bit_depth)
+{
+       return allocate_frame(frame, width, height, format,
+                             padded_width, raw_bit_depth, false);
+}
+
+enum sh_css_err
+sh_css_frame_allocate_from_info(struct sh_css_frame **frame,
+                               const struct sh_css_frame_info *info)
+{
+       return sh_css_frame_allocate(frame,
+                                    info->width,
+                                    info->height,
+                                    info->format,
+                                    info->padded_width,
+                                    info->raw_bit_depth);
+}
+
+enum sh_css_err
+sh_css_frame_allocate_contiguous(struct sh_css_frame **frame,
+                                unsigned int width,
+                                unsigned int height,
+                                enum sh_css_frame_format format,
+                                unsigned int padded_width,
+                                unsigned int raw_bit_depth)
+{
+       return allocate_frame(frame, width, height, format, padded_width,
+                             raw_bit_depth, true);
+}
+
+enum sh_css_err
+sh_css_frame_allocate_contiguous_from_info(struct sh_css_frame **frame,
+                                          const struct sh_css_frame_info
+                                               *info)
+{
+       return sh_css_frame_allocate_contiguous(frame,
+                                               info->width,
+                                               info->height,
+                                               info->format,
+                                               info->padded_width,
+                                               info->raw_bit_depth);
+}
+
+void
+sh_css_frame_free(struct sh_css_frame *frame)
+{
+       if (frame) {
+               hrt_isp_css_mm_free(frame->data);
+               sh_css_free(frame);
+       }
+}
+
+bool
+sh_css_frame_info_equal_resolution(const struct sh_css_frame_info *info_a,
+                                  const struct sh_css_frame_info *info_b)
+{
+       if (!info_a || !info_b)
+               return false;
+       return (info_a->width == info_b->width) &&
+           (info_a->height == info_b->height);
+}
+
+bool
+sh_css_frame_equal_types(const struct sh_css_frame *frame_a,
+                        const struct sh_css_frame *frame_b)
+{
+       const struct sh_css_frame_info *info_a = &frame_a->info,
+           *info_b = &frame_b->info;
+       if (!info_a || !info_b)
+               return false;
+       if (info_a->format != info_b->format)
+               return false;
+       if (info_a->padded_width != info_b->padded_width)
+               return false;
+       return sh_css_frame_info_equal_resolution(info_a, info_b);
+}
+
+static void
+append_firmware(struct sh_css_acc_fw **l, struct sh_css_acc_fw *firmware)
+{
+       while (*l)
+               l = &(*l)->next;
+       *l = firmware;
+       firmware->next = NULL;
+}
+
+static void
+remove_firmware(struct sh_css_acc_fw **l, struct sh_css_acc_fw *firmware)
+{
+       while (*l && *l != firmware)
+               l = &(*l)->next;
+       if (!*l)
+               return;
+       *l = firmware->next;
+       firmware->next = NULL;
+}
+
+/* Load firmware for acceleration */
+enum sh_css_err
+sh_css_load_acceleration(struct sh_css_acc_fw *firmware)
+{
+       my_css.invalidate = true;
+       if (firmware->header.type == SH_CSS_ACC_OUTPUT)
+               append_firmware(&my_css.output_stage, firmware);
+       else if (firmware->header.type == SH_CSS_ACC_VIEWFINDER)
+               append_firmware(&my_css.vf_stage, firmware);
+       return sh_css_acc_load(firmware);
+}
+
+/* Unload firmware for acceleration */
+void
+sh_css_unload_acceleration(struct sh_css_acc_fw *firmware)
+{
+       my_css.invalidate = true;
+       if (firmware->header.type == SH_CSS_ACC_OUTPUT)
+               remove_firmware(&my_css.output_stage, firmware);
+       else if (firmware->header.type == SH_CSS_ACC_VIEWFINDER)
+               remove_firmware(&my_css.vf_stage, firmware);
+       sh_css_acc_unload(firmware);
+}
+
+/* Set argument <num> of size <size> to value <val> */
+enum sh_css_err
+sh_css_set_acceleration_argument(struct sh_css_acc_fw *firmware,
+                                unsigned num, void *val, size_t size)
+{
+       return sh_css_acc_set_argument(firmware, num, val, size);
+}
+
+/* Start acceleration of firmware with sp-args as SP arguments. */
+enum sh_css_err
+sh_css_start_acceleration(struct sh_css_acc_fw *firmware)
+{
+       return sh_css_acc_start(firmware, NULL);
+}
+
+/* To be called when acceleration has terminated.
+*/
+void
+sh_css_acceleration_done(struct sh_css_acc_fw *firmware)
+{
+       sh_css_acc_done(firmware);
+}
+
+/* Abort acceleration within <deadline> microseconds
+*/
+void
+sh_css_abort_acceleration(struct sh_css_acc_fw *firmware, unsigned deadline)
+{
+       /* TODO: implement time-out */
+       (void)deadline;
+       sh_css_acc_abort(firmware);
+}
diff --git a/drivers/media/video/atomisp/css/sh_css.h b/drivers/media/video/atomisp/css/sh_css.h
new file mode 100644 (file)
index 0000000..f187d68
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_H_
+#define _SH_CSS_H_
+
+#include "sh_css_types.h"
+#include "sh_css_params.h"
+
+/* ===== GENERIC ===== */
+
+/* Initialize the API. This is required before any other function in this
+ * API can be called.
+ * Arguments:
+ *  - malloc_func: memory allocation function such as malloc or kalloc.
+ *  - free_func:   memory free function such as free or kfree
+ *  - irq_setting: the way interrupts should be used (or not)
+ */
+enum sh_css_err
+sh_css_init(void *(*malloc_func) (size_t size),
+           void (*free_func) (void *ptr),
+           enum sh_css_interrupt_setting irq_setting,
+           const char *fw_data,
+           unsigned int fw_size);
+
+/* Uninitialize the API. This cleans up all internal data structures. */
+void
+sh_css_uninit(void);
+
+/* Suspend/resume: use suspend before powering the CSS and use resume
+   after powering it up again. The resume function will make sure the
+   CSS is correctly reprogrammed. This assumes that all buffers allocated
+   in DDR will remain alive during power down. If this is not the case,
+   use sh_css_unit() followed by sh_css_init() at power up. */
+void
+sh_css_suspend(void);
+
+void
+sh_css_resume(void);
+
+/* Set the print function. This function is used to print debug information
+ * if debugging is enable. An example of the argument is printf.
+ */
+void
+sh_css_set_print_function(int (*func) (const char *fmt, ...));
+
+/* When an interrupt occurs from the ISP_CSS, use this function to get
+ * information about this interrupt. Since multiple interrupts can occur
+ * at the same time, this function returns whether there are more interrupts
+ * pending. This function should be called until this return value becomes
+ * false.
+ */
+enum sh_css_err
+sh_css_translate_interrupt(unsigned int *irq_infos);
+
+/* Get all interrupt bits from the CSS receiver. */
+void
+sh_css_rx_get_interrupt_info(unsigned int *irq_infos);
+
+/* Reset all bits in the irq_infos variable. */
+void
+sh_css_rx_clear_interrupt_info(unsigned int irq_infos);
+
+/* To be called on a SH_CSS_IRQ_INFO_FW_ACC_DONE interrupt */
+void
+sh_css_terminate_firmware(void);
+
+enum sh_css_err
+sh_css_start_next_stage(void);
+
+void
+sh_css_mmu_set_page_table_base_address(void *base_address);
+
+void *
+sh_css_mmu_get_page_table_base_address(void);
+
+void
+sh_css_mmu_invalidate_cache(void);
+
+/* Enable or disable certain interrupts. The interrupt info type is used
+ * here to indicate the interrupt to enable or disable.
+ */
+enum sh_css_err
+sh_css_enable_interrupt(enum sh_css_interrupt_info info, bool enable);
+
+/* Return the value of a SW interrupt */
+unsigned int
+sh_css_get_sw_interrupt_value(void);
+
+/* Allocate a histogram. */
+enum sh_css_err
+sh_css_histogram_allocate(unsigned int num_elements,
+                         struct sh_css_histogram **histogram);
+
+/* Free a histogram */
+void
+sh_css_histogram_free(struct sh_css_histogram *histogram);
+
+/* Return true if UV values range from 0 to 255 and false if UV values
+ *  range from -127 to 128.
+ */
+void
+sh_css_uv_offset_is_zero(bool *uv_offset_is_zero);
+
+/* When interrupts are disabled, use this function to wait for a particular
+ * ISP mode to complete.
+ */
+enum sh_css_err
+sh_css_wait_for_completion(void);
+
+/* Set the current input resolution. This needs to be called every time the
+ * sensor resolution changes.
+ */
+enum sh_css_err
+sh_css_input_set_resolution(unsigned int width, unsigned int height);
+
+/* Set the part of the input resolution that will be the input to the ISP.
+ * The difference between the input resolution and effective input resolution
+ * will be cropped off. When the effective input resolution is exceeds the
+ * output resolution, the ISP will downscale the input to the output resolution
+ * in the domain.
+ * Note that the effective input resolution cannot be smaller than the output
+ * resolution.
+ */
+enum sh_css_err
+sh_css_input_set_effective_resolution(unsigned int width, unsigned int height);
+
+/* Specify the format of the input data. This format is used for all input
+ * sources except memory (mipi receiver, prbs, tpg, fifo).
+ */
+void
+sh_css_input_set_format(enum sh_css_input_format format);
+
+void
+sh_css_input_set_binning_factor(unsigned int binning_factor);
+
+/* Translate an input format and mipi compression pair to the fmt_type.
+ * This is normally done by the sensor, but when using the input fifo, this
+ * format type must be sumitted correctly by the application.
+ */
+enum sh_css_err
+sh_css_input_format_type(enum sh_css_input_format input_format,
+                        enum sh_css_mipi_compression compression,
+                        unsigned int *fmt_type);
+
+/* Specify that the input will be sent as 2 pixels per clock.
+ * The default is one pixel per clock.
+ */
+void
+sh_css_input_set_two_pixels_per_clock(bool two_pixels_per_clock);
+
+/* Specify the bayer order of the input. The default is grbg. */
+void
+sh_css_input_set_bayer_order(enum sh_css_bayer_order bayer_order);
+
+/* Get the number of extra rows and columns needed to program the
+ * sensor driver with the correct resolution.
+ * This is dependent upon the bayer order which is assumed to have
+ * been already set using the API sh_css_input_set_bayer_order
+ */
+int
+sh_css_get_extra_pixels_count(int *extra_rows, int *extra_columns);
+
+/* Specify which channel carries the input for the CSS. */
+void
+sh_css_input_set_channel(unsigned int channel_id);
+
+/* Set the input mode to be used. */
+void
+sh_css_input_set_mode(enum sh_css_input_mode mode);
+
+/* Configure the MIPI receiver:
+ *  - port: select the 1lane or 4lane port
+ *  - num_lanes: this argument is only valid for the 4lane port. it specifies
+ *               how many of these 4 lanes are in use. Valid values are 1, 2,
+ *               3 or 4.
+ *  - timeout: this specifies the timeout after which a timeout interrupt is
+ *             generated.
+ *             The timeout is specified in terms of <TO BE CLARIFIED>.
+ */
+enum sh_css_err
+sh_css_input_configure_port(enum sh_css_mipi_port port,
+                           unsigned int num_lanes, unsigned int timeout);
+
+/* Specify the number of bits per compressed and uncompressed pixel for a given
+ * compression mode.
+ */
+enum sh_css_err
+sh_css_input_set_compression(enum sh_css_mipi_compression comp,
+                            unsigned int compressed_bits_per_pixel,
+                            unsigned int uncompressed_bits_per_pixel);
+
+/* Configure the Test Pattern Generator, the way these values are used to
+ * generate the pattern can be seen in the HRT extension for the test pattern
+ * generator:
+ * devices/test_pat_gen/hrt/include/test_pat_gen.h: hrt_calc_tpg_data().
+ */
+void
+sh_css_tpg_configure(unsigned int x_mask, int x_delta,
+                    unsigned int y_mask, int y_delta, unsigned int xy_mask);
+
+/* Seed the for the Pseudo Random Bit Sequence */
+void
+sh_css_prbs_set_seed(int seed);
+
+/* Digital zoom: this feature can be configured with a zoom factor
+ * which determines the amount of zoom and a zoom center which determines
+ * the point to zoom in at.
+ * This feature is currently available only for video, but will become
+ * available for preview and capture as well.
+ * Set the digital zoom factor, this is a logarithmic scale. The actual zoom
+ * factor will be 64/x.
+ * Setting dx or dy to 0 disables digital zoom for that direction.
+ */
+void
+sh_css_set_zoom_factor(unsigned int dx, unsigned int dy);
+
+/* Get the current zoom factor. This will return the same values as were set
+ * during the last video_set_zoom_factor() call.
+ */
+void
+sh_css_get_zoom_factor(unsigned int *dx, unsigned int *dy);
+
+/* Specify the overlay to be used for each viewfinder frame generated.
+ * This overlay will remain active until it is reset by passing NULL to
+ * this same function.
+ */
+void
+sh_css_overlay_set_for_viewfinder(const struct sh_css_overlay *overlay);
+
+/* Set the shading table for the current sensor module. This table will be
+ * used for shading correction in each mode that supports this feature.
+ */
+void
+sh_css_set_shading_table(const struct sh_css_shading_table *table);
+
+/* ===== FRAMES ===== */
+
+/* Allocate a frame of a certain resolution and format. */
+enum sh_css_err
+sh_css_frame_allocate(struct sh_css_frame **frame,
+                     unsigned int width,
+                     unsigned int height,
+                     enum sh_css_frame_format format,
+                     unsigned int padded_width,
+                     unsigned int raw_bit_depth);
+
+/* Allocate a frame using the resolution and format from a frame info struct. */
+enum sh_css_err
+sh_css_frame_allocate_from_info(struct sh_css_frame **frame,
+                               const struct sh_css_frame_info *info);
+
+/* Free a frame */
+void
+sh_css_frame_free(struct sh_css_frame *frame);
+
+/* ===== FPGA display frames ====== */
+/* Contiguous frame allocation, only for FPGA display driver which needs
+   physically contiguous memory. */
+enum sh_css_err
+sh_css_frame_allocate_contiguous(struct sh_css_frame **frame,
+                                unsigned int width,
+                                unsigned int height,
+                                enum sh_css_frame_format format,
+                                unsigned int padded_width,
+                                unsigned int raw_bit_depth);
+
+enum sh_css_err
+sh_css_frame_allocate_contiguous_from_info(struct sh_css_frame **frame,
+                                         const struct sh_css_frame_info *info);
+
+/* ===== PREVIEW ===== */
+
+/* Start the ISP in preview mode, this will run the preview ISP on one frame.
+ * After this has completed, it needs to be started again for the next frame.
+ */
+enum sh_css_err
+sh_css_preview_start(struct sh_css_frame *raw_out_frame,
+                    struct sh_css_frame *out_frame);
+
+/* Enable or disable online binaries if available. Default is enabled. */
+void
+sh_css_preview_enable_online(bool enable);
+
+/* Enable or disable continuous binaries if available. Default is disabled. */
+void
+sh_css_enable_continuous(bool enable);
+
+/* Return whether continuous binaries are enabled */
+bool
+sh_css_continuous_is_enabled(void);
+
+/* Disable vf_pp: used to replace by dynamic binary */
+void
+sh_css_disable_vf_pp(bool disable);
+
+/* Disable capture_pp: used to replace by dynamic binary */
+void
+sh_css_disable_capture_pp(bool disable);
+
+/* Specify the output resolution to be used by the preview ISP. */
+enum sh_css_err
+sh_css_preview_configure_output(unsigned int width,
+                               unsigned int height,
+                               enum sh_css_frame_format format);
+
+/* Get the information about the output frames, this contains the resolution
+ * and the stride. To allocate frames, use the information returned here.
+ */
+enum sh_css_err
+sh_css_preview_get_output_frame_info(struct sh_css_frame_info *info);
+
+enum sh_css_err
+sh_css_preview_get_grid_info(struct sh_css_grid_info *info);
+
+enum sh_css_err
+sh_css_preview_get_input_resolution(unsigned int *width,
+                                   unsigned int *height);
+
+/* Set the input resolution for viewfinder post processing.
+   When this is not set, the input resolution is equal to the input
+   resolution of the preview pipeline. When this is set, the YUV scaler
+   in the viewfinder post processing step will be activated. */
+enum sh_css_err
+sh_css_preview_configure_pp_input(unsigned int width, unsigned int height);
+
+/* ===== CAPTURE ===== */
+
+/* Start the ISP in capture mode:
+ *  - out_frame: pointer to the output frame
+ *  - vf_frame: pointer to the viewfinder frame
+ */
+enum sh_css_err
+sh_css_capture_start(struct sh_css_frame *raw_out_frame,
+                    struct sh_css_frame *out_frame,
+                    struct sh_css_frame *vf_frame);
+
+/* Specify the mode used for capturing. */
+void
+sh_css_capture_set_mode(enum sh_css_capture_mode mode);
+
+/* Enable the eXtra Noise Reduction as a post processing step. This will be
+ * run on both the captured output and the viewfinder output.
+ */
+void
+sh_css_capture_enable_xnr(bool enable);
+
+/* Specify the output resolution for captured images. */
+enum sh_css_err
+sh_css_capture_configure_output(unsigned int width,
+                               unsigned int height,
+                               enum sh_css_frame_format format);
+
+/* Specify the viewfinder resolution. Note that this resolution currently
+ * has to be a division of the captured output by a power of 2. The API will
+ * automatically select the resolution that's closest to the one requested
+ * here.
+ */
+enum sh_css_err
+sh_css_capture_configure_viewfinder(unsigned int width,
+                                   unsigned int height,
+                                   enum sh_css_frame_format format);
+
+/* For non-raw still captures, downscaling in the YUV domain can be done
+ * during post processing. This function specifies the input resolution
+ * for the YUV downscaling step. If this resolution is not set, the YUV
+ * downscaling will not be done. The output resolution of the YUV
+ * downscaling is taken from the configure_output function above.
+ */
+enum sh_css_err
+sh_css_capture_configure_pp_input(unsigned int width,
+                                 unsigned int height);
+
+/* Enable or disable online binaries if available. Default is enabled. */
+void
+sh_css_capture_enable_online(bool enable);
+
+/* Retrieve the format and resolution of the output frames. Note that this
+ * can differ from the requested resolution.
+ */
+enum sh_css_err
+sh_css_capture_get_output_frame_info(struct sh_css_frame_info *info);
+
+/* Retrieve the format and resolution of the viewfinder frames. Note that this
+ * can differ from the requested resolution.
+ */
+enum sh_css_err
+sh_css_capture_get_viewfinder_frame_info(struct sh_css_frame_info *info);
+
+/* Retrieve the format and resolution of the RAW frame. This is only available
+ * when the capture is set to offline or continuous using:
+ * sh_css_capture_enable_online(false) or
+ * sh_css_enable_continuous(true).
+ */
+enum sh_css_err
+sh_css_capture_get_output_raw_frame_info(struct sh_css_frame_info *info);
+
+enum sh_css_err
+sh_css_capture_get_grid_info(struct sh_css_grid_info *info);
+
+enum sh_css_err
+sh_css_capture_get_input_resolution(unsigned int *width,
+                                   unsigned int *height);
+/* ===== VIDEO ===== */
+
+/* Start the video ISP for one frame:
+ *  - in_frame: pointer to the input frame, this argument is only used if the
+ *              input_mode is set to sh_css_input_mode_memory.
+ *  - out_frame: pointer to the output frame.
+ *  - vf_frame: pointer to the viewfinder output frame.
+ */
+enum sh_css_err
+sh_css_video_start(struct sh_css_frame *in_frame,
+                  struct sh_css_frame *out_frame,
+                  struct sh_css_frame *vf_frame);
+
+/* Specify the output resolution for output frames. Note that the actual
+ * resolution can be different from the requested resolution.
+ */
+enum sh_css_err
+sh_css_video_configure_output(unsigned int width,
+                             unsigned int height,
+                             enum sh_css_frame_format format);
+
+/* Specify the viewfinder resolution. Note that this resolution currently has
+ * to be a division of the captured output by a power of 2. The API will
+ * automatically select the resolution that's closest to the one requested
+ * here.
+ */
+enum sh_css_err
+sh_css_video_configure_viewfinder(unsigned int width,
+                                 unsigned int height,
+                                 enum sh_css_frame_format format);
+
+/* Set the motion vector for Digital Image Stabilization (DIS).
+ * These positions are normally calculated using the DIS statistics.
+ */
+void
+sh_css_video_set_dis_vector(int x, int y);
+
+/* Specify the envelope to be used for DIS. */
+void
+sh_css_video_set_dis_envelope(unsigned int width, unsigned int height);
+
+/* Retrieve the envelope to be used for DIS. */
+void
+sh_css_video_get_dis_envelope(unsigned int *width, unsigned int *height);
+
+/* Retrieve the format and resolution of the output frames. Note that this
+ * can differ from the requested resolution.
+ */
+enum sh_css_err
+sh_css_video_get_output_frame_info(struct sh_css_frame_info *info);
+
+/* Retrieve the format and resolution of the viewfinder frames. Note that this
+ * can differ from the requested resolution.
+ */
+enum sh_css_err
+sh_css_video_get_viewfinder_frame_info(struct sh_css_frame_info *info);
+
+enum sh_css_err
+sh_css_video_get_grid_info(struct sh_css_grid_info *info);
+
+enum sh_css_err
+sh_css_video_get_input_resolution(unsigned int *width,
+                                 unsigned int *height);
+
+/* Generate a luminance histogram from a frame. The width of the frame
+ * cannot exceed 640 pixels and the frame must be a yuv420 frame.
+ */
+enum sh_css_err
+sh_css_histogram_start(const struct sh_css_frame *input_frame,
+                      struct sh_css_histogram *histogram);
+
+/* Send streaming data into the css input FIFO. This is for testing purposes
+ * only. This uses the channel ID and input format as set by the user with
+ * the regular functions for this.
+ * This function blocks until the entire frame has been written into the
+ * input FIFO.
+ */
+void
+sh_css_send_input_frame(unsigned short *data,
+                       unsigned int width,
+                       unsigned int height);
+
+/* Temporary function to poll whether the ISP has been started. Once it has,
+ * the sensor can also be started. */
+bool
+sh_css_isp_has_started(void);
+
+/* Load firmware for acceleration */
+enum sh_css_err
+sh_css_load_acceleration(struct sh_css_acc_fw *firmware);
+
+/* Unload firmware for acceleration */
+void
+sh_css_unload_acceleration(struct sh_css_acc_fw *firmware);
+
+/* Set argument <num> of size <size> to value <val> */
+enum sh_css_err
+sh_css_set_acceleration_argument(struct sh_css_acc_fw *firmware,
+                                unsigned num, void *val, size_t size);
+
+/* Start acceleration of firmware.
+   Load the firmware if not yet loaded.
+*/
+enum sh_css_err
+sh_css_start_acceleration(struct sh_css_acc_fw *firmware);
+
+/* To be called when acceleration has terminated.
+*/
+void
+sh_css_acceleration_done(struct sh_css_acc_fw *firmware);
+
+/* Abort acceleration within <deadline> microseconds
+*/
+void
+sh_css_abort_acceleration(struct sh_css_acc_fw *firmware, unsigned deadline);
+
+#endif /* _SH_CSS_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_accelerate.c b/drivers/media/video/atomisp/css/sh_css_accelerate.c
new file mode 100644 (file)
index 0000000..ab6fc85
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_hrt.h"
+#include "sh_css_sp_start.h"
+#include "sh_css_sp.h"
+#include "sh_css_internal.h"
+#include "sh_css_accelerate.h"
+
+#if !defined(C_RUN) && !defined(HRT_UNSCHED)
+static void
+sh_css_acc_upload_isp_code(const struct sh_css_acc_fw *firmware)
+{
+       const unsigned char *blob = SH_CSS_ACC_ISP_CODE(firmware);
+       unsigned size             = SH_CSS_ACC_ISP_SIZE(firmware);
+       const unsigned char *binary = sh_css_load_blob(blob, size);
+
+       sh_css_sp_dmem_store((unsigned int)firmware->header.sp.isp_code,
+                            &binary, sizeof(binary));
+}
+#endif
+
+static void
+upload_frame(struct sh_css_frame *sp_address, struct sh_css_frame *frame)
+{
+       if (!frame || !sp_address)
+               return;
+       sh_css_sp_dmem_store((unsigned int)sp_address, frame, sizeof(*frame));
+}
+
+static void
+upload_int(unsigned *sp_address, unsigned *val)
+{
+       if (!sp_address)
+               return;
+       sh_css_sp_dmem_store((unsigned int)sp_address, val, sizeof(*val));
+}
+
+/* Load the firmware into xmem */
+enum sh_css_err
+sh_css_acc_load(const struct sh_css_acc_fw *firmware)
+{
+       struct sh_css_acc_fw_hdr *header
+               = (struct sh_css_acc_fw_hdr *)&firmware->header;
+       header->sp_args =
+               sh_css_malloc(sizeof(*header->sp_args) *
+                             header->sp.args_cnt);
+       if (!header->sp_args)
+               return sh_css_err_cannot_allocate_memory;
+       header->loaded = true;
+       return sh_css_success;
+}
+
+void
+sh_css_acc_unload(const struct sh_css_acc_fw *firmware)
+{
+       struct sh_css_acc_fw_hdr *header
+               = (struct sh_css_acc_fw_hdr *)&firmware->header;
+       sh_css_free(header->sp_args);
+       header->sp_args = NULL;
+       header->loaded = false;
+}
+
+/* Set argument <num> of size <size> to value <val> */
+enum sh_css_err
+sh_css_acc_set_argument(struct sh_css_acc_fw *firmware,
+                       unsigned num, void *val, size_t size)
+{
+       if (!firmware->header.sp_args)
+               return sh_css_err_invalid_arguments;
+       if (num >= firmware->header.sp.args_cnt)
+               return sh_css_err_invalid_arguments;
+       firmware->header.sp_args[num].type  = sh_css_argument_type(firmware,
+                                                                  num);
+       firmware->header.sp_args[num].value = val;
+       firmware->header.sp_args[num].size  = size;
+       return sh_css_success;
+}
+
+/* Get type for argument <num> */
+enum sh_css_acc_arg_type
+sh_css_argument_type(struct sh_css_acc_fw *firmware, unsigned num)
+{
+       return SH_CSS_ACC_SP_ARGS(firmware)[num];
+}
+
+/* Set host private data for argument <num> */
+enum sh_css_err
+sh_css_argument_set_host(struct sh_css_acc_fw *firmware,
+                        unsigned num, void *host)
+{
+       if (!firmware->header.sp_args)
+               return sh_css_err_invalid_arguments;
+       if (num >= firmware->header.sp.args_cnt)
+               return sh_css_err_invalid_arguments;
+       firmware->header.sp_args[num].host = host;
+       return sh_css_success;
+}
+
+/* Get host private data for argument <num> */
+void *
+sh_css_argument_get_host(struct sh_css_acc_fw *firmware, unsigned num)
+{
+       if (!firmware->header.sp_args)
+               return NULL;
+       if (num >= firmware->header.sp.args_cnt)
+               return NULL;
+       return firmware->header.sp_args[num].host;
+}
+
+static void
+copy_sp_arguments(struct sh_css_acc_fw *firmware, bool to_sp)
+{
+       unsigned sp_address = (unsigned)firmware->header.sp.args;
+       unsigned i;
+       for (i = 0; i < firmware->header.sp.args_cnt; i++) {
+               enum sh_css_acc_arg_type type =
+                       firmware->header.sp_args[i].type;
+               void *value = firmware->header.sp_args[i].value;
+               unsigned size = firmware->header.sp_args[i].size;
+               bool copy = to_sp;
+               switch (type) {
+               case SH_CSS_ACC_ARG_SCALAR_IN:
+                       break;
+               case SH_CSS_ACC_ARG_SCALAR_IO:
+                       copy = true;
+                       break;
+               case SH_CSS_ACC_ARG_SCALAR_OUT:
+                       copy = !to_sp;
+                       break;
+               case SH_CSS_ACC_ARG_PTR_IN:
+               case SH_CSS_ACC_ARG_PTR_OUT:
+               case SH_CSS_ACC_ARG_PTR_IO:
+                       value = &firmware->header.sp_args[i].value;
+                       size = sizeof(void *);
+                       break;
+               case SH_CSS_ACC_ARG_FRAME:
+                       size = sizeof(struct sh_css_frame);
+                       break;
+               }
+               if (copy) {
+                       if (to_sp)
+                               sh_css_sp_dmem_store(sp_address, value, size);
+                       else
+                               sh_css_sp_dmem_load(sp_address, value, size);
+               }
+               sp_address += size;
+       }
+}
+
+/* Start the sp, which will start the isp.
+*/
+enum sh_css_err
+sh_css_acc_start(struct sh_css_acc_fw *firmware,
+                struct sh_css_binary_args *args)
+{
+       struct sh_css_acc_fw_hdr *header
+               = (struct sh_css_acc_fw_hdr *)&firmware->header;
+       bool has_extension_args = (args != NULL);
+       bool is_extension = (header->type != SH_CSS_ACC_STANDALONE);
+       const struct sh_css_sp_fw *sp_fw = &header->sp.fw;
+       *(const void **)&sp_fw->text = SH_CSS_ACC_SP_CODE(firmware);
+       *(const void **)&sp_fw->data = SH_CSS_ACC_SP_DATA(firmware);
+
+       if (!header->loaded)
+               return sh_css_err_invalid_arguments;
+       if (has_extension_args != is_extension)
+               return sh_css_err_invalid_arguments;
+
+       if (!sh_css_sp_load_program(sp_fw, SH_CSS_ACC_PROG_NAME(firmware)))
+               return sh_css_err_cannot_allocate_memory;
+#if !defined(C_RUN) && !defined(HRT_UNSCHED)
+       sh_css_acc_upload_isp_code(firmware);
+#endif
+
+#ifdef C_RUN
+       header->sp.init(firmware);
+#endif
+
+       if (args) {
+               upload_frame(header->sp.input,  args->in_frame);
+               upload_frame(header->sp.output, args->out_frame);
+               upload_frame(header->sp.out_vf, args->out_vf_frame);
+               upload_frame(header->sp.extra,  args->extra_frame);
+               upload_int  (header->sp.vf_downscale_bits,
+                            &args->vf_downscale_log2);
+       }
+       copy_sp_arguments(firmware, true);
+
+       /* Start the firmware on the sp, which will start the isp */
+#ifdef C_RUN
+       sh_css_sp_do_invalidate_mmu();
+       csim_processor_set_crun_func(SP, header->sp.entry);
+       hrt_ctl_run(SP, 1);
+       hrt_ctl_start(SP);
+       hrt_sleep();
+#elif defined(HRT_CSIM)
+       sh_css_sp_do_invalidate_mmu();
+       _hrt_cell_start(SP, header->sp.entry);
+#else
+       sh_css_sp_start((unsigned int)header->sp.entry);
+#endif
+       return sh_css_success;
+}
+
+/* To be called when acceleration has terminated.
+*/
+void
+sh_css_acc_done(struct sh_css_acc_fw *firmware)
+{
+       copy_sp_arguments(firmware, false);
+}
+
+void
+sh_css_acc_wait(void)
+{
+       sh_css_hrt_sp_wait();
+}
+
+/* Flag abortion of acceleration */
+void sh_css_acc_abort(struct sh_css_acc_fw *firmware)
+{
+       unsigned int t = true;
+       upload_int(firmware->header.sp.css_abort, &t);
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_accelerate.h b/drivers/media/video/atomisp/css/sh_css_accelerate.h
new file mode 100644 (file)
index 0000000..ce139b1
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_ACCELERATE_H_
+#define _SH_CSS_ACCELERATE_H_
+
+#include "sh_css_types.h"
+
+/* Load the firmware into xmem */
+enum sh_css_err
+sh_css_acc_load(const struct sh_css_acc_fw *firmware);
+
+/* Unload the firmware*/
+void
+sh_css_acc_unload(const struct sh_css_acc_fw *firmware);
+
+/* Set argument <num> of size <size> to value <val> */
+enum sh_css_err
+sh_css_acc_set_argument(struct sh_css_acc_fw *firmware,
+                       unsigned int num,
+                       void *val,
+                       unsigned int size);
+
+/* Get type for argument <num> */
+enum sh_css_acc_arg_type
+sh_css_argument_type(struct sh_css_acc_fw *firmware, unsigned int num);
+
+/* Set host private data for argument <num> */
+enum sh_css_err
+sh_css_argument_set_host(struct sh_css_acc_fw *firmware,
+                        unsigned num, void *host);
+
+/* Get host private data for argument <num> */
+void *
+sh_css_argument_get_host(struct sh_css_acc_fw *firmware, unsigned num);
+
+/* Start the sp, which will start the isp.
+   Load the firmware if not yet loaded.
+*/
+enum sh_css_err
+sh_css_acc_start(struct sh_css_acc_fw *firmware,
+                struct sh_css_binary_args *args);
+
+/* To be called when acceleration has terminated.
+*/
+void
+sh_css_acc_done(struct sh_css_acc_fw *firmware);
+
+/* Wait for the firmware to terminate */
+void
+sh_css_acc_wait(void);
+
+/* Flag abortion of acceleration */
+void sh_css_acc_abort(struct sh_css_acc_fw *firmware);
+
+#endif /* _SH_CSS_ACCELERATE_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_binary.c b/drivers/media/video/atomisp/css/sh_css_binary.c
new file mode 100644 (file)
index 0000000..e451509
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_binary.h"
+#include "sh_css.h"
+#include "sh_css_internal.h"
+#include "sh_css_hrt.h"
+#include "sh_css_sp.h"
+#include "sh_css_firmware.h"
+#include "sh_css_defs.h"
+#include "sh_css_binary_info.h"
+
+static struct sh_css_binary_info all_binaries[SH_CSS_BINARY_NUM_IDS];
+static struct sh_css_binary_info *binary_infos[SH_CSS_BINARY_NUM_MODES];
+
+enum sh_css_err
+sh_css_binary_grid_info(struct sh_css_binary *binary,
+                       struct sh_css_grid_info *info)
+{
+       /* for DIS, we use a division instead of a ceil_div. If this is smaller
+        * than the 3a grid size, it indicates that the outer values are not
+        * valid for DIS.
+        */
+       info->dis_width             = binary->dis_ver_proj_num_3a;
+       info->dis_height            = binary->dis_hor_proj_num_3a;
+       info->dis_bqs_per_grid_cell = 1 << binary->dis_deci_factor_log2;
+       info->dis_hor_coef_num      = binary->dis_hor_coef_num_3a;
+       info->dis_ver_coef_num      = binary->dis_ver_coef_num_3a;
+       /* 3A statistics grid */
+       info->s3a_width = binary->s3atbl_width;
+       info->s3a_height = binary->s3atbl_height;
+       info->s3a_bqs_per_grid_cell = (1 << binary->deci_factor_log2);
+
+       return sh_css_success;
+}
+
+static enum sh_css_err
+load_binary(struct sh_css_binary_info *binary, bool *binary_found)
+{
+       const unsigned char *blob = sh_css_blob_info[binary->id].blob;
+       unsigned size = sh_css_blob_info[binary->id].size;
+
+       *binary_found = blob != NULL;
+       /* we don't have this binary, skip it */
+       if (!size)
+               return sh_css_success;
+
+       binary->xmem_addr = sh_css_load_blob(blob, size);
+       if (!binary->xmem_addr)
+               return sh_css_err_cannot_allocate_memory;
+       return sh_css_success;
+}
+
+static void init_pc_histogram(struct sh_css_pc_histogram *histo)
+{
+       histo->length = 0;
+       histo->run = NULL;
+       histo->stall = NULL;
+}
+
+static void init_metrics(struct sh_css_binary_metrics *metrics,
+                        unsigned int binary_id)
+{
+       metrics->mode = binary_id;
+       metrics->next = NULL;
+       init_pc_histogram(&metrics->isp_histogram);
+       init_pc_histogram(&metrics->sp_histogram);
+}
+
+#define _init_binary_info(binary, prefix) { \
+       int i; \
+       enum sh_css_frame_format out_fmts[] = prefix ## OUTPUT_FORMATS; \
+       binary->num_output_formats = sizeof(out_fmts)/sizeof(*out_fmts); \
+       for (i = 0; i < binary->num_output_formats; i++) \
+               binary->output_formats[i] = out_fmts[i]; \
+       for (i = binary->num_output_formats; \
+            i < SH_CSS_MAX_NUM_FRAME_FORMATS; \
+            i++) \
+               binary->output_formats[i] = -1; \
+       binary->mode                    = prefix ## MODE; \
+       binary->enable_sc               = prefix ## ENABLE_SC; \
+       binary->enable_fpnr             = prefix ## ENABLE_FPNR; \
+       binary->enable_s3a              = prefix ## ENABLE_S3A; \
+       binary->enable_ds               = prefix ## ENABLE_DS; \
+       binary->enable_uds              = prefix ## ENABLE_UDS; \
+       binary->enable_dis              = prefix ## ENABLE_SDIS; \
+       binary->enable_dvs_envelope     = prefix ## ENABLE_DVS_ENVELOPE; \
+       binary->left_cropping           = prefix ## LEFT_CROPPING; \
+       binary->top_cropping            = prefix ## TOP_CROPPING; \
+       binary->c_subsampling           = prefix ## C_SUBSAMPLING; \
+       binary->pipelining              = prefix ## PIPELINING; \
+       binary->fixed_s3a_deci_log      = prefix ## FIXED_S3A_DECI_LOG; \
+       binary->input                   = prefix ## INPUT; \
+       binary->max_dvs_envelope_width  = prefix ## MAX_DVS_ENVELOPE_WIDTH; \
+       binary->max_dvs_envelope_height = prefix ## MAX_DVS_ENVELOPE_HEIGHT; \
+       binary->min_output_width        = prefix ## MIN_OUTPUT_WIDTH; \
+       binary->max_output_width        = prefix ## MAX_OUTPUT_WIDTH; \
+       binary->max_vf_log_downscale    = prefix ## MAX_VF_LOG_DOWNSCALE; \
+       binary->enable_vf_veceven       = prefix ## ENABLE_VF_VECEVEN; \
+       binary->output_num_chunks       = prefix ## OUTPUT_NUM_CHUNKS; \
+}
+
+static enum sh_css_err
+init_binary_info(struct sh_css_binary_info *info, bool *binary_found)
+{
+       unsigned int max_internal_width;
+
+       switch (info->id) {
+       case SH_CSS_BINARY_ID_COPY:
+               _init_binary_info(info, ISP_COPY_);
+               break;
+       case SH_CSS_BINARY_ID_VF_PP:
+               _init_binary_info(info, ISP_VF_PP_);
+               break;
+       case SH_CSS_BINARY_ID_CAPTURE_PP:
+               _init_binary_info(info, ISP_CAPTURE_PP_);
+               break;
+       case SH_CSS_BINARY_ID_PRE_GDC:
+               _init_binary_info(info, ISP_PRE_GDC_);
+               break;
+       case SH_CSS_BINARY_ID_GDC:
+               _init_binary_info(info, ISP_GDC_);
+               break;
+       case SH_CSS_BINARY_ID_POST_GDC:
+               _init_binary_info(info, ISP_POST_GDC_);
+               break;
+       case SH_CSS_BINARY_ID_PRE_ANR:
+               _init_binary_info(info, ISP_PRE_ANR_);
+               break;
+       case SH_CSS_BINARY_ID_ANR:
+               _init_binary_info(info, ISP_ANR_);
+               break;
+       case SH_CSS_BINARY_ID_POST_ANR:
+               _init_binary_info(info, ISP_POST_ANR_);
+               break;
+       case SH_CSS_BINARY_ID_PREVIEW_DZ:
+               _init_binary_info(info, ISP_PREVIEW_DZ_);
+               break;
+       case SH_CSS_BINARY_ID_PREVIEW_DS:
+               _init_binary_info(info, ISP_PREVIEW_DS_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_SMALL:
+               _init_binary_info(info, ISP_PRIMARY_SMALL_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_DS:
+               _init_binary_info(info, ISP_PRIMARY_DS_);
+               break;
+       case SH_CSS_BINARY_ID_BAYER_DS:
+               _init_binary_info(info, ISP_BAYER_DS_);
+               break;
+       case SH_CSS_BINARY_ID_VIDEO_OFFLINE:
+               _init_binary_info(info, ISP_VIDEO_OFFLINE_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_VAR:
+               _init_binary_info(info, ISP_PRIMARY_VAR_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_8MP:
+               _init_binary_info(info, ISP_PRIMARY_8MP_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_14MP:
+               _init_binary_info(info, ISP_PRIMARY_14MP_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_16MP:
+               _init_binary_info(info, ISP_PRIMARY_16MP_);
+               break;
+       case SH_CSS_BINARY_ID_PRIMARY_REF:
+               _init_binary_info(info, ISP_PRIMARY_REF_);
+               break;
+       case SH_CSS_BINARY_ID_VIDEO_DZ:
+               _init_binary_info(info, ISP_VIDEO_DZ_);
+               break;
+       case SH_CSS_BINARY_ID_VIDEO_NODZ:
+               _init_binary_info(info, ISP_VIDEO_NODZ_);
+               break;
+       case SH_CSS_BINARY_ID_VIDEO_DS:
+               _init_binary_info(info, ISP_VIDEO_DS_);
+               break;
+       default:
+               break;
+       }
+       info->s3atbl_use_dmem = _S3ATBL_USE_DMEM(info->min_output_width !=
+                                                info->max_output_width);
+       /* The ISP uses the veceven module for output, on the host however
+        * we don't want to know about it. We treat preview output as regular
+        * output, not as viewfinder output. */
+       if (info->mode == SH_CSS_BINARY_MODE_PREVIEW)
+               info->enable_vf_veceven = false;
+       info->variable_vf_veceven = info->mode == SH_CSS_BINARY_MODE_COPY;
+       max_internal_width =
+               __ISP_INTERNAL_WIDTH(info->max_output_width,
+                                    info->max_dvs_envelope_width,
+                                    info->left_cropping,
+                                    info->mode,
+                                    info->c_subsampling,
+                                    info->output_num_chunks,
+                                    info->pipelining);
+       info->max_input_width = _ISP_MAX_INPUT_WIDTH(max_internal_width,
+                                                    info->enable_ds);
+       info->xmem_addr = NULL;
+       info->next      = NULL;
+       return load_binary(info, binary_found);
+}
+
+/* When binaries are put at the beginning, they will only
+ * be selected if no other primary matches.
+ */
+enum sh_css_err
+sh_css_init_binary_infos(void)
+{
+       int i;
+
+       for (i = 0; i < SH_CSS_BINARY_NUM_IDS; i++) {
+               enum sh_css_err ret;
+               struct sh_css_binary_info *binary = &all_binaries[i];
+               bool binary_found;
+
+               binary->id = (enum sh_css_binary_id) i;
+               ret = init_binary_info(binary, &binary_found);
+               if (ret != sh_css_success)
+                       return ret;
+               if (!binary_found)
+                       continue;
+               /* Prepend new binary information */
+               binary->next = binary_infos[binary->mode];
+               binary_infos[binary->mode] = binary;
+       }
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_binary_uninit(void)
+{
+       unsigned int i;
+       struct sh_css_binary_info *b;
+
+       for (i = 0; i < SH_CSS_BINARY_NUM_MODES; i++) {
+               for (b = binary_infos[i]; b; b = b->next) {
+                       if (b->xmem_addr)
+                               hrt_isp_css_mm_free(b->xmem_addr);
+                       b->xmem_addr = NULL;
+               }
+               binary_infos[i] = NULL;
+       }
+       return sh_css_success;
+}
+
+static bool
+supports_output_format(const struct sh_css_binary_info *info,
+                      enum sh_css_frame_format format)
+{
+       int i;
+
+       for (i = 0; i < info->num_output_formats; i++) {
+               if (info->output_formats[i] == format)
+                       return true;
+       }
+       return false;
+}
+
+static int
+sh_css_grid_deci_factor_log2(int width, int height)
+{
+       int fact, fact1;
+       fact = 5;
+       while (ISP_BQ_GRID_WIDTH(width, fact - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH &&
+              ISP_BQ_GRID_HEIGHT(height, fact - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT
+              && fact > 3)
+               fact--;
+
+       /* fact1 satisfies the specification of grid size. fact and fact1 is
+          not the same for some resolution (fact=4 and fact1=5 for 5mp). */
+       if (width >= 2560)
+               fact1 = 5;
+       else if (width >= 1280)
+               fact1 = 4;
+       else
+               fact1 = 3;
+       return max(fact, fact1);
+}
+
+static enum sh_css_err
+fill_binary_info(const struct sh_css_binary_info *info,
+                bool online,
+                bool two_ppc,
+                enum sh_css_input_format stream_format,
+                const struct sh_css_frame_info *in_info,
+                const struct sh_css_frame_info *out_info,
+                const struct sh_css_frame_info *vf_info,
+                struct sh_css_binary *binary)
+{
+       unsigned int dvs_env_width = 0,
+                    dvs_env_height = 0,
+                    vf_log_ds = 0,
+                    s3a_log_deci = 0,
+                    bits_per_pixel = in_info->raw_bit_depth,
+                    ds_input_width = 0,
+                    ds_input_height = 0,
+                    isp_input_width,
+                    isp_input_height,
+                    isp_internal_width,
+                    isp_internal_height,
+                    isp_output_width  = out_info->padded_width,
+                    isp_output_height = out_info->height,
+                    s3a_isp_width;
+
+       if (info->enable_dvs_envelope) {
+               sh_css_video_get_dis_envelope(&dvs_env_width, &dvs_env_height);
+               dvs_env_width  = MAX(dvs_env_width, SH_CSS_MIN_DVS_ENVELOPE);
+               dvs_env_height = MAX(dvs_env_height, SH_CSS_MIN_DVS_ENVELOPE);
+               binary->dvs_envelope_width  = dvs_env_width;
+               binary->dvs_envelope_height = dvs_env_height;
+       }
+       if (vf_info) {
+               enum sh_css_err err;
+               err = sh_css_vf_downscale_log2(out_info, vf_info, &vf_log_ds);
+               if (err != sh_css_success)
+                       return err;
+               vf_log_ds = min(vf_log_ds, info->max_vf_log_downscale);
+       }
+       if (online) {
+               bits_per_pixel = sh_css_input_format_bits_per_pixel(
+                                       stream_format, two_ppc);
+       }
+       if (info->enable_ds) {
+               ds_input_width  = in_info->padded_width + info->left_cropping;
+               ds_input_height = in_info->height + info->top_cropping;
+       }
+       /* We first calculate the resolutions used by the ISP. After that,
+        * we use those resolutions to compute sizes for tables etc. */
+       isp_internal_width  =
+               __ISP_INTERNAL_WIDTH(isp_output_width, dvs_env_width,
+                                    info->left_cropping, info->mode,
+                                    info->c_subsampling,
+                                    info->output_num_chunks, info->pipelining);
+       isp_internal_height =
+               __ISP_INTERNAL_HEIGHT(isp_output_height, info->top_cropping,
+                                     dvs_env_height);
+       isp_input_width = _ISP_INPUT_WIDTH(isp_internal_width,
+                                          ds_input_width, info->enable_ds);
+       isp_input_height = _ISP_INPUT_HEIGHT(isp_internal_height,
+                                            ds_input_height, info->enable_ds);
+
+       s3a_isp_width = _ISP_S3A_ISP_WIDTH(isp_input_width,
+               info->left_cropping);
+       if (info->fixed_s3a_deci_log)
+               s3a_log_deci = info->fixed_s3a_deci_log;
+       else
+               s3a_log_deci = sh_css_grid_deci_factor_log2(s3a_isp_width,
+                                                           isp_input_height);
+
+       binary->vf_downscale_log2 = vf_log_ds;
+       binary->deci_factor_log2  = s3a_log_deci;
+       binary->input_buf_vectors =
+                       SH_CSS_NUM_INPUT_BUF_LINES * _ISP_VECS(isp_input_width);
+       binary->online            = online;
+       binary->input_format      = stream_format;
+       /* input info */
+       binary->in_frame_info.format = in_info->format;
+       binary->in_frame_info.width = in_info->width + info->left_cropping +
+                                     dvs_env_width;
+       binary->in_frame_info.padded_width  = isp_input_width;
+       binary->in_frame_info.height        = isp_input_height;
+       binary->in_frame_info.raw_bit_depth = bits_per_pixel;
+       /* internal frame info */
+       binary->internal_frame_info.format          = out_info->format;
+       binary->internal_frame_info.width           = isp_internal_width;
+       binary->internal_frame_info.padded_width    = isp_internal_width;
+       binary->internal_frame_info.height          = isp_internal_height;
+       binary->internal_frame_info.raw_bit_depth   = bits_per_pixel;
+       /* output info */
+       binary->out_frame_info.format        = out_info->format;
+       binary->out_frame_info.width         = out_info->width;
+       binary->out_frame_info.padded_width  = isp_output_width;
+       binary->out_frame_info.height        = isp_output_height;
+       binary->out_frame_info.raw_bit_depth = bits_per_pixel;
+
+       /* viewfinder output info */
+       binary->vf_frame_info.format = SH_CSS_FRAME_FORMAT_YUV_LINE;
+       if (vf_info) {
+               unsigned int vf_out_vecs, vf_out_width, vf_out_height;
+               vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(isp_output_width,
+                                                        vf_log_ds);
+               vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs);
+               vf_out_height = _ISP_VF_OUTPUT_HEIGHT(isp_output_height,
+                                                     vf_log_ds);
+               /* we also store the raw downscaled width. This is used for
+                * digital zoom in preview to zoom only on the width that
+                * we actually want to keep, not on the aligned width. */
+               binary->vf_frame_info.width = (out_info->width >> vf_log_ds);
+               binary->vf_frame_info.padded_width = vf_out_width;
+               binary->vf_frame_info.height       = vf_out_height;
+       } else {
+               binary->vf_frame_info.width        = 0;
+               binary->vf_frame_info.padded_width = 0;
+               binary->vf_frame_info.height       = 0;
+       }
+       if (info->mode == SH_CSS_BINARY_MODE_GDC) {
+               binary->morph_tbl_width =
+                       _ISP_MORPH_TABLE_WIDTH(isp_internal_width);
+               binary->morph_tbl_aligned_width  =
+                       _ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width);
+               binary->morph_tbl_height =
+                       _ISP_MORPH_TABLE_HEIGHT(isp_internal_height);
+       } else {
+               binary->morph_tbl_width  = 0;
+               binary->morph_tbl_aligned_width  = 0;
+               binary->morph_tbl_height = 0;
+       }
+       if (info->enable_sc)
+               binary->sctbl_width_per_color =
+                       SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR;
+       else
+               binary->sctbl_width_per_color = 0;
+
+       if (info->enable_s3a) {
+               binary->s3atbl_width  =
+                       _ISP_S3ATBL_WIDTH(binary->in_frame_info.width,
+                               s3a_log_deci);
+               binary->s3atbl_height =
+                       _ISP_S3ATBL_HEIGHT(isp_input_height, s3a_log_deci);
+               binary->s3atbl_isp_width =
+                       _ISP_S3ATBL_ISP_WIDTH(isp_input_width, s3a_log_deci,
+                                         info->left_cropping);
+               binary->s3atbl_isp_height =
+                       _ISP_S3ATBL_ISP_HEIGHT(isp_input_height, s3a_log_deci);
+       } else {
+               binary->s3atbl_width  = 0;
+               binary->s3atbl_height = 0;
+               binary->s3atbl_isp_width  = 0;
+               binary->s3atbl_isp_height = 0;
+       }
+
+       if (info->enable_sc) {
+               binary->sctbl_width_per_color  =
+                       _ISP_SCTBL_WIDTH_PER_COLOR(isp_input_width,
+                                                  s3a_log_deci);
+               binary->sctbl_aligned_width_per_color =
+                       SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
+               binary->sctbl_height =
+                       _ISP_SCTBL_HEIGHT(isp_input_height, s3a_log_deci);
+       } else {
+               binary->sctbl_width_per_color         = 0;
+               binary->sctbl_aligned_width_per_color = 0;
+               binary->sctbl_height                  = 0;
+       }
+       if (info->enable_dis) {
+               binary->dis_deci_factor_log2 = SH_CSS_DIS_DECI_FACTOR_LOG2;
+               binary->dis_hor_coef_num_3a  =
+                       _ISP_SDIS_HOR_COEF_NUM_3A(binary->in_frame_info.width,
+                                                 SH_CSS_DIS_DECI_FACTOR_LOG2);
+               binary->dis_ver_coef_num_3a  =
+                       _ISP_SDIS_VER_COEF_NUM_3A(isp_input_height,
+                                                 SH_CSS_DIS_DECI_FACTOR_LOG2);
+               binary->dis_hor_coef_num_isp =
+                       _ISP_SDIS_HOR_COEF_NUM_ISP(isp_input_width);
+               binary->dis_ver_coef_num_isp =
+                       _ISP_SDIS_VER_COEF_NUM_ISP(isp_input_height);
+               binary->dis_hor_proj_num_3a  =
+                       _ISP_SDIS_HOR_PROJ_NUM_3A(isp_input_height,
+                                                 SH_CSS_DIS_DECI_FACTOR_LOG2);
+               binary->dis_ver_proj_num_3a  =
+                       _ISP_SDIS_VER_PROJ_NUM_3A(binary->in_frame_info.width,
+                                                 SH_CSS_DIS_DECI_FACTOR_LOG2);
+               binary->dis_hor_proj_num_isp =
+                       __ISP_SDIS_HOR_PROJ_NUM_ISP(isp_input_height,
+                                               SH_CSS_DIS_DECI_FACTOR_LOG2);
+               binary->dis_ver_proj_num_isp =
+                       __ISP_SDIS_VER_PROJ_NUM_ISP(isp_input_width,
+                                               SH_CSS_DIS_DECI_FACTOR_LOG2);
+       } else {
+               binary->dis_deci_factor_log2 = 0;
+               binary->dis_hor_coef_num_3a  = 0;
+               binary->dis_ver_coef_num_3a  = 0;
+               binary->dis_hor_coef_num_isp = 0;
+               binary->dis_ver_coef_num_isp = 0;
+               binary->dis_hor_proj_num_3a  = 0;
+               binary->dis_ver_proj_num_3a  = 0;
+               binary->dis_hor_proj_num_isp = 0;
+               binary->dis_ver_proj_num_isp = 0;
+       }
+       if (info->left_cropping)
+               binary->left_padding = 2 * ISP_VEC_NELEMS - info->left_cropping;
+       else
+               binary->left_padding = 0;
+
+       binary->info = info;
+       return sh_css_success;
+}
+enum sh_css_err
+sh_css_binary_find(struct sh_css_binary_descr *descr,
+                  struct sh_css_binary *binary)
+{
+       int mode = descr->mode;
+       bool online = descr->online;
+       bool two_ppc = descr->two_ppc;
+       enum sh_css_input_format stream_format = descr->stream_format;
+       const struct sh_css_frame_info *req_in_info = descr->in_info,
+                                      *req_out_info = descr->out_info,
+                                      *req_vf_info = descr->vf_info;
+       struct sh_css_binary_info *candidate;
+       unsigned int dvs_envelope_width = 0,
+                    dvs_envelope_height = 0;
+       bool need_ds = false,
+            need_dz = false,
+            need_dvs = false;
+       enum sh_css_err err = sh_css_success;
+
+       if (mode == SH_CSS_BINARY_MODE_VIDEO) {
+               unsigned int dx, dy;
+               sh_css_get_zoom_factor(&dx, &dy);
+               sh_css_video_get_dis_envelope(&dvs_envelope_width,
+                                             &dvs_envelope_height);
+
+               /* Video is the only mode that has a nodz variant. */
+               need_dz = (dx != 64 || dy != 64);
+               need_dvs = dvs_envelope_width || dvs_envelope_height;
+       }
+
+       need_ds = req_in_info->width > req_out_info->width ||
+                 req_in_info->height > req_out_info->height;
+
+       for (candidate = binary_infos[mode]; candidate;
+            candidate = candidate->next) {
+               if (candidate->enable_vf_veceven && !req_vf_info)
+                       continue;
+               if (req_vf_info && !(candidate->enable_vf_veceven ||
+                                    candidate->variable_vf_veceven))
+                       continue;
+               if (!candidate->enable_dvs_envelope && need_dvs)
+                       continue;
+               if (dvs_envelope_width > candidate->max_dvs_envelope_width)
+                       continue;
+               if (dvs_envelope_height > candidate->max_dvs_envelope_height)
+                       continue;
+               if (!candidate->enable_ds && need_ds)
+                       continue;
+               if (!candidate->enable_uds && need_dz)
+                       continue;
+               if (online && candidate->input == SH_CSS_BINARY_INPUT_MEMORY)
+                       continue;
+               if (!online && candidate->input == SH_CSS_BINARY_INPUT_SENSOR)
+                       continue;
+               if (req_out_info->padded_width < candidate->min_output_width ||
+                   req_out_info->padded_width > candidate->max_output_width)
+                       continue;
+
+               if (req_in_info->padded_width > candidate->max_input_width)
+                       continue;
+
+               if (!supports_output_format(candidate, req_out_info->format))
+                       continue;
+
+               /* reconfigure any variable properties of the binary */
+               err = fill_binary_info(candidate, online, two_ppc,
+                                      stream_format, req_in_info,
+                                      req_out_info, req_vf_info,
+                                      binary);
+               if (err)
+                       return err;
+               init_metrics(&binary->metrics, binary->info->id);
+               return sh_css_success;
+       }
+       return sh_css_err_internal_error;
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_binary.h b/drivers/media/video/atomisp/css/sh_css_binary.h
new file mode 100644 (file)
index 0000000..c3e4b67
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_BINARY_H_
+#define _SH_CSS_BINARY_H_
+
+#include "sh_css_types.h"
+#include "sh_css_metrics.h"
+
+/* The binary mode is used in pre-processor expressions so we cannot
+ * use an enum here. */
+#define SH_CSS_BINARY_MODE_COPY       0
+#define SH_CSS_BINARY_MODE_PREVIEW    1
+#define SH_CSS_BINARY_MODE_PRIMARY    2
+#define SH_CSS_BINARY_MODE_VIDEO      3
+#define SH_CSS_BINARY_MODE_PRE_GDC    4
+#define SH_CSS_BINARY_MODE_GDC        5
+#define SH_CSS_BINARY_MODE_POST_GDC   6
+#define SH_CSS_BINARY_MODE_PRE_ANR    7
+#define SH_CSS_BINARY_MODE_ANR        8
+#define SH_CSS_BINARY_MODE_POST_ANR   9
+#define SH_CSS_BINARY_MODE_CAPTURE_PP 10
+#define SH_CSS_BINARY_MODE_BAYER_DS   11
+#define SH_CSS_BINARY_MODE_VF_PP      12
+#define SH_CSS_BINARY_NUM_MODES       13
+#define SH_CSS_BINARY_MODE_NONE       14
+
+/* Indicate where binaries can read input from */
+#define SH_CSS_BINARY_INPUT_SENSOR   0
+#define SH_CSS_BINARY_INPUT_MEMORY   1
+#define SH_CSS_BINARY_INPUT_VARIABLE 2
+
+/* ISP binary identifiers.
+   these determine the order in which the binaries are looked up, do not change
+   this!
+   Also, the SP firmware uses this same order (sp_main_funcs in sp.hive.c).
+   Also, gen_firmware.c uses this order in its firmware_header.
+*/
+enum sh_css_binary_id {
+       SH_CSS_BINARY_ID_COPY,
+       SH_CSS_BINARY_ID_BAYER_DS,
+       SH_CSS_BINARY_ID_VF_PP,
+       SH_CSS_BINARY_ID_CAPTURE_PP,
+       SH_CSS_BINARY_ID_PRE_GDC,
+       SH_CSS_BINARY_ID_GDC,
+       SH_CSS_BINARY_ID_POST_GDC,
+       SH_CSS_BINARY_ID_PRE_ANR,
+       SH_CSS_BINARY_ID_ANR,
+       SH_CSS_BINARY_ID_POST_ANR,
+       SH_CSS_BINARY_ID_PREVIEW_DS,
+       SH_CSS_BINARY_ID_PREVIEW_DZ,
+       SH_CSS_BINARY_ID_PRIMARY_DS,
+       SH_CSS_BINARY_ID_PRIMARY_VAR,
+       SH_CSS_BINARY_ID_PRIMARY_8MP,
+       SH_CSS_BINARY_ID_PRIMARY_14MP,
+       SH_CSS_BINARY_ID_PRIMARY_16MP,
+       SH_CSS_BINARY_ID_PRIMARY_SMALL,
+       SH_CSS_BINARY_ID_PRIMARY_REF,
+       SH_CSS_BINARY_ID_VIDEO_OFFLINE,
+       SH_CSS_BINARY_ID_VIDEO_DS,
+       SH_CSS_BINARY_ID_VIDEO_DZ,
+       SH_CSS_BINARY_ID_VIDEO_NODZ,
+       SH_CSS_BINARY_NUM_IDS,
+};
+
+#define SH_CSS_BINARY_ID(BINARY) SH_CSS_BINARY_##BINARY
+/* The maximum number of different frame formats any binary can support */
+#define SH_CSS_MAX_NUM_FRAME_FORMATS 18
+
+struct sh_css_binary_descr {
+       int mode;
+       bool online;
+       bool continuous;
+       bool two_ppc;
+       enum sh_css_input_format stream_format;
+       struct sh_css_frame_info *in_info;
+       struct sh_css_frame_info *out_info;
+       struct sh_css_frame_info *vf_info;
+};
+
+struct sh_css_binary;
+
+struct sh_css_binary_info {
+       enum sh_css_binary_id    id;
+       int                      mode;
+       int                      num_output_formats;
+       enum sh_css_frame_format output_formats[SH_CSS_MAX_NUM_FRAME_FORMATS];
+       unsigned int             max_input_width;
+       unsigned int             min_output_width;
+       unsigned int             max_output_width;
+       unsigned int             max_dvs_envelope_width;
+       unsigned int             max_dvs_envelope_height;
+       bool                     variable_vf_veceven;
+       unsigned int             max_vf_log_downscale;
+       bool                     enable_vf_veceven;
+       bool                     enable_dis;
+       bool                     enable_dvs_envelope;
+       bool                     enable_uds;
+       bool                     enable_ds;
+       bool                     enable_s3a;
+       bool                     enable_fpnr;
+       bool                     enable_sc;
+       unsigned int             top_cropping;
+       unsigned int             left_cropping;
+       int                      s3atbl_use_dmem;
+       int                      input;
+       void                    *xmem_addr;
+       unsigned int             c_subsampling;
+       unsigned int             output_num_chunks;
+       unsigned int             pipelining;
+       unsigned int             fixed_s3a_deci_log;
+       struct sh_css_binary_info *next;
+};
+
+struct sh_css_binary {
+       const struct sh_css_binary_info *info;
+       enum sh_css_input_format input_format;
+       struct sh_css_frame_info in_frame_info;
+       struct sh_css_frame_info internal_frame_info;
+       struct sh_css_frame_info out_frame_info;
+       struct sh_css_frame_info vf_frame_info;
+       int                      input_buf_vectors;
+       int                      deci_factor_log2;
+       int                      dis_deci_factor_log2;
+       int                      vf_downscale_log2;
+       int                      s3atbl_width;
+       int                      s3atbl_height;
+       int                      s3atbl_isp_width;
+       int                      s3atbl_isp_height;
+       unsigned int             morph_tbl_width;
+       unsigned int             morph_tbl_aligned_width;
+       unsigned int             morph_tbl_height;
+       int                      sctbl_width_per_color;
+       int                      sctbl_aligned_width_per_color;
+       int                      sctbl_height;
+       int                      dis_hor_coef_num_3a;
+       int                      dis_ver_coef_num_3a;
+       int                      dis_hor_coef_num_isp;
+       int                      dis_ver_coef_num_isp;
+       int                      dis_hor_proj_num_3a;
+       int                      dis_ver_proj_num_3a;
+       int                      dis_hor_proj_num_isp;
+       int                      dis_ver_proj_num_isp;
+       unsigned int             dvs_envelope_width;
+       unsigned int             dvs_envelope_height;
+       bool                     online;
+       unsigned int             uds_xc;
+       unsigned int             uds_yc;
+       unsigned int             left_padding;
+       struct sh_css_binary_metrics metrics;
+};
+
+enum sh_css_err
+sh_css_init_binary_infos(void);
+
+enum sh_css_err
+sh_css_binary_uninit(void);
+
+enum sh_css_err
+sh_css_binary_find(struct sh_css_binary_descr *descr,
+                  struct sh_css_binary *binary);
+
+enum sh_css_err
+sh_css_binary_grid_info(struct sh_css_binary *binary,
+                       struct sh_css_grid_info *info);
+
+void sh_css_binary_init(struct sh_css_binary *binary);
+
+#endif /* _SH_CSS_BINARY_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_binary_info.h b/drivers/media/video/atomisp/css/sh_css_binary_info.h
new file mode 100644 (file)
index 0000000..46f486e
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_BINARY_INFO_H_
+#define _SH_CSS_BINARY_INFO_H_
+
+#include "sh_css_defs.h"
+
+/* Bayer DS */
+#define ISP_BAYER_DS_BINARY_ID               SH_CSS_BINARY_ID_BAYER_DS
+#define ISP_BAYER_DS_BINARY                  isp_bayer_ds_var
+#define ISP_BAYER_DS_MODE                    SH_CSS_BINARY_MODE_BAYER_DS
+#define ISP_BAYER_DS_OUTPUT_FRAME_FORMAT     SH_CSS_FRAME_FORMAT_RAW
+#define ISP_BAYER_DS_ENABLE_DS               1
+#define ISP_BAYER_DS_ENABLE_FPNR             0
+#define ISP_BAYER_DS_ENABLE_SC               0
+#define ISP_BAYER_DS_ENABLE_S3A              0
+#define ISP_BAYER_DS_ENABLE_SDIS             0
+#define ISP_BAYER_DS_ENABLE_VF_VECEVEN       0
+#define ISP_BAYER_DS_ENABLE_UDS              0
+#define ISP_BAYER_DS_PIPELINING              1
+#define ISP_BAYER_DS_OUTPUT_NUM_CHUNKS       1
+#define ISP_BAYER_DS_DUMMY_BUF_VECTORS       0
+#define ISP_BAYER_DS_LEFT_CROPPING           0
+#define ISP_BAYER_DS_TOP_CROPPING            0
+#define ISP_BAYER_DS_ENABLE_DVS_ENVELOPE     0
+#define ISP_BAYER_DS_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_BAYER_DS_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_BAYER_DS_MAX_OUTPUT_WIDTH        SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_BAYER_DS_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_BAYER_DS_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_BAYER_DS_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_BAYER_DS_OUTPUT_FORMATS          { SH_CSS_FRAME_FORMAT_RAW }
+#define ISP_BAYER_DS_MAX_VF_LOG_DOWNSCALE    0
+#define ISP_BAYER_DS_INPUT                   SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_BAYER_DS_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_BAYER_DS_FIXED_S3A_DECI_LOG      0
+
+/* Capture PP */
+#define ISP_CAPTURE_PP_BINARY_ID               SH_CSS_BINARY_ID_CAPTURE_PP
+#define ISP_CAPTURE_PP_BINARY                  isp_capture_pp_var
+#define ISP_CAPTURE_PP_MODE                    SH_CSS_BINARY_MODE_CAPTURE_PP
+#define ISP_CAPTURE_PP_ENABLE_UDS              1
+#define ISP_CAPTURE_PP_ENABLE_DS               1
+#define ISP_CAPTURE_PP_ENABLE_VF_VECEVEN       1
+#define ISP_CAPTURE_PP_ENABLE_FPNR             0
+#define ISP_CAPTURE_PP_ENABLE_SC               0
+#define ISP_CAPTURE_PP_ENABLE_S3A              0
+#define ISP_CAPTURE_PP_ENABLE_SDIS             0
+#define ISP_CAPTURE_PP_PIPELINING              1
+#define ISP_CAPTURE_PP_OUTPUT_NUM_CHUNKS       2
+#define ISP_CAPTURE_PP_DUMMY_BUF_VECTORS       0
+#define ISP_CAPTURE_PP_LEFT_CROPPING           0
+#define ISP_CAPTURE_PP_TOP_CROPPING            0
+#define ISP_CAPTURE_PP_ENABLE_DVS_ENVELOPE     0
+#define ISP_CAPTURE_PP_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_CAPTURE_PP_MAX_DVS_ENVELOPE_HEIGHT 0
+/* max width currently limited because of VMEM shortage */
+#define ISP_CAPTURE_PP_MAX_OUTPUT_WIDTH       MAX(4480, SH_CSS_MAX_SENSOR_WIDTH)
+#define ISP_CAPTURE_PP_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_CAPTURE_PP_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_CAPTURE_PP_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_CAPTURE_PP_OUTPUT_FORMATS          SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_CAPTURE_PP_MAX_VF_LOG_DOWNSCALE    1
+#define ISP_CAPTURE_PP_INPUT                   SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_CAPTURE_PP_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_CAPTURE_PP_FIXED_S3A_DECI_LOG      0
+
+/* Copy */
+#define ISP_COPY_BINARY_ID                 SH_CSS_BINARY_ID_COPY
+#define ISP_COPY_MODE                      SH_CSS_BINARY_MODE_COPY
+#define ISP_COPY_BINARY                    isp_copy_var
+#define ISP_COPY_ENABLE_DS                 0
+#define ISP_COPY_ENABLE_FPNR               0
+#define ISP_COPY_ENABLE_SC                 0
+#define ISP_COPY_ENABLE_S3A                0
+#define ISP_COPY_ENABLE_SDIS               0
+#define ISP_COPY_ENABLE_VF_VECEVEN         0
+#define ISP_COPY_ENABLE_UDS                0
+#define ISP_COPY_PIPELINING                1
+#define ISP_COPY_OUTPUT_NUM_CHUNKS         1
+#define ISP_COPY_DUMMY_BUF_VECTORS         0
+#define ISP_COPY_LEFT_CROPPING             0
+#define ISP_COPY_TOP_CROPPING              0
+#define ISP_COPY_ENABLE_DVS_ENVELOPE       0
+#define ISP_COPY_MAX_DVS_ENVELOPE_WIDTH    0
+#define ISP_COPY_MAX_DVS_ENVELOPE_HEIGHT   0
+#define ISP_COPY_MAX_VF_LOG_DOWNSCALE      2
+#define ISP_COPY_MAX_OUTPUT_WIDTH          SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_COPY_MAX_OUTPUT_HEIGHT         SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_COPY_MIN_OUTPUT_WIDTH          SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_COPY_MIN_OUTPUT_HEIGHT         SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_COPY_INPUT                     SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_COPY_C_SUBSAMPLING             SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_COPY_FIXED_S3A_DECI_LOG        0
+#define ISP_COPY_OUTPUT_FORMATS \
+       { \
+               SH_CSS_FRAME_FORMAT_NV11, \
+               SH_CSS_FRAME_FORMAT_NV12, \
+               SH_CSS_FRAME_FORMAT_NV16, \
+               SH_CSS_FRAME_FORMAT_NV21, \
+               SH_CSS_FRAME_FORMAT_NV61, \
+               SH_CSS_FRAME_FORMAT_YV12, \
+               SH_CSS_FRAME_FORMAT_YV16, \
+               SH_CSS_FRAME_FORMAT_YUV420, \
+               SH_CSS_FRAME_FORMAT_YUV420_16, \
+               SH_CSS_FRAME_FORMAT_YUV422, \
+               SH_CSS_FRAME_FORMAT_YUV422_16, \
+               SH_CSS_FRAME_FORMAT_YUV_LINE, \
+               SH_CSS_FRAME_FORMAT_RAW, \
+               SH_CSS_FRAME_FORMAT_UYVY, \
+               SH_CSS_FRAME_FORMAT_YUYV, \
+               SH_CSS_FRAME_FORMAT_RGB565, \
+               SH_CSS_FRAME_FORMAT_PLANAR_RGB888, \
+               SH_CSS_FRAME_FORMAT_RGBA888 \
+       }
+
+/* GDC */
+#define ISP_GDC_BINARY_ID                 SH_CSS_BINARY_ID_GDC
+#define ISP_GDC_BINARY                    isp_gdc_var
+#define ISP_GDC_MODE                      SH_CSS_BINARY_MODE_GDC
+#define ISP_GDC_OUTPUT_NUM_CHUNKS         2
+#define ISP_GDC_ENABLE_DS                 0
+#define ISP_GDC_ENABLE_FPNR               0
+#define ISP_GDC_ENABLE_SC                 0
+#define ISP_GDC_ENABLE_S3A                0
+#define ISP_GDC_ENABLE_SDIS               0
+#define ISP_GDC_ENABLE_VF_VECEVEN         0
+#define ISP_GDC_ENABLE_UDS                0
+#define ISP_GDC_PIPELINING                1
+#define ISP_GDC_DUMMY_BUF_VECTORS         0
+#define ISP_GDC_LEFT_CROPPING             0
+#define ISP_GDC_TOP_CROPPING              0
+#define ISP_GDC_ENABLE_DVS_ENVELOPE       0
+#define ISP_GDC_MAX_DVS_ENVELOPE_WIDTH    0
+#define ISP_GDC_MAX_DVS_ENVELOPE_HEIGHT   0
+#define ISP_GDC_MAX_OUTPUT_WIDTH          SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_GDC_MAX_OUTPUT_HEIGHT         SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_GDC_MIN_OUTPUT_WIDTH          SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_GDC_MIN_OUTPUT_HEIGHT         SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_GDC_OUTPUT_FORMATS            { SH_CSS_FRAME_FORMAT_YUV420_16 }
+#define ISP_GDC_MAX_VF_LOG_DOWNSCALE      0
+#define ISP_GDC_INPUT                     SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_GDC_C_SUBSAMPLING             SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_GDC_FIXED_S3A_DECI_LOG        0
+
+/* Post GDC */
+#define ISP_POST_GDC_BINARY_ID               SH_CSS_BINARY_ID_POST_GDC
+#define ISP_POST_GDC_BINARY                  isp_postgdc_var
+#define ISP_POST_GDC_MODE                    SH_CSS_BINARY_MODE_POST_GDC
+#define ISP_POST_GDC_PIPELINING              2
+#define ISP_POST_GDC_ENABLE_VF_VECEVEN       1
+#define ISP_POST_GDC_ENABLE_DS               0
+#define ISP_POST_GDC_ENABLE_FPNR             0
+#define ISP_POST_GDC_ENABLE_SC               0
+#define ISP_POST_GDC_ENABLE_S3A              0
+#define ISP_POST_GDC_ENABLE_SDIS             0
+#define ISP_POST_GDC_ENABLE_UDS              0
+#define ISP_POST_GDC_OUTPUT_NUM_CHUNKS       1
+#define ISP_POST_GDC_DUMMY_BUF_VECTORS       0
+#define ISP_POST_GDC_LEFT_CROPPING           SH_CSS_MAX_LEFT_CROPPING
+#define ISP_POST_GDC_TOP_CROPPING            8
+#define ISP_POST_GDC_ENABLE_DVS_ENVELOPE     0
+#define ISP_POST_GDC_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_POST_GDC_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_POST_GDC_MAX_VF_LOG_DOWNSCALE    2
+/* limited due to VMEM shortage */
+#define ISP_POST_GDC_MAX_OUTPUT_WIDTH        4352 /* was 4416 */
+#define ISP_POST_GDC_MAX_OUTPUT_HEIGHT       3312
+#define ISP_POST_GDC_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_POST_GDC_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_POST_GDC_OUTPUT_FORMATS          SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_POST_GDC_INPUT                   SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_POST_GDC_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_POST_GDC_FIXED_S3A_DECI_LOG      0
+
+/* Pre GDC */
+#define ISP_PRE_GDC_BINARY_ID               SH_CSS_BINARY_ID_PRE_GDC
+#define ISP_PRE_GDC_BINARY                  isp_pregdc_var
+#define ISP_PRE_GDC_MODE                    SH_CSS_BINARY_MODE_PRE_GDC
+#define ISP_PRE_GDC_ENABLE_FPNR             1
+#define ISP_PRE_GDC_ENABLE_SC               1
+#define ISP_PRE_GDC_ENABLE_S3A              1
+#define ISP_PRE_GDC_ENABLE_SDIS             1
+#define ISP_PRE_GDC_ENABLE_DS               0
+#define ISP_PRE_GDC_ENABLE_VF_VECEVEN       0
+#define ISP_PRE_GDC_ENABLE_UDS              0
+#define ISP_PRE_GDC_PIPELINING              1
+#define ISP_PRE_GDC_OUTPUT_NUM_CHUNKS       1
+#define ISP_PRE_GDC_DUMMY_BUF_VECTORS       0
+#define ISP_PRE_GDC_LEFT_CROPPING           0
+#define ISP_PRE_GDC_TOP_CROPPING            0
+#define ISP_PRE_GDC_ENABLE_DVS_ENVELOPE     0
+#define ISP_PRE_GDC_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_PRE_GDC_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_PRE_GDC_MAX_OUTPUT_WIDTH        SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_PRE_GDC_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRE_GDC_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRE_GDC_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRE_GDC_OUTPUT_FORMATS          { SH_CSS_FRAME_FORMAT_QPLANE6 }
+#define ISP_PRE_GDC_MAX_VF_LOG_DOWNSCALE    0
+#define ISP_PRE_GDC_INPUT                   SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRE_GDC_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRE_GDC_FIXED_S3A_DECI_LOG      0
+
+/* ANR */
+#define ISP_ANR_BINARY_ID                 SH_CSS_BINARY_ID_ANR
+#define ISP_ANR_BINARY                    isp_anr_var
+#define ISP_ANR_MODE                      SH_CSS_BINARY_MODE_ANR
+#define ISP_ANR_OUTPUT_NUM_CHUNKS         1
+#define ISP_ANR_ENABLE_DS                 0
+#define ISP_ANR_ENABLE_FPNR               0
+#define ISP_ANR_ENABLE_SC                 0
+#define ISP_ANR_ENABLE_S3A                0
+#define ISP_ANR_ENABLE_SDIS               0
+#define ISP_ANR_ENABLE_VF_VECEVEN         0
+#define ISP_ANR_ENABLE_UDS                0
+#define ISP_ANR_PIPELINING                1
+#define ISP_ANR_DUMMY_BUF_VECTORS         0
+#define ISP_ANR_LEFT_CROPPING             0
+#define ISP_ANR_TOP_CROPPING              0
+#define ISP_ANR_ENABLE_DVS_ENVELOPE       0
+#define ISP_ANR_MAX_DVS_ENVELOPE_WIDTH    0
+#define ISP_ANR_MAX_DVS_ENVELOPE_HEIGHT   0
+#define ISP_ANR_MAX_OUTPUT_WIDTH          3264
+#define ISP_ANR_MAX_OUTPUT_HEIGHT         SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_ANR_MIN_OUTPUT_WIDTH          SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_ANR_MIN_OUTPUT_HEIGHT         SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_ANR_OUTPUT_FORMATS            { SH_CSS_FRAME_FORMAT_RAW }
+#define ISP_ANR_MAX_VF_LOG_DOWNSCALE      0
+#define ISP_ANR_INPUT                     SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_ANR_C_SUBSAMPLING             SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_ANR_FIXED_S3A_DECI_LOG        0
+
+/* Post ANR */
+#define ISP_POST_ANR_BINARY_ID               SH_CSS_BINARY_ID_POST_ANR
+#define ISP_POST_ANR_BINARY                  isp_postanr_var
+#define ISP_POST_ANR_MODE                    SH_CSS_BINARY_MODE_POST_ANR
+#define ISP_POST_ANR_PIPELINING              2
+#define ISP_POST_ANR_ENABLE_VF_VECEVEN       1
+#define ISP_POST_ANR_ENABLE_DS               0
+#define ISP_POST_ANR_ENABLE_FPNR             0
+#define ISP_POST_ANR_ENABLE_SC               0
+#define ISP_POST_ANR_ENABLE_S3A              0
+#define ISP_POST_ANR_ENABLE_SDIS             0
+#define ISP_POST_ANR_ENABLE_UDS              0
+#define ISP_POST_ANR_OUTPUT_NUM_CHUNKS       1
+#define ISP_POST_ANR_DUMMY_BUF_VECTORS       0
+#define ISP_POST_ANR_LEFT_CROPPING           SH_CSS_MAX_LEFT_CROPPING
+#define ISP_POST_ANR_TOP_CROPPING            8
+#define ISP_POST_ANR_ENABLE_DVS_ENVELOPE     0
+#define ISP_POST_ANR_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_POST_ANR_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_POST_ANR_MAX_VF_LOG_DOWNSCALE    2
+/* limited due to VMEM shortage */
+#define ISP_POST_ANR_MAX_OUTPUT_WIDTH        3264
+#define ISP_POST_ANR_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_POST_ANR_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_POST_ANR_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_POST_ANR_OUTPUT_FORMATS          SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_POST_ANR_INPUT                   SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_POST_ANR_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_POST_ANR_FIXED_S3A_DECI_LOG      0
+
+/* Pre ANR */
+#define ISP_PRE_ANR_BINARY_ID               SH_CSS_BINARY_ID_PRE_ANR
+#define ISP_PRE_ANR_BINARY                  isp_preanr_var
+#define ISP_PRE_ANR_MODE                    SH_CSS_BINARY_MODE_PRE_ANR
+#define ISP_PRE_ANR_ENABLE_FPNR             1
+#define ISP_PRE_ANR_ENABLE_SC               1
+#define ISP_PRE_ANR_ENABLE_S3A              1
+#define ISP_PRE_ANR_ENABLE_SDIS             1
+#define ISP_PRE_ANR_ENABLE_DS               0
+#define ISP_PRE_ANR_ENABLE_VF_VECEVEN       0
+#define ISP_PRE_ANR_ENABLE_UDS              0
+#define ISP_PRE_ANR_PIPELINING              1
+#define ISP_PRE_ANR_OUTPUT_NUM_CHUNKS       1
+#define ISP_PRE_ANR_DUMMY_BUF_VECTORS       0
+#define ISP_PRE_ANR_LEFT_CROPPING           0
+#define ISP_PRE_ANR_TOP_CROPPING            0
+#define ISP_PRE_ANR_ENABLE_DVS_ENVELOPE     0
+#define ISP_PRE_ANR_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_PRE_ANR_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_PRE_ANR_MAX_OUTPUT_WIDTH        SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_PRE_ANR_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRE_ANR_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRE_ANR_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRE_ANR_OUTPUT_FORMATS          { SH_CSS_FRAME_FORMAT_RAW }
+#define ISP_PRE_ANR_MAX_VF_LOG_DOWNSCALE    0
+#define ISP_PRE_ANR_INPUT                   SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRE_ANR_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRE_ANR_FIXED_S3A_DECI_LOG      0
+
+/* Preview DS */
+#define ISP_PREVIEW_DS_BINARY_ID               SH_CSS_BINARY_ID_PREVIEW_DS
+#define ISP_PREVIEW_DS_BINARY                  isp_preview_ds
+#define ISP_PREVIEW_DS_MODE                    SH_CSS_BINARY_MODE_PREVIEW
+#define ISP_PREVIEW_DS_OUTPUT_NUM_CHUNKS       2
+#define ISP_PREVIEW_DS_DUMMY_BUF_VECTORS       2
+#define ISP_PREVIEW_DS_PIPELINING              2
+#define ISP_PREVIEW_DS_ENABLE_SC               1
+#define ISP_PREVIEW_DS_ENABLE_S3A              1
+#define ISP_PREVIEW_DS_ENABLE_VF_VECEVEN       1
+#define ISP_PREVIEW_DS_ENABLE_DS               1
+#define ISP_PREVIEW_DS_ENABLE_FPNR             0
+#define ISP_PREVIEW_DS_ENABLE_SDIS             0
+#define ISP_PREVIEW_DS_ENABLE_UDS              0
+#define ISP_PREVIEW_DS_LEFT_CROPPING           0
+#define ISP_PREVIEW_DS_TOP_CROPPING            8
+#define ISP_PREVIEW_DS_ENABLE_DVS_ENVELOPE     0
+#define ISP_PREVIEW_DS_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_PREVIEW_DS_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_PREVIEW_DS_MAX_OUTPUT_WIDTH \
+       __ISP_MAX_VF_OUTPUT_WIDTH(2*SH_CSS_MAX_VF_WIDTH, \
+                                 ISP_PREVIEW_DS_LEFT_CROPPING)
+#define ISP_PREVIEW_DS_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_VF_HEIGHT
+#define ISP_PREVIEW_DS_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PREVIEW_DS_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PREVIEW_DS_OUTPUT_FORMATS          { SH_CSS_FRAME_FORMAT_YUV_LINE }
+#define ISP_PREVIEW_DS_MAX_VF_LOG_DOWNSCALE    0
+#define ISP_PREVIEW_DS_INPUT                   SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_PREVIEW_DS_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PREVIEW_DS_FIXED_S3A_DECI_LOG      0
+
+/* Preview DZ */
+#define ISP_PREVIEW_DZ_BINARY_ID               SH_CSS_BINARY_ID_PREVIEW_DZ
+#define ISP_PREVIEW_DZ_BINARY                  isp_preview_var
+#define ISP_PREVIEW_DZ_MODE                    SH_CSS_BINARY_MODE_PREVIEW
+#define ISP_PREVIEW_DZ_PIPELINING              3
+#define ISP_PREVIEW_DZ_LEFT_CROPPING           SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PREVIEW_DZ_ENABLE_VF_VECEVEN       1
+#define ISP_PREVIEW_DZ_ENABLE_UDS              0
+#define ISP_PREVIEW_DZ_ENABLE_SC               1
+#define ISP_PREVIEW_DZ_ENABLE_S3A              1
+#define ISP_PREVIEW_DZ_ENABLE_DS               0
+#define ISP_PREVIEW_DZ_ENABLE_FPNR             0
+#define ISP_PREVIEW_DZ_ENABLE_SDIS             0
+#define ISP_PREVIEW_DZ_OUTPUT_NUM_CHUNKS       1
+#define ISP_PREVIEW_DZ_DUMMY_BUF_VECTORS       0
+#define ISP_PREVIEW_DZ_TOP_CROPPING            8
+#define ISP_PREVIEW_DZ_ENABLE_DVS_ENVELOPE     0
+#define ISP_PREVIEW_DZ_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_PREVIEW_DZ_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_PREVIEW_DZ_MAX_OUTPUT_WIDTH \
+       __ISP_MAX_VF_OUTPUT_WIDTH(2*SH_CSS_MAX_VF_WIDTH, \
+                                 ISP_PREVIEW_DZ_LEFT_CROPPING)
+#define ISP_PREVIEW_DZ_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_VF_HEIGHT
+#define ISP_PREVIEW_DZ_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PREVIEW_DZ_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PREVIEW_DZ_OUTPUT_FORMATS          { SH_CSS_FRAME_FORMAT_YUV_LINE }
+#define ISP_PREVIEW_DZ_MAX_VF_LOG_DOWNSCALE    0
+#define ISP_PREVIEW_DZ_INPUT                   SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PREVIEW_DZ_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PREVIEW_DZ_FIXED_S3A_DECI_LOG      0
+
+/* Primary 14MP */
+#define ISP_PRIMARY_14MP_BINARY_ID               SH_CSS_BINARY_ID_PRIMARY_14MP
+#define ISP_PRIMARY_14MP_BINARY                  isp_primary_14mp
+#define ISP_PRIMARY_14MP_MODE                    SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_14MP_VF_LOG_DOWNSCALE        2
+#define ISP_PRIMARY_14MP_LEFT_CROPPING           SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PRIMARY_14MP_PIPELINING              4
+#define ISP_PRIMARY_14MP_ENABLE_VF_VECEVEN       1
+#define ISP_PRIMARY_14MP_ENABLE_FPNR             1
+#define ISP_PRIMARY_14MP_ENABLE_SC               1
+#define ISP_PRIMARY_14MP_ENABLE_S3A              1
+#define ISP_PRIMARY_14MP_ENABLE_DS               0
+#define ISP_PRIMARY_14MP_ENABLE_SDIS             0
+#define ISP_PRIMARY_14MP_ENABLE_UDS              0
+#define ISP_PRIMARY_14MP_OUTPUT_NUM_CHUNKS       1
+#define ISP_PRIMARY_14MP_DUMMY_BUF_VECTORS       0
+#define ISP_PRIMARY_14MP_TOP_CROPPING            8
+#define ISP_PRIMARY_14MP_ENABLE_DVS_ENVELOPE     0
+#define ISP_PRIMARY_14MP_MAX_DVS_ENVELOPE_WIDTH  0
+#define ISP_PRIMARY_14MP_MAX_DVS_ENVELOPE_HEIGHT 0
+#define ISP_PRIMARY_14MP_MAX_OUTPUT_WIDTH        4352
+#define ISP_PRIMARY_14MP_MAX_OUTPUT_HEIGHT       SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_14MP_MIN_OUTPUT_WIDTH     ISP_PRIMARY_14MP_MAX_OUTPUT_WIDTH
+#define ISP_PRIMARY_14MP_MIN_OUTPUT_HEIGHT    ISP_PRIMARY_14MP_MAX_OUTPUT_HEIGHT
+#define ISP_PRIMARY_14MP_OUTPUT_FORMATS       { SH_CSS_FIXED_PRIMARY_FORMAT }
+#define ISP_PRIMARY_14MP_MAX_VF_LOG_DOWNSCALE ISP_PRIMARY_14MP_VF_LOG_DOWNSCALE
+#define ISP_PRIMARY_14MP_INPUT                SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_PRIMARY_14MP_C_SUBSAMPLING        1
+#define ISP_PRIMARY_14MP_FIXED_S3A_DECI_LOG   6
+
+/* Primary 16MP */
+#define ISP_PRIMARY_16MP_BINARY_ID           SH_CSS_BINARY_ID_PRIMARY_16MP
+#define ISP_PRIMARY_16MP_BINARY              isp_primary_16mp
+#define ISP_PRIMARY_16MP_MODE                SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_16MP_VF_LOG_DOWNSCALE    2
+#define ISP_PRIMARY_16MP_PIPELINING          4
+#define ISP_PRIMARY_16MP_ENABLE_FPNR         1
+#define ISP_PRIMARY_16MP_ENABLE_SC           1
+#define ISP_PRIMARY_16MP_ENABLE_S3A          1
+#define ISP_PRIMARY_16MP_ENABLE_VF_VECEVEN   1
+#define ISP_PRIMARY_16MP_ENABLE_DS           0
+#define ISP_PRIMARY_16MP_ENABLE_SDIS         0
+#define ISP_PRIMARY_16MP_ENABLE_UDS          0
+#define ISP_PRIMARY_16MP_OUTPUT_NUM_CHUNKS   1
+#define ISP_PRIMARY_16MP_DUMMY_BUF_VECTORS   0
+#define ISP_PRIMARY_16MP_LEFT_CROPPING       0
+#define ISP_PRIMARY_16MP_TOP_CROPPING        8
+#define ISP_PRIMARY_16MP_ENABLE_DVS_ENVELOPE 0
+#define ISP_PRIMARY_16MP_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_16MP_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_PRIMARY_16MP_MAX_OUTPUT_WIDTH    4608
+#define ISP_PRIMARY_16MP_MAX_OUTPUT_HEIGHT   SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_16MP_MIN_OUTPUT_WIDTH    ISP_PRIMARY_16MP_MAX_OUTPUT_WIDTH
+#define ISP_PRIMARY_16MP_MIN_OUTPUT_HEIGHT   ISP_PRIMARY_16MP_MAX_OUTPUT_HEIGHT
+#define ISP_PRIMARY_16MP_OUTPUT_FORMATS      { SH_CSS_FIXED_PRIMARY_FORMAT }
+#define ISP_PRIMARY_16MP_MAX_VF_LOG_DOWNSCALE ISP_PRIMARY_16MP_VF_LOG_DOWNSCALE
+#define ISP_PRIMARY_16MP_INPUT                SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_PRIMARY_16MP_C_SUBSAMPLING        1
+#define ISP_PRIMARY_16MP_FIXED_S3A_DECI_LOG   6
+
+/* Primary 8MP */
+#define ISP_PRIMARY_8MP_BINARY_ID           SH_CSS_BINARY_ID_PRIMARY_8MP
+#define ISP_PRIMARY_8MP_BINARY              isp_primary_8mp
+#define ISP_PRIMARY_8MP_MODE                SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_8MP_VF_LOG_DOWNSCALE    1
+#define ISP_PRIMARY_8MP_LEFT_CROPPING       SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PRIMARY_8MP_PIPELINING          4
+#define ISP_PRIMARY_8MP_ENABLE_FPNR         1
+#define ISP_PRIMARY_8MP_ENABLE_SC           1
+#define ISP_PRIMARY_8MP_ENABLE_S3A          1
+#define ISP_PRIMARY_8MP_ENABLE_VF_VECEVEN   1
+#define ISP_PRIMARY_8MP_ENABLE_DS           0
+#define ISP_PRIMARY_8MP_ENABLE_SDIS         0
+#define ISP_PRIMARY_8MP_ENABLE_UDS          0
+#define ISP_PRIMARY_8MP_OUTPUT_NUM_CHUNKS   1
+#define ISP_PRIMARY_8MP_DUMMY_BUF_VECTORS   0
+#define ISP_PRIMARY_8MP_TOP_CROPPING        8
+#define ISP_PRIMARY_8MP_ENABLE_DVS_ENVELOPE 0
+#define ISP_PRIMARY_8MP_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_8MP_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_PRIMARY_8MP_MAX_OUTPUT_WIDTH    3264
+#define ISP_PRIMARY_8MP_MAX_OUTPUT_HEIGHT   SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_8MP_MIN_OUTPUT_WIDTH    ISP_PRIMARY_8MP_MAX_OUTPUT_WIDTH
+#define ISP_PRIMARY_8MP_MIN_OUTPUT_HEIGHT   ISP_PRIMARY_8MP_MAX_OUTPUT_HEIGHT
+#define ISP_PRIMARY_8MP_OUTPUT_FORMATS      { SH_CSS_FIXED_PRIMARY_FORMAT }
+#define ISP_PRIMARY_8MP_MAX_VF_LOG_DOWNSCALE ISP_PRIMARY_8MP_VF_LOG_DOWNSCALE
+#define ISP_PRIMARY_8MP_INPUT                SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_PRIMARY_8MP_C_SUBSAMPLING        1
+#define ISP_PRIMARY_8MP_FIXED_S3A_DECI_LOG   6
+
+/* Primary DS */
+#define ISP_PRIMARY_DS_BINARY_ID            SH_CSS_BINARY_ID_PRIMARY_DS
+#define ISP_PRIMARY_DS_BINARY               isp_primary_ds
+#define ISP_PRIMARY_DS_MODE                 SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_DS_OUTPUT_NUM_CHUNKS    2
+#define ISP_PRIMARY_DS_DUMMY_BUF_VECTORS    2
+#define ISP_PRIMARY_DS_PIPELINING           2
+#define ISP_PRIMARY_DS_ENABLE_FPNR          1
+#define ISP_PRIMARY_DS_ENABLE_SC            1
+#define ISP_PRIMARY_DS_ENABLE_S3A           1
+#define ISP_PRIMARY_DS_ENABLE_VF_VECEVEN    1
+#define ISP_PRIMARY_DS_ENABLE_DS            1
+#define ISP_PRIMARY_DS_ENABLE_SDIS          0
+#define ISP_PRIMARY_DS_ENABLE_UDS           0
+#define ISP_PRIMARY_DS_LEFT_CROPPING        0
+#define ISP_PRIMARY_DS_TOP_CROPPING         8
+#define ISP_PRIMARY_DS_ENABLE_DVS_ENVELOPE  0
+#define ISP_PRIMARY_DS_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_DS_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_PRIMARY_DS_MAX_OUTPUT_WIDTH     2560
+#define ISP_PRIMARY_DS_MAX_OUTPUT_HEIGHT    1920
+#define ISP_PRIMARY_DS_MIN_OUTPUT_WIDTH     SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRIMARY_DS_MIN_OUTPUT_HEIGHT    SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRIMARY_DS_OUTPUT_FORMATS       SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_PRIMARY_DS_MAX_VF_LOG_DOWNSCALE 1
+#define ISP_PRIMARY_DS_INPUT                SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRIMARY_DS_C_SUBSAMPLING        SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRIMARY_DS_FIXED_S3A_DECI_LOG   0
+
+/* Primary Small */
+#define ISP_PRIMARY_SMALL_BINARY_ID           SH_CSS_BINARY_ID_PRIMARY_SMALL
+#define ISP_PRIMARY_SMALL_BINARY              isp_primary_small
+#define ISP_PRIMARY_SMALL_MODE                SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_SMALL_LEFT_CROPPING       SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PRIMARY_SMALL_PIPELINING          2
+#define ISP_PRIMARY_SMALL_ENABLE_FPNR         1
+#define ISP_PRIMARY_SMALL_ENABLE_SC           1
+#define ISP_PRIMARY_SMALL_ENABLE_S3A          1
+#define ISP_PRIMARY_SMALL_ENABLE_VF_VECEVEN   1
+#define ISP_PRIMARY_SMALL_ENABLE_DS           0
+#define ISP_PRIMARY_SMALL_ENABLE_SDIS         0
+#define ISP_PRIMARY_SMALL_ENABLE_UDS          0
+#define ISP_PRIMARY_SMALL_OUTPUT_NUM_CHUNKS   1
+#define ISP_PRIMARY_SMALL_DUMMY_BUF_VECTORS   0
+#define ISP_PRIMARY_SMALL_TOP_CROPPING        8
+#define ISP_PRIMARY_SMALL_ENABLE_DVS_ENVELOPE 0
+#define ISP_PRIMARY_SMALL_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_SMALL_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_PRIMARY_SMALL_MAX_OUTPUT_WIDTH    2560
+#define ISP_PRIMARY_SMALL_MAX_OUTPUT_HEIGHT   1920
+#define ISP_PRIMARY_SMALL_MIN_OUTPUT_WIDTH    SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRIMARY_SMALL_MIN_OUTPUT_HEIGHT   SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRIMARY_SMALL_OUTPUT_FORMATS      SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_PRIMARY_SMALL_MAX_VF_LOG_DOWNSCALE 1
+#define ISP_PRIMARY_SMALL_INPUT                SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRIMARY_SMALL_C_SUBSAMPLING        SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRIMARY_SMALL_FIXED_S3A_DECI_LOG   0
+
+/* Primary Var */
+#define ISP_PRIMARY_VAR_BINARY_ID           SH_CSS_BINARY_ID_PRIMARY_VAR
+#define ISP_PRIMARY_VAR_BINARY              isp_primary_var
+#define ISP_PRIMARY_VAR_MODE                SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_VAR_OUTPUT_NUM_CHUNKS   4
+#define ISP_PRIMARY_VAR_LEFT_CROPPING       SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PRIMARY_VAR_PIPELINING          3
+#define ISP_PRIMARY_VAR_ENABLE_FPNR         1
+#define ISP_PRIMARY_VAR_ENABLE_SC           1
+#define ISP_PRIMARY_VAR_ENABLE_S3A          1
+#define ISP_PRIMARY_VAR_ENABLE_VF_VECEVEN   1
+#define ISP_PRIMARY_VAR_ENABLE_DS           0
+#define ISP_PRIMARY_VAR_ENABLE_SDIS         0
+#define ISP_PRIMARY_VAR_ENABLE_UDS          0
+#define ISP_PRIMARY_VAR_DUMMY_BUF_VECTORS   0
+#define ISP_PRIMARY_VAR_TOP_CROPPING        8
+#define ISP_PRIMARY_VAR_ENABLE_DVS_ENVELOPE 0
+#define ISP_PRIMARY_VAR_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_VAR_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_PRIMARY_VAR_MAX_VF_LOG_DOWNSCALE     2
+#define ISP_PRIMARY_VAR_MAX_OUTPUT_WIDTH    SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_PRIMARY_VAR_MAX_OUTPUT_HEIGHT   SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_VAR_MIN_OUTPUT_WIDTH    SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRIMARY_VAR_MIN_OUTPUT_HEIGHT   SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRIMARY_VAR_OUTPUT_FORMATS      SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_PRIMARY_VAR_INPUT               SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRIMARY_VAR_C_SUBSAMPLING       SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRIMARY_VAR_FIXED_S3A_DECI_LOG  0
+
+/* Primary Ref */
+#define ISP_PRIMARY_REF_BINARY_ID           SH_CSS_BINARY_ID_PRIMARY_REF
+#define ISP_PRIMARY_REF_BINARY              isp_primary_ref
+#define ISP_PRIMARY_REF_MODE                SH_CSS_BINARY_MODE_PRIMARY
+#define ISP_PRIMARY_REF_VF_LOG_DOWNSCALE    1
+#define ISP_PRIMARY_REF_LEFT_CROPPING       SH_CSS_MAX_LEFT_CROPPING
+#define ISP_PRIMARY_REF_PIPELINING          4
+#define ISP_PRIMARY_REF_ENABLE_FPNR         1
+#define ISP_PRIMARY_REF_ENABLE_SC           1
+#define ISP_PRIMARY_REF_ENABLE_S3A          1
+#define ISP_PRIMARY_REF_ENABLE_VF_VECEVEN   1
+#define ISP_PRIMARY_REF_ENABLE_DS           0
+#define ISP_PRIMARY_REF_ENABLE_SDIS         0
+#define ISP_PRIMARY_REF_ENABLE_UDS          0
+#define ISP_PRIMARY_REF_OUTPUT_NUM_CHUNKS   1
+#define ISP_PRIMARY_REF_DUMMY_BUF_VECTORS   0
+#define ISP_PRIMARY_REF_TOP_CROPPING        8
+#define ISP_PRIMARY_REF_ENABLE_DVS_ENVELOPE 0
+#define ISP_PRIMARY_REF_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_PRIMARY_REF_MAX_DVS_ENVELOPE_HEIGHT  0
+/*
+#define ISP_PRIMARY_REF_MAX_OUTPUT_WIDTH    SH_CSS_MAX_SENSOR_WIDTH
+#define ISP_PRIMARY_REF_MAX_OUTPUT_HEIGHT   SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_REF_MIN_OUTPUT_WIDTH    SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_PRIMARY_REF_MIN_OUTPUT_HEIGHT   SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_PRIMARY_REF_OUTPUT_FORMATS      SH_CSS_CAPTURE_OUTPUT_FORMATS
+#define ISP_PRIMARY_REF_INPUT               SH_CSS_BINARY_INPUT_VARIABLE
+#define ISP_PRIMARY_REF_C_SUBSAMPLING       SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_PRIMARY_REF_FIXED_S3A_DECI_LOG  0
+*/
+#define ISP_PRIMARY_REF_MAX_OUTPUT_WIDTH    3328
+#define ISP_PRIMARY_REF_MAX_OUTPUT_HEIGHT   SH_CSS_MAX_SENSOR_HEIGHT
+#define ISP_PRIMARY_REF_MIN_OUTPUT_WIDTH    ISP_PRIMARY_REF_MAX_OUTPUT_WIDTH
+#define ISP_PRIMARY_REF_MIN_OUTPUT_HEIGHT   ISP_PRIMARY_REF_MAX_OUTPUT_HEIGHT
+#define ISP_PRIMARY_REF_OUTPUT_FORMATS      { SH_CSS_FIXED_PRIMARY_FORMAT }
+#define ISP_PRIMARY_REF_MAX_VF_LOG_DOWNSCALE ISP_PRIMARY_REF_VF_LOG_DOWNSCALE
+#define ISP_PRIMARY_REF_INPUT                SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_PRIMARY_REF_C_SUBSAMPLING        1
+#define ISP_PRIMARY_REF_FIXED_S3A_DECI_LOG   6
+
+/* Video Offline */
+#define ISP_VIDEO_OFFLINE_BINARY_ID           SH_CSS_BINARY_ID_VIDEO_OFFLINE
+#define ISP_VIDEO_OFFLINE_BINARY              isp_video_offline
+#define ISP_VIDEO_OFFLINE_MODE                SH_CSS_BINARY_MODE_VIDEO
+#define ISP_VIDEO_OFFLINE_PIPELINING          3
+/* we use the VF_VECEVEN dma channel for the input frame so
+ * we cannot generate viewfinder output here. This is also not
+ * needed for the demo. */
+#define ISP_VIDEO_OFFLINE_ENABLE_VF_VECEVEN   0
+#define ISP_VIDEO_OFFLINE_ENABLE_SC           1
+#define ISP_VIDEO_OFFLINE_ENABLE_S3A          1
+#define ISP_VIDEO_OFFLINE_ENABLE_SDIS         1
+#define ISP_VIDEO_OFFLINE_ENABLE_DVS_ENVELOPE 0
+#define ISP_VIDEO_OFFLINE_ENABLE_UDS          0
+#define ISP_VIDEO_OFFLINE_ENABLE_DS           0
+#define ISP_VIDEO_OFFLINE_ENABLE_FPNR         0
+#define ISP_VIDEO_OFFLINE_OUTPUT_NUM_CHUNKS   1
+#define ISP_VIDEO_OFFLINE_DUMMY_BUF_VECTORS   0
+#define ISP_VIDEO_OFFLINE_LEFT_CROPPING       0
+#define ISP_VIDEO_OFFLINE_TOP_CROPPING        8
+#define ISP_VIDEO_OFFLINE_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_VIDEO_OFFLINE_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_VIDEO_OFFLINE_MAX_OUTPUT_WIDTH    1920
+#define ISP_VIDEO_OFFLINE_MAX_OUTPUT_HEIGHT   1080
+#define ISP_VIDEO_OFFLINE_MIN_OUTPUT_WIDTH    SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_VIDEO_OFFLINE_MIN_OUTPUT_HEIGHT   SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_VIDEO_OFFLINE_OUTPUT_FORMATS      SH_CSS_VIDEO_OUTPUT_FORMATS
+#define ISP_VIDEO_OFFLINE_MAX_VF_LOG_DOWNSCALE 1
+#define ISP_VIDEO_OFFLINE_INPUT               SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_VIDEO_OFFLINE_C_SUBSAMPLING       SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_VIDEO_OFFLINE_FIXED_S3A_DECI_LOG  0
+
+/* Video Online DZ */
+#define ISP_VIDEO_DZ_BINARY_ID               SH_CSS_BINARY_ID_VIDEO_DZ
+#define ISP_VIDEO_DZ_BINARY                  isp_video_dz
+#define ISP_VIDEO_DZ_MODE                    SH_CSS_BINARY_MODE_VIDEO
+#define ISP_VIDEO_DZ_OUTPUT_NUM_CHUNKS       2
+#define ISP_VIDEO_DZ_PIPELINING              3
+#define ISP_VIDEO_DZ_MAX_DVS_ENVELOPE_WIDTH  384
+#define ISP_VIDEO_DZ_MAX_DVS_ENVELOPE_HEIGHT 216
+#define ISP_VIDEO_DZ_ENABLE_SC               1
+#define ISP_VIDEO_DZ_ENABLE_S3A              1
+#define ISP_VIDEO_DZ_ENABLE_SDIS             1
+#define ISP_VIDEO_DZ_ENABLE_DVS_ENVELOPE     1
+#define ISP_VIDEO_DZ_ENABLE_UDS              1
+#define ISP_VIDEO_DZ_ENABLE_VF_VECEVEN       1
+#define ISP_VIDEO_DZ_ENABLE_DS               0
+#define ISP_VIDEO_DZ_ENABLE_FPNR             0
+#define ISP_VIDEO_DZ_DUMMY_BUF_VECTORS       0
+#define ISP_VIDEO_DZ_LEFT_CROPPING           0
+#define ISP_VIDEO_DZ_TOP_CROPPING            0
+#define ISP_VIDEO_DZ_MAX_OUTPUT_WIDTH        1920
+#define ISP_VIDEO_DZ_MAX_OUTPUT_HEIGHT       1080
+#define ISP_VIDEO_DZ_MIN_OUTPUT_WIDTH        SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_VIDEO_DZ_MIN_OUTPUT_HEIGHT       SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_VIDEO_DZ_OUTPUT_FORMATS          SH_CSS_VIDEO_OUTPUT_FORMATS
+#define ISP_VIDEO_DZ_MAX_VF_LOG_DOWNSCALE    1
+#define ISP_VIDEO_DZ_INPUT                   SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_VIDEO_DZ_C_SUBSAMPLING           SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_VIDEO_DZ_FIXED_S3A_DECI_LOG      0
+
+/* Video Online DS */
+#define ISP_VIDEO_DS_BINARY_ID            SH_CSS_BINARY_ID_VIDEO_DS
+#define ISP_VIDEO_DS_BINARY               isp_video_ds
+#define ISP_VIDEO_DS_MODE                 SH_CSS_BINARY_MODE_VIDEO
+#define ISP_VIDEO_DS_OUTPUT_NUM_CHUNKS    2
+#define ISP_VIDEO_DS_DUMMY_BUF_VECTORS    2
+#define ISP_VIDEO_DS_PIPELINING           2
+#define ISP_VIDEO_DS_ENABLE_SC            1
+#define ISP_VIDEO_DS_ENABLE_S3A           1
+#define ISP_VIDEO_DS_ENABLE_SDIS          0
+#define ISP_VIDEO_DS_ENABLE_DVS_ENVELOPE  1
+#define ISP_VIDEO_DS_ENABLE_VF_VECEVEN    1
+#define ISP_VIDEO_DS_ENABLE_DS            1
+#define ISP_VIDEO_DS_ENABLE_FPNR          0
+#define ISP_VIDEO_DS_ENABLE_UDS           0
+#define ISP_VIDEO_DS_LEFT_CROPPING        0
+#define ISP_VIDEO_DS_TOP_CROPPING         8
+#define ISP_VIDEO_DS_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_VIDEO_DS_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_VIDEO_DS_MAX_OUTPUT_WIDTH     1920
+#define ISP_VIDEO_DS_MAX_OUTPUT_HEIGHT    1080
+#define ISP_VIDEO_DS_MIN_OUTPUT_WIDTH     SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_VIDEO_DS_MIN_OUTPUT_HEIGHT    SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_VIDEO_DS_OUTPUT_FORMATS       SH_CSS_VIDEO_OUTPUT_FORMATS
+#define ISP_VIDEO_DS_MAX_VF_LOG_DOWNSCALE 1
+#define ISP_VIDEO_DS_INPUT                SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_VIDEO_DS_C_SUBSAMPLING        SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_VIDEO_DS_FIXED_S3A_DECI_LOG   0
+
+/* Video Online no DZ */
+#define ISP_VIDEO_NODZ_BINARY_ID                SH_CSS_BINARY_ID_VIDEO_NODZ
+#define ISP_VIDEO_NODZ_BINARY                   isp_video_nodz
+#define ISP_VIDEO_NODZ_MODE                     SH_CSS_BINARY_MODE_VIDEO
+#define ISP_VIDEO_NODZ_PIPELINING               3
+#define ISP_VIDEO_NODZ_MAX_DVS_ENVELOPE_WIDTH   384
+#define ISP_VIDEO_NODZ_MAX_DVS_ENVELOPE_HEIGHT  216
+#define ISP_VIDEO_NODZ_ENABLE_SC                1
+#define ISP_VIDEO_NODZ_ENABLE_S3A               1
+#define ISP_VIDEO_NODZ_ENABLE_SDIS              1
+#define ISP_VIDEO_NODZ_ENABLE_DVS_ENVELOPE      1
+#define ISP_VIDEO_NODZ_ENABLE_VF_VECEVEN        1
+#define ISP_VIDEO_NODZ_ENABLE_DS                0
+#define ISP_VIDEO_NODZ_ENABLE_FPNR              0
+#define ISP_VIDEO_NODZ_ENABLE_UDS               0
+#define ISP_VIDEO_NODZ_OUTPUT_NUM_CHUNKS        2
+#define ISP_VIDEO_NODZ_DUMMY_BUF_VECTORS        0
+#define ISP_VIDEO_NODZ_LEFT_CROPPING            0
+#define ISP_VIDEO_NODZ_TOP_CROPPING             0
+#define ISP_VIDEO_NODZ_MAX_OUTPUT_WIDTH         1920
+#define ISP_VIDEO_NODZ_MAX_OUTPUT_HEIGHT        1080
+#define ISP_VIDEO_NODZ_MIN_OUTPUT_WIDTH         SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_VIDEO_NODZ_MIN_OUTPUT_HEIGHT        SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_VIDEO_NODZ_OUTPUT_FORMATS           SH_CSS_VIDEO_OUTPUT_FORMATS
+#define ISP_VIDEO_NODZ_MAX_VF_LOG_DOWNSCALE     1
+#define ISP_VIDEO_NODZ_INPUT                    SH_CSS_BINARY_INPUT_SENSOR
+#define ISP_VIDEO_NODZ_C_SUBSAMPLING            SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_VIDEO_NODZ_FIXED_S3A_DECI_LOG       0
+
+/* Viewfinder Post-processing */
+#define ISP_VF_PP_BINARY_ID             SH_CSS_BINARY_ID_VF_PP
+#define ISP_VF_PP_BINARY                isp_vf_pp
+#define ISP_VF_PP_MODE                  SH_CSS_BINARY_MODE_VF_PP
+#define ISP_VF_PP_ENABLE_DS             1
+#define ISP_VF_PP_ENABLE_FPNR           0
+#define ISP_VF_PP_ENABLE_SC             0
+#define ISP_VF_PP_ENABLE_S3A            0
+#define ISP_VF_PP_ENABLE_SDIS           0
+#define ISP_VF_PP_ENABLE_VF_VECEVEN     0
+#define ISP_VF_PP_ENABLE_UDS            0
+#define ISP_VF_PP_PIPELINING            1
+#define ISP_VF_PP_OUTPUT_NUM_CHUNKS     1
+#define ISP_VF_PP_DUMMY_BUF_VECTORS     0
+#define ISP_VF_PP_LEFT_CROPPING         0
+#define ISP_VF_PP_TOP_CROPPING          0
+#define ISP_VF_PP_ENABLE_DVS_ENVELOPE   0
+#define ISP_VF_PP_MAX_DVS_ENVELOPE_WIDTH   0
+#define ISP_VF_PP_MAX_DVS_ENVELOPE_HEIGHT  0
+#define ISP_VF_PP_MAX_OUTPUT_WIDTH         SH_CSS_MAX_VF_WIDTH
+#define ISP_VF_PP_MAX_OUTPUT_HEIGHT        SH_CSS_MAX_VF_HEIGHT
+#define ISP_VF_PP_MIN_OUTPUT_WIDTH         SH_CSS_MIN_SENSOR_WIDTH
+#define ISP_VF_PP_MIN_OUTPUT_HEIGHT        SH_CSS_MIN_SENSOR_HEIGHT
+#define ISP_VF_PP_OUTPUT_FORMATS           SH_CSS_VF_OUTPUT_FORMATS
+#define ISP_VF_PP_MAX_VF_LOG_DOWNSCALE     0
+#define ISP_VF_PP_INPUT                    SH_CSS_BINARY_INPUT_MEMORY
+#define ISP_VF_PP_C_SUBSAMPLING            SH_CSS_DEFAULT_C_SUBSAMPLING
+#define ISP_VF_PP_FIXED_S3A_DECI_LOG       0
+
+#endif /* _SH_CSS_BINARY_INFO_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_debug.c b/drivers/media/video/atomisp/css/sh_css_debug.c
new file mode 100644 (file)
index 0000000..05a4023
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_debug.h"
+#include "sh_css.h"
+#include "sh_css_hrt.h"
+#include "sh_css_internal.h"
+#include "sh_css_rx.h"
+
+static void
+print_cell_state(struct sh_css_cell_state *state, const char *cell)
+{
+       sh_css_print("%s state:\n", cell);
+       sh_css_print("  PC: 0x%x\n", state->pc);
+       sh_css_print(" Status register : 0x%x\n", state->status_register);
+       sh_css_print(" is broken:   %d\n", state->is_broken);
+       sh_css_print(" is idle:    %d\n", state->is_idle);
+       sh_css_print(" is sleeping: %d\n", state->is_sleeping);
+       sh_css_print(" is stalling: %d\n", state->is_stalling);
+}
+
+void
+sh_css_dump_isp_state(void)
+{
+       struct sh_css_cell_state state;
+       struct sh_css_isp_stall_state stall_state;
+       sh_css_hrt_isp_get_state(&state, &stall_state);
+       print_cell_state(&state, "ISP");
+       if (state.is_stalling) {
+               sh_css_print("  FIFO 0 stalled: %d\n", stall_state.fifo0);
+               sh_css_print("  FIFO 1 stalled: %d\n", stall_state.fifo1);
+               sh_css_print("  FIFO 2 stalled: %d\n", stall_state.fifo2);
+               sh_css_print("  FIFO 3 stalled: %d\n", stall_state.fifo3);
+               sh_css_print("  FIFO 4 stalled: %d\n", stall_state.fifo4);
+               sh_css_print("  FIFO 5 stalled: %d\n", stall_state.fifo5);
+               sh_css_print("  status & control stalled: %d\n",
+                               stall_state.stat_ctrl);
+               sh_css_print("  dmem stalled: %d\n", stall_state.dmem);
+               sh_css_print("  vmem stalled: %d\n", stall_state.vmem);
+               sh_css_print("  vamem1 stalled: %d\n", stall_state.vamem1);
+               sh_css_print("  vamem2 stalled: %d\n", stall_state.vamem2);
+       }
+}
+
+void
+sh_css_dump_sp_state(void)
+{
+       struct sh_css_cell_state state;
+       struct sh_css_sp_stall_state stall_state;
+       sh_css_hrt_sp_get_state(&state, &stall_state);
+       print_cell_state(&state, "SP");
+       if (state.is_stalling) {
+               sh_css_print("  if_prim_FIFO    stalled: %d\n",
+                               stall_state.fifo0);
+               sh_css_print("  if_sec_FIFO     stalled: %d\n",
+                               stall_state.fifo1);
+               sh_css_print("  str_to_mem_FIFO stalled: %d\n",
+                               stall_state.fifo2);
+               sh_css_print("  dma_FIFO       stalled: %d\n",
+                               stall_state.fifo3);
+               sh_css_print("  gdc_FIFO       stalled: %d\n",
+                               stall_state.fifo4);
+               sh_css_print("  isp_FIFO       stalled: %d\n",
+                               stall_state.fifo5);
+               sh_css_print("  gp_FIFO        stalled: %d\n",
+                               stall_state.fifo6);
+               sh_css_print("  if_prim_b_FIFO stalled: %d\n",
+                               stall_state.fifo7);
+               sh_css_print("  dmem stalled: %d\n", stall_state.dmem);
+               sh_css_print("  control master stalled: %d\n",
+                               stall_state.control_master);
+               sh_css_print("  i-cache master stalled: %d\n",
+                               stall_state.icache_master);
+       }
+}
+
+static void
+print_if_state(struct sh_css_if_state *state)
+{
+       unsigned int val;
+       sh_css_print("InputFormatter State:\n");
+       sh_css_print("  Configuration:\n");
+       sh_css_print("    Software reset:             %s\n",
+                    state->reset ? "Active" : "Not active");
+       sh_css_print("    Start line:                 %d\n", state->start_line);
+       sh_css_print("    Start column:               %d\n",
+                    state->start_column);
+       sh_css_print("    Cropped height:             %d\n",
+                    state->cropped_height);
+       sh_css_print("    Cropped width:              %d\n",
+                    state->cropped_width);
+       sh_css_print("    Vertical decimation:        %d\n",
+                    state->ver_decimation);
+       sh_css_print("    Horizontal decimation:      %d\n",
+                    state->hor_decimation);
+       sh_css_print("    Deinterleaving:             %d\n",
+                    state->deinterleaving);
+       sh_css_print("    Left padding:               %d\n",
+                    state->left_padding);
+       sh_css_print("    End-of-line offset (bytes): %d\n",
+                    state->eol_offset);
+       sh_css_print("    VMEM start address:         0x%06X\n",
+                    state->vmem_start_address);
+       sh_css_print("    VMEM end address:           0x%06X\n",
+                    state->vmem_end_address);
+       sh_css_print("    VMEM increment:             0x%06X\n",
+                    state->vmem_increment);
+       sh_css_print("    YUV 420 format:             %d\n", state->yuv420);
+       sh_css_print("    Vsync:                      Active %s\n",
+                    state->vsync_active_low ? "low" : "high");
+       sh_css_print("    Hsync:                      Active %s\n",
+                    state->hsync_active_low ? "low" : "high");
+#if 0
+       /* not supported on  css_dev */
+       sh_css_print("    Sensor stalling:            %s\n",
+                    state->allow_fifo_overflow ? "Allowed" : "Not allowed");
+#endif
+       sh_css_print("  FSM Status\n");
+       val = state->fsm_sync_status;
+       sh_css_print("    FSM Synchronization Status 0x%X: ", val);
+       if (val > 7)
+               sh_css_print("ERROR : ");
+
+       switch (val & 0x7) {
+       case 0:
+               sh_css_print("idle\n");
+               break;
+       case 1:
+               sh_css_print("request frame\n");
+               break;
+       case 2:
+               sh_css_print("request lines\n");
+               break;
+       case 3:
+               sh_css_print("request vectors\n");
+               break;
+       case 4:
+               sh_css_print("send acknowledge\n");
+               break;
+       default:
+               sh_css_print("unknown\n");
+               break;
+       }
+       sh_css_print("    FSM Synchronization Counter               %d\n",
+                    state->fsm_sync_counter);
+       val = state->fsm_crop_status;
+       sh_css_print("    FSM Crop Status                           0x%X: ",
+                    val);
+       if (val > 7)
+               sh_css_print("ERROR : ");
+       switch (val & 0x7) {
+       case 0:
+               sh_css_print("idle\n");
+               break;
+       case 1:
+               sh_css_print("wait line\n");
+               break;
+       case 2:
+               sh_css_print("crop line\n");
+               break;
+       case 3:
+               sh_css_print("crop pixel\n");
+               break;
+       case 4:
+               sh_css_print("pass pixel\n");
+               break;
+       case 5:
+               sh_css_print("pass line\n");
+               break;
+       case 6:
+               sh_css_print("lost line\n");
+               break;
+       default:
+               sh_css_print("unknown\n");
+               break;
+       }
+
+       sh_css_print("    FSM Crop Line Counter                     %d\n",
+                    state->fsm_crop_line_counter);
+       sh_css_print("    FSM Crop Pixel Counter                    %d\n",
+                    state->fsm_crop_pixel_counter);
+       sh_css_print("    FSM Deinterleaving idx buffer             %d\n",
+                    state->fsm_deinterleaving_index);
+       sh_css_print("    FSM Decimation H decimation counter       %d\n",
+                    state->fsm_dec_h_counter);
+       sh_css_print("    FSM Decimation V decimation counter       %d\n",
+                    state->fsm_dec_v_counter);
+       sh_css_print("    FSM Decimation block V decimation counter %d\n",
+                    state->fsm_dec_block_v_counter);
+
+       val = state->fsm_padding_status;
+       sh_css_print("    FSM Padding Status 0x%X: ", val);
+       if (val > 7)
+               sh_css_print("ERROR : ");
+
+       switch (val & 0x7) {
+       case 0:
+               sh_css_print("idle\n");
+               break;
+       case 1:
+               sh_css_print("left pad\n");
+               break;
+       case 2:
+               sh_css_print("write\n");
+               break;
+       case 3:
+               sh_css_print("right pad\n");
+               break;
+       case 4:
+               sh_css_print("send end of line\n");
+               break;
+       default:
+               sh_css_print("unknown\n");
+               break;
+       }
+       sh_css_print("FSM Padding element index counter             %d\n",
+                    state->fsm_padding_elem_counter);
+       sh_css_print("FSM Vector support error                      %d\n",
+                    state->fsm_vector_support_error);
+       sh_css_print("FSM Vector support buf full                   %d\n",
+                    state->fsm_vector_buffer_full);
+       sh_css_print("FSM Vector support                            %d\n",
+                    state->vector_support);
+       sh_css_print("Fifo sensor data lost                         %d\n",
+                    state->sensor_data_lost);
+}
+
+void
+sh_css_dump_if_state(void)
+{
+       struct sh_css_if_state state;
+       sh_css_hrt_if_prim_a_get_state(&state);
+       print_if_state(&state);
+       sh_css_dump_pif_isp_fifo_state();
+}
+
+void
+sh_css_dump_dma_state(void)
+{
+       struct sh_css_dma_state state;
+       int i, ch_id, num_ports = 3, num_channels = 8;
+
+       sh_css_hrt_dma_get_state(&state);
+       sh_css_print("DMA dump status:\n\t");
+       sh_css_print("FSM Command flag state:\n\t\t");
+       if (state.fsm_command_idle)
+               sh_css_print("IDLE\n\t\t");
+       if (state.fsm_command_run)
+               sh_css_print("RUN\n\t\t");
+       if (state.fsm_command_stalling)
+               sh_css_print("STALL\n\t\t");
+       if (state.fsm_command_error)
+               sh_css_print("ERROR\n\t\t");
+       ch_id = state.last_command_channel;
+       sh_css_print("last command received (0x%x) : ", state.last_command);
+       if (state.last_command == sh_css_dma_command_read)
+               sh_css_print(" Read  2D Block with settings from ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_write)
+               sh_css_print(" Write 2D Block with settings from ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_set_channel)
+               sh_css_print(" Set Channel:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_set_param)
+               sh_css_print(" Set Param:%d on Channel:%d",
+                               state.last_command_param, ch_id);
+       if (state.last_command == sh_css_dma_command_read_spec)
+               sh_css_print(" Read Specific 2D Block on ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_write_spec)
+               sh_css_print(" Write Specific 2D Block on ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_init)
+               sh_css_print(" Init 2D Block on Device A on ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_init_spec)
+               sh_css_print(" Init Specific 2D Block on ch:%d", ch_id);
+       if (state.last_command == sh_css_dma_command_reset)
+               sh_css_print(" DMA SW Reset");
+       sh_css_print("\n\t");
+       sh_css_print("DMA registers,  connection group 0\n\t");
+       sh_css_print("Cmd Fifo Command    0x%x\n\t\t", state.current_command);
+       sh_css_print("Cmd Fifo Address A  0x%x\n\t\t", state.current_addr_a);
+       sh_css_print("Cmd Fifo Address B  0x%x\n\t\t", state.current_addr_b);
+       sh_css_print("FSM Ctrl flag and state:\n\t\t\t");
+       if (state.fsm_ctrl_idle)
+               sh_css_print("IDLE -> ");
+       if (state.fsm_ctrl_run)
+               sh_css_print("RUN -> ");
+       if (state.fsm_ctrl_stalling)
+               sh_css_print("STALL -> ");
+       if (state.fsm_ctrl_error)
+               sh_css_print("ERROR -> ");
+       if (state.fsm_ctrl_state == sh_css_dma_ctrl_state_idle)
+               sh_css_print("Idle state\n\t\t");
+       if (state.fsm_ctrl_state == sh_css_dma_ctrl_state_req_rcv)
+               sh_css_print("Req Rcv state\n\t\t");
+       if (state.fsm_ctrl_state == sh_css_dma_ctrl_state_rcv)
+               sh_css_print("Rcv state\n\t\t");
+       if (state.fsm_ctrl_state == sh_css_dma_ctrl_state_rcv_req)
+               sh_css_print("Rcv Req state\n\t\t");
+       if (state.fsm_ctrl_state == sh_css_dma_ctrl_state_init)
+               sh_css_print("Init state\n\t\t");
+       sh_css_print("FSM Ctrl source dev          : %d\n\t\t",
+                       state.fsm_ctrl_source_dev);
+       sh_css_print("FSM Ctrl source addr         : 0x%x\n\t\t",
+                       state.fsm_ctrl_source_addr);
+       sh_css_print("FSM Ctrl source stride       : 0x%x\n\t\t",
+                       state.fsm_ctrl_source_stride);
+       sh_css_print("FSM Ctrl source width        : %d\n\t\t",
+                       state.fsm_ctrl_source_width);
+       sh_css_print("FSM Ctrl source height       : %d\n\t\t",
+                       state.fsm_ctrl_source_height);
+       sh_css_print("FSM Ctrl pack source dev     : %d\n\t\t",
+                       state.fsm_ctrl_pack_source_dev);
+       sh_css_print("FSM Ctrl pack dest dev       : %d\n\t\t",
+                       state.fsm_ctrl_pack_dest_dev);
+       sh_css_print("FSM Ctrl dest addr           : 0x%x\n\t\t",
+                       state.fsm_ctrl_dest_addr);
+       sh_css_print("FSM Ctrl dest stride         : 0x%x\n\t\t",
+                       state.fsm_ctrl_dest_stride);
+       sh_css_print("FSM Ctrl pack source width   : %d\n\t\t",
+                       state.fsm_ctrl_pack_source_width);
+       sh_css_print("FSM Ctrl pack dest height    : %d\n\t\t",
+                       state.fsm_ctrl_pack_dest_height);
+       sh_css_print("FSM Ctrl pack dest width     : %d\n\t\t",
+                       state.fsm_ctrl_pack_dest_width);
+       sh_css_print("FSM Ctrl pack source elems   : %d\n\t\t",
+                       state.fsm_ctrl_pack_source_elems);
+       sh_css_print("FSM Ctrl pack dest elems     : %d\n\t\t",
+                       state.fsm_ctrl_pack_dest_elems);
+       sh_css_print("FSM Ctrl pack extension      : %d\n\t\t",
+                       state.fsm_ctrl_pack_extension);
+       sh_css_print("FSM Pack flag state\t\t\t");
+       if (state.pack_idle)
+               sh_css_print("IDLE\t\t");
+       if (state.pack_run)
+               sh_css_print("RUN\t\t");
+       if (state.pack_stalling)
+               sh_css_print("STALL\t\t");
+       if (state.pack_error)
+               sh_css_print("ERROR\t\t");
+       sh_css_print("FSM Pack cnt height          : %d\n\t\t",
+                       state.pack_cnt_height);
+       sh_css_print("FSM Pack src cnt width       : %d\n\t\t",
+                       state.pack_src_cnt_width);
+       sh_css_print("FSM Pack dest cnt width      : %d\n\t\t",
+                       state.pack_dest_cnt_width);
+       sh_css_print("FSM Read state\n\t\t");
+       if (state.read_state == sh_css_dma_rw_state_idle)
+               sh_css_print("\tIdle state\n\t\t");
+       if (state.read_state == sh_css_dma_rw_state_req)
+               sh_css_print("\tReq state\n\t\t");
+       if (state.read_state == sh_css_dma_rw_state_next_line)
+               sh_css_print("\tNext line\n\t\t");
+       if (state.read_state == sh_css_dma_rw_state_unlock_channel)
+               sh_css_print("\tUnlock channel\n\t\t");
+       sh_css_print("FSM Read cnt height          : %d\n\t\t",
+                       state.read_cnt_height);
+       sh_css_print("FSM Read cnt width           : %d\n\t\t",
+                       state.read_cnt_width);
+       sh_css_print("FSM Write state\n\t\t\t");
+       if (state.write_state == sh_css_dma_rw_state_idle)
+               sh_css_print("\tIdle state\n\t\t");
+       if (state.write_state == sh_css_dma_rw_state_req)
+               sh_css_print("\tReq state\n\t\t");
+       if (state.write_state == sh_css_dma_rw_state_next_line)
+               sh_css_print("\tNext line\n\t\t");
+       if (state.write_state == sh_css_dma_rw_state_unlock_channel)
+               sh_css_print("\tUnlock channel\n\t\t");
+       sh_css_print("FSM Write height             : %d\n\t\t",
+                       state.write_height);
+       sh_css_print("FSM Write width              : %d\n\t\t",
+                       state.write_width);
+       sh_css_print("\n\t");
+       for (i = 0; i < num_ports; i++) {
+               sh_css_print("DMA device interface %d\n", i);
+               sh_css_print("\t\tDMA internal side state\n\t\t\t");
+               sh_css_print("CS: %d - We_n: %d - Run: %d - Ack: %d\n",
+                               state.port_states[i].req_cs,
+                               state.port_states[i].req_we_n,
+                               state.port_states[i].req_run,
+                               state.port_states[i].req_ack);
+               sh_css_print("\t\tMaster Output side state\n\t\t\t");
+               sh_css_print("CS: %d - We_n: %d - Run: s%d - Ack: %d\n",
+                               state.port_states[i].send_cs,
+                               state.port_states[i].send_we_n,
+                               state.port_states[i].send_run,
+                               state.port_states[i].send_ack);
+               sh_css_print("\t\tFifo state\n\t\t\t");
+               if (state.port_states[i].fifo_state ==
+                               sh_css_dma_fifo_state_will_be_full) {
+                       sh_css_print("FiFo will be full\n");
+               }
+               if (state.port_states[i].fifo_state ==
+                               sh_css_dma_fifo_state_full) {
+                       sh_css_print("Fifo Full\n");
+               }
+               if (state.port_states[i].fifo_state ==
+                               sh_css_dma_fifo_state_empty) {
+                       sh_css_print("Fifo Empty\n");
+               }
+               sh_css_print("\t\tFifo counter %d\n\t",
+                               state.port_states[i].fifo_counter);
+       }
+       sh_css_print("\n\t");
+       for (i = 0; i < num_channels; i++) {
+               struct sh_css_dma_channel_state *ch;
+               ch = &(state.channel_states[i]);
+               sh_css_print("DMA channel register %d\n\t\t", i);
+               sh_css_print("Connection      : %d\n\t\t", ch->connection);
+               sh_css_print("Sign extend:    : %d\n\t\t", ch->sign_extend);
+               sh_css_print("Reverse elems  : %d\n\t\t",
+                               ch->reverse_elem_order);
+               sh_css_print("Stride Dev A    : 0x%x\n\t\t", ch->stride_a);
+               sh_css_print("Elems Dev A     : %d\n\t\t", ch->elems_a);
+               sh_css_print("Cropping Dev A  : %d\n\t\t", ch->cropping_a);
+               sh_css_print("Width Dev A     : %d\n\t\t", ch->width_a);
+               sh_css_print("Stride Dev B    : 0x%x\n\t\t", ch->stride_b);
+               sh_css_print("Elems Dev B     : %d\n\t\t", ch->elems_b);
+               sh_css_print("Cropping Dev B  : %d\n\t\t", ch->cropping_b);
+               sh_css_print("Width Dev B     : %d\n\t\t", ch->width_b);
+               sh_css_print("Height          : %d\n\t", ch->height);
+       }
+       sh_css_print("\n");
+}
+
+static void
+print_fifo_channel_state(struct sh_css_fifo_channel_state *state,
+               const char *descr)
+{
+       sh_css_print("FIFO channel: %s\n", descr);
+       sh_css_print("  source valid: %d\n", state->src_valid);
+       sh_css_print("  fifo accept:  %d\n", state->fifo_accept);
+       sh_css_print("  fifo valid:   %d\n", state->fifo_valid);
+       sh_css_print("  sink accept:  %d\n", state->sink_accept);
+}
+
+void
+sh_css_dump_pif_isp_fifo_state(void)
+{
+       struct sh_css_fifo_channel_state pif_to_isp,
+                                        isp_to_pif;
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_isp_to_if_prim_a,
+                                         &isp_to_pif);
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_if_prim_a_to_isp,
+                                         &pif_to_isp);
+       print_fifo_channel_state(&pif_to_isp, "Primary IF A to ISP");
+       print_fifo_channel_state(&isp_to_pif, "ISP to Primary IF A)");
+}
+
+void
+sh_css_dump_dma_sp_fifo_state(void)
+{
+       struct sh_css_fifo_channel_state dma_to_sp,
+                                        sp_to_dma;
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_dma_to_sp,
+                                         &dma_to_sp);
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_sp_to_dma,
+                                         &sp_to_dma);
+       print_fifo_channel_state(&dma_to_sp, "DMA to SP");
+       print_fifo_channel_state(&sp_to_dma, "SP to DMA");
+}
+
+void
+sh_css_dump_dma_isp_fifo_state(void)
+{
+       struct sh_css_fifo_channel_state dma_to_isp,
+                                        isp_to_dma;
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_dma_to_isp,
+                                         &dma_to_isp);
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_isp_to_dma,
+                                         &isp_to_dma);
+       print_fifo_channel_state(&dma_to_isp, "DMA to ISP");
+       print_fifo_channel_state(&isp_to_dma, "ISP to DMA");
+}
+
+void
+sh_css_dump_isp_sp_fifo_state(void)
+{
+       struct sh_css_fifo_channel_state sp_to_isp,
+                                        isp_to_sp;
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_sp_to_isp,
+                                         &sp_to_isp);
+       sh_css_hrt_fifo_channel_get_state(sh_css_hrt_fifo_isp_to_sp,
+                                         &isp_to_sp);
+       print_fifo_channel_state(&sp_to_isp, "SP to ISP");
+       print_fifo_channel_state(&isp_to_sp, "ISP to SP");
+}
+
+void
+sh_css_dump_debug_info(void)
+{
+       sh_css_dump_rx_state();
+       sh_css_dump_if_state();
+       /* some of these are commented out because they usually don't offer
+          anything meaningful. */
+       if (0) {
+               sh_css_dump_isp_state();
+               sh_css_dump_isp_sp_fifo_state();
+       }
+       sh_css_dump_sp_state();
+       if (0) {
+               sh_css_dump_dma_isp_fifo_state();
+               sh_css_dump_dma_sp_fifo_state();
+               sh_css_dump_dma_state();
+       }
+}
+
+static void
+sh_css_binary_info_print(const struct sh_css_binary_info *info)
+{
+       sh_css_print("id = %d\n", info->id);
+       sh_css_print("mode = %d\n", info->mode);
+       sh_css_print("max_input_width = %d\n", info->max_input_width);
+       sh_css_print("min_output_width = %d\n", info->min_output_width);
+       sh_css_print("max_output_width = %d\n", info->max_output_width);
+       sh_css_print("top_cropping = %d\n", info->top_cropping);
+       sh_css_print("left_cropping = %d\n", info->left_cropping);
+       sh_css_print("xmem_addr = %p\n", info->xmem_addr);
+       sh_css_print("enable_vf_veceven = %d\n", info->enable_vf_veceven);
+       sh_css_print("enable_dis = %d\n", info->enable_dis);
+       sh_css_print("enable_uds = %d\n", info->enable_uds);
+       sh_css_print("enable ds = %d\n", info->enable_ds);
+       sh_css_print("s3atbl_use_dmem = %d\n", info->s3atbl_use_dmem);
+}
+
+void
+sh_css_binary_print(const struct sh_css_binary *bi)
+{
+       sh_css_binary_info_print(bi->info);
+       sh_css_print("input:  %dx%d, format = %d, padded width = %d\n",
+                    bi->in_frame_info.width, bi->in_frame_info.height,
+                    bi->in_frame_info.format, bi->in_frame_info.padded_width);
+       sh_css_print("internal :%dx%d, format = %d, padded width = %d\n",
+                    bi->internal_frame_info.width,
+                    bi->internal_frame_info.height,
+                    bi->internal_frame_info.format,
+                    bi->internal_frame_info.padded_width);
+       sh_css_print("out:    %dx%d, format = %d, padded width = %d\n",
+                    bi->out_frame_info.width, bi->out_frame_info.height,
+                    bi->out_frame_info.format,
+                    bi->out_frame_info.padded_width);
+       sh_css_print("vf out: %dx%d, format = %d, padded width = %d\n",
+                    bi->vf_frame_info.width, bi->vf_frame_info.height,
+                    bi->vf_frame_info.format, bi->vf_frame_info.padded_width);
+       sh_css_print("online = %d\n", bi->online);
+       sh_css_print("input_buf_vectors = %d\n", bi->input_buf_vectors);
+       sh_css_print("deci_factor_log2 = %d\n", bi->deci_factor_log2);
+       sh_css_print("vf_downscale_log2 = %d\n", bi->vf_downscale_log2);
+       sh_css_print("dis_deci_factor_log2 = %d\n", bi->dis_deci_factor_log2);
+       sh_css_print("dis hor coef num = %d\n", bi->dis_hor_coef_num_isp);
+       sh_css_print("dis ver coef num = %d\n", bi->dis_ver_coef_num_isp);
+       sh_css_print("dis hor proj num = %d\n", bi->dis_ver_proj_num_isp);
+       sh_css_print("sctbl_width_per_color = %d\n", bi->sctbl_width_per_color);
+       sh_css_print("s3atbl_width = %d\n", bi->s3atbl_width);
+       sh_css_print("s3atbl_height = %d\n", bi->s3atbl_height);
+}
+
+void
+sh_css_frame_print(const struct sh_css_frame *frame, const char *descr)
+{
+       sh_css_print("frame %s (%p):\n", descr, frame);
+       sh_css_print("  resolution    = %dx%d\n",
+                    frame->info.width, frame->info.height);
+       sh_css_print("  padded width  = %d\n", frame->info.padded_width);
+       sh_css_print("  format        = %d\n", frame->info.format);
+       sh_css_print("  is contiguous = %s\n",
+                    frame->contiguous ? "yes" : "no");
+       switch (frame->info.format) {
+       case SH_CSS_FRAME_FORMAT_NV12:
+       case SH_CSS_FRAME_FORMAT_NV16:
+       case SH_CSS_FRAME_FORMAT_NV21:
+       case SH_CSS_FRAME_FORMAT_NV61:
+               sh_css_print("  Y = %p\n", frame->planes.nv.y.data);
+               sh_css_print("  UV = %p\n", frame->planes.nv.uv.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUYV:
+       case SH_CSS_FRAME_FORMAT_UYVY:
+       case SH_CSS_FRAME_FORMAT_YUV_LINE:
+               sh_css_print("  YUYV = %p\n", frame->planes.yuyv.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_YUV420:
+       case SH_CSS_FRAME_FORMAT_YUV422:
+       case SH_CSS_FRAME_FORMAT_YUV444:
+       case SH_CSS_FRAME_FORMAT_YV12:
+       case SH_CSS_FRAME_FORMAT_YV16:
+       case SH_CSS_FRAME_FORMAT_YUV420_16:
+       case SH_CSS_FRAME_FORMAT_YUV422_16:
+               sh_css_print("  Y = %p\n", frame->planes.yuv.y.data);
+               sh_css_print("  U = %p\n", frame->planes.yuv.u.data);
+               sh_css_print("  V = %p\n", frame->planes.yuv.v.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_RAW:
+               sh_css_print("  RAW = %p\n", frame->planes.raw.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_RGBA888:
+       case SH_CSS_FRAME_FORMAT_RGB565:
+               sh_css_print("  RGB = %p\n", frame->planes.rgb.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_QPLANE6:
+               sh_css_print("  R    = %p\n", frame->planes.plane6.r.data);
+               sh_css_print("  RatB = %p\n", frame->planes.plane6.r_at_b.data);
+               sh_css_print("  Gr   = %p\n", frame->planes.plane6.gr.data);
+               sh_css_print("  Gb   = %p\n", frame->planes.plane6.gb.data);
+               sh_css_print("  B    = %p\n", frame->planes.plane6.b.data);
+               sh_css_print("  BatR = %p\n", frame->planes.plane6.b_at_r.data);
+               break;
+       case SH_CSS_FRAME_FORMAT_BINARY_8:
+               sh_css_print("  Binary data = %p\n",
+                               frame->planes.binary.data.data);
+               break;
+       default:
+               sh_css_print("  unknown frame type\n");
+               break;
+       }
+}
+
+void
+sh_css_print_sp_debug_state(const struct sh_css_sp_debug_state *state)
+{
+       int i;
+
+       sh_css_print("sp_error = 0x%x\n", state->error);
+       for (i = 0; i < 16; i++)
+               sh_css_print("sp_debug[%d] = %d\n", i, state->debug[i]);
+}
+
+void
+sh_css_dump_rx_state(void)
+{
+       unsigned int infos = 0, bits;
+       bits = sh_css_rx_get_interrupt_reg();
+       sh_css_rx_get_interrupt_info(&infos);
+
+       sh_css_print("CSI Receiver errors: (irq reg = 0x%X\n", bits);
+       if (infos & SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN)
+               sh_css_print("  buffer overrun");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_SOT)
+               sh_css_print("  start-of-transmission error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_SOT_SYNC)
+               sh_css_print("  start-of-transmission sync error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_CONTROL)
+               sh_css_print("  control error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE)
+               sh_css_print("  2 or more ECC errors");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_CRC)
+               sh_css_print("  CRC mismatch");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID)
+               sh_css_print("  unknown error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC)
+               sh_css_print("  frame sync error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_DATA)
+               sh_css_print("  frame data error");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT)
+               sh_css_print("  data timeout");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC)
+               sh_css_print("  unknown escape command entry");
+       if (infos & SH_CSS_RX_IRQ_INFO_ERR_LINE_SYNC)
+               sh_css_print("  line sync error");
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_debug.h b/drivers/media/video/atomisp/css/sh_css_debug.h
new file mode 100644 (file)
index 0000000..de4bae0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_DEBUG_H_
+#define _SH_CSS_DEBUG_H_
+
+#include "sh_css_types.h"
+
+void sh_css_dump_if_state(void);
+void sh_css_dump_isp_state(void);
+void sh_css_dump_sp_state(void);
+void sh_css_dump_dma_state(void);
+void sh_css_dump_debug_info(void);
+void sh_css_dump_dma_isp_fifo_state(void);
+void sh_css_dump_dma_sp_fifo_state(void);
+void sh_css_dump_pif_isp_fifo_state(void);
+void sh_css_dump_isp_sp_fifo_state(void);
+void sh_css_dump_rx_state(void);
+void sh_css_frame_print(const struct sh_css_frame *frame,
+                       const char *descr);
+
+#endif /* _SH_CSS_DEBUG_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_defs.h b/drivers/media/video/atomisp/css/sh_css_defs.h
new file mode 100644 (file)
index 0000000..e7b99c4
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_DEFS_H_
+#define _SH_CSS_DEFS_H_
+
+/* the max macro from the kernel only works within function context. We use
+   these macros also as global initializers (for now). for this, we need
+   the MAX macro. */
+#define MAX(a, b)        ((a) > (b) ? (a) : (b))
+#define CEIL_MUL(a, b)   (CEIL_DIV(a, b) * (b))
+#define CEIL_DIV(a, b)   ((b) ? ((a)+(b)-1)/(b) : 0)
+#define CEIL_SHIFT(a, b) (((a)+(1<<(b))-1)>>(b))
+
+/* Digital Image Stabilization */
+#define SH_CSS_DIS_DECI_FACTOR_LOG2       6
+
+/* Width of a DDR word in bytes */
+#define HIVE_ISP_DDR_WORD_BYTES           (HIVE_ISP_DDR_WORD_BITS/8)
+
+/* UV offset: 1:uv=-128...127, 0:uv=0...255 */
+#define SH_CSS_UV_OFFSET_IS_0             0
+
+/* Bits of bayer is adjusted as 13 in ISP */
+#define SH_CSS_BAYER_BITS                 13
+/* Max value of bayer data (unsigned 13bit in ISP) */
+#define SH_CSS_BAYER_MAXVAL               ((1U << SH_CSS_BAYER_BITS) - 1)
+
+#define SH_CSS_DP_GAIN_SHIFT              5
+#define SH_CSS_BNR_GAIN_SHIFT             13
+#define SH_CSS_AE_YCOEF_SHIFT             13
+#define SH_CSS_AF_FIR_SHIFT               13
+#define SH_CSS_YEE_DETAIL_GAIN_SHIFT      8  /* [u5.8] */
+#define SH_CSS_YEE_SCALE_SHIFT            8
+#define SH_CSS_TNR_COEF_SHIFT                    13
+#define SH_CSS_MACC_COEF_SHIFT            11 /* [s2.11] */
+
+#define SH_CSS_NUM_INPUT_BUF_LINES        4
+
+/* Left cropping only applicable for sufficiently large nway */
+#if ISP_VEC_NELEMS == 16
+#define SH_CSS_MAX_LEFT_CROPPING          0
+#else
+#define SH_CSS_MAX_LEFT_CROPPING          8
+#endif
+
+#define        SH_CSS_SP_MAX_WIDTH               2560
+#define SH_CSS_SP_MAX_OVERLAY_WIDTH       640
+
+/* This is the maximum grid we can handle in the ISP binaries.
+ * The host code makes sure no bigger grid is ever selected. */
+#define SH_CSS_MAX_BQ_GRID_WIDTH          80
+#define SH_CSS_MAX_BQ_GRID_HEIGHT         60
+
+/* The minimum dvs envelope is 8x8 to make sure the invalid rows/columns
+   that result from filter initialization are skipped. */
+#define SH_CSS_MIN_DVS_ENVELOPE           8
+
+/* The FPGA system (vec_nelems == 16) only supports upto 5MP */
+#if ISP_VEC_NELEMS == 16
+#define SH_CSS_MAX_SENSOR_WIDTH           2560
+#define SH_CSS_MAX_SENSOR_HEIGHT          1920
+#else
+#define SH_CSS_MAX_SENSOR_WIDTH           4608
+#define SH_CSS_MAX_SENSOR_HEIGHT          3450
+#endif
+
+#define SH_CSS_MIN_SENSOR_WIDTH           2
+#define SH_CSS_MIN_SENSOR_HEIGHT          2
+
+#define SH_CSS_MAX_VF_WIDTH               1280
+#define SH_CSS_MAX_VF_HEIGHT              960
+
+#define SH_CSS_DEFAULT_C_SUBSAMPLING      2
+
+/* We use 16 bits per coordinate component, including integer
+   and fractional bits */
+#define SH_CSS_MORPH_TABLE_GRID               ISP_VEC_NELEMS
+#define SH_CSS_MORPH_TABLE_ELEM_BYTES         2
+#define SH_CSS_MORPH_TABLE_ELEMS_PER_DDR_WORD \
+       (HIVE_ISP_DDR_WORD_BYTES/SH_CSS_MORPH_TABLE_ELEM_BYTES)
+
+#define SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR   (SH_CSS_MAX_BQ_GRID_WIDTH + 1)
+#define SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR \
+       CEIL_MUL(SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS)
+
+/* Each line of this table is aligned to the maximum line width. */
+#define SH_CSS_MAX_S3ATBL_WIDTH              SH_CSS_MAX_BQ_GRID_WIDTH
+
+/* Rules: these implement logic shared between the host code and ISP firmware.
+   The ISP firmware needs these rules to be applied at pre-processor time,
+   that's why these are macros, not functions. */
+#define _ISP_BQS(num)  ((num)/2)
+#define _ISP_VECS(width) CEIL_DIV(width, ISP_VEC_NELEMS)
+
+#define ISP_BQ_GRID_WIDTH(elements_per_line, deci_factor_log2) \
+       CEIL_SHIFT(elements_per_line/2,  deci_factor_log2)
+#define ISP_BQ_GRID_HEIGHT(lines_per_frame, deci_factor_log2) \
+       CEIL_SHIFT(lines_per_frame/2,  deci_factor_log2)
+#define ISP_C_VECTORS_PER_LINE(elements_per_line) \
+       _ISP_VECS(elements_per_line/2)
+
+/* The morphing table is similar to the shading table in the sense that we
+   have 1 more value than we have cells in the grid. */
+#define _ISP_MORPH_TABLE_WIDTH(int_width) \
+       (CEIL_DIV(int_width, SH_CSS_MORPH_TABLE_GRID) + 1)
+#define _ISP_MORPH_TABLE_HEIGHT(int_height) \
+       (CEIL_DIV(int_height, SH_CSS_MORPH_TABLE_GRID) + 1)
+#define _ISP_MORPH_TABLE_ALIGNED_WIDTH(width) \
+       CEIL_MUL(_ISP_MORPH_TABLE_WIDTH(width), \
+                SH_CSS_MORPH_TABLE_ELEMS_PER_DDR_WORD)
+
+#define _ISP_SCTBL_WIDTH_PER_COLOR(input_width, deci_factor_log2) \
+       (ISP_BQ_GRID_WIDTH(input_width, deci_factor_log2) + 1)
+#define _ISP_SCTBL_HEIGHT(input_height, deci_factor_log2) \
+       (ISP_BQ_GRID_HEIGHT(input_height, deci_factor_log2) + 1)
+#define _ISP_SCTBL_ALIGNED_WIDTH_PER_COLOR(input_width, deci_factor_log2) \
+       CEIL_MUL(_ISP_SCTBL_WIDTH_PER_COLOR(input_width, deci_factor_log2), \
+                ISP_VEC_NELEMS)
+
+/* As an optimization we use DMEM to store the 3A statistics for fixed
+ * resolution primary binaries on the ASIC system (not on FPGA). */
+#define _S3ATBL_USE_DMEM(var_res)       (ISP_VEC_NELEMS != 64 || !(var_res))
+
+/* ********************************************************
+ * Statistics for Digital Image Stabilization
+ * ********************************************************/
+/* Some binaries put the vertical coefficients in DMEM instead
+   of VMEM to save VMEM. */
+#define _SDIS_VER_COEF_TBL_USE_DMEM(mode, enable_sdis) \
+       (mode == SH_CSS_BINARY_MODE_VIDEO && enable_sdis)
+
+/* SDIS Projections:
+ * Horizontal projections are calculated for each line.
+ * Vertical projections are calculated for each column.
+ * Grid cells that do not fall completely within the image are not
+ * valid. The host needs to use the bigger one for the stride but
+ * should only return the valid ones to the 3A. */
+#define __ISP_SDIS_HOR_PROJ_NUM_ISP(in_height, deci_factor_log2) \
+       CEIL_SHIFT(_ISP_BQS(in_height), deci_factor_log2)
+#define __ISP_SDIS_VER_PROJ_NUM_ISP(in_width, deci_factor_log2) \
+       CEIL_SHIFT(_ISP_BQS(in_width), deci_factor_log2)
+
+#define _ISP_SDIS_HOR_PROJ_NUM_3A(in_height, deci_factor_log2) \
+       (_ISP_BQS(in_height) >> deci_factor_log2)
+#define _ISP_SDIS_VER_PROJ_NUM_3A(in_width, deci_factor_log2) \
+       (_ISP_BQS(in_width) >> deci_factor_log2)
+
+/* SDIS Coefficients: */
+/* The ISP uses vectors to store the coefficients, so we round
+   the number of coefficients up to vectors. */
+#define __ISP_SDIS_HOR_COEF_NUM_VECS(in_width)  _ISP_VECS(_ISP_BQS(in_width))
+#define __ISP_SDIS_VER_COEF_NUM_VECS(in_height) _ISP_VECS(_ISP_BQS(in_height))
+
+/* The number of coefficients produced by the ISP */
+#define _ISP_SDIS_HOR_COEF_NUM_ISP(in_width) \
+       (__ISP_SDIS_HOR_COEF_NUM_VECS(in_width) * ISP_VEC_NELEMS)
+#define _ISP_SDIS_VER_COEF_NUM_ISP(in_height) \
+       (__ISP_SDIS_VER_COEF_NUM_VECS(in_height) * ISP_VEC_NELEMS)
+
+/* The number of coefficients used by the 3A library. This excludes
+   coefficients from grid cells that do not fall completely within the image. */
+#define _ISP_SDIS_HOR_COEF_NUM_3A(in_width, deci_factor_log2) \
+       ((_ISP_BQS(in_width) >> deci_factor_log2) << deci_factor_log2)
+#define _ISP_SDIS_VER_COEF_NUM_3A(in_height, deci_factor_log2) \
+       ((_ISP_BQS(in_height) >> deci_factor_log2) << deci_factor_log2)
+
+/* *****************************************************************
+ * Statistics for 3A (Auto Focus, Auto White Balance, Auto Exposure)
+ * *****************************************************************/
+/* if left cropping is used, 3A statistics are also cropped by 2 vectors. */
+#define _ISP_S3ATBL_WIDTH(in_width, deci_factor_log2) \
+       (_ISP_BQS(in_width) >> deci_factor_log2)
+#define _ISP_S3ATBL_HEIGHT(in_height, deci_factor_log2) \
+       (_ISP_BQS(in_height) >> deci_factor_log2)
+#define _ISP_S3A_ISP_WIDTH(in_width, left_crop) \
+       ((in_width) - ((left_crop) ? 2*ISP_VEC_NELEMS : 0))
+#define _ISP_S3ATBL_ISP_WIDTH(in_width, deci_log2, left_crop) \
+       CEIL_SHIFT(_ISP_BQS(_ISP_S3A_ISP_WIDTH(in_width, left_crop)), deci_log2)
+#define _ISP_S3ATBL_ISP_HEIGHT(in_height, deci_factor_log2) \
+       CEIL_SHIFT(_ISP_BQS(in_height), deci_factor_log2)
+#define ISP_S3ATBL_VECTORS \
+       _ISP_VECS(SH_CSS_MAX_S3ATBL_WIDTH * \
+                 (sizeof(struct sh_css_3a_output)/sizeof(int)))
+#define ISP_S3ATBL_HI_LO_STRIDE \
+       (ISP_S3ATBL_VECTORS * ISP_VEC_NELEMS)
+#define ISP_S3ATBL_HI_LO_STRIDE_BYTES \
+       (sizeof(unsigned short) * ISP_S3ATBL_HI_LO_STRIDE)
+
+/* Viewfinder support */
+#define __ISP_MAX_VF_OUTPUT_WIDTH(width, left_crop) \
+       (width - 2*ISP_VEC_NELEMS + ((left_crop) ? 2 * ISP_VEC_NELEMS : 0))
+
+/* Number of vectors per vf line is determined by the chroma width,
+ * the luma width is derived from that. That's why we have the +1. */
+#define __ISP_VF_OUTPUT_WIDTH_VECS(out_width, vf_log_downscale) \
+       (_ISP_VECS((out_width) >> ((vf_log_downscale)+1)) * 2)
+
+#define _ISP_VF_OUTPUT_WIDTH(vf_out_vecs) ((vf_out_vecs) * ISP_VEC_NELEMS)
+#define _ISP_VF_OUTPUT_HEIGHT(out_height, vf_log_ds) \
+       ((out_height) >> (vf_log_ds))
+
+#define _ISP_LOG_VECTOR_STEP(mode) \
+       ((mode) == SH_CSS_BINARY_MODE_CAPTURE_PP ? 2 : 1)
+
+/* Rules for computing the internal width. This is extremely complicated
+ * and definitely needs to be commented and explained. */
+#define _ISP_LEFT_CROP_EXTRA(left_crop) ((left_crop) > 0 ? 2*ISP_VEC_NELEMS : 0)
+
+#define __ISP_MIN_INTERNAL_WIDTH(num_chunks, pipelining, mode) \
+       ((num_chunks) * (pipelining) * (1<<_ISP_LOG_VECTOR_STEP(mode)) * \
+        ISP_VEC_NELEMS)
+#define __ISP_PADDED_OUTPUT_WIDTH(out_width, dvs_env_width, left_crop) \
+       ((out_width) + MAX(dvs_env_width, _ISP_LEFT_CROP_EXTRA(left_crop)))
+#define __ISP_CHUNK_STRIDE_ISP(mode) \
+       ((1<<_ISP_LOG_VECTOR_STEP(mode)) * ISP_VEC_NELEMS)
+#define __ISP_CHUNK_STRIDE_DDR(c_subsampling, num_chunks) \
+       ((c_subsampling) * (num_chunks) * HIVE_ISP_DDR_WORD_BYTES)
+#define __ISP_INTERNAL_WIDTH(out_width, \
+                            dvs_env_width, \
+                            left_crop, \
+                            mode, \
+                            c_subsampling, \
+                            num_chunks, \
+                            pipelining) \
+       CEIL_MUL(CEIL_MUL(MAX(__ISP_PADDED_OUTPUT_WIDTH(out_width, \
+                                                       dvs_env_width, \
+                                                       left_crop), \
+                             __ISP_MIN_INTERNAL_WIDTH(num_chunks, \
+                                                      pipelining, \
+                                                      mode) \
+                            ), \
+                         __ISP_CHUNK_STRIDE_ISP(mode) \
+                        ), \
+                __ISP_CHUNK_STRIDE_DDR(c_subsampling, num_chunks) \
+               )
+
+#define __ISP_INTERNAL_HEIGHT(out_height, dvs_env_height, top_crop) \
+       ((out_height) + (dvs_env_height) + top_crop)
+
+#define _ISP_MAX_INPUT_WIDTH(max_internal_width, enable_ds) \
+       ((enable_ds) ? SH_CSS_MAX_SENSOR_WIDTH : max_internal_width)
+
+#define _ISP_INPUT_WIDTH(internal_width, ds_input_width, enable_ds) \
+       ((enable_ds) ? (ds_input_width) : (internal_width))
+
+#define _ISP_INPUT_HEIGHT(internal_height, ds_input_height, enable_ds) \
+       ((enable_ds) ? (ds_input_height) : (internal_height))
+
+#define SH_CSS_VF_OUTPUT_FORMATS \
+       { \
+               SH_CSS_FRAME_FORMAT_NV11, \
+               SH_CSS_FRAME_FORMAT_NV12, \
+               SH_CSS_FRAME_FORMAT_NV16, \
+               SH_CSS_FRAME_FORMAT_NV21, \
+               SH_CSS_FRAME_FORMAT_NV61, \
+               SH_CSS_FRAME_FORMAT_YV12, \
+               SH_CSS_FRAME_FORMAT_YV16, \
+               SH_CSS_FRAME_FORMAT_YUV420, \
+               SH_CSS_FRAME_FORMAT_YUV420_16, \
+               SH_CSS_FRAME_FORMAT_YUV422, \
+               SH_CSS_FRAME_FORMAT_YUV422_16, \
+               SH_CSS_FRAME_FORMAT_UYVY, \
+               SH_CSS_FRAME_FORMAT_YUYV, \
+               SH_CSS_FRAME_FORMAT_RGB565, \
+               SH_CSS_FRAME_FORMAT_PLANAR_RGB888, \
+               SH_CSS_FRAME_FORMAT_RGBA888 \
+       }
+
+#define SH_CSS_VIDEO_OUTPUT_FORMATS \
+       { \
+               SH_CSS_FRAME_FORMAT_NV11, \
+               SH_CSS_FRAME_FORMAT_NV12, \
+               SH_CSS_FRAME_FORMAT_NV16, \
+               SH_CSS_FRAME_FORMAT_NV21, \
+               SH_CSS_FRAME_FORMAT_NV61, \
+               SH_CSS_FRAME_FORMAT_YV12, \
+               SH_CSS_FRAME_FORMAT_YV16, \
+               SH_CSS_FRAME_FORMAT_YUV420, \
+               SH_CSS_FRAME_FORMAT_YUV420_16, \
+               SH_CSS_FRAME_FORMAT_YUV422, \
+               SH_CSS_FRAME_FORMAT_YUV422_16, \
+               SH_CSS_FRAME_FORMAT_UYVY, \
+               SH_CSS_FRAME_FORMAT_YUYV \
+       }
+
+#define SH_CSS_CAPTURE_OUTPUT_FORMATS \
+       { \
+               SH_CSS_FRAME_FORMAT_NV12, \
+               SH_CSS_FRAME_FORMAT_NV16, \
+               SH_CSS_FRAME_FORMAT_NV21, \
+               SH_CSS_FRAME_FORMAT_NV61, \
+               SH_CSS_FRAME_FORMAT_YV12, \
+               SH_CSS_FRAME_FORMAT_YV16, \
+               SH_CSS_FRAME_FORMAT_YUV420, \
+               SH_CSS_FRAME_FORMAT_YUV420_16, \
+               SH_CSS_FRAME_FORMAT_YUV422, \
+               SH_CSS_FRAME_FORMAT_YUV422_16, \
+               SH_CSS_FRAME_FORMAT_UYVY, \
+               SH_CSS_FRAME_FORMAT_YUYV, \
+               SH_CSS_FRAME_FORMAT_YUV444, \
+               SH_CSS_FRAME_FORMAT_RGB565, \
+               SH_CSS_FRAME_FORMAT_PLANAR_RGB888, \
+               SH_CSS_FRAME_FORMAT_RGBA888 \
+       }
+
+/* Fixed resolution primaries only output this format */
+#define SH_CSS_FIXED_PRIMARY_FORMAT SH_CSS_FRAME_FORMAT_NV12
+
+#endif /* _SH_CSS_DEFS_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_firmware.c b/drivers/media/video/atomisp/css/sh_css_firmware.c
new file mode 100644 (file)
index 0000000..99dcd73
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_hrt.h"
+#include "sh_css_defs.h"
+#include "sh_css_firmware.h"
+#include "sh_css_internal.h"
+
+/* One extra for the sp binary */
+#define NUM_BINARIES (SH_CSS_BINARY_NUM_IDS+1)
+
+struct sh_css_sp_fw sh_css_sp_fw;
+struct sh_css_blob_info sh_css_blob_info[SH_CSS_BINARY_NUM_IDS];
+
+/*
+ * Split the loaded firmware into blobs
+ */
+
+/* Setup sp binary */
+static void
+setup_sp(struct sh_css_fw_bi_h *fw, const char *fw_data)
+{
+       const char *blob_data;
+       unsigned int blob_size;
+
+       blob_data = fw_data + fw->offset;
+       blob_size = fw->size;
+
+       sh_css_sp_fw.text        = blob_data + fw->text_source;
+       sh_css_sp_fw.text_size   = fw->text_size;
+
+       sh_css_sp_fw.data        = blob_data + fw->data_source;
+       sh_css_sp_fw.data_target = fw->data_target;
+       sh_css_sp_fw.data_size   = fw->data_size;
+
+       sh_css_sp_fw.bss_target  = fw->bss_target;
+       sh_css_sp_fw.bss_size    = fw->bss_size;
+}
+
+enum sh_css_err
+sh_css_load_firmware(const char *fw_data,
+                    unsigned int fw_size)
+{
+       int i, num_binaries;
+       struct sh_css_fw_bi_h *binaries;
+       struct sh_css_fw_bi_file_h *file_header;
+
+       file_header = (struct sh_css_fw_bi_file_h *)fw_data;
+       binaries = (struct sh_css_fw_bi_h *)(&file_header[1]);
+
+       /* some sanity checks */
+       if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h))
+               return sh_css_err_internal_error;
+
+       if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h))
+               return sh_css_err_internal_error;
+
+       num_binaries = file_header->binary_nr;
+
+       for (i = 0; i < num_binaries; i++) {
+               struct sh_css_fw_bi_h *bi = &binaries[i];
+
+               /* sanity check */
+               if (bi->size != bi->text_size + bi->data_size)
+                       return sh_css_err_internal_error;
+
+               if (bi->offset + bi->size > fw_size)
+                       return sh_css_err_internal_error;
+
+               if (bi->id == 0) {
+                       setup_sp(bi, fw_data);
+               } else if (bi->id > 0) {
+                       const unsigned char *blob = fw_data + bi->offset;
+                       sh_css_blob_info[bi->id-1].blob = blob;
+                       sh_css_blob_info[bi->id-1].size = bi->size;
+               }
+       }
+       return sh_css_success;
+}
+
+void *
+sh_css_load_blob(const unsigned char *blob, unsigned size)
+{
+       void *target_addr = hrt_isp_css_mm_alloc(size);
+       /* this will allocate memory aligned to a DDR word boundary which
+          is required for the CSS DMA to read the instructions. */
+       hrt_isp_css_mm_store(target_addr, blob, size);
+       if (SH_CSS_PREVENT_UNINIT_READS) {
+               unsigned i;
+               unsigned padded_size = CEIL_MUL(size, HIVE_ISP_DDR_WORD_BYTES);
+               for (i = 0; i < padded_size - size; i++)
+                       hrt_isp_css_mm_store_char(target_addr + size + i, 0);
+       }
+       return target_addr;
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_firmware.h b/drivers/media/video/atomisp/css/sh_css_firmware.h
new file mode 100644 (file)
index 0000000..62a4e85
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_FIRMWARE_H_
+#define _SH_CSS_FIRMWARE_H_
+
+#include "sh_css_binary.h"
+
+/* This is for the firmware loaded from user space */
+struct  sh_css_fw_bi_file_h {
+       int version;                    /* Date in the form YYYYMMDD */
+       int binary_nr;                  /* Number of binaries */
+       unsigned int h_size;            /* sizeof(struct sh_css_fw_bi_file_h) */
+};
+
+struct sh_css_fw_bi_h {
+       int          id;                /* Binary id */
+       unsigned int offset;            /* Offset in firmware file */
+       unsigned int size;              /* Size of blob */
+       unsigned int text_source;
+       unsigned int text_size;
+       unsigned int data_source;
+       unsigned int data_target;
+       unsigned int data_size;
+       unsigned int bss_target;
+       unsigned int bss_size;
+};
+
+struct sh_css_blob_info {
+       const unsigned char *blob;
+       unsigned int size;
+};
+
+extern struct sh_css_sp_fw sh_css_sp_fw;
+extern struct sh_css_blob_info sh_css_blob_info[SH_CSS_BINARY_NUM_IDS];
+
+enum sh_css_err
+sh_css_load_firmware(const char *fw_data,
+                    unsigned int fw_size);
+
+void *sh_css_load_blob(const unsigned char *blob, unsigned size);
+
+#endif /* _SH_CSS_FIRMWARE_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_hrt.c b/drivers/media/video/atomisp/css/sh_css_hrt.c
new file mode 100644 (file)
index 0000000..5a6d415
--- /dev/null
@@ -0,0 +1,1922 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_hrt.h"
+#include "sh_css_internal.h"
+#define HRT_NO_BLOB_sp
+#include "sp.map.h"
+#include "sh_css.h"
+#include "sh_css_hw.h"
+#include "sh_css_debug.h"
+
+/* The data type is used to send special cases:
+ * yuv420: odd lines (1, 3 etc) are twice as wide as even
+ *         lines (0, 2, 4 etc).
+ * rgb: for two pixels per clock, the R and B values are sent
+ *      to output_0 while only G is sent to output_1. This means
+ *      that output_1 only gets half the number of values of output_0.
+ *      WARNING: This type should also be used for Legacy YUV420.
+ * regular: used for all other data types (RAW, YUV422, etc)
+ */
+enum sh_css_mipi_data_type {
+       sh_css_mipi_data_type_regular,
+       sh_css_mipi_data_type_yuv420,
+       sh_css_mipi_data_type_yuv420_legacy,
+       sh_css_mipi_data_type_rgb,
+};
+
+/* these are unsigned long pointers such that we can simply
+ * add the register index to get the right address.
+ */
+static unsigned long *mmu_base_address         = MMU_BASE,
+                    *gdc_lut_base_address     = GDC_LUT_BASE,
+                    *dma_base_address         = DMA_BASE,
+                    *if_prim_a_base_address   = IF_PRIM_A_BASE,
+                    *if_prim_b_base_address   = IF_PRIM_B_BASE,
+                    *sp_sc_base_address       = SP_SC_BASE,
+                    *isp_sc_base_address      = ISP_SC_BASE,
+                    *str_monitor_base_address = STR_MON_BASE,
+                    *irq_ctrl_base_address    = IRQ_CTRL_BASE,
+                    *gp_fifo_base_address     = GP_FIFO_BASE;
+
+static unsigned int curr_ch_id, curr_fmt_type;
+
+void
+sh_css_sp_ctrl_store(unsigned int reg, unsigned int value)
+{
+       unsigned int addr = (unsigned int)(sp_sc_base_address + reg);
+       hrt_master_port_store_32(addr, value);
+}
+
+static unsigned long
+sh_css_sp_ctrl_load(unsigned int reg)
+{
+       unsigned int addr = (unsigned int)(sp_sc_base_address + reg);
+       return hrt_master_port_uload_32(addr);
+}
+
+static unsigned long
+sh_css_isp_ctrl_load(unsigned int reg)
+{
+       unsigned int addr = (unsigned int)(isp_sc_base_address + reg);
+       return hrt_master_port_uload_32(addr);
+}
+
+static unsigned int
+isp_ctrl_get_bit(unsigned int reg, unsigned int bit)
+{
+       unsigned long val;
+       val = sh_css_isp_ctrl_load(reg);
+       return (val & (1U << bit)) != 0;
+}
+
+void
+sh_css_sp_ctrl_set_bits(unsigned int reg, unsigned long bits)
+{
+       unsigned long val;
+       val = sh_css_sp_ctrl_load(reg);
+       val |= bits;
+       sh_css_sp_ctrl_store(reg, val);
+}
+
+static unsigned int
+sp_ctrl_get_bit(unsigned int reg, unsigned int bit)
+{
+       unsigned long val;
+       val = sh_css_sp_ctrl_load(reg);
+       return (val & (1U << bit)) != 0;
+}
+
+static void
+sh_css_sp_ctrl_reset_bits(unsigned int reg, unsigned long bits)
+{
+       unsigned long val;
+       val = sh_css_sp_ctrl_load(reg);
+       val &= ~bits;
+       sh_css_sp_ctrl_store(reg, val);
+}
+
+void
+sh_css_hrt_irq_enable_sp(bool enable)
+{
+       if (enable)
+               sh_css_sp_ctrl_set_bits(SP_IRQ_READY_REG,
+                                       1UL<<SP_IRQ_READY_BIT);
+       else
+               sh_css_sp_ctrl_reset_bits(SP_IRQ_READY_REG,
+                                         1UL<<SP_IRQ_READY_BIT);
+}
+
+void
+sh_css_hrt_irq_clear_sp(void)
+{
+       sh_css_sp_ctrl_set_bits(SP_IRQ_CLEAR_REG, 1UL<<SP_IRQ_CLEAR_BIT);
+}
+
+static int
+sh_css_cell_is_ready(unsigned long *status_reg, unsigned int ready_bit)
+{
+       unsigned long ready_reg;
+       ready_reg = hrt_master_port_uload_32((unsigned long)status_reg);
+       return (ready_reg & (1U << ready_bit)) != 0;
+}
+
+static enum sh_css_err
+sh_css_cell_wait(unsigned long *status_reg, unsigned int ready_bit)
+{
+       while (!sh_css_cell_is_ready(status_reg, ready_bit))
+               hrt_sleep();
+       return sh_css_success;
+}
+
+enum sh_css_err
+sh_css_hrt_sp_wait(void)
+{
+       return sh_css_cell_wait(sp_sc_base_address + SP_SC_REG, SP_IDLE_BIT);
+}
+
+bool
+sh_css_hrt_sp_is_idle(void)
+{
+       return sh_css_cell_is_ready(sp_sc_base_address + SP_SC_REG,
+                                   SP_IDLE_BIT);
+}
+
+bool
+sh_css_hrt_sp_is_stalling(void)
+{
+       return sh_css_cell_is_ready(sp_sc_base_address + SP_SC_REG,
+                                   SP_STALLING_BIT);
+}
+
+unsigned int
+sh_css_hrt_sp_current_pc(void)
+{
+       return sh_css_sp_ctrl_load(SP_PC_REG);
+}
+
+unsigned int
+sh_css_hrt_sp_current_msink(void)
+{
+       return sh_css_sp_ctrl_load(SP_CTRL_SINK_REG);
+}
+
+void
+sh_css_hrt_sp_start_init_dmem(void)
+{
+       sh_css_sp_start_function(sp_init_dmem);
+}
+
+void
+sh_css_hrt_sp_start_histogram(void)
+{
+       sh_css_sp_start_function(sp_gen_histogram);
+}
+
+void
+sh_css_hrt_sp_start_copy_binary_data(void)
+{
+       sh_css_sp_start_function(sp_bin_copy);
+}
+
+void
+sh_css_hrt_sp_start_copy_raw_data(void)
+{
+       sh_css_sp_start_function(sp_raw_copy);
+}
+
+void
+sh_css_hrt_sp_start_isp(void)
+{
+       sh_css_sp_start_function(sp_start_isp);
+}
+
+bool
+sh_css_hrt_isp_is_idle(void)
+{
+       return sh_css_cell_is_ready(isp_sc_base_address + ISP_SC_REG,
+                                   ISP_IDLE_BIT);
+}
+
+bool
+sh_css_hrt_isp_is_stalling(void)
+{
+       return sh_css_cell_is_ready(isp_sc_base_address + ISP_SC_REG,
+                                   ISP_STALLING_BIT);
+}
+
+unsigned int
+sh_css_hrt_isp_current_pc(void)
+{
+       return sh_css_isp_ctrl_load(ISP_PC_REG);
+}
+
+unsigned int
+sh_css_hrt_isp_current_msink(void)
+{
+       return sh_css_isp_ctrl_load(ISP_CTRL_SINK_REG);
+}
+
+unsigned int
+sh_css_hrt_isp_current_sc(void)
+{
+       return sh_css_isp_ctrl_load(ISP_SC_REG);
+}
+
+void
+sh_css_isp_ctrl_store(unsigned int reg, unsigned int value)
+{
+       unsigned int addr = (unsigned int)(isp_sc_base_address + reg);
+       hrt_master_port_store_32(addr, value);
+}
+
+void
+sh_css_hrt_sp_get_state(struct sh_css_cell_state *state,
+                       struct sh_css_sp_stall_state *stall_state)
+{
+       unsigned int sc;
+
+       sc = sh_css_sp_ctrl_load(SP_SC_REG);
+       state->pc = sh_css_sp_ctrl_load(SP_PC_REG);
+       state->status_register = sc;
+       state->is_broken   = (sc & (1U << SP_BROKEN_BIT)) != 0;
+       state->is_idle     = (sc & (1U << SP_IDLE_BIT)) != 0;
+       state->is_sleeping = (sc & (1U << SP_SLEEPING_BIT)) != 0;
+       state->is_stalling = (sc & (1U << SP_STALLING_BIT)) != 0;
+       stall_state->fifo0 =
+               sp_ctrl_get_bit(SP_FIFO0_SINK_BIT, SP_FIFO0_SINK_REG);
+       stall_state->fifo1 =
+               sp_ctrl_get_bit(SP_FIFO1_SINK_BIT, SP_FIFO1_SINK_REG);
+       stall_state->fifo2 =
+               sp_ctrl_get_bit(SP_FIFO2_SINK_BIT, SP_FIFO2_SINK_REG);
+       stall_state->fifo3 =
+               sp_ctrl_get_bit(SP_FIFO3_SINK_BIT, SP_FIFO3_SINK_REG);
+       stall_state->fifo4 =
+               sp_ctrl_get_bit(SP_FIFO4_SINK_BIT, SP_FIFO4_SINK_REG);
+       stall_state->fifo5 =
+               sp_ctrl_get_bit(SP_FIFO5_SINK_BIT, SP_FIFO5_SINK_REG);
+       stall_state->fifo6 =
+               sp_ctrl_get_bit(SP_FIFO6_SINK_BIT, SP_FIFO6_SINK_REG);
+       stall_state->fifo7 =
+               sp_ctrl_get_bit(SP_FIFO7_SINK_BIT, SP_FIFO7_SINK_REG);
+       stall_state->dmem =
+               sp_ctrl_get_bit(SP_DMEM_SINK_BIT, SP_DMEM_SINK_REG);
+       stall_state->control_master =
+               sp_ctrl_get_bit(SP_CTRL_MT_SINK_BIT, SP_CTRL_MT_SINK_REG);
+       stall_state->icache_master =
+               sp_ctrl_get_bit(SP_ICACHE_MT_SINK_BIT, SP_ICACHE_MT_SINK_REG);
+}
+
+void
+sh_css_hrt_isp_get_state(struct sh_css_cell_state *state,
+                        struct sh_css_isp_stall_state *stall_state)
+{
+       unsigned int sc;
+       sc = sh_css_isp_ctrl_load(ISP_SC_REG);
+       state->pc = sh_css_isp_ctrl_load(ISP_PC_REG);
+       state->status_register = sc;
+       state->is_broken = isp_ctrl_get_bit(ISP_SC_REG, ISP_BROKEN_BIT);
+       state->is_idle = isp_ctrl_get_bit(ISP_SC_REG, ISP_IDLE_BIT);
+       state->is_sleeping = isp_ctrl_get_bit(ISP_SC_REG, ISP_SLEEPING_BIT);
+       state->is_stalling = isp_ctrl_get_bit(ISP_SC_REG, ISP_STALLING_BIT);
+       stall_state->stat_ctrl =
+               isp_ctrl_get_bit(ISP_CTRL_SINK_BIT, ISP_CTRL_SINK_REG);
+       stall_state->dmem =
+               isp_ctrl_get_bit(ISP_DMEM_SINK_BIT, ISP_DMEM_SINK_REG);
+       stall_state->vmem =
+               isp_ctrl_get_bit(ISP_VMEM_SINK_BIT, ISP_VMEM_SINK_REG);
+       stall_state->fifo0 =
+               isp_ctrl_get_bit(ISP_FIFO0_SINK_BIT, ISP_FIFO0_SINK_REG);
+       stall_state->fifo1 =
+               isp_ctrl_get_bit(ISP_FIFO1_SINK_BIT, ISP_FIFO1_SINK_REG);
+       stall_state->fifo2 =
+               isp_ctrl_get_bit(ISP_FIFO2_SINK_BIT, ISP_FIFO2_SINK_REG);
+       stall_state->fifo3 =
+               isp_ctrl_get_bit(ISP_FIFO3_SINK_BIT, ISP_FIFO3_SINK_REG);
+       stall_state->fifo4 =
+               isp_ctrl_get_bit(ISP_FIFO4_SINK_BIT, ISP_FIFO4_SINK_REG);
+       stall_state->fifo5 =
+               isp_ctrl_get_bit(ISP_FIFO5_SINK_BIT, ISP_FIFO5_SINK_REG);
+       stall_state->vamem1 =
+               isp_ctrl_get_bit(ISP_VAMEM1_SINK_BIT, ISP_VAMEM1_SINK_REG);
+       stall_state->vamem2 =
+               isp_ctrl_get_bit(ISP_VAMEM2_SINK_BIT, ISP_VAMEM2_SINK_REG);
+}
+
+static inline unsigned long
+_sh_css_dma_get_register(unsigned int addr)
+{
+       unsigned char *dma_base = (unsigned char *)dma_base_address;
+       unsigned int bus_addr = (unsigned int)(dma_base + addr);
+       return hrt_master_port_load_32(bus_addr);
+}
+
+/* Command FSM state */
+static inline unsigned
+sh_css_dma_get_command_fsm_state(void)
+{
+       return _sh_css_dma_get_register(_hrt_dma_v1_sel_comp(0));
+}
+
+/* Get channel parameters */
+static inline unsigned
+_sh_css_dma_get_channel_parameter(int ch, int param)
+{
+       return _sh_css_dma_get_register(
+                   hrt_dma_v1_channel_parameter_register_address(ch, param));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_connection(int channel)
+{
+       return _hrt_dma_v1_get_connection(
+                       _sh_css_dma_get_channel_parameter(channel, 0));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_extension(int channel)
+{
+       return _hrt_dma_v1_get_extension(
+                       _sh_css_dma_get_channel_parameter(channel, 0));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_element_order(int channel)
+{
+       return _hrt_dma_v1_get_element_order(
+                       _sh_css_dma_get_channel_parameter(channel, 0));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_stride_A(int channel)
+{
+       return _sh_css_dma_get_channel_parameter(channel, 1);
+}
+
+static inline unsigned
+sh_css_dma_get_channel_elements_A(int channel)
+{
+       return _hrt_dma_v1_get_elements(
+                       _sh_css_dma_get_channel_parameter(channel, 2));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_cropping_A(int channel)
+{
+       return _hrt_dma_v1_get_cropping(
+                       _sh_css_dma_get_channel_parameter(channel, 2));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_width_A(int channel)
+{
+       return _sh_css_dma_get_channel_parameter(channel, 3);
+}
+
+static inline unsigned
+sh_css_dma_get_channel_stride_B(int channel)
+{
+       return _sh_css_dma_get_channel_parameter(channel, 4);
+}
+
+static inline unsigned
+sh_css_dma_get_channel_elements_B(int channel)
+{
+       return  _hrt_dma_v1_get_elements(
+                       _sh_css_dma_get_channel_parameter(channel, 5));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_cropping_B(int channel)
+{
+       return _hrt_dma_v1_get_cropping(
+                       _sh_css_dma_get_channel_parameter(channel, 5));
+}
+
+static inline unsigned
+sh_css_dma_get_channel_width_B(int channel)
+{
+       return _sh_css_dma_get_channel_parameter(channel, 6);
+}
+
+static inline unsigned
+sh_css_dma_get_channel_height(int channel)
+{
+       return _sh_css_dma_get_channel_parameter(channel, 7);
+}
+
+/* Connection group */
+
+static inline unsigned
+_sh_css_dma_get_conn_group_info(int info_id, int comp_id, int gr_id)
+{
+       return _sh_css_dma_get_register(
+                 hrt_dma_v1_conn_group_info_register_address(info_id,
+                         comp_id, gr_id));
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_command(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 0, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_address_A(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 1, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_address_B(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 2, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_state(int        gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_request_device(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(1, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_request_address(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(2, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_request_stride(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(3, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_request_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(4, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_request_height(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(5, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_request_device(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(6, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_write_device(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(7, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_write_address(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(8, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_write_stride(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(9, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_request_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(10, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_write_height(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(11, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_write_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(12, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_request_elems(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(13, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_write_elems(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(14, 3, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_control_pack_extension_and_elem_order(int
+                                                                   gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(15, 3, gr_id);
+}
+
+static inline unsigned sh_css_dma_get_conn_group_fsm_pack_state(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 4, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_pack_counter_height(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(1, 4, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_pack_request_counter_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(2, 4, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_pack_write_counter_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(3, 4, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_request_state(int        gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(0, 5, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_request_counter_height(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(1, 5, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_request_counter_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(2, 5, gr_id);
+}
+
+static inline unsigned
+sh_css_dma_get_conn_group_fsm_write_height(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(1, 6, gr_id);
+}
+
+static inline unsigned sh_css_dma_get_conn_group_fsm_write_width(int gr_id)
+{
+       return _sh_css_dma_get_conn_group_info(2, 6, gr_id);
+}
+
+/* Device Interface */
+static inline unsigned
+_sh_css_dma_get_device_interface_info(int info_id, int dev_id)
+{
+       return _sh_css_dma_get_register(
+                 hrt_dma_v1_device_interface_info_register_address(info_id,
+                         dev_id));
+}
+
+static inline unsigned
+sh_css_dma_get_device_interface_request_side_state(int dev_id)
+{
+       return _sh_css_dma_get_device_interface_info(0, dev_id);
+}
+
+static inline unsigned
+sh_css_dma_get_device_interface_send_side_state(int dev_id)
+{
+       return _sh_css_dma_get_device_interface_info(1, dev_id);
+}
+
+static inline unsigned
+sh_css_dma_get_device_interface_fifo_state(int dev_id)
+{
+       return _sh_css_dma_get_device_interface_info(2, dev_id);
+}
+
+void
+sh_css_hrt_dma_get_state(struct sh_css_dma_state *state)
+{
+       int tmp, i, num_ports = 3, num_channels = 8;
+       tmp = sh_css_dma_get_command_fsm_state();
+       state->fsm_command_idle = tmp & 0x1;
+       state->fsm_command_run = tmp & 0x2;
+       state->fsm_command_stalling = tmp & 0x4;
+       state->fsm_command_error    = tmp & 0x8;
+       state->last_command_channel = (tmp>>8 & 0xFF);
+       state->last_command_param =  (tmp>>16 & 0xF);
+       tmp = (tmp>>4) & 0xF;
+       if (tmp == 0)
+               state->last_command = sh_css_dma_command_read;
+       if (tmp == 1)
+               state->last_command = sh_css_dma_command_write;
+       if (tmp == 2)
+               state->last_command = sh_css_dma_command_set_channel;
+       if (tmp == 3)
+               state->last_command = sh_css_dma_command_set_param;
+       if (tmp == 4)
+               state->last_command = sh_css_dma_command_read_spec;
+       if (tmp == 5)
+               state->last_command = sh_css_dma_command_write_spec;
+       if (tmp == 8)
+               state->last_command = sh_css_dma_command_init;
+       if (tmp == 12)
+               state->last_command = sh_css_dma_command_init_spec;
+       if (tmp == 15)
+               state->last_command = sh_css_dma_command_reset;
+       state->current_command = sh_css_dma_get_conn_group_command(0);
+       state->current_addr_a = sh_css_dma_get_conn_group_address_A(0);
+       state->current_addr_b = sh_css_dma_get_conn_group_address_B(0);
+       tmp = sh_css_dma_get_conn_group_fsm_control_state(0);
+       state->fsm_ctrl_idle = tmp & 0x1;
+       state->fsm_ctrl_run = tmp & 0x2;
+       state->fsm_ctrl_stalling = tmp & 0x4;
+       state->fsm_ctrl_error = tmp & 0x8;
+       tmp = tmp >> 4;
+       if (tmp == 0)
+               state->fsm_ctrl_state = sh_css_dma_ctrl_state_idle;
+       if (tmp == 1)
+               state->fsm_ctrl_state = sh_css_dma_ctrl_state_req_rcv;
+       if (tmp == 2)
+               state->fsm_ctrl_state = sh_css_dma_ctrl_state_rcv;
+       if (tmp == 3)
+               state->fsm_ctrl_state = sh_css_dma_ctrl_state_rcv_req;
+       if (tmp == 4)
+               state->fsm_ctrl_state = sh_css_dma_ctrl_state_init;
+       state->fsm_ctrl_source_dev  =
+               sh_css_dma_get_conn_group_fsm_control_request_device(0);
+       state->fsm_ctrl_source_addr =
+               sh_css_dma_get_conn_group_fsm_control_request_address(0);
+       state->fsm_ctrl_source_stride =
+               sh_css_dma_get_conn_group_fsm_control_request_stride(0);
+       state->fsm_ctrl_source_width =
+               sh_css_dma_get_conn_group_fsm_control_request_width(0);
+       state->fsm_ctrl_source_height =
+               sh_css_dma_get_conn_group_fsm_control_request_height(0);
+       state->fsm_ctrl_pack_source_dev =
+           sh_css_dma_get_conn_group_fsm_control_pack_request_device(0);
+       state->fsm_ctrl_pack_dest_dev =
+               sh_css_dma_get_conn_group_fsm_control_pack_write_device(0);
+       state->fsm_ctrl_dest_addr =
+               sh_css_dma_get_conn_group_fsm_control_write_address(0);
+       state->fsm_ctrl_dest_stride =
+               sh_css_dma_get_conn_group_fsm_control_write_stride(0);
+       state->fsm_ctrl_pack_source_width =
+           sh_css_dma_get_conn_group_fsm_control_pack_request_width(0);
+       state->fsm_ctrl_pack_dest_height =
+               sh_css_dma_get_conn_group_fsm_control_pack_write_height(0);
+       state->fsm_ctrl_pack_dest_width =
+               sh_css_dma_get_conn_group_fsm_control_pack_write_width(0);
+       state->fsm_ctrl_pack_source_elems =
+               sh_css_dma_get_conn_group_fsm_control_pack_request_elems(0);
+       state->fsm_ctrl_pack_dest_elems =
+               sh_css_dma_get_conn_group_fsm_control_pack_write_elems(0);
+       state->fsm_ctrl_pack_extension =
+       sh_css_dma_get_conn_group_fsm_control_pack_extension_and_elem_order(0);
+       tmp = sh_css_dma_get_conn_group_fsm_pack_state(0);
+       state->pack_idle     = tmp & 0x1;
+       state->pack_run      = tmp & 0x2;
+       state->pack_stalling = tmp & 0x4;
+       state->pack_error    = tmp & 0x8;
+       state->pack_cnt_height =
+               sh_css_dma_get_conn_group_fsm_pack_counter_height(0);
+       state->pack_src_cnt_width =
+           sh_css_dma_get_conn_group_fsm_pack_request_counter_width(0);
+       state->pack_dest_cnt_width =
+               sh_css_dma_get_conn_group_fsm_pack_write_counter_width(0);
+       tmp = sh_css_dma_get_conn_group_fsm_request_state(0) & 0x3;
+       if (tmp == 0)
+               state->read_state = sh_css_dma_rw_state_idle;
+       if (tmp == 1)
+               state->read_state = sh_css_dma_rw_state_req;
+       if (tmp == 2)
+               state->read_state = sh_css_dma_rw_state_next_line;
+       if (tmp == 3)
+               state->read_state = sh_css_dma_rw_state_unlock_channel;
+       state->read_cnt_height =
+               sh_css_dma_get_conn_group_fsm_request_counter_height(0);
+       state->read_cnt_width =
+               sh_css_dma_get_conn_group_fsm_request_counter_width(0);
+       tmp = sh_css_dma_get_conn_group_fsm_request_state(0) & 0x3;
+       if (tmp == 0)
+               state->write_state = sh_css_dma_rw_state_idle;
+       if (tmp == 1)
+               state->write_state = sh_css_dma_rw_state_req;
+       if (tmp == 2)
+               state->write_state = sh_css_dma_rw_state_next_line;
+       if (tmp == 3)
+               state->write_state = sh_css_dma_rw_state_unlock_channel;
+       state->write_height =
+               sh_css_dma_get_conn_group_fsm_write_height(0);
+       state->write_width = sh_css_dma_get_conn_group_fsm_write_width(0);
+       for (i = 0; i < num_ports; i++) {
+               tmp =
+                   sh_css_dma_get_device_interface_request_side_state(i);
+               state->port_states[i].req_cs   = (tmp & 0x1) != 0;
+               state->port_states[i].req_we_n = (tmp & 0x2) != 0;
+               state->port_states[i].req_run  = (tmp & 0x4) != 0;
+               state->port_states[i].req_ack  = (tmp & 0x8) != 0;
+               tmp = sh_css_dma_get_device_interface_send_side_state(i);
+               state->port_states[i].send_cs   = (tmp & 0x1) != 0;
+               state->port_states[i].send_we_n = (tmp & 0x2) != 0;
+               state->port_states[i].send_run  = (tmp & 0x4) != 0;
+               state->port_states[i].send_ack  = (tmp & 0x8) != 0;
+               tmp = sh_css_dma_get_device_interface_fifo_state(i);
+               if (tmp & 0x1) {
+                       state->port_states[i].fifo_state =
+                               sh_css_dma_fifo_state_will_be_full;
+               }
+               if (tmp & 0x2) {
+                       state->port_states[i].fifo_state =
+                               sh_css_dma_fifo_state_full;
+               }
+               if (tmp & 0x4) {
+                       state->port_states[i].fifo_state =
+                               sh_css_dma_fifo_state_empty;
+               }
+               state->port_states[i].fifo_counter = tmp >> 3;
+       }
+       for (i = 0; i < num_channels; i++) {
+               state->channel_states[i].connection =
+                       sh_css_dma_get_channel_connection(i);
+               state->channel_states[i].sign_extend =
+                       sh_css_dma_get_channel_extension(i);
+               state->channel_states[i].reverse_elem_order =
+                       sh_css_dma_get_channel_element_order(i);
+               state->channel_states[i].height =
+                       sh_css_dma_get_channel_height(i);
+               state->channel_states[i].stride_a =
+                       sh_css_dma_get_channel_stride_A(i);
+               state->channel_states[i].elems_a =
+                       sh_css_dma_get_channel_elements_A(i);
+               state->channel_states[i].cropping_a =
+                       sh_css_dma_get_channel_cropping_A(i);
+               state->channel_states[i].width_a =
+                       sh_css_dma_get_channel_width_A(i);
+               state->channel_states[i].stride_b =
+                       sh_css_dma_get_channel_stride_B(i);
+               state->channel_states[i].elems_b =
+                       sh_css_dma_get_channel_elements_B(i);
+               state->channel_states[i].cropping_b =
+                       sh_css_dma_get_channel_cropping_B(i);
+               state->channel_states[i].width_b =
+                       sh_css_dma_get_channel_width_B(i);
+       }
+}
+
+static inline void
+_sh_css_gdc_set_lut_entry(unsigned int index, unsigned int val)
+{
+       hrt_master_port_store_32(gdc_lut_base_address + index, val);
+}
+
+void
+sh_css_hrt_gdc_set_lut(const int lut[4][HRT_GDC_N])
+{
+       unsigned int i, entry_0, entry_1, entry_2, entry_3,
+                    word_0, word_1, lut_offset = HRT_GDC_LUT_IDX;
+
+       for (i = 0; i < HRT_GDC_N; i++) {
+               entry_0 = lut[0][i] & HRT_GDC_BCI_COEF_MASK;
+               entry_1 = lut[1][i] & HRT_GDC_BCI_COEF_MASK;
+               entry_2 = lut[2][i] & HRT_GDC_BCI_COEF_MASK;
+               entry_3 = lut[3][i] & HRT_GDC_BCI_COEF_MASK;
+               word_0  = entry_0 | (entry_1 << HRT_GDC_BCI_COEF_BITS);
+               word_1  = entry_2 | (entry_3 << HRT_GDC_BCI_COEF_BITS);
+               _sh_css_gdc_set_lut_entry(lut_offset++, word_0);
+               _sh_css_gdc_set_lut_entry(lut_offset++, word_1);
+       }
+}
+
+static inline void
+_sh_css_mmu_set_register(unsigned int index, unsigned int value)
+{
+       hrt_master_port_store_32(mmu_base_address + index, value);
+}
+
+static inline unsigned int
+_sh_css_mmu_get_register(unsigned int index)
+{
+       return hrt_master_port_uload_32(mmu_base_address + index);
+}
+
+void
+sh_css_hrt_mmu_set_page_table_base_address(void *base_address)
+{
+       _sh_css_mmu_set_register(_HRT_MMU_PAGE_TABLE_BASE_ADDRESS_REG_IDX,
+                 (unsigned long)base_address);
+}
+
+void *
+sh_css_hrt_mmu_get_page_table_base_address(void)
+{
+       return (void *)_sh_css_mmu_get_register(
+               _HRT_MMU_PAGE_TABLE_BASE_ADDRESS_REG_IDX);
+}
+
+void
+sh_css_hrt_mmu_invalidate_cache(void)
+{
+       _sh_css_mmu_set_register(_HRT_MMU_INVALIDATE_TLB_REG_IDX, 1);
+}
+
+static inline unsigned long
+_sh_css_if_get_register(unsigned long *base, unsigned addr)
+{
+       /* offsets are in bytes, so we cast the base to char*
+          to get the right address for each register */
+       unsigned char *if_base = (unsigned char *)base;
+       unsigned int bus_addr = (unsigned int)(if_base + addr);
+       return hrt_master_port_load_32(bus_addr);
+}
+
+static inline void
+_sh_css_if_set_register(unsigned long *base, unsigned addr, unsigned long value)
+{
+       /* offsets are in bytes, so we cast the base to char*
+          to get the right address for each register */
+       unsigned char *if_base = (unsigned char *)base;
+       unsigned int bus_addr = (unsigned int)(if_base + addr);
+       hrt_master_port_store_32(bus_addr, value);
+       /* hack */
+       (void)hrt_master_port_load_32(bus_addr);
+}
+
+static inline unsigned
+sh_css_if_get_start_line(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_START_LINE_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_start_column(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_START_COLUMN_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_cropped_height(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_CROPPED_HEIGHT_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_cropped_width(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_CROPPED_WIDTH_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_vertical_decimation(unsigned long        *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_VERTICAL_DECIMATION_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_horizontal_decimation(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_HORIZONTAL_DECIMATION_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_v_deinterleaving(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_V_DEINTERLEAVING_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_h_deinterleaving(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_H_DEINTERLEAVING_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_leftpadding_width(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_LEFTPADDING_WIDTH_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_vmem_start_address(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_VMEM_START_ADDRESS_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_end_of_line_offset(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_END_OF_LINE_OFFSET_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_vmem_end_address(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_VMEM_END_ADDRESS_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_allow_fifo_overflow(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_ALLOW_FIFO_OVERFLOW_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_vmem_increment(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_VMEM_INCREMENT_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_sync_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase, HIVE_IF_FSM_SYNC_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_crop_status(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase, HIVE_IF_FSM_CROP_STATUS);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_crop_line_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_CROP_LINE_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_crop_pixel_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_CROP_PIXEL_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_deinterleaving_index(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_DEINTERLEAVING_IDX);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_dec_h_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_DECIMATION_H_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_dec_v_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_DECIMATION_V_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_dec_block_v_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_DECIMATION_BLOCK_V_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_padding_status(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_PADDING_STATUS);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_padding_elem_counter(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                                      HIVE_IF_FSM_PADDING_ELEMENT_COUNTER);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_vector_support_error(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_VECTOR_SUPPORT_ERROR);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_vector_buffer_full(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_VECTOR_SUPPORT_BUFF_FULL);
+}
+
+static inline unsigned
+sh_css_if_get_vector_support(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FSM_VECTOR_SUPPORT);
+}
+
+static inline unsigned
+sh_css_if_get_sensor_data_lost(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                       HIVE_IF_FIFO_SENSOR_DATA_LOST);
+}
+
+static inline unsigned
+sh_css_if_get_reset(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase, HIVE_IF_RESET_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_fsm_sync_status(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase, HIVE_IF_FSM_SYNC_STATUS);
+}
+
+static inline unsigned
+sh_css_if_get_yuv_420_format(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                                      HIVE_IF_YUV_420_FORMAT_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_vsynck_active_low(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                                      HIVE_IF_VSYNCK_ACTIVE_LOW_ADDRESS);
+}
+
+static inline unsigned
+sh_css_if_get_hsynck_active_low(unsigned long *ifbase)
+{
+       return _sh_css_if_get_register(ifbase,
+                                      HIVE_IF_HSYNCK_ACTIVE_LOW_ADDRESS);
+}
+
+static inline void
+sh_css_if_set_block_fifo_no_reqs(unsigned long *ifbase, bool enable)
+{
+       _sh_css_if_set_register(ifbase,
+                               HIVE_IF_BLOCK_FIFO_NO_REQ_ADDRESS,
+                               enable);
+}
+
+static void
+sh_css_if_get_state(unsigned long *ifbase, struct sh_css_if_state *state)
+{
+       state->reset = sh_css_if_get_reset(ifbase);
+       state->start_line = sh_css_if_get_start_line(ifbase);
+       state->start_column = sh_css_if_get_start_column(ifbase);
+       state->cropped_height = sh_css_if_get_cropped_height(ifbase);
+       state->cropped_width = sh_css_if_get_cropped_width(ifbase);
+       state->ver_decimation = sh_css_if_get_vertical_decimation(ifbase);
+       state->hor_decimation = sh_css_if_get_horizontal_decimation(ifbase);
+       state->deinterleaving = sh_css_if_get_h_deinterleaving(ifbase);
+       state->left_padding = sh_css_if_get_leftpadding_width(ifbase);
+       state->eol_offset = sh_css_if_get_end_of_line_offset(ifbase);
+       state->vmem_start_address = sh_css_if_get_vmem_start_address(ifbase);
+       state->vmem_end_address = sh_css_if_get_vmem_end_address(ifbase);
+       state->vmem_increment = sh_css_if_get_vmem_increment(ifbase);
+       state->yuv420 = sh_css_if_get_yuv_420_format(ifbase);
+       state->vsync_active_low = sh_css_if_get_vsynck_active_low(ifbase);
+       state->hsync_active_low = sh_css_if_get_hsynck_active_low(ifbase);
+       state->allow_fifo_overflow = sh_css_if_get_allow_fifo_overflow(ifbase);
+       state->fsm_sync_status = sh_css_if_get_fsm_sync_status(ifbase);
+       state->fsm_sync_counter = sh_css_if_get_fsm_sync_counter(ifbase);
+       state->fsm_crop_status = sh_css_if_get_fsm_crop_status(ifbase);
+       state->fsm_crop_line_counter =
+               sh_css_if_get_fsm_crop_line_counter(ifbase);
+       state->fsm_crop_pixel_counter =
+               sh_css_if_get_fsm_crop_pixel_counter(ifbase);
+       state->fsm_deinterleaving_index =
+               sh_css_if_get_fsm_deinterleaving_index(ifbase);
+       state->fsm_dec_h_counter = sh_css_if_get_fsm_dec_h_counter(ifbase);
+       state->fsm_dec_v_counter = sh_css_if_get_fsm_dec_v_counter(ifbase);
+       state->fsm_dec_block_v_counter =
+               sh_css_if_get_fsm_dec_block_v_counter(ifbase);
+       state->fsm_padding_status = sh_css_if_get_fsm_padding_status(ifbase);
+       state->fsm_padding_elem_counter =
+               sh_css_if_get_fsm_padding_elem_counter(ifbase);
+       state->fsm_vector_support_error =
+               sh_css_if_get_fsm_vector_support_error(ifbase);
+       state->fsm_vector_buffer_full =
+               sh_css_if_get_fsm_vector_buffer_full(ifbase);
+       state->vector_support = sh_css_if_get_vector_support(ifbase);
+       state->sensor_data_lost = sh_css_if_get_sensor_data_lost(ifbase);
+}
+
+unsigned int
+sh_css_hrt_if_prim_vec_align(void)
+{
+       return _HRT_IF_VEC_ALIGN(IF_PRIM);
+}
+
+void
+sh_css_hrt_if_prim_a_get_state(struct sh_css_if_state *state)
+{
+       sh_css_if_get_state(if_prim_a_base_address, state);
+}
+
+void
+sh_css_hrt_if_prim_b_get_state(struct sh_css_if_state *state)
+{
+       sh_css_if_get_state(if_prim_b_base_address, state);
+}
+
+void
+sh_css_hrt_if_reset(void)
+{
+       _sh_css_if_set_register(if_prim_a_base_address,
+                               HIVE_IF_RESET_ADDRESS, 1);
+       _sh_css_if_set_register(if_prim_b_base_address,
+                               HIVE_IF_RESET_ADDRESS, 1);
+}
+
+void
+sh_css_hrt_if_set_block_fifo_no_reqs(bool enable_prim, bool enable_prim_b)
+{
+       sh_css_if_set_block_fifo_no_reqs(if_prim_a_base_address, enable_prim);
+       sh_css_if_set_block_fifo_no_reqs(if_prim_b_base_address, enable_prim_b);
+}
+
+/* Streaming monitors */
+static inline unsigned long
+sh_css_stream_monitor_get_register(unsigned addr)
+{
+       unsigned int bus_addr = (unsigned int)(str_monitor_base_address + addr);
+       return hrt_master_port_load_32(bus_addr);
+}
+
+static inline unsigned int
+sh_css_sp_stream_monitor_get_status(void)
+{
+       return sh_css_stream_monitor_get_register(HIVE_GP_REGS_SP_STREAM_STAT);
+}
+
+static inline unsigned int
+sh_css_isp_stream_monitor_get_status(void)
+{
+       return sh_css_stream_monitor_get_register(HIVE_GP_REGS_ISP_STREAM_STAT);
+}
+
+static inline unsigned int
+sh_css_mod_stream_monitor_get_status(void)
+{
+       return sh_css_stream_monitor_get_register(HIVE_GP_REGS_MOD_STREAM_STAT);
+}
+
+/* use the following function if the stream stat word is already available.  */
+static inline unsigned int
+sh_css_get_stream_stat_valid(unsigned int stream_stat_word,
+                            unsigned int port_id)
+{
+       return ((stream_stat_word) >>
+               (((port_id * 2) + _hive_str_mon_valid_offset))) & 0x1;
+}
+
+static inline unsigned int
+sh_css_get_stream_stat_accept(unsigned int stream_stat_word,
+                             unsigned int port_id)
+{
+       return ((stream_stat_word) >>
+               (((port_id * 2) + _hive_str_mon_accept_offset))) & 0x1;
+}
+
+/* Following functions are intended for single bit lookup.
+ * If multiple valid/accept bits are required from the same words
+ * use the hrt_get_*_stream_stat_word in combination with
+ * hrt_gets_stream_valid/accept functions.
+ */
+static inline unsigned int
+sh_css_get_sp_stream_stat_valid(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_sp_stream_monitor_get_status();
+       return sh_css_get_stream_stat_valid(status, port_id);
+}
+
+static inline unsigned int
+sh_css_get_sp_stream_stat_accept(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_sp_stream_monitor_get_status();
+       return sh_css_get_stream_stat_accept(status, port_id);
+}
+
+static inline unsigned int
+sh_css_get_isp_stream_stat_valid(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_isp_stream_monitor_get_status();
+       return sh_css_get_stream_stat_valid(status, port_id);
+}
+
+static inline unsigned int
+sh_css_get_isp_stream_stat_accept(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_isp_stream_monitor_get_status();
+       return sh_css_get_stream_stat_accept(status, port_id);
+}
+
+static inline unsigned int
+sh_css_get_mod_stream_stat_valid(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_mod_stream_monitor_get_status();
+       return sh_css_get_stream_stat_valid(status, port_id);
+}
+
+static inline unsigned int
+sh_css_get_mod_stream_stat_accept(unsigned int port_id)
+{
+       unsigned int status;
+       status = sh_css_mod_stream_monitor_get_status();
+       return sh_css_get_stream_stat_accept(status, port_id);
+}
+
+bool
+sh_css_hrt_system_is_idle(void)
+{
+       bool not_idle = false;
+
+       not_idle |= !sh_css_cell_is_ready(isp_sc_base_address + ISP_SC_REG,
+                                         ISP_IDLE_BIT);
+       /* ISP to SP */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_SND_SP);
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_RCV_ISP);
+       /* SP to ISP */
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_SND_ISP);
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_RCV_SP);
+       /* IF_PRIM_A to ISP */
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_SND_PIF_A);
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_RCV_PIF_A);
+       /* ISP to IF_PRIM_A */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_SND_PIF_A);
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_RCV_PIF_A);
+       /* IF_PRIM_B to ISP */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_RCV_PIF_B);
+       /* ISP to IF_PRIM_B */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_SND_PIF_B);
+       /* DMA to SP */
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_SND_DMA);
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_RCV_DMA);
+       /* SP to DMA */
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_SND_DMA);
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_RCV_DMA);
+       /* DMA to ISP */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_RCV_DMA);
+       /* ISP to DMA */
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_SND_DMA);
+       /* GDC to SP/ISP */
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_SND_GDC);
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_RCV_GDC);
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_RCV_GDC);
+       /* SP/ISP to GDC */
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_SND_GDC);
+       not_idle |=
+           sh_css_get_isp_stream_stat_valid(ISP_STR_MON_PORT_SND_GDC);
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_RCV_GDC);
+       /* Stream2Mem to SP */
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_SND_MC);
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_RCV_MC);
+       /* SP to Stream2Mem */
+       not_idle |=
+           sh_css_get_sp_stream_stat_valid(SP_STR_MON_PORT_SND_MC);
+       not_idle |=
+           sh_css_get_mod_stream_stat_valid(MOD_STR_MON_PORT_RCV_MC);
+       return !not_idle;
+}
+
+void
+sh_css_hrt_fifo_channel_get_state(enum sh_css_fifo_channel channel,
+                                 struct sh_css_fifo_channel_state *state)
+{
+       switch (channel) {
+       case sh_css_hrt_fifo_isp_to_sp:
+               state->src_valid   = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_SND_SP);
+               state->fifo_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_SND_SP);
+               state->fifo_valid  = sh_css_get_sp_stream_stat_valid(
+                                       SP_STR_MON_PORT_RCV_ISP);
+               state->sink_accept = sh_css_get_sp_stream_stat_accept(
+                                       SP_STR_MON_PORT_RCV_ISP);
+               break;
+       case sh_css_hrt_fifo_sp_to_isp:
+               state->src_valid   = sh_css_get_sp_stream_stat_valid(
+                                       SP_STR_MON_PORT_SND_ISP);
+               state->fifo_accept = sh_css_get_sp_stream_stat_accept(
+                                       SP_STR_MON_PORT_SND_ISP);
+               state->fifo_valid  = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_RCV_SP);
+               state->sink_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_RCV_SP);
+               break;
+       case sh_css_hrt_fifo_isp_to_if_prim_a:
+               state->src_valid   = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_SND_PIF_A);
+               state->fifo_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_SND_PIF_A);
+               state->fifo_valid  = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_RCV_PIF_A);
+               state->sink_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_RCV_PIF_A);
+               break;
+       case sh_css_hrt_fifo_if_prim_a_to_isp:
+               state->src_valid   = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_SND_PIF_A);
+               state->fifo_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_SND_PIF_A);
+               state->fifo_valid  = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_RCV_PIF_A);
+               state->sink_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_RCV_PIF_A);
+               break;
+       case sh_css_hrt_fifo_isp_to_if_prim_b:
+               state->src_valid   = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_SND_PIF_B);
+               state->fifo_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_SND_PIF_B);
+               state->fifo_valid  = false; /* no monitor connected */
+               state->sink_accept = false; /* no monitor connected */
+               break;
+       case sh_css_hrt_fifo_if_prim_b_to_isp:
+               state->src_valid   = false; /* no monitor connected */
+               state->fifo_accept = false; /* no monitor connected */
+               state->fifo_valid  = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_RCV_PIF_B);
+               state->sink_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_RCV_PIF_B);
+               break;
+       case sh_css_hrt_fifo_isp_to_dma:
+               state->src_valid   = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_SND_DMA);
+               state->fifo_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_SND_DMA);
+               state->fifo_valid  = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_RCV_DMA);
+               state->sink_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_RCV_DMA);
+               break;
+       case sh_css_hrt_fifo_dma_to_isp:
+               state->src_valid   = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_SND_DMA);
+               state->fifo_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_SND_DMA);
+               state->fifo_valid  = sh_css_get_isp_stream_stat_valid(
+                                       ISP_STR_MON_PORT_RCV_DMA);
+               state->sink_accept = sh_css_get_isp_stream_stat_accept(
+                                       ISP_STR_MON_PORT_RCV_DMA);
+               break;
+       case sh_css_hrt_fifo_sp_to_dma:
+               state->src_valid   = sh_css_get_sp_stream_stat_valid(
+                                       SP_STR_MON_PORT_SND_DMA);
+               state->fifo_accept = sh_css_get_sp_stream_stat_accept(
+                                       SP_STR_MON_PORT_SND_DMA);
+               state->fifo_valid  = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_RCV_DMA);
+               state->sink_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_RCV_DMA);
+               break;
+       case sh_css_hrt_fifo_dma_to_sp:
+               state->src_valid   = sh_css_get_mod_stream_stat_valid(
+                                       MOD_STR_MON_PORT_SND_DMA);
+               state->fifo_accept = sh_css_get_mod_stream_stat_accept(
+                                       MOD_STR_MON_PORT_SND_DMA);
+               state->fifo_valid  = sh_css_get_sp_stream_stat_valid(
+                                       SP_STR_MON_PORT_RCV_DMA);
+               state->sink_accept = sh_css_get_sp_stream_stat_accept(
+                                       SP_STR_MON_PORT_RCV_DMA);
+               break;
+       }
+}
+
+static inline unsigned long
+_sh_css_irq_get_reg(unsigned addr)
+{
+       unsigned int bus_addr = (unsigned int)(irq_ctrl_base_address + addr);
+       return hrt_master_port_load_32(bus_addr);
+}
+
+static inline void
+_sh_css_irq_set_reg(unsigned addr, unsigned long value)
+{
+       hrt_master_port_store_32(irq_ctrl_base_address + addr, value);
+       /* workaround: without this read, the write sometimes does not
+          get propagated into the register. This being investigated by
+          Jozef. */
+#ifndef HRT_CSIM
+       /* todo: make this register readable in hss model */
+       (void)hrt_master_port_load_32(irq_ctrl_base_address + addr);
+#else
+       /* Lex: write needs to be processed by IRQ controller.
+          Therefore, we need a context switch to let it do this.
+          The asic system has a bus with delay, so that will do this
+          context switch. The fpga system, however, does not have a bus delay.
+          Jozef to find a clean sync mechanism.
+        */
+       hrt_sleep();
+#endif
+}
+
+/* set register */
+static inline void
+sh_css_irq_set_edge_reg(unsigned long val)
+{
+       _sh_css_irq_set_reg(_HRT_IRQ_CONTROLLER_EDGE_REG_IDX, val);
+}
+
+static inline void
+sh_css_irq_set_mask_reg(unsigned long val)
+{
+       _sh_css_irq_set_reg(_HRT_IRQ_CONTROLLER_MASK_REG_IDX, val);
+}
+
+static inline void
+sh_css_irq_clear_status_reg(unsigned long val)
+{
+       _sh_css_irq_set_reg(_HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, val);
+}
+
+static inline void
+sh_css_irq_set_enable_reg(unsigned long val)
+{
+       _sh_css_irq_set_reg(_HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, val);
+}
+
+static inline void
+sh_css_irq_set_edge_not_pulse_reg(unsigned long val)
+{
+       _sh_css_irq_set_reg(_HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX, val);
+}
+
+static inline unsigned
+sh_css_irq_get_edge_reg(void)
+{
+       return _sh_css_irq_get_reg(_HRT_IRQ_CONTROLLER_EDGE_REG_IDX);
+}
+
+static inline unsigned
+sh_css_irq_get_mask_reg(void)
+{
+       return _sh_css_irq_get_reg(_HRT_IRQ_CONTROLLER_MASK_REG_IDX);
+}
+
+static inline unsigned
+sh_css_irq_get_status_reg(void)
+{
+       return _sh_css_irq_get_reg(_HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
+}
+
+static inline unsigned
+sh_css_irq_get_enable_reg(void)
+{
+       return _sh_css_irq_get_reg(_HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
+}
+
+static inline unsigned
+sh_css_irq_get_edge_not_pulse_reg(void)
+{
+       return _sh_css_irq_get_reg(_HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX);
+}
+
+void
+sh_css_hrt_irq_clear_all(void)
+{
+       sh_css_irq_clear_status_reg(0xFFFFFFFF);
+}
+
+void
+sh_css_hrt_irq_enable(enum hrt_isp_css_irq irq_id,
+                     bool rising_edge_in,
+                     bool edge_not_pulse_out)
+{
+       unsigned int mask = sh_css_irq_get_mask_reg();
+       unsigned int enable = sh_css_irq_get_enable_reg();
+       unsigned int edge_in = sh_css_irq_get_edge_reg();
+       unsigned int edge_out = sh_css_irq_get_edge_not_pulse_reg();
+       unsigned int me = 1u << irq_id;
+
+       mask |= me;
+       enable |= me;
+       if (rising_edge_in)
+               edge_in |= me;
+       if (edge_not_pulse_out)
+               edge_out |= me;
+
+       /* to avoid mishaps configuration must follow the following order */
+
+       /* mask this interrupt */
+       sh_css_irq_set_mask_reg(mask & ~me);
+       /* rising edge at input */
+       sh_css_irq_set_edge_reg(edge_in);
+       /* enable interrupt to output */
+       sh_css_irq_set_enable_reg(enable);
+       /* output is given as edge, not pulse */
+       sh_css_irq_set_edge_not_pulse_reg(edge_out);
+       /* clear current irq only */
+       sh_css_irq_clear_status_reg(me);
+       /* unmask interrupt from input */
+       sh_css_irq_set_mask_reg(mask);
+}
+
+void
+sh_css_hrt_irq_disable(enum hrt_isp_css_irq irq_id)
+{
+       unsigned int mask = sh_css_irq_get_mask_reg();
+       unsigned int enable = sh_css_irq_get_enable_reg();
+       unsigned int me = 1u << irq_id;
+
+       mask &= ~me;
+       enable &= ~me;
+
+       /* enable interrupt to output */
+       sh_css_irq_set_enable_reg(enable);
+       /* unmask interrupt from input */
+       sh_css_irq_set_mask_reg(mask);
+       /* clear current irq only */
+       sh_css_irq_clear_status_reg(me);
+}
+
+enum hrt_isp_css_irq_status
+sh_css_hrt_irq_get_id(enum hrt_isp_css_irq *irq_id)
+{
+       unsigned int irq_status = sh_css_irq_get_status_reg();
+       unsigned int irq_mask = sh_css_irq_get_mask_reg();
+       unsigned int i;
+       int irq_idx_found = -1;
+       enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
+
+       /* find the first irq bit */
+       for (i = 0;
+            (i < hrt_isp_css_irq_num_irqs) && (irq_idx_found == -1);
+            i++) {
+               if (irq_status & (1u << i))
+                       irq_idx_found = i;
+       }
+       if (irq_idx_found == -1)
+               return hrt_isp_css_irq_status_error;
+
+       /* now check whether there are more bits set */
+       for (i = irq_idx_found + 1; (i < hrt_isp_css_irq_num_irqs)
+            && (status == hrt_isp_css_irq_status_success); i++) {
+               if (irq_status & (1u << i))
+                       status = hrt_isp_css_irq_status_more_irqs;
+       }
+
+       /* now we clear the irq status bit, to avoid generating a
+        * new IRQ, we must set the mask temporarily to zero.
+        */
+       sh_css_irq_set_mask_reg(0);
+       sh_css_irq_clear_status_reg(1u << irq_idx_found);
+       sh_css_irq_set_mask_reg(irq_mask);
+       if (irq_id)
+               *irq_id = (enum hrt_isp_css_irq) irq_idx_found;
+       return status;
+}
+
+/* Streaming to MIPI */
+static inline unsigned
+_sh_css_wrap_marker(unsigned marker)
+{
+       return marker |
+              (curr_ch_id << HIVE_STR_TO_MIPI_CH_ID_LSB) |
+              (curr_fmt_type << _HIVE_STR_TO_MIPI_FMT_TYPE_LSB);
+}
+
+static inline void
+_sh_css_fifo_snd(unsigned token)
+{
+       hrt_master_port_store_32(gp_fifo_base_address, token);
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_data_a(unsigned int data)
+{
+       unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
+                            (data << HIVE_STR_TO_MIPI_DATA_A_LSB);
+       _sh_css_fifo_snd(token);
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_data_b(unsigned int data)
+{
+       unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
+                            (data << _HIVE_STR_TO_MIPI_DATA_B_LSB);
+       _sh_css_fifo_snd(token);
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_data(unsigned int a, unsigned int b)
+{
+       unsigned int token = ((1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
+                             (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
+                             (a << HIVE_STR_TO_MIPI_DATA_A_LSB) |
+                             (b << _HIVE_STR_TO_MIPI_DATA_B_LSB));
+       _sh_css_fifo_snd(token);
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_sol(void)
+{
+       _sh_css_fifo_snd(_sh_css_wrap_marker(1 << HIVE_STR_TO_MIPI_SOL_BIT));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_eol(void)
+{
+       _sh_css_fifo_snd(_sh_css_wrap_marker(1 << HIVE_STR_TO_MIPI_EOL_BIT));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_sof(void)
+{
+       _sh_css_fifo_snd(_sh_css_wrap_marker(1 << HIVE_STR_TO_MIPI_SOF_BIT));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_eof(void)
+{
+       _sh_css_fifo_snd(_sh_css_wrap_marker(1 << HIVE_STR_TO_MIPI_EOF_BIT));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_ch_id(unsigned int ch_id)
+{
+       curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
+       /* we send an zero marker, this will wrap the ch_id and
+        * fmt_type automatically.
+        */
+       _sh_css_fifo_snd(_sh_css_wrap_marker(0));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_fmt_type(unsigned int fmt_type)
+{
+       curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
+       /* we send an zero marker, this will wrap the ch_id and
+        * fmt_type automatically.
+        */
+       _sh_css_fifo_snd(_sh_css_wrap_marker(0));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_ch_id_and_fmt_type(unsigned int ch_id,
+                                                unsigned int fmt_type)
+{
+       curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
+       curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
+       /* we send an zero marker, this will wrap the ch_id and
+        * fmt_type automatically.
+        */
+       _sh_css_fifo_snd(_sh_css_wrap_marker(0));
+}
+
+static inline void
+sh_css_streaming_to_mipi_send_empty_token(void)
+{
+       _sh_css_fifo_snd(_sh_css_wrap_marker(0));
+}
+
+static inline void
+sh_css_streaming_to_mipi_start_frame(unsigned int ch_id,
+                                    unsigned int fmt_type)
+{
+       sh_css_streaming_to_mipi_send_ch_id_and_fmt_type(ch_id, fmt_type);
+       sh_css_streaming_to_mipi_send_sof();
+}
+
+static void
+sh_css_streaming_to_mipi_end_frame(unsigned int marker_cycles)
+{
+       unsigned int i;
+       for (i = 0; i < marker_cycles; i++)
+               sh_css_streaming_to_mipi_send_empty_token();
+       sh_css_streaming_to_mipi_send_eof();
+}
+
+static void
+sh_css_streaming_to_mipi_send_line(unsigned short *data,
+                                  unsigned int width,
+                                  unsigned int hblank_cycles,
+                                  unsigned int marker_cycles,
+                                  unsigned int two_ppc,
+                                  enum sh_css_mipi_data_type type)
+{
+       unsigned int i, is_rgb = 0, is_legacy = 0;
+
+       if (type == sh_css_mipi_data_type_rgb)
+               is_rgb = 1;
+
+       if (type == sh_css_mipi_data_type_yuv420_legacy)
+               is_legacy = 1;
+
+       for (i = 0; i < hblank_cycles; i++)
+               sh_css_streaming_to_mipi_send_empty_token();
+       sh_css_streaming_to_mipi_send_sol();
+       for (i = 0; i < marker_cycles; i++)
+               sh_css_streaming_to_mipi_send_empty_token();
+       for (i = 0; i < width; i++, data++) {
+               /* for RGB in two_ppc, we only actually send 2 pixels per
+                * clock in the even pixels (0, 2 etc). In the other cycles,
+                * we only send 1 pixel, to data[0].
+                */
+               unsigned int send_two_pixels = two_ppc;
+               if ((is_rgb || is_legacy) && (i % 3 == 2))
+                       send_two_pixels = 0;
+               if (send_two_pixels) {
+                       if (i + 1 == width) {
+                               /* for jpg (binary) copy, this can occur
+                                * if the file contains an odd number of bytes.
+                                */
+                               sh_css_streaming_to_mipi_send_data(data[0],
+                                                                  0);
+                       } else {
+                               sh_css_streaming_to_mipi_send_data(data[0],
+                                                                  data
+                                                                  [1]);
+                       }
+                       data++;
+                       i++;
+               } else if (two_ppc && is_legacy) {
+                       sh_css_streaming_to_mipi_send_data_b(data[0]);
+               } else {
+                       sh_css_streaming_to_mipi_send_data_a(data[0]);
+               }
+#if 0 /* Disabled, this is now modeled in the config bus */
+               hrt_sleep();
+#endif
+       }
+       for (i = 0; i < hblank_cycles; i++)
+               sh_css_streaming_to_mipi_send_empty_token();
+       sh_css_streaming_to_mipi_send_eol();
+}
+
+/* Send a frame of data into the input network via the GP FIFO.
+ *  Parameters:
+ *   - data: array of 16 bit values that contains all data for the frame.
+ *   - width: width of a line in number of subpixels, for yuv420 it is the
+ *            number of Y components per line.
+ *   - height: height of the frame in number of lines.
+ *   - ch_id: channel ID.
+ *   - fmt_type: format type.
+ *   - hblank_cycles: length of horizontal blanking in cycles.
+ *   - marker_cycles: number of empty cycles after start-of-line and before
+ *                    end-of-frame.
+ *   - two_ppc: boolean, describes whether to send one or two pixels per clock
+ *              cycle. In this mode, we sent pixels N and N+1 in the same cycle,
+ *              to IF_PRIM_A and IF_PRIM_B respectively. The caller must make
+ *              sure the input data has been formatted correctly for this.
+ *              For example, for RGB formats this means that unused values
+ *              must be inserted.
+ *   - yuv420: boolean, describes whether (non-legacy) yuv420 data is used. In
+ *             this mode, the odd lines (1,3,5 etc) are half as long as the
+ *             even lines (2,4,6 etc).
+ *             Note that the first line is odd (1) and the second line is even
+ *             (2).
+ *
+ * This function does not do any reordering of pixels, the caller must make
+ * sure the data is in the righ format. Please refer to the CSS receiver
+ * documentation for details on the data formats.
+ */
+static void
+sh_css_streaming_to_mipi_send_frame(unsigned short *data,
+                                   unsigned int width,
+                                   unsigned int height,
+                                   unsigned int ch_id,
+                                   unsigned int fmt_type,
+                                   unsigned int hblank_cycles,
+                                   unsigned int marker_cycles,
+                                   unsigned int two_ppc,
+                                   enum sh_css_mipi_data_type type)
+{
+       unsigned int i;
+
+       sh_css_streaming_to_mipi_start_frame(ch_id, fmt_type);
+       for (i = 0; i < height; i++) {
+               if ((type == sh_css_mipi_data_type_yuv420) &&
+                   (i & 1) == 1) {
+                       sh_css_streaming_to_mipi_send_line(data, 2 * width,
+                                                          hblank_cycles,
+                                                          marker_cycles,
+                                                          two_ppc, type);
+                       data += 2 * width;
+               } else {
+                       sh_css_streaming_to_mipi_send_line(data, width,
+                                                          hblank_cycles,
+                                                          marker_cycles,
+                                                          two_ppc, type);
+                       data += width;
+               }
+       }
+       sh_css_streaming_to_mipi_end_frame(marker_cycles);
+}
+
+void
+sh_css_hrt_send_input_frame(unsigned short *data,
+                           unsigned int width,
+                           unsigned int height,
+                           unsigned int ch_id,
+                           enum sh_css_input_format input_format,
+                           bool two_ppc)
+{
+       unsigned int fmt_type, hblank_cycles, marker_cycles;
+       enum sh_css_mipi_data_type str_to_mipi_type;
+
+       hblank_cycles = 187;
+       marker_cycles = 6;
+       sh_css_input_format_type(input_format,
+                                SH_CSS_MIPI_COMPRESSION_NONE,
+                                &fmt_type);
+       str_to_mipi_type = sh_css_mipi_data_type_regular;
+       if (input_format == SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY) {
+               str_to_mipi_type =
+                       sh_css_mipi_data_type_yuv420_legacy;
+       } else if (input_format == SH_CSS_INPUT_FORMAT_YUV420_8 ||
+                  input_format == SH_CSS_INPUT_FORMAT_YUV420_10) {
+               str_to_mipi_type =
+                       sh_css_mipi_data_type_yuv420;
+       } else if (input_format >= SH_CSS_INPUT_FORMAT_RGB_444 &&
+                  input_format <= SH_CSS_INPUT_FORMAT_RGB_888) {
+               str_to_mipi_type =
+                       sh_css_mipi_data_type_rgb;
+       }
+       sh_css_streaming_to_mipi_send_frame(data, width, height,
+                       ch_id, fmt_type, hblank_cycles, marker_cycles,
+                       two_ppc, str_to_mipi_type);
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_hrt.h b/drivers/media/video/atomisp/css/sh_css_hrt.h
new file mode 100644 (file)
index 0000000..93b0bb2
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+/* This module provides access to the CSS hardware. This includes access to
+   local memories, registers and starting processors. */
+
+#ifndef _SH_CSS_HRT_H_
+#define _SH_CSS_HRT_H_
+
+#include <hmm/hmm.h>
+
+/* here we include some system header files that provide constants and such
+   about the system and the ISP processor. */
+#include <hive_isp_css_host_ids_hrt.h>
+#include <hive_isp_css_defs.h>
+#include <isp2300_medfield_params.h>
+#include <scalar_processor_params.h>
+#include <gdc_defs.h>
+
+/* The following files provide access to types and memory related functions
+   that contain system specific behavior. */
+#include <hive_isp_css_irq_types_hrt.h>
+#include <hive_isp_css_mm_hrt.h>
+
+#include "sh_css_types.h"
+#include "sh_css_rx.h"
+#include "sh_css_sp_start.h"
+
+enum sh_css_fifo_channel {
+       /* SP <-> ISP */
+       sh_css_hrt_fifo_isp_to_sp,
+       sh_css_hrt_fifo_sp_to_isp,
+       /* ISP <-> PRIM IF A */
+       sh_css_hrt_fifo_isp_to_if_prim_a,
+       sh_css_hrt_fifo_if_prim_a_to_isp,
+       /* ISP <-> PRIM IF B (only ISP side) */
+       sh_css_hrt_fifo_isp_to_if_prim_b,
+       sh_css_hrt_fifo_if_prim_b_to_isp,
+       /* ISP <-> DMA */
+       sh_css_hrt_fifo_isp_to_dma,
+       sh_css_hrt_fifo_dma_to_isp,
+       /* SP <-> DMA */
+       sh_css_hrt_fifo_sp_to_dma,
+       sh_css_hrt_fifo_dma_to_sp
+};
+
+enum sh_css_dma_ctrl_state {
+       sh_css_dma_ctrl_state_idle,
+       sh_css_dma_ctrl_state_req_rcv,
+       sh_css_dma_ctrl_state_rcv,
+       sh_css_dma_ctrl_state_rcv_req,
+       sh_css_dma_ctrl_state_init
+};
+
+enum sh_css_dma_command {
+       sh_css_dma_command_read,
+       sh_css_dma_command_write,
+       sh_css_dma_command_set_channel,
+       sh_css_dma_command_set_param,
+       sh_css_dma_command_read_spec,
+       sh_css_dma_command_write_spec,
+       sh_css_dma_command_init,
+       sh_css_dma_command_init_spec,
+       sh_css_dma_command_reset
+};
+
+enum sh_css_dma_rw_state {
+       sh_css_dma_rw_state_idle,
+       sh_css_dma_rw_state_req,
+       sh_css_dma_rw_state_next_line,
+       sh_css_dma_rw_state_unlock_channel
+};
+
+enum sh_css_dma_fifo_state {
+       sh_css_dma_fifo_state_will_be_full,
+       sh_css_dma_fifo_state_full,
+       sh_css_dma_fifo_state_empty
+};
+
+struct sh_css_dma_port_state {
+       bool                       req_cs;
+       bool                       req_we_n;
+       bool                       req_run;
+       bool                       req_ack;
+       bool                       send_cs;
+       bool                       send_we_n;
+       bool                       send_run;
+       bool                       send_ack;
+       enum sh_css_dma_fifo_state fifo_state;
+       int                        fifo_counter;
+};
+
+struct sh_css_dma_channel_state {
+       int  connection;
+       bool sign_extend;
+       bool reverse_elem_order;
+       int  height;
+       int  stride_a;
+       int  elems_a;
+       int  cropping_a;
+       int  width_a;
+       int  stride_b;
+       int  elems_b;
+       int  cropping_b;
+       int  width_b;
+};
+
+struct sh_css_dma_state {
+       bool                       fsm_command_idle;
+       bool                       fsm_command_run;
+       bool                       fsm_command_stalling;
+       bool                       fsm_command_error;
+       enum sh_css_dma_command    last_command;
+       int                        last_command_channel;
+       int                        last_command_param;
+       enum sh_css_dma_command    current_command;
+       int                        current_addr_a;
+       int                        current_addr_b;
+       bool                       fsm_ctrl_idle;
+       bool                       fsm_ctrl_run;
+       bool                       fsm_ctrl_stalling;
+       bool                       fsm_ctrl_error;
+       enum sh_css_dma_ctrl_state fsm_ctrl_state;
+       int                        fsm_ctrl_source_dev;
+       int                        fsm_ctrl_source_addr;
+       int                        fsm_ctrl_source_stride;
+       int                        fsm_ctrl_source_width;
+       int                        fsm_ctrl_source_height;
+       int                        fsm_ctrl_pack_source_dev;
+       int                        fsm_ctrl_pack_dest_dev;
+       int                        fsm_ctrl_dest_addr;
+       int                        fsm_ctrl_dest_stride;
+       int                        fsm_ctrl_pack_source_width;
+       int                        fsm_ctrl_pack_dest_height;
+       int                        fsm_ctrl_pack_dest_width;
+       int                        fsm_ctrl_pack_source_elems;
+       int                        fsm_ctrl_pack_dest_elems;
+       int                        fsm_ctrl_pack_extension;
+       int                        pack_idle;
+       int                        pack_run;
+       int                        pack_stalling;
+       int                        pack_error;
+       int                        pack_cnt_height;
+       int                        pack_src_cnt_width;
+       int                        pack_dest_cnt_width;
+       enum sh_css_dma_rw_state   read_state;
+       int                        read_cnt_height;
+       int                        read_cnt_width;
+       enum sh_css_dma_rw_state   write_state;
+       int                        write_height;
+       int                        write_width;
+       struct sh_css_dma_port_state    port_states[3];
+       struct sh_css_dma_channel_state channel_states[8];
+};
+
+struct sh_css_if_state {
+       int reset,
+           start_line,
+           start_column,
+           cropped_height,
+           cropped_width,
+           ver_decimation,
+           hor_decimation,
+           deinterleaving,
+           left_padding,
+           eol_offset,
+           vmem_start_address,
+           vmem_end_address,
+           vmem_increment,
+           yuv420,
+           vsync_active_low,
+           hsync_active_low,
+           allow_fifo_overflow,
+           fsm_sync_status,
+           fsm_sync_counter,
+           fsm_crop_status,
+           fsm_crop_line_counter,
+           fsm_crop_pixel_counter,
+           fsm_deinterleaving_index,
+           fsm_dec_h_counter,
+           fsm_dec_v_counter,
+           fsm_dec_block_v_counter,
+           fsm_padding_status,
+           fsm_padding_elem_counter,
+           fsm_vector_support_error,
+           fsm_vector_buffer_full,
+           vector_support,
+           sensor_data_lost;
+};
+
+struct sh_css_cell_state {
+       int    pc;
+       int    status_register;
+       bool is_broken;
+       bool is_idle;
+       bool is_sleeping;
+       bool is_stalling;
+};
+
+struct sh_css_sp_stall_state {
+       bool fifo0;
+       bool fifo1;
+       bool fifo2;
+       bool fifo3;
+       bool fifo4;
+       bool fifo5;
+       bool fifo6;
+       bool fifo7;
+       bool dmem;
+       bool control_master;
+       bool icache_master;
+};
+
+struct sh_css_isp_stall_state {
+       bool fifo0;
+       bool fifo1;
+       bool fifo2;
+       bool fifo3;
+       bool fifo4;
+       bool fifo5;
+       bool stat_ctrl;
+       bool dmem;
+       bool vmem;
+       bool vamem1;
+       bool vamem2;
+};
+
+struct sh_css_fifo_channel_state {
+       bool src_valid;
+       bool fifo_accept;
+       bool fifo_valid;
+       bool sink_accept;
+};
+
+void
+sh_css_sp_ctrl_store(unsigned int reg, unsigned int value);
+
+void
+sh_css_sp_ctrl_set_bits(unsigned int reg, unsigned long bits);
+
+/* SP access */
+void
+sh_css_hrt_sp_start_si(void);
+
+void
+sh_css_hrt_sp_start_init_dmem(void);
+
+void
+sh_css_hrt_sp_start_histogram(void);
+
+void
+sh_css_hrt_sp_start_copy_frame(void);
+
+void
+sh_css_hrt_sp_start_copy_binary_data(void);
+
+void
+sh_css_hrt_sp_start_copy_raw_data(void);
+
+void
+sh_css_hrt_sp_start_isp(void);
+
+enum sh_css_err
+sh_css_hrt_sp_wait(void);
+
+bool
+sh_css_hrt_sp_is_idle(void);
+
+bool
+sh_css_hrt_sp_is_stalling(void);
+
+unsigned int
+sh_css_hrt_sp_current_pc(void);
+
+unsigned int
+sh_css_hrt_sp_current_msink(void);
+
+void
+sh_css_hrt_sp_get_state(struct sh_css_cell_state *state,
+                       struct sh_css_sp_stall_state *stall_state);
+
+/* ISP access */
+bool
+sh_css_hrt_isp_is_idle(void);
+
+bool
+sh_css_hrt_isp_is_stalling(void);
+
+void
+sh_css_hrt_isp_get_state(struct sh_css_cell_state *state,
+                        struct sh_css_isp_stall_state *stall_state);
+
+void
+sh_css_hrt_fifo_channel_get_state(enum sh_css_fifo_channel,
+                                 struct sh_css_fifo_channel_state *state);
+
+unsigned int
+sh_css_hrt_isp_current_pc(void);
+
+void
+sh_css_isp_ctrl_store(unsigned int reg, unsigned int value);
+
+unsigned int
+sh_css_hrt_isp_current_msink(void);
+
+unsigned int
+sh_css_hrt_isp_current_sc(void);
+
+/* Input formatters */
+unsigned int
+sh_css_hrt_if_prim_vec_align(void);
+
+void
+sh_css_hrt_if_prim_a_get_state(struct sh_css_if_state *state);
+
+void
+sh_css_hrt_if_prim_b_get_state(struct sh_css_if_state *state);
+
+void
+sh_css_hrt_if_reset(void);
+
+void
+sh_css_hrt_if_set_block_fifo_no_reqs(bool enable_prim, bool enable_prim_b);
+
+bool
+sh_css_hrt_system_is_idle(void);
+
+void
+sh_css_hrt_dma_get_state(struct sh_css_dma_state *state);
+
+/* Interrupts */
+void
+sh_css_hrt_irq_enable(enum hrt_isp_css_irq irq,
+                     bool rising_edge_in,
+                     bool edge_not_pulse_out);
+
+void
+sh_css_hrt_irq_enable_sp(bool enable);
+
+void
+sh_css_hrt_irq_disable(enum hrt_isp_css_irq irq);
+
+void
+sh_css_hrt_irq_clear_all(void);
+
+enum hrt_isp_css_irq_status
+sh_css_hrt_irq_get_id(enum hrt_isp_css_irq *irq);
+
+void
+sh_css_hrt_irq_clear_sp(void);
+
+/* GDC */
+void
+sh_css_hrt_gdc_set_lut(const int data[4][HRT_GDC_N]);
+
+/* MMU */
+void
+sh_css_hrt_mmu_set_page_table_base_address(void *base_address);
+
+void *
+sh_css_hrt_mmu_get_page_table_base_address(void);
+
+void
+sh_css_hrt_mmu_invalidate_cache(void);
+
+void
+sh_css_hrt_send_input_frame(unsigned short *data,
+                           unsigned int width,
+                           unsigned int height,
+                           unsigned int ch_id,
+                           enum sh_css_input_format input_format,
+                           bool two_ppc);
+
+#endif /* _SH_CSS_HRT_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_hw.h b/drivers/media/video/atomisp/css/sh_css_hw.h
new file mode 100644 (file)
index 0000000..5b11667
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_HW_H_
+#define _SH_CSS_HW_H_
+
+#ifdef HRT_ISP_CSS_CUSTOM_HOST
+#ifndef HRT_USE_VIR_ADDRS
+#define HRT_USE_VIR_ADDRS
+#endif
+#include <hive_isp_css_custom_host_hrt.h>
+#endif
+
+#include <hrt/master_port.h>
+#include <hrt/bits.h>
+
+#include <sp_hrt.h>
+#include <irq_controller_defs.h>
+#include <if_defs.h>
+#include <dma_v1_defs.h>
+#include <gp_regs_defs.h>
+#include <mmu_defs.h>
+#include <css_receiver_ahb_defs.h>
+#include <hive_isp_css_streaming_monitors_types_hrt.h>
+#include <hive_isp_css_if_hrt.h>
+#include <hive_isp_css_streaming_to_mipi_types_hrt.h>
+
+#define MMU_BASE       ((void *)0x10250000)
+#define GDC_LUT_BASE   ((void *)0x10180000)
+#define DMA_BASE       ((void *)0x10240000)
+#define IF_PRIM_A_BASE ((void *)0x10210000)
+#define IF_PRIM_B_BASE ((void *)0x10270000)
+#define SP_DMEM_BASE   ((void *)0x10100000)
+#define SP_SC_BASE     ((void *)0x10104000)
+#define ISP_SC_BASE    ((void *)0x10020000)
+#define STR_MON_BASE   ((void *)0x10200000)
+#define IRQ_CTRL_BASE  ((void *)0x10200500)
+#define GP_FIFO_BASE   ((void *)0x10200304)
+#define CSS_RX_BASE    ((void *)0x10260000)
+
+/* SP Registers */
+#define SP_PC_REG        0x9
+#define SP_SC_REG        0x0
+#define SP_START_ADDR_REG  0x1
+#define SP_ICACHE_ADDR_REG 0x5
+#define SP_IRQ_READY_REG   0x0
+#define SP_IRQ_CLEAR_REG   0x0
+#define SP_ICACHE_INV_REG  0x0
+#define SP_CTRL_SINK_REG   0xA
+
+/* SP Register bits */
+#define SP_START_BIT       0x1
+#define SP_RUN_BIT         0x3
+#define SP_BROKEN_BIT      0x4
+#define SP_IDLE_BIT        0x5
+#define SP_STALLING_BIT    0x7
+#define SP_IRQ_CLEAR_BIT   0x8
+#define SP_IRQ_READY_BIT   0xA
+#define SP_SLEEPING_BIT    0xB
+#define SP_ICACHE_INV_BIT  0xC
+
+/* ISP Registers */
+#define ISP_PC_REG       0x5
+#define ISP_SC_REG       0x0
+#define ISP_BROKEN_BIT   0x4
+#define ISP_IDLE_BIT     0x5
+#define ISP_STALLING_BIT 0x7
+#define ISP_SLEEPING_BIT 0xB
+
+/* ISP Register bits */
+#define ISP_CTRL_SINK_BIT   0x0
+#define ISP_DMEM_SINK_BIT   0x1
+#define ISP_VMEM_SINK_BIT   0x2
+#define ISP_FIFO0_SINK_BIT  0x3
+#define ISP_FIFO1_SINK_BIT  0x4
+#define ISP_FIFO2_SINK_BIT  0x5
+#define ISP_FIFO3_SINK_BIT  0x6
+#define ISP_FIFO4_SINK_BIT  0x7
+#define ISP_FIFO5_SINK_BIT  0x8
+#define ISP_VAMEM1_SINK_BIT 0x9
+#define ISP_VAMEM2_SINK_BIT 0xA
+
+#define ISP_CTRL_SINK_REG   0x6
+#define ISP_DMEM_SINK_REG   0x6
+#define ISP_VMEM_SINK_REG   0x6
+#define ISP_FIFO0_SINK_REG  0x6
+#define ISP_FIFO1_SINK_REG  0x6
+#define ISP_FIFO2_SINK_REG  0x6
+#define ISP_FIFO3_SINK_REG  0x6
+#define ISP_FIFO4_SINK_REG  0x6
+#define ISP_FIFO5_SINK_REG  0x6
+#define ISP_VAMEM1_SINK_REG 0x6
+#define ISP_VAMEM2_SINK_REG 0x6
+
+#define SP_FIFO0_SINK_BIT     0x0
+#define SP_FIFO1_SINK_BIT     0x1
+#define SP_FIFO2_SINK_BIT     0x2
+#define SP_FIFO3_SINK_BIT     0x3
+#define SP_FIFO4_SINK_BIT     0x4
+#define SP_FIFO5_SINK_BIT     0x5
+#define SP_FIFO6_SINK_BIT     0x6
+#define SP_FIFO7_SINK_BIT     0x7
+#define SP_DMEM_SINK_BIT      0x8
+#define SP_CTRL_MT_SINK_BIT   0x9
+#define SP_ICACHE_MT_SINK_BIT 0xA
+
+#define SP_FIFO0_SINK_REG     0xA
+#define SP_FIFO1_SINK_REG     0xA
+#define SP_FIFO2_SINK_REG     0xA
+#define SP_FIFO3_SINK_REG     0xA
+#define SP_FIFO4_SINK_REG     0xA
+#define SP_FIFO5_SINK_REG     0xA
+#define SP_FIFO6_SINK_REG     0xA
+#define SP_FIFO7_SINK_REG     0xA
+#define SP_DMEM_SINK_REG      0xA
+#define SP_CTRL_MT_SINK_REG   0xA
+#define SP_ICACHE_MT_SINK_REG 0xA
+
+#endif /* _SH_CSS_HW_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_internal.h b/drivers/media/video/atomisp/css/sh_css_internal.h
new file mode 100644 (file)
index 0000000..086591e
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_INTERNAL_H_
+#define _SH_CSS_INTERNAL_H_
+
+#include "sh_css_types.h"
+#include "sh_css_binary.h"
+#include "sh_css_sp.h"
+
+#define sh_css_print(fmt, s...) \
+       do { \
+               if (sh_css_printf) { \
+                       sh_css_printf(fmt, ## s); \
+               } \
+       } while (0)
+
+/* Data structures shared with ISP */
+struct sh_css_isp_params {
+       /* FPNR (Fixed Pattern Noise Reduction) */
+       int fpn_shift;
+       int fpn_enabled;
+
+       /* OB (Optical Black) */
+       int ob_blacklevel_gr;
+       int ob_blacklevel_r;
+       int ob_blacklevel_b;
+       int ob_blacklevel_gb;
+       int obarea_start_bq;
+       int obarea_length_bq;
+       int obarea_length_bq_inverse;
+
+       /* SC (Shading Corrction) */
+       int sc_gain_shift;
+
+       /* WB (White Balance) */
+       int wb_gain_shift;
+       int wb_gain_gr;
+       int wb_gain_r;
+       int wb_gain_b;
+       int wb_gain_gb;
+
+       /* DP (Defect Pixel Correction) */
+       int dp_threshold_single_when_2adjacent_on;
+       int dp_threshold_2adjacent_when_2adjacent_on;
+       int dp_threshold_single_when_2adjacent_off;
+       int dp_threshold_2adjacent_when_2adjacent_off;
+       int dp_gain;
+
+       /* BNR (Bayer Noise Reduction) */
+       int bnr_gain_all;
+       int bnr_gain_dir;
+       int bnr_threshold_low;
+       int bnr_threshold_width_log2;
+       int bnr_threshold_width;
+       int bnr_clip;
+
+       /* S3A (3A Support): coefficients to calculate Y */
+       int ae_y_coef_r;
+       int ae_y_coef_g;
+       int ae_y_coef_b;
+
+       /* S3A (3A Support): af fir coefficients */
+       int af_fir1[7];
+       int af_fir2[7];
+
+       /* DE (Demosaic) */
+       int de_pixelnoise;
+       int de_c1_coring_threshold;
+       int de_c2_coring_threshold;
+
+       /* YNR (Y Noise Reduction), YEE (Y Edge Enhancement) */
+       int ynr_threshold;
+       int ynr_gain_all;
+       int ynr_gain_dir;
+       int ynryee_dirthreshold_s;
+       int ynryee_dirthreshold_g;
+       int ynryee_dirthreshold_width_log2;
+       int ynryee_dirthreshold_width;
+       int yee_detailgain;
+       int yee_coring_s;
+       int yee_coring_g;
+       int yee_scale_plus_s;
+       int yee_scale_plus_g;
+       int yee_scale_minus_s;
+       int yee_scale_minus_g;
+       int yee_clip_plus_s;
+       int yee_clip_plus_g;
+       int yee_clip_minus_s;
+       int yee_clip_minus_g;
+       int ynryee_Yclip;
+
+       /* CSC (Color Space Conversion) */
+       /* YC1C2->YCbCr */
+       int csc_coef_shift;
+       int yc1c2_to_ycbcr_00;
+       int yc1c2_to_ycbcr_01;
+       int yc1c2_to_ycbcr_02;
+       int yc1c2_to_ycbcr_10;
+       int yc1c2_to_ycbcr_11;
+       int yc1c2_to_ycbcr_12;
+       int yc1c2_to_ycbcr_20;
+       int yc1c2_to_ycbcr_21;
+       int yc1c2_to_ycbcr_22;
+
+       /* GC (Gamma Correction) */
+       int gamma_gain_k1;
+       int gamma_gain_k2;
+
+       /* TNR (Temporal Noise Reduction) */
+       int tnr_coef;
+       int tnr_threshold_Y;
+       int tnr_threshold_C;
+
+       /* ANR (Advance Noise Reduction) */
+       int anr_threshold;
+};
+
+/* xmem address map allocation */
+struct sh_css_ddr_address_map {
+       void *isp_param;
+       void *ctc_tbl;
+       void *gamma_tbl;
+       void *macc_tbl;
+       void *fpn_tbl;
+       void *sc_tbl;
+       void *s3a_tbl;
+       void *s3a_tbl_hi;
+       void *s3a_tbl_lo;
+       void *sdis_hor_coef;
+       void *sdis_ver_coef;
+       void *sdis_hor_proj;
+       void *sdis_ver_proj;
+       void *tetra_r_x;
+       void *tetra_r_y;
+       void *tetra_gr_x;
+       void *tetra_gr_y;
+       void *tetra_gb_x;
+       void *tetra_gb_y;
+       void *tetra_b_x;
+       void *tetra_b_y;
+       void *tetra_ratb_x;
+       void *tetra_ratb_y;
+       void *tetra_batr_x;
+       void *tetra_batr_y;
+};
+
+/* Group all host initialized SP variables into this struct. */
+struct sh_css_sp_group {
+       int                             sp_isp_binary_id;
+       int                             sp_enable_xnr;
+       unsigned int                    sp_uds_curr_dx;
+       unsigned int                    sp_uds_curr_dy;
+       unsigned int                    sp_uds_xc;
+       unsigned int                    sp_uds_yc;
+       int                             sp_input_stream_format;
+       unsigned int                    isp_dvs_envelope_width;
+       unsigned int                    isp_dvs_envelope_height;
+       unsigned int                    isp_deci_log_factor;
+       unsigned int                    isp_vf_downscale_bits;
+       unsigned int                    isp_online;
+       unsigned int                    isp_copy_vf;
+       unsigned int                    isp_copy_output;
+       unsigned int                    isp_2ppc;
+       unsigned int                    sp_out_crop_pos_x;
+       unsigned int                    sp_out_crop_pos_y;
+       unsigned int                    sp_run_copy;
+       void                            *xmem_bin_addr;
+       void                            *xmem_map_addr;
+       struct sh_css_frame             sp_in_frame;
+       struct sh_css_frame             sp_out_frame;
+       struct sh_css_frame             sp_ref_in_frame;
+       struct sh_css_frame             sp_tnr_in_frame;
+       struct sh_css_frame             sp_out_vf_frame;
+       struct sh_css_frame             sp_extra_frame;
+       struct sh_css_frame             sp_ref_out_frame;
+       struct sh_css_frame             sp_tnr_out_frame;
+       struct sh_css_frame_info        sp_internal_frame_info;
+} ;
+
+extern struct sh_css_sp_group sp_group;
+extern struct sh_css_frame sp_in_frame;
+extern struct sh_css_frame sp_out_frame;
+
+extern int (*sh_css_printf) (const char *fmt, ...);
+
+void *
+sh_css_params_ddr_address_map(void);
+
+enum sh_css_err
+sh_css_params_write_to_ddr(const struct sh_css_binary *binary_info);
+
+void
+sh_css_params_set_current_binary(const struct sh_css_binary *binary);
+
+enum sh_css_err
+sh_css_params_init(void);
+
+void
+sh_css_params_uninit(void);
+
+void
+sh_css_params_reconfigure_gdc_lut(void);
+
+void *
+sh_css_malloc(size_t size);
+
+void
+sh_css_free(void *ptr);
+
+/* Check two frames for equality (format, resolution, bits per element) */
+bool
+sh_css_frame_equal_types(const struct sh_css_frame *frame_a,
+                        const struct sh_css_frame *frame_b);
+
+bool
+sh_css_frame_info_equal_resolution(const struct sh_css_frame_info *info_a,
+                                  const struct sh_css_frame_info *info_b);
+
+unsigned int
+sh_css_input_format_bits_per_pixel(enum sh_css_input_format format,
+                                  bool two_ppc);
+
+enum sh_css_err
+sh_css_vf_downscale_log2(const struct sh_css_frame_info *out_info,
+                        const struct sh_css_frame_info *vf_info,
+                        unsigned int *downscale_log2);
+
+void
+sh_css_capture_enable_bayer_downscaling(bool enable);
+
+void
+sh_css_binary_print(const struct sh_css_binary *binary);
+
+void
+sh_css_print_sp_debug_state(const struct sh_css_sp_debug_state *state);
+
+void
+sh_css_frame_info_set_width(struct sh_css_frame_info *info,
+                           unsigned int width);
+
+/* Return whether the sp copy process should be started */
+bool
+sh_css_continuous_start_sp_copy(void);
+
+/* The following functions are used for testing purposes only */
+const struct sh_css_fpn_table *
+sh_css_get_fpn_table(void);
+
+const struct sh_css_shading_table *
+sh_css_get_shading_table(void);
+
+const struct sh_css_isp_params *
+sh_css_get_isp_params(void);
+
+const struct sh_css_binary *
+sh_css_get_3a_binary(void);
+
+void
+sh_css_get_isp_dis_coefficients(short *horizontal_coefficients,
+                               short *vertical_coefficients);
+
+void
+sh_css_get_isp_dis_projections(int *horizontal_projections,
+                              int *vertical_projections);
+
+void *
+sh_css_store_sp_group_to_ddr(void);
+
+#endif /* _SH_CSS_INTERNAL_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_metrics.c b/drivers/media/video/atomisp/css/sh_css_metrics.c
new file mode 100644 (file)
index 0000000..24034ec
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "sh_css_hw.h"
+#include "sh_css_hrt.h"
+#include "sh_css_internal.h"
+#include "sh_css_metrics.h"
+
+#define ISP_RUN_BIT 0x3
+#define MULTIPLE_PCS 0
+#define SUSPEND      0
+#define NOF_PCS      1
+#define RESUME_MASK  0x8
+#define STOP_MASK    0x0
+
+static bool pc_histogram_enabled;
+static struct sh_css_pc_histogram *isp_histogram;
+static struct sh_css_pc_histogram *sp_histogram;
+
+struct sh_css_metrics sh_css_metrics;
+
+void
+sh_css_metrics_start_frame(void)
+{
+       sh_css_metrics.frame_metrics.num_frames++;
+}
+
+static void
+clear_histogram(struct sh_css_pc_histogram *histogram)
+{
+       unsigned i;
+       for (i = 0; i < histogram->length; i++) {
+               histogram->run[i] = 0;
+               histogram->stall[i] = 0;
+               histogram->msink[i] = 0xFFFF;
+       }
+}
+
+void
+sh_css_metrics_enable_pc_histogram(bool enable)
+{
+       pc_histogram_enabled = enable;
+}
+
+static void
+make_histogram(struct sh_css_pc_histogram *histogram, unsigned length)
+{
+       if (histogram->length)
+               return;
+       if (histogram->run)
+               return;
+       histogram->run = sh_css_malloc(length * sizeof(*histogram->run));
+       if (!histogram->run)
+               return;
+       histogram->stall = sh_css_malloc(length * sizeof(*histogram->stall));
+       if (!histogram->stall)
+               return;
+       histogram->msink = sh_css_malloc(length * sizeof(*histogram->msink));
+       if (!histogram->msink)
+               return;
+
+       histogram->length = length;
+       clear_histogram(histogram);
+}
+
+static void
+insert_binary_metrics(struct sh_css_binary_metrics **l,
+                       struct sh_css_binary_metrics *metrics)
+{
+       for (; *l; l = &(*l)->next)
+               if (*l == metrics)
+                       return;
+
+       *l = metrics;
+       metrics->next = NULL;
+}
+
+void
+sh_css_metrics_start_binary(struct sh_css_binary_metrics *metrics)
+{
+       if (!pc_histogram_enabled)
+               return;
+
+       isp_histogram = &metrics->isp_histogram;
+       sp_histogram = &metrics->sp_histogram;
+       make_histogram(isp_histogram, ISP_PMEM_DEPTH);
+       make_histogram(sp_histogram, SP_PMEM_DEPTH);
+       insert_binary_metrics(&sh_css_metrics.binary_metrics, metrics);
+}
+
+void
+sh_css_metrics_sample_pcs(void)
+{
+       bool stall;
+       unsigned int pc;
+       unsigned int msink;
+
+#if SUSPEND
+       unsigned int sc = 0;
+       unsigned int stopped_sc = 0;
+       unsigned int resume_sc = 0;
+#endif
+
+
+#if MULTIPLE_PCS
+       int i;
+       unsigned int pc_tab[NOF_PCS] ;
+
+       for (i = 0; i < NOF_PCS; i++)
+               pc_tab[i] = 0;
+#endif
+
+       if (!pc_histogram_enabled)
+               return;
+
+       if (isp_histogram) {
+#if SUSPEND
+               /* STOP the ISP */
+               sh_css_isp_ctrl_store(ISP_SC_REG, STOP_MASK);
+#endif
+               msink = sh_css_hrt_isp_current_msink();
+#if MULTIPLE_PCS
+               for (i = 0; i < NOF_PCS; i++)
+                       pc_tab[i] = sh_css_hrt_isp_current_pc();
+#else
+               pc = sh_css_hrt_isp_current_pc();
+#endif
+
+#if SUSPEND
+               /* RESUME the ISP */
+               sh_css_isp_ctrl_store(ISP_SC_REG, RESUME_MASK);
+#endif
+               isp_histogram->msink[pc] &= msink;
+               stall = (msink != 0x7FF);
+
+               if (stall)
+                       isp_histogram->stall[pc]++;
+               else
+                       isp_histogram->run[pc]++;
+
+#if MULTIPLE_PCS
+               printk(KERN_INFO "msink = 0%X\n", msink);
+               for (i = 0; i < NOF_PCS; i++)
+                       printk(KERN_INFO "PC = %d  ", pc_tab[i]);
+               printk(KERN_INFO "\n");
+#endif
+       }
+
+       if (sp_histogram && 0) {
+               msink = sh_css_hrt_sp_current_msink();
+               pc = sh_css_hrt_sp_current_pc();
+               sp_histogram->msink[pc] &= msink;
+               stall = (msink != 0x7FF);
+               if (stall)
+                       sp_histogram->stall[pc]++;
+               else
+                       sp_histogram->run[pc]++;
+       }
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_metrics.h b/drivers/media/video/atomisp/css/sh_css_metrics.h
new file mode 100644 (file)
index 0000000..1406d0c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Support for Medfield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef _SH_CSS_METRICS_H_
+#define _SH_CSS_METRICS_H_
+
+#include "sh_css_types.h"
+
+struct sh_css_pc_histogram {
+       unsigned length;
+       unsigned *run;
+       unsigned *stall;
+       unsigned *msink;
+};
+
+struct sh_css_binary_metrics {
+       unsigned mode;
+       struct sh_css_pc_histogram isp_histogram;
+       struct sh_css_pc_histogram sp_histogram;
+       struct sh_css_binary_metrics *next;
+};
+
+struct sh_css_frame_metrics {
+       unsigned num_frames;
+};
+
+struct sh_css_metrics {
+       struct sh_css_binary_metrics *binary_metrics;
+       struct sh_css_frame_metrics   frame_metrics;
+};
+
+extern struct sh_css_metrics sh_css_metrics;
+
+/* Sample ISP and SP pc and add to histogram */
+void sh_css_metrics_enable_pc_histogram(bool enable);
+void sh_css_metrics_start_frame(void);
+void sh_css_metrics_start_binary(struct sh_css_binary_metrics *metrics);
+void sh_css_metrics_sample_pcs(void);
+
+#endif /* _SH_CSS_METRICS_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_params.c b/drivers/media/video/atomisp/css/sh_css_params.c
new file mode 100644 (file)
index 0000000..25c3c93
--- /dev/null
@@ -0,0 +1,2119 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include <hmm/hmm.h>
+
+#include "sh_css.h"
+#include "sh_css_params.h"
+#include "sh_css_internal.h"
+#include "sh_css_hrt.h"
+#include "sh_css_defs.h"
+
+#define sISP_REG_BIT              ISP_VEC_ELEMBITS
+#define uISP_REG_BIT              (sISP_REG_BIT-1)
+#define sSHIFT                    (16-sISP_REG_BIT)
+#define uSHIFT                    (16-uISP_REG_BIT)
+#define sFRACTION_BITS_FITTING(a) (a-sSHIFT)
+#define uFRACTION_BITS_FITTING(a) (a-uSHIFT)
+/* a:fraction bits for 16bit precision, b:fraction bits for ISP precision */
+#define sDIGIT_FITTING(v, a, b) \
+       (((v)>>sSHIFT) >> (sFRACTION_BITS_FITTING(a)-(b)))
+#define uDIGIT_FITTING(v, a, b) \
+       (((v)>>uSHIFT) >> (uFRACTION_BITS_FITTING(a)-(b)))
+
+#define FPNTBL_BYTES(binary) \
+       (sizeof(char) * (binary)->in_frame_info.height * \
+        (binary)->in_frame_info.padded_width)
+#define SCTBL_BYTES(binary) \
+       (sizeof(unsigned short) * (binary)->sctbl_height * \
+        (binary)->sctbl_aligned_width_per_color * SH_CSS_SC_NUM_COLORS)
+#define S3ATBL_BYTES(binary) \
+       (sizeof(struct sh_css_3a_output) * (binary)->s3atbl_isp_width * \
+        (binary)->s3atbl_isp_height)
+/* TODO: check if the stride is always the same max value or whether
+ * it varies per resolution. */
+#define S3ATBL_HI_LO_BYTES(binary) \
+       (ISP_S3ATBL_HI_LO_STRIDE_BYTES * (binary)->s3atbl_isp_height)
+/* SDIS */
+#define SDIS_VER_COEF_TBL__IN_DMEM(b) \
+       _SDIS_VER_COEF_TBL_USE_DMEM(b->info->mode, b->info->enable_dis)
+
+#define SH_CSS_DIS_VER_NUM_COEF_TYPES(b) \
+       (SDIS_VER_COEF_TBL__IN_DMEM(b) ? \
+               SH_CSS_DIS_COEF_TYPES_ON_DMEM : \
+               SH_CSS_DIS_NUM_COEF_TYPES)
+
+#define SDIS_HOR_COEF_TBL_BYTES(b) \
+       (sizeof(short) * SH_CSS_DIS_NUM_COEF_TYPES * (b)->dis_hor_coef_num_isp)
+#define SDIS_VER_COEF_TBL_BYTES(b) \
+       (sizeof(short) * SH_CSS_DIS_VER_NUM_COEF_TYPES(b) * \
+               (b)->dis_ver_coef_num_isp)
+#define SDIS_HOR_PROJ_TBL_BYTES(b) \
+       (sizeof(int)   * SH_CSS_DIS_NUM_COEF_TYPES * (b)->dis_hor_proj_num_isp)
+#define SDIS_VER_PROJ_TBL_BYTES(b) \
+       (sizeof(int)   * SH_CSS_DIS_NUM_COEF_TYPES * (b)->dis_ver_proj_num_isp)
+#define MORPH_PLANE_BYTES(binary) \
+       (SH_CSS_MORPH_TABLE_ELEM_BYTES * (binary)->morph_tbl_aligned_width * \
+        (binary)->morph_tbl_height)
+
+static struct sh_css_isp_params isp_parameters;
+static struct sh_css_fpn_table fpn_table;
+static const struct sh_css_morph_table   *morph_table;
+static const struct sh_css_shading_table *sc_table;
+static const struct sh_css_macc_table    *macc_table;
+static const struct sh_css_gamma_table   *gamma_table;
+static const struct sh_css_ctc_table     *ctc_table;
+static const struct sh_css_3a_config     *s3a_config;
+static const struct sh_css_wb_config     *wb_config;
+static const struct sh_css_cc_config     *cc_config;
+static const struct sh_css_tnr_config    *tnr_config;
+static const struct sh_css_ob_config     *ob_config;
+static const struct sh_css_dp_config     *dp_config;
+static const struct sh_css_nr_config     *nr_config;
+static const struct sh_css_ee_config     *ee_config;
+static const struct sh_css_de_config     *de_config;
+static const struct sh_css_gc_config     *gc_config;
+static const struct sh_css_anr_config    *anr_config;
+static bool isp_params_changed,
+           fpn_table_changed,
+           dis_coef_table_changed,
+           morph_table_changed,
+           sc_table_changed,
+           macc_table_changed,
+           gamma_table_changed,
+           ctc_table_changed,
+           s3a_config_changed,
+           wb_config_changed,
+           cc_config_changed,
+           tnr_config_changed,
+           ob_config_changed,
+           dp_config_changed,
+           nr_config_changed,
+           ee_config_changed,
+           de_config_changed,
+           gc_config_changed,
+               anr_config_changed;
+
+static size_t fpn_tbl_size,
+             sc_tbl_size,
+             s3a_tbl_size,
+             s3a_tbl_hi_size,
+             s3a_tbl_lo_size,
+             sdis_hor_coef_size,
+             sdis_ver_coef_size,
+             sdis_hor_proj_size,
+             sdis_ver_proj_size,
+             tetra_r_x_size,
+             tetra_r_y_size,
+             tetra_gr_x_size,
+             tetra_gr_y_size,
+             tetra_gb_x_size,
+             tetra_gb_y_size,
+             tetra_b_x_size,
+             tetra_b_y_size,
+             tetra_batr_x_size,
+             tetra_batr_y_size,
+             tetra_ratb_x_size,
+             tetra_ratb_y_size;
+
+/* local buffers, used to re-order the 3a statistics in vmem-format */
+static unsigned short s3a_tbl_hi_buf[ISP_S3ATBL_HI_LO_STRIDE *
+                                    SH_CSS_MAX_BQ_GRID_HEIGHT],
+                     s3a_tbl_lo_buf[ISP_S3ATBL_HI_LO_STRIDE *
+                                    SH_CSS_MAX_BQ_GRID_HEIGHT];
+static struct sh_css_macc_table converted_macc_table;
+static const short *dis_hor_coef_tbl,
+                  *dis_ver_coef_tbl;
+static const struct sh_css_binary *current_3a_binary;
+/* for csim and fpga, we need to keep a copy of all data in DDR.
+   On the chip this is not necessary through.
+   TODO: remove this for the chip */
+static struct sh_css_ddr_address_map ddr_ptrs;
+/* We keep a second copy of the ptr struct for the SP to access.
+   Again, this would not be necessary on the chip. */
+static void *sp_ddr_ptrs;
+
+/* sp group address on DDR */
+static void *xmem_sp_group_ptrs;
+
+/* Default Parameters */
+static const struct sh_css_gamma_table default_gamma_table = {
+       .data = {
+               0, 1, 2, 3, 4, 5, 6, 7,
+               8, 9, 10, 11, 12, 13, 14, 16,
+               17, 18, 19, 20, 21, 23, 24, 25,
+               27, 28, 29, 31, 32, 33, 35, 36,
+               38, 39, 41, 42, 44, 45, 47, 48,
+               49, 51, 52, 54, 55, 57, 58, 60,
+               61, 62, 64, 65, 66, 68, 69, 70,
+               71, 72, 74, 75, 76, 77, 78, 79,
+               80, 81, 82, 83, 84, 85, 86, 87,
+               88, 89, 90, 91, 92, 93, 93, 94,
+               95, 96, 97, 98, 98, 99, 100, 101,
+               102, 102, 103, 104, 105, 105, 106, 107,
+               108, 108, 109, 110, 110, 111, 112, 112,
+               113, 114, 114, 115, 116, 116, 117, 118,
+               118, 119, 120, 120, 121, 121, 122, 123,
+               123, 124, 125, 125, 126, 126, 127, 127, /* 128 */
+               128, 129, 129, 130, 130, 131, 131, 132,
+               132, 133, 134, 134, 135, 135, 136, 136,
+               137, 137, 138, 138, 139, 139, 140, 140,
+               141, 141, 142, 142, 143, 143, 144, 144,
+               145, 145, 145, 146, 146, 147, 147, 148,
+               148, 149, 149, 150, 150, 150, 151, 151,
+               152, 152, 152, 153, 153, 154, 154, 155,
+               155, 155, 156, 156, 156, 157, 157, 158,
+               158, 158, 159, 159, 160, 160, 160, 161,
+               161, 161, 162, 162, 162, 163, 163, 163,
+               164, 164, 164, 165, 165, 165, 166, 166,
+               166, 167, 167, 167, 168, 168, 168, 169,
+               169, 169, 170, 170, 170, 170, 171, 171,
+               171, 172, 172, 172, 172, 173, 173, 173,
+               174, 174, 174, 174, 175, 175, 175, 176,
+               176, 176, 176, 177, 177, 177, 177, 178, /* 256 */
+               178, 178, 178, 179, 179, 179, 179, 180,
+               180, 180, 180, 181, 181, 181, 181, 182,
+               182, 182, 182, 182, 183, 183, 183, 183,
+               184, 184, 184, 184, 184, 185, 185, 185,
+               185, 186, 186, 186, 186, 186, 187, 187,
+               187, 187, 187, 188, 188, 188, 188, 188,
+               189, 189, 189, 189, 189, 190, 190, 190,
+               190, 190, 191, 191, 191, 191, 191, 192,
+               192, 192, 192, 192, 192, 193, 193, 193,
+               193, 193, 194, 194, 194, 194, 194, 194,
+               195, 195, 195, 195, 195, 195, 196, 196,
+               196, 196, 196, 196, 197, 197, 197, 197,
+               197, 197, 198, 198, 198, 198, 198, 198,
+               198, 199, 199, 199, 199, 199, 199, 200,
+               200, 200, 200, 200, 200, 200, 201, 201,
+               201, 201, 201, 201, 201, 202, 202, 202, /* 384 */
+               202, 202, 202, 202, 203, 203, 203, 203,
+               203, 203, 203, 204, 204, 204, 204, 204,
+               204, 204, 204, 205, 205, 205, 205, 205,
+               205, 205, 205, 206, 206, 206, 206, 206,
+               206, 206, 206, 207, 207, 207, 207, 207,
+               207, 207, 207, 208, 208, 208, 208, 208,
+               208, 208, 208, 209, 209, 209, 209, 209,
+               209, 209, 209, 209, 210, 210, 210, 210,
+               210, 210, 210, 210, 210, 211, 211, 211,
+               211, 211, 211, 211, 211, 211, 212, 212,
+               212, 212, 212, 212, 212, 212, 212, 213,
+               213, 213, 213, 213, 213, 213, 213, 213,
+               214, 214, 214, 214, 214, 214, 214, 214,
+               214, 214, 215, 215, 215, 215, 215, 215,
+               215, 215, 215, 216, 216, 216, 216, 216,
+               216, 216, 216, 216, 216, 217, 217, 217, /* 512 */
+               217, 217, 217, 217, 217, 217, 217, 218,
+               218, 218, 218, 218, 218, 218, 218, 218,
+               218, 219, 219, 219, 219, 219, 219, 219,
+               219, 219, 219, 220, 220, 220, 220, 220,
+               220, 220, 220, 220, 220, 221, 221, 221,
+               221, 221, 221, 221, 221, 221, 221, 221,
+               222, 222, 222, 222, 222, 222, 222, 222,
+               222, 222, 223, 223, 223, 223, 223, 223,
+               223, 223, 223, 223, 223, 224, 224, 224,
+               224, 224, 224, 224, 224, 224, 224, 224,
+               225, 225, 225, 225, 225, 225, 225, 225,
+               225, 225, 225, 226, 226, 226, 226, 226,
+               226, 226, 226, 226, 226, 226, 226, 227,
+               227, 227, 227, 227, 227, 227, 227, 227,
+               227, 227, 228, 228, 228, 228, 228, 228,
+               228, 228, 228, 228, 228, 228, 229, 229,
+               229, 229, 229, 229, 229, 229, 229, 229,
+               229, 229, 230, 230, 230, 230, 230, 230,
+               230, 230, 230, 230, 230, 230, 231, 231,
+               231, 231, 231, 231, 231, 231, 231, 231,
+               231, 231, 231, 232, 232, 232, 232, 232,
+               232, 232, 232, 232, 232, 232, 232, 233,
+               233, 233, 233, 233, 233, 233, 233, 233,
+               233, 233, 233, 233, 234, 234, 234, 234,
+               234, 234, 234, 234, 234, 234, 234, 234,
+               234, 235, 235, 235, 235, 235, 235, 235,
+               235, 235, 235, 235, 235, 235, 236, 236,
+               236, 236, 236, 236, 236, 236, 236, 236,
+               236, 236, 236, 236, 237, 237, 237, 237,
+               237, 237, 237, 237, 237, 237, 237, 237,
+               237, 237, 238, 238, 238, 238, 238, 238,
+               238, 238, 238, 238, 238, 238, 238, 238,
+               239, 239, 239, 239, 239, 239, 239, 239,
+               239, 239, 239, 239, 239, 239, 240, 240,
+               240, 240, 240, 240, 240, 240, 240, 240,
+               240, 240, 240, 240, 241, 241, 241, 241,
+               241, 241, 241, 241, 241, 241, 241, 241,
+               241, 241, 241, 242, 242, 242, 242, 242,
+               242, 242, 242, 242, 242, 242, 242, 242,
+               242, 242, 243, 243, 243, 243, 243, 243,
+               243, 243, 243, 243, 243, 243, 243, 243,
+               243, 244, 244, 244, 244, 244, 244, 244,
+               244, 244, 244, 244, 244, 244, 244, 244,
+               245, 245, 245, 245, 245, 245, 245, 245,
+               245, 245, 245, 245, 245, 245, 245, 246,
+               246, 246, 246, 246, 246, 246, 246, 246,
+               246, 246, 246, 246, 246, 246, 246, 247,
+               247, 247, 247, 247, 247, 247, 247, 247,
+               247, 247, 247, 247, 247, 247, 247, 248,
+               248, 248, 248, 248, 248, 248, 248, 248,
+               248, 248, 248, 248, 248, 248, 248, 249,
+               249, 249, 249, 249, 249, 249, 249, 249,
+               249, 249, 249, 249, 249, 249, 249, 250,
+               250, 250, 250, 250, 250, 250, 250, 250,
+               250, 250, 250, 250, 250, 250, 250, 251,
+               251, 251, 251, 251, 251, 251, 251, 251,
+               251, 251, 251, 251, 251, 251, 251, 252,
+               252, 252, 252, 252, 252, 252, 252, 252,
+               252, 252, 252, 252, 252, 252, 252, 253,
+               253, 253, 253, 253, 253, 253, 253, 253,
+               253, 253, 253, 253, 253, 253, 253, 253,
+               254, 254, 254, 254, 254, 254, 254, 254,
+               254, 254, 254, 254, 254, 254, 254, 254,
+               255, 255, 255, 255, 255, 255, 255, 255
+       }
+};
+
+static const struct sh_css_ctc_table default_ctc_table = {
+       .data = {
+               0, 0, 256, 384, 384, 497, 765, 806,
+               837, 851, 888, 901, 957, 981, 993, 1001,
+               1011, 1029, 1028, 1039, 1062, 1059, 1073, 1080,
+               1083, 1085, 1085, 1098, 1080, 1084, 1085, 1093,
+               1078, 1073, 1070, 1069, 1077, 1066, 1072, 1063,
+               1053, 1044, 1046, 1053, 1039, 1028, 1025, 1024,
+               1012, 1013, 1016, 996, 992, 990, 990, 980,
+               969, 968, 961, 955, 951, 949, 933, 930,
+               929, 925, 921, 916, 906, 901, 895, 893,
+               886, 877, 872, 869, 866, 861, 857, 849,
+               845, 838, 836, 832, 823, 821, 815, 813,
+               809, 805, 796, 793, 790, 785, 784, 778,
+               772, 768, 766, 763, 758, 752, 749, 745,
+               741, 740, 736, 730, 726, 724, 723, 718,
+               711, 709, 706, 704, 701, 698, 691, 689,
+               688, 683, 683, 678, 675, 673, 671, 669,
+               666, 663, 661, 660, 656, 656, 653, 650,
+               648, 647, 646, 643, 639, 638, 637, 635,
+               633, 632, 629, 627, 626, 625, 622, 621,
+               618, 618, 614, 614, 612, 609, 606, 606,
+               603, 600, 600, 597, 594, 591, 590, 586,
+               582, 581, 578, 575, 572, 569, 563, 560,
+               557, 554, 551, 548, 545, 539, 536, 533,
+               529, 527, 524, 519, 516, 513, 510, 507,
+               504, 501, 498, 493, 491, 488, 485, 484,
+               480, 476, 474, 471, 467, 466, 464, 460,
+               459, 455, 453, 449, 447, 446, 443, 441,
+               438, 435, 432, 432, 429, 427, 426, 422,
+               419, 418, 416, 414, 412, 410, 408, 406,
+               404, 402, 401, 398, 397, 395, 393, 390,
+               389, 388, 387, 384, 382, 380, 378, 377,
+               376, 375, 372, 370, 368, 368, 366, 364,
+               363, 361, 360, 358, 357, 355, 354, 352,
+               351, 350, 349, 346, 345, 344, 344, 342,
+               340, 339, 337, 337, 336, 335, 333, 331,
+               330, 329, 328, 326, 326, 324, 324, 322,
+               321, 320, 318, 318, 318, 317, 315, 313,
+               312, 311, 311, 310, 308, 307, 306, 306,
+               304, 304, 302, 301, 300, 300, 299, 297,
+               297, 296, 296, 294, 294, 292, 291, 291,
+               291, 290, 288, 287, 286, 286, 287, 285,
+               284, 283, 282, 282, 281, 281, 279, 278,
+               278, 278, 276, 276, 275, 274, 274, 273,
+               271, 270, 269, 268, 268, 267, 265, 262,
+               261, 260, 260, 259, 257, 254, 252, 252,
+               251, 251, 249, 246, 245, 244, 243, 242,
+               240, 239, 239, 237, 235, 235, 233, 231,
+               232, 230, 229, 226, 225, 224, 225, 224,
+               223, 220, 219, 219, 218, 217, 217, 214,
+               213, 213, 212, 211, 209, 209, 209, 208,
+               206, 205, 204, 203, 204, 203, 201, 200,
+               199, 197, 198, 198, 197, 195, 194, 194,
+               193, 192, 192, 191, 189, 190, 189, 188,
+               186, 187, 186, 185, 185, 184, 183, 181,
+               183, 182, 181, 180, 179, 178, 178, 178,
+               177, 176, 175, 176, 175, 174, 174, 173,
+               172, 173, 172, 171, 170, 170, 169, 169,
+               169, 168, 167, 166, 167, 167, 166, 165,
+               164, 164, 164, 163, 164, 163, 162, 163,
+               162, 161, 160, 161, 160, 160, 160, 159,
+               158, 157, 158, 158, 157, 157, 156, 156,
+               156, 156, 155, 155, 154, 154, 154, 154,
+               154, 153, 152, 153, 152, 152, 151, 152,
+               151, 152, 151, 150, 150, 149, 149, 150,
+               149, 149, 148, 148, 148, 149, 148, 147,
+               146, 146, 147, 146, 147, 146, 145, 146,
+               146, 145, 144, 145, 144, 145, 144, 144,
+               143, 143, 143, 144, 143, 142, 142, 142,
+               142, 142, 142, 141, 141, 141, 141, 140,
+               140, 141, 140, 140, 141, 140, 139, 139,
+               139, 140, 139, 139, 138, 138, 137, 139,
+               138, 138, 138, 137, 138, 137, 137, 137,
+               137, 136, 137, 136, 136, 136, 136, 135,
+               136, 135, 135, 135, 135, 136, 135, 135,
+               134, 134, 133, 135, 134, 134, 134, 133,
+               134, 133, 134, 133, 133, 132, 133, 133,
+               132, 133, 132, 132, 132, 132, 131, 131,
+               131, 132, 131, 131, 130, 131, 130, 132,
+               131, 130, 130, 129, 130, 129, 130, 129,
+               129, 129, 130, 129, 128, 128, 128, 128,
+               129, 128, 128, 127, 127, 128, 128, 127,
+               127, 126, 126, 127, 127, 126, 126, 126,
+               127, 126, 126, 126, 125, 125, 126, 125,
+               125, 124, 124, 124, 125, 125, 124, 124,
+               123, 124, 124, 123, 123, 122, 122, 122,
+               122, 122, 121, 120, 120, 119, 118, 118,
+               118, 117, 117, 116, 115, 115, 115, 114,
+               114, 113, 113, 112, 111, 111, 111, 110,
+               110, 109, 109, 108, 108, 108, 107, 107,
+               106, 106, 105, 105, 105, 104, 104, 103,
+               103, 102, 102, 102, 102, 101, 101, 100,
+               100, 99, 99, 99, 99, 99, 99, 98,
+               97, 98, 97, 97, 97, 96, 96, 95,
+               96, 95, 96, 95, 95, 94, 94, 95,
+               94, 94, 94, 93, 93, 92, 93, 93,
+               93, 93, 92, 92, 91, 92, 92, 92,
+               91, 91, 90, 90, 91, 91, 91, 90,
+               90, 90, 90, 91, 90, 90, 90, 89,
+               89, 89, 90, 89, 89, 89, 89, 89,
+               88, 89, 89, 88, 88, 88, 88, 87,
+               89, 88, 88, 88, 88, 88, 87, 88,
+               88, 88, 87, 87, 87, 87, 87, 88,
+               87, 87, 87, 87, 87, 87, 88, 87,
+               87, 87, 87, 86, 86, 87, 87, 87,
+               87, 86, 86, 86, 87, 87, 86, 87,
+               86, 86, 86, 87, 87, 86, 86, 86,
+               86, 86, 87, 87, 86, 85, 85, 85,
+               84, 85, 85, 84, 84, 83, 83, 82,
+               82, 82, 81, 81, 80, 79, 79, 79,
+               78, 77, 77, 76, 76, 76, 75, 74,
+               74, 74, 73, 73, 72, 71, 71, 71,
+               70, 70, 69, 69, 68, 68, 67, 67,
+               67, 66, 66, 65, 65, 64, 64, 63,
+               62, 62, 62, 61, 60, 60, 59, 59,
+               58, 58, 57, 57, 56, 56, 56, 55,
+               55, 54, 55, 55, 54, 53, 53, 52,
+               53, 53, 52, 51, 51, 50, 51, 50,
+               49, 49, 50, 49, 49, 48, 48, 47,
+               47, 48, 46, 45, 45, 45, 46, 45,
+               45, 44, 45, 45, 45, 43, 42, 42,
+               41, 43, 41, 40, 40, 39, 40, 41,
+               39, 39, 39, 39, 39, 38, 35, 35,
+               34, 37, 36, 34, 33, 33, 33, 35,
+               34, 32, 32, 31, 32, 30, 29, 26,
+               25, 25, 27, 26, 23, 23, 23, 25,
+               24, 24, 22, 21, 20, 19, 16, 14,
+               13, 13, 13, 10, 9, 7, 7, 7,
+               12, 12, 12, 7, 0, 0, 0, 0
+       }
+};
+
+/* multiple axis color correction table,
+ * 64values = 2x2matrix for 16area, [s2.11].
+ */
+static const struct sh_css_macc_table default_macc_table = {
+       .data = {
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192,
+               8192, 0, 0, 8192, 8192, 0, 0, 8192
+       }
+};
+
+/* Digital Zoom lookup table. See documentation for more details about the
+ * contents of this table.
+ */
+static const int zoom_table[4][HRT_GDC_N] = {
+       {0, 0, 0, 0, 0, 0, -1, -1,
+        -1, -2, -2, -3, -3, -4, -4, -5,
+        -6, -6, -7, -7, -8, -9, -9, -10,
+        -11, -11, -12, -13, -13, -14, -14, -15,
+        -16, -16, -16, -17, -17, -18, -18, -18,
+        -18, -18, -18, -18, -18, -18, -18, -18,
+        -18, -17, -17, -16, -15, -15, -14, -13,
+        -12, -11, -9, -8, -7, -5, -3, -1},
+       {0, 2, 4, 7, 9, 12, 16, 19,
+        23, 27, 31, 35, 39, 43, 48, 53,
+        58, 62, 67, 73, 78, 83, 88, 94,
+        99, 105, 110, 116, 121, 127, 132, 138,
+        144, 149, 154, 160, 165, 170, 176, 181,
+        186, 191, 195, 200, 205, 209, 213, 218,
+        222, 225, 229, 232, 236, 239, 241, 244,
+        246, 248, 250, 252, 253, 254, 255, 255},
+       {256, 255, 255, 254, 253, 252, 250, 248,
+        246, 244, 241, 239, 236, 232, 229, 225,
+        222, 218, 213, 209, 205, 200, 195, 191,
+        186, 181, 176, 170, 165, 160, 154, 149,
+        144, 138, 132, 127, 121, 116, 110, 105,
+        99, 94, 88, 83, 78, 73, 67, 62,
+        58, 53, 48, 43, 39, 35, 31, 27,
+        23, 19, 16, 12, 9, 7, 4, 2},
+       {0, -1, -3, -5, -6, -8, -9, -10,
+        -12, -13, -14, -15, -16, -15, -17, -17,
+        -18, -18, -17, -19, -19, -18, -18, -19,
+        -18, -19, -18, -17, -17, -17, -16, -16,
+        -16, -15, -14, -14, -13, -12, -12, -12,
+        -11, -11, -9, -9, -9, -8, -6, -6,
+        -6, -5, -4, -3, -4, -3, -2, -2,
+        -1, 0, -1, 0, 1, 0, 0, 0}
+};
+
+static const struct sh_css_3a_config default_3a_config = {
+       .ae_y_coef_r  = 25559,
+       .ae_y_coef_g  = 32768,
+       .ae_y_coef_b  = 7209,
+       .af_fir1_coef = {-3344, -6104, -19143, 19143, 6104, 3344, 0},
+       .af_fir2_coef = {1027, 0, -9219, 16384, -9219, 1027, 0}
+};
+
+static const struct sh_css_3a_config disabled_3a_config = {
+       .ae_y_coef_r  = 25559,
+       .ae_y_coef_g  = 32768,
+       .ae_y_coef_b  = 7209,
+       .af_fir1_coef = {-6689, -12207, -32768, 32767, 12207, 6689, 0},
+       .af_fir2_coef = {2053, 0, -18437, 32767, -18437, 2053, 0}
+};
+
+static const struct sh_css_wb_config default_wb_config = {
+       .integer_bits = 1,
+       .gr           = 32768,
+       .r            = 32768,
+       .b            = 32768,
+       .gb           = 32768
+};
+
+static const struct sh_css_wb_config disabled_wb_config = {
+       .integer_bits = 1,
+       .gr           = 32768,
+       .r            = 32768,
+       .b            = 32768,
+       .gb           = 32768
+};
+
+static const struct sh_css_cc_config default_cc_config = {
+       .fraction_bits = 8,
+       .matrix        = {255, 29, 120, 0, -374, -342, 0, -672, 301},
+};
+
+static const struct sh_css_cc_config disabled_cc_config = {
+       .fraction_bits = 8,
+       .matrix        = {256, 44, 47, 0, -169, -171, 0, -214, 148},
+};
+
+static const struct sh_css_tnr_config default_tnr_config = {
+       .gain         = 32768,
+       .threshold_y  = 32,
+       .threshold_uv = 32,
+};
+
+static const struct sh_css_tnr_config disabled_tnr_config = {
+       .gain         = 0,
+       .threshold_y  = 65535,
+       .threshold_uv = 65535,
+};
+
+static const struct sh_css_ob_config default_ob_config = {
+       .mode           = sh_css_ob_mode_none,
+       .level_gr       = 0,
+       .level_r        = 0,
+       .level_b        = 0,
+       .level_gb       = 0,
+       .start_position = 0,
+       .end_position   = 0
+};
+
+static const struct sh_css_ob_config disabled_ob_config = {
+       .mode           = sh_css_ob_mode_none,
+       .level_gr       = 0,
+       .level_r        = 0,
+       .level_b        = 0,
+       .level_gb       = 0,
+       .start_position = 0,
+       .end_position   = 0
+};
+
+static const struct sh_css_dp_config default_dp_config = {
+       .threshold = 8192,
+       .gain      = 2048
+};
+
+static const struct sh_css_dp_config disabled_dp_config = {
+       .threshold = 65535,
+       .gain      = 65535
+};
+
+static const struct sh_css_nr_config default_nr_config = {
+       .gain         = 16384,
+       .direction    = 1280,
+       .threshold_cb = 0,
+       .threshold_cr = 0
+};
+
+static const struct sh_css_nr_config disabled_nr_config = {
+       .gain         = 0,
+       .direction    = 0,
+       .threshold_cb = 0,
+       .threshold_cr = 0
+};
+
+static const struct sh_css_ee_config default_ee_config = {
+       .gain        = 8192,
+       .threshold   = 128,
+       .detail_gain = 2048
+};
+
+static const struct sh_css_ee_config disabled_ee_config = {
+       .gain        = 0,
+       .threshold   = 0,
+       .detail_gain = 0
+};
+
+static const struct sh_css_de_config default_de_config = {
+       .pixelnoise          = 0,
+       .c1_coring_threshold = 0,
+       .c2_coring_threshold = 0
+};
+
+static const struct sh_css_de_config disabled_de_config = {
+       .pixelnoise          = 65535,
+       .c1_coring_threshold = 0,
+       .c2_coring_threshold = 0
+};
+
+static const struct sh_css_gc_config default_gc_config = {
+       .gain_k1 = 2457,        /* (1<<13) * 0.3 */
+       .gain_k2 = 2457         /* idem */
+};
+
+static const struct sh_css_gc_config disabled_gc_config = {
+       .gain_k1 = 2457,        /* (1<<13) * 0.3 */
+       .gain_k2 = 2457         /* idem */
+};
+
+static const struct sh_css_anr_config default_anr_config = {
+       .threshold   = 5,
+};
+
+int
+sh_css_get_gdc_coord_one(void)
+{
+       return HRT_GDC_COORD_ONE;
+}
+
+void
+sh_css_set_dis_coefficients(const short *horizontal_coefficients,
+                           const short *vertical_coefficients)
+{
+       dis_hor_coef_tbl = horizontal_coefficients;
+       dis_ver_coef_tbl = vertical_coefficients;
+       dis_coef_table_changed = true;
+}
+
+void
+sh_css_get_dis_projections(int *horizontal_projections,
+                          int *vertical_projections)
+{
+       unsigned int hor_num_isp, ver_num_isp,
+                    hor_num_3a, ver_num_3a, i;
+       int *hor_ptr_3a  = horizontal_projections,
+           *ver_ptr_3a  = vertical_projections,
+           *hor_ptr_isp = ddr_ptrs.sdis_hor_proj,
+           *ver_ptr_isp = ddr_ptrs.sdis_ver_proj;
+
+       if (current_3a_binary == NULL)
+               return;
+
+       hor_num_isp = current_3a_binary->dis_hor_proj_num_isp;
+       ver_num_isp = current_3a_binary->dis_ver_proj_num_isp;
+       hor_num_3a  = current_3a_binary->dis_hor_proj_num_3a;
+       ver_num_3a  = current_3a_binary->dis_ver_proj_num_3a;
+
+       for (i = 0; i < SH_CSS_DIS_NUM_COEF_TYPES; i++) {
+               hrt_isp_css_mm_load(hor_ptr_isp, hor_ptr_3a,
+                                   hor_num_3a * sizeof(int));
+               hor_ptr_isp += hor_num_isp;
+               hor_ptr_3a  += hor_num_3a;
+
+               hrt_isp_css_mm_load(ver_ptr_isp, ver_ptr_3a,
+                                   ver_num_3a * sizeof(int));
+               ver_ptr_isp += ver_num_isp;
+               ver_ptr_3a  += ver_num_3a;
+       }
+}
+
+static void
+get_3a_stats_from_dmem(struct sh_css_3a_output *output)
+{
+       int ddr_width  = current_3a_binary->s3atbl_isp_width,
+                 out_width  = current_3a_binary->s3atbl_width,
+                       out_height = current_3a_binary->s3atbl_height,
+                       i;
+       struct sh_css_3a_output
+                       *ddr_ptr = ddr_ptrs.s3a_tbl,
+                       *out_ptr = output;
+
+       for (i = 0; i < out_height; i++) {
+               hrt_isp_css_mm_load(ddr_ptr, out_ptr,
+                       out_width * sizeof(*output));
+               ddr_ptr += ddr_width;
+               out_ptr += out_width;
+       }
+}
+
+static inline int
+merge_hi14bit_lo14bit(unsigned short hi, unsigned short lo)
+{
+       int val = (int) ((((unsigned int) hi << 14) & 0xfffc000) |
+                        ((unsigned int) lo & 0x3fff));
+       return val;
+}
+
+static void
+get_3a_stats_from_vmem(struct sh_css_3a_output *output)
+{
+       int out_width  = current_3a_binary->s3atbl_width,
+           out_height = current_3a_binary->s3atbl_height;
+       unsigned short *hi, *lo;
+       int chunk, rest, kmax, y, x, k, elm_start, elm, ofs, bytes;
+
+       hi = s3a_tbl_hi_buf;
+       lo = s3a_tbl_lo_buf;
+
+       chunk = (ISP_VEC_NELEMS >> current_3a_binary->deci_factor_log2);
+       chunk = max(chunk, 1);
+       bytes = ISP_S3ATBL_HI_LO_STRIDE_BYTES * out_height;
+
+       hrt_isp_css_mm_load(ddr_ptrs.s3a_tbl_hi, hi, bytes);
+       hrt_isp_css_mm_load(ddr_ptrs.s3a_tbl_lo, lo, bytes);
+
+       for (y = 0; y < out_height; y++) {
+               elm_start = y * ISP_S3ATBL_HI_LO_STRIDE;
+               rest = out_width;
+               x = 0;
+               while (x < out_width) {
+                       kmax = (rest > chunk) ? chunk : rest;
+                       ofs = y * out_width + x;
+                       elm = elm_start + x * sizeof(*output) / sizeof(int);
+                       for (k = 0; k < kmax; k++, elm++) {
+                               output[ofs + k].ae_y =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm], lo[elm]);
+                               output[ofs + k].awb_cnt =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk], lo[elm + chunk]);
+                               output[ofs + k].awb_gr =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 2],
+                                    lo[elm + chunk * 2]);
+                               output[ofs + k].awb_r =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 3],
+                                    lo[elm + chunk * 3]);
+                               output[ofs + k].awb_b =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 4],
+                                    lo[elm + chunk * 4]);
+                               output[ofs + k].awb_gb =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 5],
+                                    lo[elm + chunk * 5]);
+                               output[ofs + k].af_hpf1 =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 6],
+                                    lo[elm + chunk * 6]);
+                               output[ofs + k].af_hpf2 =
+                                   merge_hi14bit_lo14bit
+                                   (hi[elm + chunk * 7],
+                                    lo[elm + chunk * 7]);
+                       }
+                       x += chunk;
+                       rest -= chunk;
+               }
+       }
+}
+
+static void
+sh_css_process_3a(void)
+{
+       unsigned int i;
+       /* coefficients to calculate Y */
+       isp_parameters.ae_y_coef_r =
+           uDIGIT_FITTING(s3a_config->ae_y_coef_r, 16, SH_CSS_AE_YCOEF_SHIFT);
+       isp_parameters.ae_y_coef_g =
+           uDIGIT_FITTING(s3a_config->ae_y_coef_g, 16, SH_CSS_AE_YCOEF_SHIFT);
+       isp_parameters.ae_y_coef_b =
+           uDIGIT_FITTING(s3a_config->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT);
+
+       /* af fir coefficients */
+       for (i = 0; i < 7; ++i) {
+               isp_parameters.af_fir1[i] =
+                 sDIGIT_FITTING(s3a_config->af_fir1_coef[i], 15,
+                                SH_CSS_AF_FIR_SHIFT);
+               isp_parameters.af_fir2[i] =
+                 sDIGIT_FITTING(s3a_config->af_fir2_coef[i], 15,
+                                SH_CSS_AF_FIR_SHIFT);
+       }
+       isp_params_changed = true;
+       s3a_config_changed = false;
+}
+
+void *
+sh_css_params_ddr_address_map(void)
+{
+       return sp_ddr_ptrs;
+}
+
+/* ****************************************************
+ * Each coefficient is stored as 7bits to fit 2 of them into one
+ * ISP vector element, so we will store 4 coefficents on every
+ * memory word (32bits)
+ *
+ * 0: Coefficient 0 used bits
+ * 1: Coefficient 1 used bits
+ * 2: Coefficient 2 used bits
+ * 3: Coefficient 3 used bit3
+ * x: not used
+ *
+ * xx33333332222222 | xx11111110000000
+ *
+ * ***************************************************
+ */
+static void
+store_fpntbl(void *ptr)
+{
+       unsigned int i, j;
+       short *data_ptr = fpn_table.data;
+
+       for (i = 0; i < fpn_table.height; i++) {
+               for (j = 0;
+                    j < fpn_table.width;
+                    j += 4, ptr += 4, data_ptr += 4) {
+                       int data = data_ptr[0] << 0 |
+                                  data_ptr[1] << 7 |
+                                  data_ptr[2] << 16 |
+                                  data_ptr[3] << 23;
+                       hrt_isp_css_mm_store_int(ptr, data);
+               }
+       }
+}
+
+static void
+convert_raw_to_fpn(void)
+{
+       short maxval = 0;
+       unsigned int i;
+
+       /* Find the maximum value in the table */
+       for (i = 0; i < fpn_table.height * fpn_table.width; i++) {
+               short val = fpn_table.data[i];
+               /* Make sure FPN value can be represented in 13-bit unsigned
+                * number (ISP precision - 1), but note that actual input range
+                * depends on precision of input frame data.
+                */
+               if (val < 0)
+                       val = 0;
+               if (val >= (1 << 13))
+                       val = (1 << 13) - 1;
+               maxval = max(maxval, val);
+       }
+       /* Find the lowest shift value to remap the values in the range
+        * 0..maxval to 0..2^shiftval*63.
+        */
+       fpn_table.shift = 0;
+       while (maxval > 63) {
+               maxval /= 2;
+               fpn_table.shift++;
+       }
+       /* Adjust the values in the table for the shift value */
+       for (i = 0; i < fpn_table.height * fpn_table.width; i++)
+               ((unsigned short *) fpn_table.data)[i] >>= fpn_table.shift;
+}
+
+enum sh_css_err
+sh_css_set_black_frame(const struct sh_css_frame *raw_black_frame)
+{
+       /* this function desperately needs to be moved to the ISP or SP such
+        * that it can use the DMA.
+        */
+       unsigned int height = raw_black_frame->info.height,
+                    width = raw_black_frame->info.padded_width,
+                    y, x, k, data;
+       void *ptr = raw_black_frame->planes.raw.data;
+
+       if (fpn_table.data &&
+           (fpn_table.width != width || fpn_table.height != height)) {
+               sh_css_free(fpn_table.data);
+               fpn_table.data = NULL;
+       }
+       if (fpn_table.data == NULL) {
+               fpn_table.data = sh_css_malloc(height * width * sizeof(short));
+               if (!fpn_table.data)
+                       return sh_css_err_cannot_allocate_memory;
+               fpn_table.width = width;
+               fpn_table.height = height;
+               fpn_table.shift = 0;
+       }
+
+       /* store raw to fpntbl */
+       for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x += (ISP_VEC_NELEMS * 2)) {
+                       int ofs = y * width + x;
+                       for (k = 0; k < ISP_VEC_NELEMS; k += 2) {
+                               hrt_isp_css_mm_load(ptr, &data, sizeof(int));
+                               fpn_table.data[ofs + 2 * k] =
+                                   (short) (data & 0xFFFF);
+                               fpn_table.data[ofs + 2 * k + 2] =
+                                   (short) ((data >> 16) & 0xFFFF);
+                               ptr += 4;       /* byte system address */
+                       }
+                       for (k = 0; k < ISP_VEC_NELEMS; k += 2) {
+                               hrt_isp_css_mm_load(ptr, &data, sizeof(int));
+                               fpn_table.data[ofs + 2 * k + 1] =
+                                   (short) (data & 0xFFFF);
+                               fpn_table.data[ofs + 2 * k + 3] =
+                                   (short) ((data >> 16) & 0xFFFF);
+                               ptr += 4;       /* byte system address */
+                       }
+               }
+       }
+
+       /* raw -> fpn */
+       convert_raw_to_fpn();
+
+       /* overwrite isp parameter */
+       isp_parameters.fpn_shift = fpn_table.shift;
+       isp_parameters.fpn_enabled = 1;
+       fpn_table_changed = true;
+       isp_params_changed = true;
+       return sh_css_success;
+}
+
+struct sh_css_shading_table *
+sh_css_shading_table_alloc(unsigned int width,
+                          unsigned int height)
+{
+       unsigned int i;
+       struct sh_css_shading_table *me = sh_css_malloc(sizeof(*me));
+
+       if (me == NULL)
+               return NULL;
+       me->width         = width;
+       me->height        = height;
+       me->sensor_width  = 0;
+       me->sensor_height = 0;
+       me->fraction_bits = 0;
+       for (i = 0; i < SH_CSS_SC_NUM_COLORS; i++) {
+               me->data[i] =
+                   sh_css_malloc(width * height * sizeof(*me->data[0]));
+               if (me->data[i] == NULL) {
+                       unsigned int j;
+                       for (j = 0; j < i; j++)
+                               sh_css_free(me->data[j]);
+                       sh_css_free(me);
+                       return NULL;
+               }
+       }
+       return me;
+}
+
+void
+sh_css_shading_table_free(struct sh_css_shading_table *table)
+{
+       unsigned int i;
+
+       if (table == NULL)
+               return;
+       for (i = 0; i < SH_CSS_SC_NUM_COLORS; i++) {
+               if (table->data[i])
+                       sh_css_free(table->data[i]);
+       }
+       sh_css_free(table);
+}
+
+void
+sh_css_params_set_shading_table(const struct sh_css_shading_table *table)
+{
+       if (table != sc_table) {
+               sc_table = table;
+               sc_table_changed = true;
+       }
+}
+
+static void
+store_sctbl(const struct sh_css_binary *binary,
+           void *ddr_addr)
+{
+       unsigned int i, j, aligned_width, row_padding;
+
+       if (!sc_table)
+               return;
+
+       aligned_width = binary->sctbl_aligned_width_per_color;
+       isp_parameters.sc_gain_shift = sc_table->fraction_bits;
+       row_padding = aligned_width - sc_table->width;
+
+       for (i = 0; i < sc_table->height; i++) {
+               for (j = 0; j < SH_CSS_SC_NUM_COLORS; j++) {
+                       hrt_isp_css_mm_store(ddr_addr,
+                                       &sc_table->data[j][i*sc_table->width],
+                                       sc_table->width * sizeof(short));
+                       ddr_addr += sc_table->width * sizeof(short);
+                       hrt_isp_css_mm_set(ddr_addr, 0,
+                                               row_padding * sizeof(short));
+                       ddr_addr += row_padding * sizeof(short);
+               }
+       }
+       isp_params_changed = true;
+}
+
+static void
+sh_css_process_wb(void)
+{
+       isp_parameters.wb_gain_shift =
+           uISP_REG_BIT - wb_config->integer_bits;
+       isp_parameters.wb_gain_gr =
+           uDIGIT_FITTING(wb_config->gr, 16 - wb_config->integer_bits,
+                          isp_parameters.wb_gain_shift);
+       isp_parameters.wb_gain_r =
+           uDIGIT_FITTING(wb_config->r, 16 - wb_config->integer_bits,
+                          isp_parameters.wb_gain_shift);
+       isp_parameters.wb_gain_b =
+           uDIGIT_FITTING(wb_config->b, 16 - wb_config->integer_bits,
+                          isp_parameters.wb_gain_shift);
+       isp_parameters.wb_gain_gb =
+           uDIGIT_FITTING(wb_config->gb, 16 - wb_config->integer_bits,
+                          isp_parameters.wb_gain_shift);
+       isp_params_changed = true;
+       wb_config_changed = false;
+}
+
+static void
+sh_css_process_cc(void)
+{
+       isp_parameters.csc_coef_shift    = (int) cc_config->fraction_bits;
+       isp_parameters.yc1c2_to_ycbcr_00 = (int) cc_config->matrix[0];
+       isp_parameters.yc1c2_to_ycbcr_01 = (int) cc_config->matrix[1];
+       isp_parameters.yc1c2_to_ycbcr_02 = (int) cc_config->matrix[2];
+       isp_parameters.yc1c2_to_ycbcr_10 = (int) cc_config->matrix[3];
+       isp_parameters.yc1c2_to_ycbcr_11 = (int) cc_config->matrix[4];
+       isp_parameters.yc1c2_to_ycbcr_12 = (int) cc_config->matrix[5];
+       isp_parameters.yc1c2_to_ycbcr_20 = (int) cc_config->matrix[6];
+       isp_parameters.yc1c2_to_ycbcr_21 = (int) cc_config->matrix[7];
+       isp_parameters.yc1c2_to_ycbcr_22 = (int) cc_config->matrix[8];
+       isp_params_changed = true;
+       cc_config_changed = false;
+}
+
+static void
+sh_css_process_tnr(void)
+{
+       isp_parameters.tnr_coef =
+           uDIGIT_FITTING(tnr_config->gain, 16, SH_CSS_TNR_COEF_SHIFT);
+       isp_parameters.tnr_threshold_Y =
+           uDIGIT_FITTING(tnr_config->threshold_y, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.tnr_threshold_C =
+           uDIGIT_FITTING(tnr_config->threshold_uv, 16, SH_CSS_BAYER_BITS);
+       isp_params_changed = true;
+       tnr_config_changed = false;
+}
+
+static void
+sh_css_process_ob(void)
+{
+       unsigned int raw_bit_depth = 16;
+       switch (ob_config->mode) {
+       case sh_css_ob_mode_fixed:
+               if (current_3a_binary)
+                       raw_bit_depth
+                         = current_3a_binary->in_frame_info.raw_bit_depth;
+               isp_parameters.ob_blacklevel_gr
+                       = ob_config->level_gr >> (16 - raw_bit_depth);
+               isp_parameters.ob_blacklevel_r
+                       = ob_config->level_r  >> (16 - raw_bit_depth);
+               isp_parameters.ob_blacklevel_b
+                       = ob_config->level_b  >> (16 - raw_bit_depth);
+               isp_parameters.ob_blacklevel_gb
+                       = ob_config->level_gb >> (16 - raw_bit_depth);
+               isp_parameters.obarea_start_bq = 0;
+               isp_parameters.obarea_length_bq = 0;
+               isp_parameters.obarea_length_bq_inverse = 0;
+               break;
+       case sh_css_ob_mode_raster:
+               isp_parameters.ob_blacklevel_gr = 0;
+               isp_parameters.ob_blacklevel_r = 0;
+               isp_parameters.ob_blacklevel_b = 0;
+               isp_parameters.ob_blacklevel_gb = 0;
+               isp_parameters.obarea_start_bq =
+                   ob_config->start_position;
+               isp_parameters.obarea_length_bq =
+                   ((ob_config->end_position - ob_config->start_position) + 1);
+               isp_parameters.obarea_length_bq_inverse =
+                   (1 << 12) / isp_parameters.obarea_length_bq;
+               break;
+       default:
+               isp_parameters.ob_blacklevel_gr = 0;
+               isp_parameters.ob_blacklevel_r = 0;
+               isp_parameters.ob_blacklevel_b = 0;
+               isp_parameters.ob_blacklevel_gb = 0;
+               isp_parameters.obarea_start_bq = 0;
+               isp_parameters.obarea_length_bq = 0;
+               isp_parameters.obarea_length_bq_inverse = 0;
+               break;
+       }
+       isp_params_changed = true;
+       ob_config_changed = false;
+}
+
+static void
+sh_css_process_dp(void)
+{
+       isp_parameters.dp_threshold_single_when_2adjacent_on =
+           SH_CSS_BAYER_MAXVAL;
+       isp_parameters.dp_threshold_2adjacent_when_2adjacent_on =
+           uDIGIT_FITTING(dp_config->threshold, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.dp_threshold_single_when_2adjacent_off =
+           uDIGIT_FITTING(dp_config->threshold, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.dp_threshold_2adjacent_when_2adjacent_off =
+           SH_CSS_BAYER_MAXVAL;
+       isp_parameters.dp_gain =
+           uDIGIT_FITTING(dp_config->gain, 8, SH_CSS_DP_GAIN_SHIFT);
+       isp_params_changed = true;
+       dp_config_changed = false;
+}
+
+static void
+sh_css_process_nr_ee(void)
+{
+       int asiWk1, asiWk2, asiWk3;
+
+       /* BNR (Bayer Noise Reduction) */
+       isp_parameters.bnr_threshold_low =
+           uDIGIT_FITTING(nr_config->direction, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.bnr_threshold_width_log2 = uFRACTION_BITS_FITTING(8);
+       isp_parameters.bnr_threshold_width =
+           1 << isp_parameters.bnr_threshold_width_log2;
+       isp_parameters.bnr_gain_all =
+           uDIGIT_FITTING(nr_config->gain, 16, SH_CSS_BNR_GAIN_SHIFT);
+       isp_parameters.bnr_gain_dir =
+           uDIGIT_FITTING(nr_config->gain, 16, SH_CSS_BNR_GAIN_SHIFT);
+       isp_parameters.bnr_clip = uDIGIT_FITTING(16384, 16, SH_CSS_BAYER_BITS);
+
+       /* YNR (Y Noise Reduction), YEE (Y Edge Enhancement) */
+       asiWk1 = (int) ee_config->gain;
+       asiWk2 = asiWk1 / 8;
+       asiWk3 = asiWk1 / 4;
+       isp_parameters.ynr_threshold =
+               uDIGIT_FITTING(8192, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.ynr_gain_dir = isp_parameters.bnr_gain_dir / 2;
+       isp_parameters.ynr_gain_all = isp_parameters.bnr_gain_all / 2;
+       isp_parameters.ynryee_dirthreshold_s =
+           min((uDIGIT_FITTING(nr_config->direction, 16, SH_CSS_BAYER_BITS)
+                                   << 1),
+               SH_CSS_BAYER_MAXVAL);
+       isp_parameters.ynryee_dirthreshold_g =
+           min((uDIGIT_FITTING(nr_config->direction, 16, SH_CSS_BAYER_BITS)
+                                   << 4),
+               SH_CSS_BAYER_MAXVAL);
+       isp_parameters.ynryee_dirthreshold_width_log2 =
+           uFRACTION_BITS_FITTING(8);
+       isp_parameters.ynryee_dirthreshold_width =
+           1 << isp_parameters.ynryee_dirthreshold_width_log2;
+       isp_parameters.yee_detailgain =
+           uDIGIT_FITTING(ee_config->detail_gain, 11,
+                          SH_CSS_YEE_DETAIL_GAIN_SHIFT);
+       isp_parameters.yee_coring_s =
+           (uDIGIT_FITTING(56, 16, SH_CSS_BAYER_BITS) *
+            ee_config->threshold) >> 8;
+       isp_parameters.yee_coring_g =
+           (uDIGIT_FITTING(224, 16, SH_CSS_BAYER_BITS) *
+            ee_config->threshold) >> 8;
+       /* 8; // *1.125 ->[s4.8] */
+       isp_parameters.yee_scale_plus_s =
+           (asiWk1 + asiWk2) >> (11 - SH_CSS_YEE_SCALE_SHIFT);
+       /* 8; // ( * -.25)->[s4.8] */
+       isp_parameters.yee_scale_plus_g =
+           (0 - asiWk3) >> (11 - SH_CSS_YEE_SCALE_SHIFT);
+       /* 8; // *0.875 ->[s4.8] */
+       isp_parameters.yee_scale_minus_s =
+           (asiWk1 - asiWk2) >> (11 - SH_CSS_YEE_SCALE_SHIFT);
+       /* 8; // ( *.25 ) ->[s4.8] */
+       isp_parameters.yee_scale_minus_g =
+           (asiWk3) >> (11 - SH_CSS_YEE_SCALE_SHIFT);
+       isp_parameters.yee_clip_plus_s =
+           uDIGIT_FITTING(32760, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.yee_clip_plus_g = 0;
+       isp_parameters.yee_clip_minus_s =
+           uDIGIT_FITTING(504, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.yee_clip_minus_g =
+           uDIGIT_FITTING(32256, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.ynryee_Yclip = SH_CSS_BAYER_MAXVAL;
+       isp_params_changed = true;
+       nr_config_changed = false;
+       ee_config_changed = false;
+}
+
+static void
+sh_css_process_de(void)
+{
+       isp_parameters.de_pixelnoise =
+           uDIGIT_FITTING(de_config->pixelnoise, 16, SH_CSS_BAYER_BITS);
+       isp_parameters.de_c1_coring_threshold =
+           uDIGIT_FITTING(de_config->c1_coring_threshold, 16,
+                          SH_CSS_BAYER_BITS);
+       isp_parameters.de_c2_coring_threshold =
+           uDIGIT_FITTING(de_config->c2_coring_threshold, 16,
+                          SH_CSS_BAYER_BITS);
+       isp_params_changed = true;
+       de_config_changed = false;
+}
+
+static void
+sh_css_process_gc(void)
+{
+       isp_parameters.gamma_gain_k1 = gc_config->gain_k1;
+       isp_parameters.gamma_gain_k2 = gc_config->gain_k2;
+       isp_params_changed = true;
+       gc_config_changed = false;
+}
+
+static void
+sh_css_process_anr(void)
+{
+       isp_parameters.anr_threshold = anr_config->threshold;
+       isp_params_changed = true;
+       anr_config_changed = false;
+}
+
+void
+sh_css_set_gamma_table(const struct sh_css_gamma_table *table)
+{
+       gamma_table = table;
+       gamma_table_changed = true;
+}
+
+void
+sh_css_get_gamma_table(const struct sh_css_gamma_table **table)
+{
+       *table = gamma_table;
+}
+
+void
+sh_css_set_ctc_table(const struct sh_css_ctc_table *table)
+{
+       ctc_table = table;
+       ctc_table_changed = true;
+}
+
+void
+sh_css_get_ctc_table(const struct sh_css_ctc_table **table)
+{
+       *table = ctc_table;
+}
+
+void
+sh_css_set_macc_table(const struct sh_css_macc_table *table)
+{
+       macc_table = table;
+       macc_table_changed = true;
+}
+
+void
+sh_css_get_macc_table(const struct sh_css_macc_table **table)
+{
+       *table = macc_table;
+}
+
+void
+sh_css_morph_table_free(struct sh_css_morph_table *me)
+{
+       unsigned int i;
+
+       if (me == NULL)
+               return;
+
+       for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+               if (me->coordinates_x[i])
+                       sh_css_free(me->coordinates_x[i]);
+               if (me->coordinates_y[i])
+                       sh_css_free(me->coordinates_y[i]);
+       }
+       sh_css_free(me);
+}
+
+struct sh_css_morph_table *
+sh_css_morph_table_allocate(unsigned int width, unsigned int height)
+{
+       unsigned int i;
+       struct sh_css_morph_table *me = sh_css_malloc(sizeof(*me));
+
+       if (!me)
+               return NULL;
+
+       for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+               me->coordinates_x[i] = NULL;
+               me->coordinates_y[i] = NULL;
+       }
+
+       for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+               me->coordinates_x[i] =
+                   sh_css_malloc(height * width *
+                                 sizeof(*me->coordinates_x[i]));
+               me->coordinates_y[i] =
+                   sh_css_malloc(height * width *
+                                 sizeof(*me->coordinates_y[i]));
+               if (!me->coordinates_x[i] || !me->coordinates_y[i]) {
+                       sh_css_morph_table_free(me);
+                       return NULL;
+               }
+       }
+       me->width = width;
+       me->height = height;
+       return me;
+}
+
+static enum sh_css_err
+sh_css_params_default_morph_table(struct sh_css_morph_table **table,
+                                 const struct sh_css_binary *binary)
+{
+       unsigned int i, j, k,
+                    step = (ISP_VEC_NELEMS / 16) * 128,
+                    width = binary->morph_tbl_width,
+                    height = binary->morph_tbl_height;
+       short start_x[SH_CSS_MORPH_TABLE_NUM_PLANES] = { -8, 0, -8, 0, 0, -8 },
+             start_y[SH_CSS_MORPH_TABLE_NUM_PLANES] = { 0, 0, -8, -8, -8, 0 };
+       struct sh_css_morph_table *tab;
+
+       tab = sh_css_morph_table_allocate(width, height);
+       if (!tab)
+               return sh_css_err_cannot_allocate_memory;
+
+       for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+               short val_y = start_y[i];
+               for (j = 0; j < height; j++) {
+                       short val_x = start_x[i];
+                       unsigned short *x_ptr, *y_ptr;
+
+                       x_ptr = &tab->coordinates_x[i][j * width];
+                       y_ptr = &tab->coordinates_y[i][j * width];
+                       for (k = 0; k < width;
+                            k++, x_ptr++, y_ptr++, val_x += step) {
+                               if (k == 0)
+                                       *x_ptr = 0;
+                               else if (k == width - 1)
+                                       *x_ptr = val_x + 2 * start_x[i];
+                               else
+                                       *x_ptr = val_x;
+                               if (j == 0)
+                                       *y_ptr = 0;
+                               else
+                                       *y_ptr = val_y;
+                       }
+                       val_y += step;
+               }
+       }
+       *table = tab;
+
+       return sh_css_success;
+}
+
+void
+sh_css_set_morph_table(const struct sh_css_morph_table *table)
+{
+       morph_table = table;
+       morph_table_changed = true;
+}
+
+void
+sh_css_get_morph_table(const struct sh_css_morph_table **table)
+{
+       *table = morph_table;
+}
+
+enum sh_css_err
+sh_css_get_3a_statistics(struct sh_css_3a_output *output)
+{
+       if (!current_3a_binary)
+               return sh_css_err_internal_error;
+
+       if (current_3a_binary->info->s3atbl_use_dmem)
+               get_3a_stats_from_dmem(output);
+       else
+               get_3a_stats_from_vmem(output);
+       return sh_css_success;
+}
+
+void
+sh_css_set_3a_config(const struct sh_css_3a_config *config)
+{
+       if (config)
+               s3a_config = config;
+       else
+               s3a_config = &disabled_3a_config;
+       s3a_config_changed = true;
+}
+
+void
+sh_css_get_3a_config(const struct sh_css_3a_config **config)
+{
+       *config = s3a_config;
+}
+
+void
+sh_css_set_wb_config(const struct sh_css_wb_config *config)
+{
+       if (config)
+               wb_config = config;
+       else
+               wb_config = &disabled_wb_config;
+       wb_config_changed = true;
+}
+
+void
+sh_css_get_wb_config(const struct sh_css_wb_config **config)
+{
+       *config = wb_config;
+}
+
+void
+sh_css_set_cc_config(const struct sh_css_cc_config *config)
+{
+       if (config)
+               cc_config = config;
+       else
+               cc_config = &disabled_cc_config;
+       cc_config_changed = true;
+}
+
+void
+sh_css_get_cc_config(const struct sh_css_cc_config **config)
+{
+       *config = cc_config;
+}
+
+void
+sh_css_set_tnr_config(const struct sh_css_tnr_config *config)
+{
+       if (config)
+               tnr_config = config;
+       else
+               tnr_config = &disabled_tnr_config;
+       tnr_config_changed = true;
+}
+
+void
+sh_css_get_tnr_config(const struct sh_css_tnr_config **config)
+{
+       *config = tnr_config;
+}
+
+void
+sh_css_set_ob_config(const struct sh_css_ob_config *config)
+{
+       if (config)
+               ob_config = config;
+       else
+               ob_config = &disabled_ob_config;
+       ob_config_changed = true;
+}
+
+void
+sh_css_get_ob_config(const struct sh_css_ob_config **config)
+{
+       *config = ob_config;
+}
+
+void
+sh_css_set_dp_config(const struct sh_css_dp_config *config)
+{
+       if (config)
+               dp_config = config;
+       else
+               dp_config = &disabled_dp_config;
+       dp_config_changed = true;
+}
+
+void
+sh_css_get_dp_config(const struct sh_css_dp_config **config)
+{
+       *config = dp_config;
+}
+
+void
+sh_css_set_nr_config(const struct sh_css_nr_config *config)
+{
+       if (config)
+               nr_config = config;
+       else
+               nr_config = &disabled_nr_config;
+       nr_config_changed = true;
+}
+
+void
+sh_css_get_nr_config(const struct sh_css_nr_config **config)
+{
+       *config = nr_config;
+}
+
+void
+sh_css_set_ee_config(const struct sh_css_ee_config *config)
+{
+       if (config)
+               ee_config = config;
+       else
+               ee_config = &disabled_ee_config;
+       ee_config_changed = true;
+}
+
+void
+sh_css_get_ee_config(const struct sh_css_ee_config **config)
+{
+       *config = ee_config;
+}
+
+void
+sh_css_set_de_config(const struct sh_css_de_config *config)
+{
+       if (config)
+               de_config = config;
+       else
+               de_config = &disabled_de_config;
+       de_config_changed = true;
+}
+
+void
+sh_css_get_de_config(const struct sh_css_de_config **config)
+{
+       *config = de_config;
+}
+
+void
+sh_css_set_gc_config(const struct sh_css_gc_config *config)
+{
+       if (config)
+               gc_config = config;
+       else
+               gc_config = &disabled_gc_config;
+       gc_config_changed = true;
+}
+
+void
+sh_css_get_gc_config(const struct sh_css_gc_config **config)
+{
+       *config = gc_config;
+}
+
+void
+sh_css_set_anr_config(const struct sh_css_anr_config *config)
+{
+       if (config)
+               anr_config = config;
+       else
+               anr_config = &default_anr_config;
+       anr_config_changed = true;
+}
+
+void
+sh_css_get_anr_config(const struct sh_css_anr_config **config)
+{
+       *config = anr_config;
+}
+
+void
+sh_css_set_anr_threshold(int threshold)
+{
+       struct sh_css_anr_config
+       **config = sh_css_malloc(sizeof(struct sh_css_anr_config *));
+       sh_css_get_anr_config((const struct sh_css_anr_config **)config);
+       (*config)->threshold = threshold;
+       sh_css_set_anr_config(*config);
+       if (config)
+               sh_css_free(config);
+}
+
+static bool
+alloc(void **ptr, unsigned int bytes)
+{
+       void *p = hrt_isp_css_mm_alloc(bytes);
+       if (p == NULL)
+               return false;
+       *ptr = p;
+       return true;
+}
+
+static inline bool
+realloc_buf(void **curr_buf, size_t *curr_size,
+           size_t needed_size, enum sh_css_err *err,
+           bool cached)
+{
+       /* Possible optimization: add a function hrt_isp_css_mm_realloc()
+        * and implement on top of hmm. */
+       if (*curr_size >= needed_size)
+               return false;
+       if (*curr_buf)
+               hrt_isp_css_mm_free(*curr_buf);
+       if (cached)
+               *curr_buf = hrt_isp_css_mm_alloc_cached(needed_size);
+       else
+               *curr_buf = hrt_isp_css_mm_alloc(needed_size);
+       if (!*curr_buf) {
+               *err = sh_css_err_cannot_allocate_memory;
+               *curr_size = 0;
+       } else {
+               *curr_size = needed_size;
+       }
+       return true;
+}
+
+static inline bool
+reallocate_buffer(void **curr_buf, size_t *curr_size,
+                 size_t needed_size, enum sh_css_err *err)
+{
+       return realloc_buf(curr_buf, curr_size, needed_size, err, false);
+}
+
+static inline bool
+reallocate_cached_buffer(void **curr_buf, size_t *curr_size,
+                        size_t needed_size, enum sh_css_err *err)
+{
+       return realloc_buf(curr_buf, curr_size, needed_size, err, true);
+}
+
+static enum sh_css_err
+reallocate_buffers(const struct sh_css_binary *binary)
+{
+       bool changed = false;
+       enum sh_css_err err = sh_css_success;
+
+       if (binary->info->enable_fpnr) {
+               changed |= reallocate_buffer(&ddr_ptrs.fpn_tbl, &fpn_tbl_size,
+                                            FPNTBL_BYTES(binary), &err);
+       }
+       if (binary->info->enable_sc) {
+               changed |= reallocate_buffer(&ddr_ptrs.sc_tbl, &sc_tbl_size,
+                                            SCTBL_BYTES(binary), &err);
+       }
+       if (binary->info->enable_s3a && binary->info->s3atbl_use_dmem) {
+               changed |= reallocate_cached_buffer(&ddr_ptrs.s3a_tbl,
+                                                   &s3a_tbl_size,
+                                                   S3ATBL_BYTES(binary), &err);
+       }
+       if (binary->info->enable_s3a && !binary->info->s3atbl_use_dmem) {
+               changed |= reallocate_cached_buffer(&ddr_ptrs.s3a_tbl_hi,
+                                                   &s3a_tbl_hi_size,
+                                                   S3ATBL_HI_LO_BYTES(binary),
+                                                   &err);
+               changed |= reallocate_cached_buffer(&ddr_ptrs.s3a_tbl_lo,
+                                                   &s3a_tbl_lo_size,
+                                                   S3ATBL_HI_LO_BYTES(binary),
+                                                   &err);
+       }
+       if (binary->info->enable_dis) {
+               changed |= reallocate_buffer(&ddr_ptrs.sdis_hor_coef,
+                                            &sdis_hor_coef_size,
+                                            SDIS_HOR_COEF_TBL_BYTES(binary),
+                                            &err);
+               changed |= reallocate_buffer(&ddr_ptrs.sdis_ver_coef,
+                                            &sdis_ver_coef_size,
+                                            SDIS_VER_COEF_TBL_BYTES(binary),
+                                            &err);
+               changed |= reallocate_buffer(&ddr_ptrs.sdis_hor_proj,
+                                            &sdis_hor_proj_size,
+                                            SDIS_HOR_PROJ_TBL_BYTES(binary),
+                                            &err);
+               changed |= reallocate_buffer(&ddr_ptrs.sdis_ver_proj,
+                                            &sdis_ver_proj_size,
+                                            SDIS_VER_PROJ_TBL_BYTES(binary),
+                                            &err);
+       }
+       if (binary->info->mode == SH_CSS_BINARY_MODE_GDC) {
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_r_x,
+                                            &tetra_r_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_r_y,
+                                            &tetra_r_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_gr_x,
+                                            &tetra_gr_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_gr_y,
+                                            &tetra_gr_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_gb_x,
+                                            &tetra_gb_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_gb_y,
+                                            &tetra_gb_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_b_x,
+                                            &tetra_b_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_b_y,
+                                            &tetra_b_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_ratb_x,
+                                            &tetra_ratb_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_ratb_y,
+                                            &tetra_ratb_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_batr_x,
+                                            &tetra_batr_x_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+               changed |= reallocate_buffer(&ddr_ptrs.tetra_batr_y,
+                                            &tetra_batr_y_size,
+                                            MORPH_PLANE_BYTES(binary), &err);
+       }
+       if (changed)
+               hrt_isp_css_mm_store(sp_ddr_ptrs, &ddr_ptrs, sizeof(ddr_ptrs));
+       return err;
+}
+
+enum sh_css_err
+sh_css_params_init(void)
+{
+       bool succ = true;
+
+       memset(&ddr_ptrs, 0, sizeof(ddr_ptrs));
+       succ &= alloc(&ddr_ptrs.isp_param, sizeof(struct sh_css_isp_params));
+       succ &= alloc(&ddr_ptrs.ctc_tbl,   sizeof(struct sh_css_ctc_table));
+       succ &= alloc(&ddr_ptrs.gamma_tbl, sizeof(struct sh_css_gamma_table));
+       succ &= alloc(&ddr_ptrs.macc_tbl,  sizeof(struct sh_css_macc_table));
+       fpn_tbl_size = 0;
+       sc_tbl_size = 0;
+       s3a_tbl_size = 0;
+       s3a_tbl_hi_size = 0;
+       s3a_tbl_lo_size = 0;
+       sdis_hor_coef_size = 0;
+       sdis_ver_coef_size = 0;
+       sdis_hor_proj_size = 0;
+       sdis_ver_proj_size = 0;
+       tetra_r_x_size = 0;
+       tetra_r_y_size = 0;
+       tetra_gr_x_size = 0;
+       tetra_gr_y_size = 0;
+       tetra_gb_x_size = 0;
+       tetra_gb_y_size = 0;
+       tetra_b_x_size = 0;
+       tetra_b_y_size = 0;
+       tetra_batr_x_size = 0;
+       tetra_batr_y_size = 0;
+       tetra_ratb_x_size = 0;
+       tetra_ratb_y_size = 0;
+
+       sp_ddr_ptrs = hrt_isp_css_mm_calloc(CEIL_MUL(sizeof(ddr_ptrs),
+                                                    HIVE_ISP_DDR_WORD_BYTES));
+       xmem_sp_group_ptrs = hrt_isp_css_mm_calloc
+               (sizeof(struct sh_css_sp_group));
+       if (!succ || !sp_ddr_ptrs || !xmem_sp_group_ptrs) {
+               sh_css_uninit();
+               return sh_css_err_cannot_allocate_memory;
+       }
+       /* Copy XMEM address map to XMEM for SP access */
+       hrt_isp_css_mm_store(sp_ddr_ptrs, &ddr_ptrs, sizeof(ddr_ptrs));
+       sh_css_set_3a_config(&default_3a_config);
+       sh_css_set_wb_config(&default_wb_config);
+       sh_css_set_cc_config(&default_cc_config);
+       sh_css_set_tnr_config(&default_tnr_config);
+       sh_css_set_ob_config(&default_ob_config);
+       sh_css_set_dp_config(&default_dp_config);
+       sh_css_set_nr_config(&default_nr_config);
+       sh_css_set_ee_config(&default_ee_config);
+       sh_css_set_de_config(&default_de_config);
+       sh_css_set_gc_config(&default_gc_config);
+       sh_css_set_macc_table(&default_macc_table);
+       sh_css_set_gamma_table(&default_gamma_table);
+       sh_css_set_ctc_table(&default_ctc_table);
+       sh_css_hrt_gdc_set_lut(zoom_table);
+       fpn_table_changed = true;
+       isp_parameters.fpn_enabled = 0;
+       morph_table = NULL;
+       morph_table_changed = true;
+       sc_table = NULL;
+       sc_table_changed = false;
+       return sh_css_success;
+}
+
+void
+sh_css_params_reconfigure_gdc_lut(void)
+{
+       sh_css_hrt_gdc_set_lut(zoom_table);
+}
+
+static void
+safe_free(void *ptr)
+{
+       if (ptr)
+               hrt_isp_css_mm_free(ptr);
+}
+
+void
+sh_css_params_uninit(void)
+{
+       safe_free(ddr_ptrs.isp_param);
+       safe_free(ddr_ptrs.ctc_tbl);
+       safe_free(ddr_ptrs.gamma_tbl);
+       safe_free(ddr_ptrs.macc_tbl);
+       safe_free(ddr_ptrs.fpn_tbl);
+       safe_free(ddr_ptrs.sc_tbl);
+       safe_free(ddr_ptrs.s3a_tbl);
+       safe_free(ddr_ptrs.s3a_tbl_hi);
+       safe_free(ddr_ptrs.s3a_tbl_lo);
+       safe_free(ddr_ptrs.sdis_hor_coef);
+       safe_free(ddr_ptrs.sdis_ver_coef);
+       safe_free(ddr_ptrs.sdis_hor_proj);
+       safe_free(ddr_ptrs.sdis_ver_proj);
+       safe_free(ddr_ptrs.tetra_r_x);
+       safe_free(ddr_ptrs.tetra_r_y);
+       safe_free(ddr_ptrs.tetra_gr_x);
+       safe_free(ddr_ptrs.tetra_gr_y);
+       safe_free(ddr_ptrs.tetra_gb_x);
+       safe_free(ddr_ptrs.tetra_gb_y);
+       safe_free(ddr_ptrs.tetra_b_x);
+       safe_free(ddr_ptrs.tetra_b_y);
+       safe_free(ddr_ptrs.tetra_ratb_x);
+       safe_free(ddr_ptrs.tetra_ratb_y);
+       safe_free(ddr_ptrs.tetra_batr_x);
+       safe_free(ddr_ptrs.tetra_batr_y);
+       safe_free(sp_ddr_ptrs);
+       safe_free(xmem_sp_group_ptrs);
+       if (fpn_table.data)
+               sh_css_free(fpn_table.data);
+}
+
+static void write_morph_plane(unsigned short *data,
+                             unsigned int width,
+                             unsigned int height,
+                             void *dest,
+                             unsigned int aligned_width)
+{
+       unsigned int i, padding, w;
+
+       /* currently we don't have morph table interpolation yet,
+        * so we allow a wider table to be used. This will be removed
+        * in the future. */
+       if (width > aligned_width) {
+               padding = 0;
+               w = aligned_width;
+       } else {
+               padding = aligned_width - width;
+               w = width;
+       }
+
+       for (i = 0; i < height; i++) {
+               hrt_isp_css_mm_store(dest, data, w * sizeof(short));
+               dest += w * sizeof(short);
+               hrt_isp_css_mm_set(dest, 0, padding * sizeof(short));
+               dest += padding * sizeof(short);
+               data += width;
+       }
+}
+
+/* Store the DIS coefficients from the 3A library to DDR where the ISP
+   will read them from. The ISP works on a grid that can be larger than
+   that of the 3a library. If that is the case, we padd the difference
+   with zeroes. */
+static void
+store_dis_coefficients(const struct sh_css_binary *binary)
+{
+       unsigned int hor_num_isp = binary->dis_hor_coef_num_isp,
+                    ver_num_isp = binary->dis_ver_coef_num_isp,
+                    hor_num_3a  = binary->dis_hor_coef_num_3a,
+                    ver_num_3a  = binary->dis_ver_coef_num_3a,
+                    hor_padding = hor_num_isp - hor_num_3a,
+                    ver_padding = ver_num_isp - ver_num_3a,
+                    i;
+       const short *hor_ptr_3a = dis_hor_coef_tbl,
+                   *ver_ptr_3a = dis_ver_coef_tbl;
+       short *hor_ptr_isp = ddr_ptrs.sdis_hor_coef,
+             *ver_ptr_isp = ddr_ptrs.sdis_ver_coef;
+
+       for (i = 0; i < SH_CSS_DIS_NUM_COEF_TYPES; i++) {
+               hrt_isp_css_mm_store(hor_ptr_isp, hor_ptr_3a,
+                                    hor_num_3a * sizeof(*hor_ptr_3a));
+               hor_ptr_3a  += hor_num_3a;
+               hor_ptr_isp += hor_num_3a;
+               hrt_isp_css_mm_set(hor_ptr_isp, 0,
+                                       hor_padding * sizeof(short));
+               hor_ptr_isp += hor_padding;
+       }
+       for (i = 0; i < SH_CSS_DIS_VER_NUM_COEF_TYPES(binary); i++) {
+               hrt_isp_css_mm_store(ver_ptr_isp, ver_ptr_3a,
+                                    ver_num_3a * sizeof(*ver_ptr_3a));
+               ver_ptr_3a  += ver_num_3a;
+               ver_ptr_isp += ver_num_3a;
+               hrt_isp_css_mm_set(ver_ptr_isp, 0,
+                                       ver_padding * sizeof(short));
+               ver_ptr_isp += ver_padding;
+       }
+       dis_coef_table_changed = false;
+}
+
+enum sh_css_err
+sh_css_params_write_to_ddr(const struct sh_css_binary *binary)
+{
+       enum sh_css_err err;
+
+       err = reallocate_buffers(binary);
+       if (err != sh_css_success)
+               return err;
+
+       if (fpn_table_changed && binary->info->enable_fpnr) {
+               if (isp_parameters.fpn_enabled) {
+                       store_fpntbl(ddr_ptrs.fpn_tbl);
+               } else if (SH_CSS_PREVENT_UNINIT_READS) {
+                       int *ptr = ddr_ptrs.fpn_tbl;
+                       /* prevent warnings when reading fpn table in csim.
+                          Actual values are not used when fpn is disabled. */
+                       hrt_isp_css_mm_set(ptr, 0, fpn_tbl_size);
+               }
+               fpn_table_changed = false;
+       }
+       if (sc_table_changed && binary->info->enable_sc) {
+               store_sctbl(binary, ddr_ptrs.sc_tbl);
+               sc_table_changed = false;
+       }
+
+       if (s3a_config && s3a_config_changed)
+               sh_css_process_3a();
+       if (wb_config && wb_config_changed)
+               sh_css_process_wb();
+       if (cc_config && cc_config_changed)
+               sh_css_process_cc();
+       if (tnr_config && tnr_config_changed)
+               sh_css_process_tnr();
+       if (ob_config && ob_config_changed)
+               sh_css_process_ob();
+       if (dp_config && dp_config_changed)
+               sh_css_process_dp();
+       if (nr_config && ee_config && (nr_config_changed || ee_config_changed))
+               sh_css_process_nr_ee();
+       if (de_config && de_config_changed)
+               sh_css_process_de();
+       if (gc_config && gc_config_changed)
+               sh_css_process_gc();
+       if (anr_config && anr_config_changed)
+               sh_css_process_anr();
+
+       if (isp_params_changed) {
+               if (SH_CSS_PREVENT_UNINIT_READS) {
+                       /* ispparm struct is read with DMA which reads
+                        * multiples of the DDR word with (32 bytes):
+                        * So we pad with zeroes to prevent warnings in csim.
+                        */
+                       unsigned int aligned_width, padding_bytes;
+                       char *pad_ptr;
+
+                       aligned_width = CEIL_MUL(
+                                         sizeof(struct sh_css_isp_params),
+                                         HIVE_ISP_DDR_WORD_BYTES);
+                       padding_bytes = aligned_width -
+                                       sizeof(struct sh_css_isp_params);
+                       pad_ptr = ddr_ptrs.isp_param +
+                                       sizeof(struct sh_css_isp_params);
+                       hrt_isp_css_mm_set(pad_ptr, 0, padding_bytes);
+               }
+               hrt_isp_css_mm_store(ddr_ptrs.isp_param,
+                                    &isp_parameters,
+                                    sizeof(struct sh_css_isp_params));
+               isp_params_changed = false;
+       }
+
+       if (ctc_table && ctc_table_changed) {
+               hrt_isp_css_mm_store(ddr_ptrs.ctc_tbl,
+                                    ctc_table->data,
+                                    sizeof(ctc_table->data));
+               ctc_table_changed = false;
+       }
+       if (gamma_table && gamma_table_changed) {
+               hrt_isp_css_mm_store(ddr_ptrs.gamma_tbl,
+                                    gamma_table->data,
+                                    sizeof(gamma_table->data));
+               gamma_table_changed = false;
+       }
+       if (macc_table && macc_table_changed) {
+               unsigned int i;
+               for (i = 0;
+                    i < SH_CSS_MACC_NUM_AXES * SH_CSS_MACC_NUM_COEFS;
+                    i++) {
+                       converted_macc_table.data[i] =
+                           sDIGIT_FITTING(macc_table->data[i], 13,
+                                          SH_CSS_MACC_COEF_SHIFT);
+               }
+               hrt_isp_css_mm_store(ddr_ptrs.macc_tbl,
+                                    converted_macc_table.data,
+                                    sizeof(converted_macc_table.data));
+               macc_table_changed = false;
+       }
+
+       if (dis_coef_table_changed && binary->info->enable_dis) {
+               store_dis_coefficients(binary);
+               dis_coef_table_changed = false;
+       }
+
+       if (binary->info->mode == SH_CSS_BINARY_MODE_GDC &&
+           morph_table_changed) {
+               unsigned int i;
+               void *virt_addr_tetra_x[SH_CSS_MORPH_TABLE_NUM_PLANES] = {
+                       ddr_ptrs.tetra_r_x,
+                       ddr_ptrs.tetra_gr_x,
+                       ddr_ptrs.tetra_gb_x,
+                       ddr_ptrs.tetra_b_x,
+                       ddr_ptrs.tetra_ratb_x,
+                       ddr_ptrs.tetra_batr_x
+               };
+               void *virt_addr_tetra_y[SH_CSS_MORPH_TABLE_NUM_PLANES] = {
+                       ddr_ptrs.tetra_r_y,
+                       ddr_ptrs.tetra_gr_y,
+                       ddr_ptrs.tetra_gb_y,
+                       ddr_ptrs.tetra_b_y,
+                       ddr_ptrs.tetra_ratb_y,
+                       ddr_ptrs.tetra_batr_y
+               };
+               const struct sh_css_morph_table *table = morph_table;
+               struct sh_css_morph_table *id_table = NULL;
+               if (table &&
+                   (table->width < binary->morph_tbl_width ||
+                    table->height < binary->morph_tbl_height)) {
+                       table = NULL;
+               }
+               if (!table) {
+                       sh_css_params_default_morph_table(&id_table, binary);
+                       table = id_table;
+               }
+
+               for (i = 0; i < SH_CSS_MORPH_TABLE_NUM_PLANES; i++) {
+                       write_morph_plane(table->coordinates_x[i],
+                                         table->width,
+                                         table->height,
+                                         virt_addr_tetra_x[i],
+                                         binary->morph_tbl_aligned_width);
+                       write_morph_plane(table->coordinates_y[i],
+                                         table->width,
+                                         table->height,
+                                         virt_addr_tetra_y[i],
+                                         binary->morph_tbl_aligned_width);
+               }
+               if (id_table)
+                       sh_css_morph_table_free(id_table);
+               morph_table_changed = false;
+       }
+       return sh_css_success;
+}
+
+void
+sh_css_params_set_current_binary(const struct sh_css_binary *binary)
+{
+       if (binary->info->enable_s3a)
+               current_3a_binary = binary;
+}
+
+const struct sh_css_fpn_table *
+sh_css_get_fpn_table(void)
+{
+       return &fpn_table;
+}
+
+const struct sh_css_shading_table *
+sh_css_get_shading_table(void)
+{
+       return sc_table;
+}
+
+const struct sh_css_isp_params *
+sh_css_get_isp_params(void)
+{
+       return &isp_parameters;
+}
+
+const struct sh_css_binary *
+sh_css_get_3a_binary(void)
+{
+       return current_3a_binary;
+}
+
+void
+sh_css_get_isp_dis_coefficients(short *horizontal_coefficients,
+                               short *vertical_coefficients)
+{
+       unsigned int hor_num_isp, ver_num_isp, i;
+       short *hor_ptr     = horizontal_coefficients,
+             *ver_ptr     = vertical_coefficients,
+             *hor_ptr_isp = ddr_ptrs.sdis_hor_coef,
+             *ver_ptr_isp = ddr_ptrs.sdis_ver_coef;
+
+       if (current_3a_binary == NULL)
+               return;
+
+       hor_num_isp = current_3a_binary->dis_hor_coef_num_isp;
+       ver_num_isp = current_3a_binary->dis_ver_coef_num_isp;
+
+       for (i = 0; i < SH_CSS_DIS_NUM_COEF_TYPES; i++) {
+               hrt_isp_css_mm_load(hor_ptr_isp, hor_ptr,
+                       hor_num_isp * sizeof(short));
+               hor_ptr_isp += hor_num_isp;
+               hor_ptr     += hor_num_isp;
+       }
+       for (i = 0; i < SH_CSS_DIS_VER_NUM_COEF_TYPES(current_3a_binary); i++) {
+               hrt_isp_css_mm_load(ver_ptr_isp, ver_ptr,
+                       ver_num_isp * sizeof(short));
+               ver_ptr_isp += ver_num_isp;
+               ver_ptr     += ver_num_isp;
+       }
+}
+
+void
+sh_css_get_isp_dis_projections(int *horizontal_projections,
+                              int *vertical_projections)
+{
+       unsigned int hor_num_isp, ver_num_isp, i;
+       int *hor_ptr     = horizontal_projections,
+           *ver_ptr     = vertical_projections,
+           *hor_ptr_isp = ddr_ptrs.sdis_hor_proj,
+           *ver_ptr_isp = ddr_ptrs.sdis_ver_proj;
+
+       if (current_3a_binary == NULL)
+               return;
+
+       hor_num_isp = current_3a_binary->dis_hor_proj_num_isp;
+       ver_num_isp = current_3a_binary->dis_ver_proj_num_isp;
+
+       for (i = 0; i < SH_CSS_DIS_NUM_COEF_TYPES; i++) {
+               hrt_isp_css_mm_load(hor_ptr_isp, hor_ptr,
+                                   hor_num_isp * sizeof(int));
+               hor_ptr_isp += hor_num_isp;
+               hor_ptr     += hor_num_isp;
+
+               hrt_isp_css_mm_load(ver_ptr_isp, ver_ptr,
+                                   ver_num_isp * sizeof(int));
+               ver_ptr_isp += ver_num_isp;
+               ver_ptr     += ver_num_isp;
+       }
+}
+
+void *
+sh_css_store_sp_group_to_ddr(void)
+{
+       hrt_isp_css_mm_store(xmem_sp_group_ptrs,
+                                    &sh_css_sp_group,
+                                    sizeof(struct sh_css_sp_group));
+       return xmem_sp_group_ptrs;
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_params.h b/drivers/media/video/atomisp/css/sh_css_params.h
new file mode 100644 (file)
index 0000000..e99441b
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_PARAMS_H_
+#define _SH_CSS_PARAMS_H_
+
+#include "sh_css_types.h"
+
+int sh_css_get_gdc_coord_one(void);
+
+/* DIS */
+/* get the pointers to the dis coefficient tables.
+ * These tables will then be written by the caller and the
+ * values will be sent to the ISP upon the next start of frame.
+ */
+void
+sh_css_set_dis_coefficients(const short *horizontal_coefs,
+                           const short *vertical_coefs);
+
+void
+sh_css_get_dis_projections(int *horizontal_projections,
+                          int *vertical_projections);
+
+/* 3A */
+enum sh_css_err
+sh_css_get_3a_statistics(struct sh_css_3a_output *output);
+
+void
+sh_css_set_3a_config(const struct sh_css_3a_config *config);
+
+void
+sh_css_get_3a_config(const struct sh_css_3a_config **config);
+
+/* FPN */
+enum sh_css_err
+sh_css_set_black_frame(const struct sh_css_frame *raw_black_frame);
+
+/* Morph Table for GDC & CAC */
+void
+sh_css_set_morph_table(const struct sh_css_morph_table *table);
+
+void
+sh_css_get_morph_table(const struct sh_css_morph_table **table);
+
+struct sh_css_morph_table *
+sh_css_morph_table_allocate(unsigned int width, unsigned int height);
+
+void
+sh_css_morph_table_free(struct sh_css_morph_table *me);
+
+/* White Balance */
+void
+sh_css_set_wb_config(const struct sh_css_wb_config *wb_config);
+
+void
+sh_css_get_wb_config(const struct sh_css_wb_config **wb_config);
+
+/* Color Correction */
+void
+sh_css_set_cc_config(const struct sh_css_cc_config *cc_config);
+
+void
+sh_css_get_cc_config(const struct sh_css_cc_config **cc_config);
+
+/* TNR */
+void
+sh_css_set_tnr_config(const struct sh_css_tnr_config *tnr_config);
+
+void
+sh_css_get_tnr_config(const struct sh_css_tnr_config **tnr_config);
+
+/* ANR */
+void
+sh_css_set_anr_threshold(int threshold);
+
+void
+sh_css_set_anr_config(const struct sh_css_anr_config *anr_config);
+
+void
+sh_css_get_anr_config(const struct sh_css_anr_config **anr_config);
+
+/* Objective Black */
+void
+sh_css_set_ob_config(const struct sh_css_ob_config *ob_config);
+
+void
+sh_css_get_ob_config(const struct sh_css_ob_config **ob_config);
+
+/* Dead Pixel */
+void
+sh_css_set_dp_config(const struct sh_css_dp_config *dp_config);
+
+void
+sh_css_get_dp_config(const struct sh_css_dp_config **dp_config);
+
+/* Noise Reduction */
+void
+sh_css_set_nr_config(const struct sh_css_nr_config *nr_config);
+
+void
+sh_css_get_nr_config(const struct sh_css_nr_config **nr_config);
+
+/* Edge Enhancement */
+void
+sh_css_set_ee_config(const struct sh_css_ee_config *ee_config);
+
+void
+sh_css_get_ee_config(const struct sh_css_ee_config **ee_config);
+
+/* Demosaic */
+void
+sh_css_set_de_config(const struct sh_css_de_config *de_config);
+
+void
+sh_css_get_de_config(const struct sh_css_de_config **de_config);
+
+/* Gamma Correction */
+void
+sh_css_set_gc_config(const struct sh_css_gc_config *gc_config);
+
+void
+sh_css_get_gc_config(const struct sh_css_gc_config **gc_config);
+
+void
+sh_css_set_gamma_table(const struct sh_css_gamma_table *table);
+
+void
+sh_css_get_gamma_table(const struct sh_css_gamma_table **table);
+
+void
+sh_css_set_ctc_table(const struct sh_css_ctc_table *table);
+
+void
+sh_css_get_ctc_table(const struct sh_css_ctc_table **table);
+
+/* Multi-Access Color Correction */
+void
+sh_css_set_macc_table(const struct sh_css_macc_table *table);
+
+void
+sh_css_get_macc_table(const struct sh_css_macc_table **table);
+
+/* Shading Correction */
+void
+sh_css_params_set_shading_table(const struct sh_css_shading_table *table);
+
+void
+sh_css_shading_table_free(struct sh_css_shading_table *table);
+
+struct sh_css_shading_table *
+sh_css_shading_table_alloc(unsigned int width,
+                          unsigned int height);
+
+#endif /* _SH_CSS_PARAMS_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_rx.c b/drivers/media/video/atomisp/css/sh_css_rx.c
new file mode 100644 (file)
index 0000000..d70b38a
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css.h"
+#include "sh_css_hw.h"
+#include "sh_css_rx.h"
+#include "sh_css_internal.h"
+
+static unsigned long *css_rx_base_address = CSS_RX_BASE;
+
+static unsigned long
+_sh_css_rx_get_register(enum sh_css_mipi_port port, unsigned int reg)
+{
+       unsigned int bus_addr = (unsigned int)(css_rx_base_address + reg);
+       if (port == SH_CSS_MIPI_PORT_1LANE)
+               bus_addr += hrt_css_receiver_ahb_1_lane_port_offset;
+       else
+               bus_addr += hrt_css_receiver_ahb_4_lane_port_offset;
+       return hrt_master_port_load_32(bus_addr);
+}
+
+static void
+_sh_css_rx_set_register(enum sh_css_mipi_port port,
+                       unsigned int reg,
+                       unsigned long val)
+{
+       unsigned int bus_addr = (unsigned int)(css_rx_base_address + reg);
+       if (port == SH_CSS_MIPI_PORT_1LANE)
+               bus_addr += hrt_css_receiver_ahb_1_lane_port_offset;
+       else
+               bus_addr += hrt_css_receiver_ahb_4_lane_port_offset;
+       hrt_master_port_store_32(bus_addr, val);
+}
+
+static void
+_sh_css_rx_set_bits(enum sh_css_mipi_port port,
+                   unsigned int reg,
+                   unsigned long bits)
+{
+       unsigned long val;
+       val = _sh_css_rx_get_register(port, reg);
+       val |= bits;
+       _sh_css_rx_set_register(port, reg, val);
+}
+
+void
+sh_css_rx_enable_all_interrupts(void)
+{
+       unsigned long bits;
+
+       bits = _HRT_CSS_RECEIVER_AHB_IRQ_OVERRUN_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_ENTRY_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_EXIT_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_HS_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_SYNC_HS_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CONTROL_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_DOUBLE_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_CORRECTED_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_NO_CORRECTION_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CRC_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ID_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_SYNC_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_DATA_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_DATA_TIMEOUT_BIT |
+              _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ESCAPE_BIT;
+
+       _sh_css_rx_set_bits(SH_CSS_MIPI_PORT_1LANE,
+                           _HRT_CSS_RECEIVER_AHB_IRQ_ENABLE_REG_IDX,
+                           bits);
+}
+
+unsigned int
+sh_css_rx_get_interrupt_reg(void)
+{
+       return _sh_css_rx_get_register(SH_CSS_MIPI_PORT_1LANE,
+                       _HRT_CSS_RECEIVER_AHB_IRQ_STATUS_REG_IDX);
+}
+
+void
+sh_css_rx_get_interrupt_info(unsigned int *irq_infos)
+{
+       unsigned long bits, infos = 0;
+
+       bits = _sh_css_rx_get_register(SH_CSS_MIPI_PORT_1LANE,
+                       _HRT_CSS_RECEIVER_AHB_IRQ_STATUS_REG_IDX);
+
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_OVERRUN_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_ENTRY_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_EXIT_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_CORRECTED_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ECC_CORRECTED;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_HS_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_SOT;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_SYNC_HS_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_SOT_SYNC;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CONTROL_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_CONTROL;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_DOUBLE_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CRC_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_CRC;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ID_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_SYNC_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_DATA_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_FRAME_DATA;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_DATA_TIMEOUT_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ESCAPE_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC;
+       if (bits & (1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_LINE_SYNC_BIT))
+               infos |= SH_CSS_RX_IRQ_INFO_ERR_LINE_SYNC;
+
+       *irq_infos = infos;
+}
+
+void
+sh_css_rx_clear_interrupt_info(unsigned int irq_infos)
+{
+       unsigned int bits = 0;
+
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_OVERRUN_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_ENTRY_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_SLEEP_MODE_EXIT_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ECC_CORRECTED)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_CORRECTED_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_SOT)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_HS_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_SOT_SYNC)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_SOT_SYNC_HS_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_CONTROL)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CONTROL_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ECC_DOUBLE_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_CRC)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_CRC_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ID_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_SYNC_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_FRAME_DATA)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_FRAME_DATA_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_DATA_TIMEOUT_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_ESCAPE_BIT;
+       if (irq_infos & SH_CSS_RX_IRQ_INFO_ERR_LINE_SYNC)
+               bits |= 1 << _HRT_CSS_RECEIVER_AHB_IRQ_ERR_LINE_SYNC_BIT;
+
+       _sh_css_rx_set_bits(SH_CSS_MIPI_PORT_1LANE,
+                           _HRT_CSS_RECEIVER_AHB_IRQ_ENABLE_REG_IDX,
+                           bits);
+}
+
+enum sh_css_err
+sh_css_input_format_type(enum sh_css_input_format input_format,
+                        enum sh_css_mipi_compression compression,
+                        unsigned int *fmt_type)
+{
+       if (compression != SH_CSS_MIPI_COMPRESSION_NONE) {
+               switch (input_format) {
+               case SH_CSS_INPUT_FORMAT_RAW_6:
+                       *fmt_type = 6;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_7:
+                       *fmt_type = 7;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_8:
+                       *fmt_type = 8;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_10:
+                       *fmt_type = 10;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_12:
+                       *fmt_type = 12;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_14:
+                       *fmt_type = 14;
+                       break;
+               case SH_CSS_INPUT_FORMAT_RAW_16:
+                       *fmt_type = 16;
+                       break;
+               default:
+                       return sh_css_err_internal_error;
+               }
+               return sh_css_success;
+       }
+       /* This mapping comes from the Arasan CSS function spec
+        * (CSS_func_spec1.08_ahb_sep29_08.pdf).
+        */
+       switch (input_format) {
+       case SH_CSS_INPUT_FORMAT_RGB_888:
+               *fmt_type = 0;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_555:
+               *fmt_type = 1;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_444:
+               *fmt_type = 2;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_565:
+               *fmt_type = 3;
+               break;
+       case SH_CSS_INPUT_FORMAT_RGB_666:
+               *fmt_type = 4;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_8:
+               *fmt_type = 5;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_10:
+               *fmt_type = 6;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_6:
+               *fmt_type = 7;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_7:
+               *fmt_type = 8;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_12:
+               *fmt_type = 9;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_14:
+               *fmt_type = 10;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV420_8:
+               *fmt_type = 11;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV420_10:
+               *fmt_type = 12;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV422_8:
+               *fmt_type = 13;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV422_10:
+               *fmt_type = 14;
+               break;
+       case SH_CSS_INPUT_FORMAT_BINARY_8:
+               *fmt_type = 15;
+               break;
+       case SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY:
+               *fmt_type = 16;
+               break;
+       case SH_CSS_INPUT_FORMAT_RAW_16:
+               /* This is not specified by Arasan, so we use
+                * 17 for now.
+                */
+               *fmt_type = 17;
+               break;
+       default:
+               return sh_css_err_internal_error;
+       }
+       return sh_css_success;
+}
+
+static void
+sh_css_rx_set_bits(enum sh_css_mipi_port port, unsigned int reg,
+                  unsigned int lsb, unsigned int bits, unsigned int val)
+{
+       /* prevent writing out of range */
+       val &= (1U << bits)-1;
+       /* shift into place */
+       val <<= lsb;
+       _sh_css_rx_set_bits(port, reg, val);
+}
+
+static void
+sh_css_rx_set_num_lanes(enum sh_css_mipi_port port, unsigned int lanes)
+{
+       sh_css_rx_set_bits(port,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_FUNC_PROG_REG_IDX,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_IDX,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_NUM_DATA_LANES_BITS,
+                          lanes);
+}
+
+static void
+sh_css_rx_port_enable(enum sh_css_mipi_port port, bool enable)
+{
+       _sh_css_rx_set_register(port,
+                               _HRT_CSS_RECEIVER_AHB_DEVICE_READY_REG_IDX,
+                               enable);
+}
+
+static void
+sh_css_rx_set_timeout(enum sh_css_mipi_port port, unsigned int timeout)
+{
+       sh_css_rx_set_bits(port,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_FUNC_PROG_REG_IDX,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_DATA_TIMEOUT_IDX,
+                          _HRT_CSS_RECEIVER_AHB_CSI2_DATA_TIMEOUT_BITS,
+                          timeout);
+}
+
+static void
+sh_css_rx_set_compression(enum sh_css_mipi_port port,
+                         enum sh_css_mipi_compression comp)
+{
+       unsigned int reg = _HRT_CSS_RECEIVER_AHB_COMP_PREDICT_REG_IDX,
+                    comp_val = _HRT_CSS_RECEIVER_AHB_PREDICT_NO_COMP;
+
+       if (comp == SH_CSS_MIPI_COMPRESSION_1)
+               comp_val = _HRT_CSS_RECEIVER_AHB_PREDICT_1;
+       if (comp == SH_CSS_MIPI_COMPRESSION_2)
+               comp_val = _HRT_CSS_RECEIVER_AHB_PREDICT_2;
+
+       _sh_css_rx_set_register(port, reg, comp_val);
+}
+
+static void
+sh_css_rx_set_uncomp_size(enum sh_css_mipi_port port, unsigned int size)
+{
+       sh_css_rx_set_bits(port,
+                          _HRT_CSS_RECEIVER_AHB_COMP_FORMAT_REG_IDX,
+                          _HRT_CSS_RECEIVER_AHB_COMP_NUM_BITS_IDX,
+                          _HRT_CSS_RECEIVER_AHB_COMP_NUM_BITS_BITS,
+                          size);
+}
+
+static void
+sh_css_rx_set_comp_size(enum sh_css_mipi_port port, unsigned int size)
+{
+       sh_css_rx_set_bits(port,
+                          _HRT_CSS_RECEIVER_AHB_COMP_FORMAT_REG_IDX,
+                          _HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_IDX,
+                          _HRT_CSS_RECEIVER_AHB_COMP_RAW_BITS_BITS,
+                          size);
+}
+
+static void
+sh_css_rx_set_two_ppc(enum sh_css_mipi_port port, bool enable)
+{
+       _sh_css_rx_set_register(port,
+                               _HRT_CSS_RECEIVER_AHB_TWO_PIXEL_EN_REG_IDX,
+                               enable);
+}
+
+void
+sh_css_rx_configure(const struct sh_css_mipi_config *config)
+{
+       /* turn off both ports just in case */
+       sh_css_rx_disable();
+
+       /* configure the selected port */
+       sh_css_rx_set_num_lanes(config->port, config->num_lanes);
+       sh_css_rx_set_timeout(config->port, config->timeout);
+       sh_css_rx_set_compression(config->port, config->comp);
+       sh_css_rx_set_uncomp_size(config->port, config->uncomp_bpp);
+       sh_css_rx_set_comp_size(config->port, config->comp_bpp);
+       sh_css_rx_set_two_ppc(config->port, config->two_ppc);
+
+       /* enable the selected port */
+       sh_css_rx_port_enable(config->port, true);
+}
+
+void
+sh_css_rx_disable(void)
+{
+       sh_css_rx_port_enable(SH_CSS_MIPI_PORT_1LANE, false);
+       sh_css_rx_port_enable(SH_CSS_MIPI_PORT_4LANE, false);
+}
+
diff --git a/drivers/media/video/atomisp/css/sh_css_rx.h b/drivers/media/video/atomisp/css/sh_css_rx.h
new file mode 100644 (file)
index 0000000..67a38d5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_RX_H_
+#define _SH_CSS_RX_H_
+
+#include "sh_css_types.h"
+
+/* CSS Receiver */
+
+struct sh_css_mipi_config {
+       enum sh_css_mipi_port        port;
+       unsigned int                 num_lanes;
+       unsigned int                 timeout;
+       unsigned int                 comp_bpp;
+       unsigned int                 uncomp_bpp;
+       enum sh_css_mipi_compression comp;
+       bool                         two_ppc;
+};
+
+void
+sh_css_rx_configure(const struct sh_css_mipi_config *config);
+
+void
+sh_css_rx_disable(void);
+
+void
+sh_css_rx_enable_all_interrupts(void);
+
+unsigned int
+sh_css_rx_get_interrupt_reg(void);
+
+#endif /* _SH_CSS_RX_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_sp.c b/drivers/media/video/atomisp/css/sh_css_sp.c
new file mode 100644 (file)
index 0000000..409e570
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css.h"
+#include "sh_css_binary.h"
+#include "sh_css_sp.h"
+#include "sh_css_sp_start.h"
+#include "sh_css_hrt.h"
+#include "sh_css_defs.h"
+#include "sh_css_internal.h"
+#define HRT_NO_BLOB_sp
+#include "sp.map.h"
+
+/* Convenience macro to force a value to a lower even value.
+ *  We do not want to (re)use the kernel macro round_down here
+ *  because the same code base is used internally by Silicon Hive
+ *  simulation environment, where the kernel macro is not available
+ */
+#define EVEN_FLOOR(x)  (x & ~1)
+
+struct sh_css_sp_group sh_css_sp_group;
+
+void
+sh_css_store_sp_group_pointer_to_sp(void)
+{
+       void *sp_group_on_ddr = sh_css_store_sp_group_to_ddr();
+
+       store_sp_ptr(sp_sp_group_addr, sp_group_on_ddr);
+       /* set flag (should read sp group from DDR) */
+       store_sp_int(sp_read_sp_group_from_ddr, 1);
+}
+
+/* Initialize the entire contents of the DMEM at once -- does not need to
+ * do this from the host
+ */
+void
+sh_css_sp_start_init_dmem(struct sh_css_sp_init_dmem_cfg *init_dmem_cfg)
+{
+       store_sp_ptr(sp_ddr_data_addr , init_dmem_cfg->ddr_data_addr);
+       store_sp_ptr(sp_dmem_data_addr, init_dmem_cfg->dmem_data_addr);
+       store_sp_int(sp_data_size     , init_dmem_cfg->data_size);
+       store_sp_ptr(sp_dmem_bss_addr , init_dmem_cfg->dmem_bss_addr);
+       store_sp_int(sp_bss_size      , init_dmem_cfg->bss_size);
+
+       sh_css_hrt_sp_start_init_dmem();
+       sh_css_hrt_sp_wait();
+}
+
+void
+sh_css_sp_start_histogram(struct sh_css_histogram *histogram,
+                         const struct sh_css_frame *frame)
+{
+       store_sp_ptr(sp_histo_addr, histogram->data);
+       sh_css_sp_group.sp_in_frame = *frame;
+       sh_css_store_sp_group_pointer_to_sp();
+       sh_css_hrt_sp_start_histogram();
+}
+
+void
+sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state)
+{
+       int i;
+
+       state->error = load_sp_uint(sp_error);
+
+       for (i = 0; i < 16; i++)
+               state->debug[i] = load_sp_array_uint(sp_debug, i);
+}
+
+void
+sh_css_sp_start_binary_copy(struct sh_css_frame *out_frame,
+                           unsigned two_ppc)
+{
+       store_sp_ptr(sp_bin_copy_out, out_frame->planes.binary.data.data);
+       store_sp_int(sp_bin_copy_bytes_available, out_frame->data_bytes);
+       sh_css_sp_group.isp_2ppc = two_ppc;
+       sh_css_store_sp_group_pointer_to_sp();
+       sh_css_hrt_sp_start_copy_binary_data();
+}
+
+void
+sh_css_sp_start_raw_copy(struct sh_css_binary *binary,
+                        struct sh_css_frame *out_frame,
+                        unsigned two_ppc,
+                        bool start)
+{
+       store_sp_ptr(sp_raw_copy_out,           out_frame->planes.raw.data);
+       store_sp_ptr(sp_raw_copy_height,        out_frame->info.height);
+       store_sp_ptr(sp_raw_copy_width,         out_frame->info.width);
+       store_sp_ptr(sp_raw_copy_padded_width,  out_frame->info.padded_width);
+       store_sp_ptr(sp_raw_copy_raw_bit_depth, out_frame->info.raw_bit_depth);
+       store_sp_ptr(sp_raw_copy_max_input_width,
+                    binary->info->max_input_width);
+       store_sp_ptr(sp_proxy_busy_wait,        true);
+       sh_css_sp_group.isp_2ppc = two_ppc;
+       sh_css_sp_group.xmem_bin_addr = binary->info->xmem_addr;
+       sh_css_store_sp_group_pointer_to_sp();
+       if (start)
+               sh_css_hrt_sp_start_copy_raw_data();
+}
+
+unsigned int
+sh_css_sp_get_binary_copy_size(void)
+{
+       return load_sp_uint(sp_bin_copy_bytes_copied);
+}
+
+unsigned int
+sh_css_sp_get_sw_interrupt_value(void)
+{
+       return load_sp_uint(sp_sw_interrupt_value);
+}
+
+static enum sh_css_err
+set_input_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       switch (frame->info.format) {
+       case SH_CSS_FRAME_FORMAT_QPLANE6:
+       case SH_CSS_FRAME_FORMAT_YUV420_16:
+       case SH_CSS_FRAME_FORMAT_RAW:
+       case SH_CSS_FRAME_FORMAT_YUV420:
+       case SH_CSS_FRAME_FORMAT_YUV_LINE:
+               break;
+       default:
+               return sh_css_err_unsupported_frame_format;
+       }
+       sh_css_sp_group.sp_in_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_output_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       switch (frame->info.format) {
+       case SH_CSS_FRAME_FORMAT_YUV420:
+       case SH_CSS_FRAME_FORMAT_YUV422:
+       case SH_CSS_FRAME_FORMAT_YUV444:
+       case SH_CSS_FRAME_FORMAT_YV12:
+       case SH_CSS_FRAME_FORMAT_YV16:
+       case SH_CSS_FRAME_FORMAT_YUV420_16:
+       case SH_CSS_FRAME_FORMAT_YUV422_16:
+       case SH_CSS_FRAME_FORMAT_NV11:
+       case SH_CSS_FRAME_FORMAT_NV12:
+       case SH_CSS_FRAME_FORMAT_NV16:
+       case SH_CSS_FRAME_FORMAT_NV21:
+       case SH_CSS_FRAME_FORMAT_NV61:
+       case SH_CSS_FRAME_FORMAT_YUYV:
+       case SH_CSS_FRAME_FORMAT_UYVY:
+       case SH_CSS_FRAME_FORMAT_YUV_LINE:
+       case SH_CSS_FRAME_FORMAT_RGB565:
+       case SH_CSS_FRAME_FORMAT_RGBA888:
+       case SH_CSS_FRAME_FORMAT_PLANAR_RGB888:
+       case SH_CSS_FRAME_FORMAT_RAW:
+       case SH_CSS_FRAME_FORMAT_QPLANE6:
+               break;
+       default:
+               return sh_css_err_unsupported_frame_format;
+       }
+       sh_css_sp_group.sp_out_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_ref_in_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       if (frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_ref_in_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_ref_out_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       if (frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_ref_out_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_tnr_in_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       if (frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_tnr_in_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_tnr_out_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       if (frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_tnr_out_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_capture_pp_frame_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       switch (frame->info.format != SH_CSS_FRAME_FORMAT_YUV420)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_extra_frame = *frame;
+       return sh_css_success;
+}
+
+static enum sh_css_err
+set_view_finder_buffer(const struct sh_css_frame *frame)
+{
+       if (frame == NULL)
+               return sh_css_err_invalid_arguments;
+
+       if (frame->info.format != SH_CSS_FRAME_FORMAT_YUV_LINE)
+               return sh_css_err_unsupported_frame_format;
+       sh_css_sp_group.sp_out_vf_frame = *frame;
+       return sh_css_success;
+}
+
+static void
+sh_css_sp_configure_cropping(const struct sh_css_binary *binary)
+{
+       sh_css_sp_group.sp_uds_xc = binary->in_frame_info.width / 2;
+       sh_css_sp_group.sp_uds_yc = binary->in_frame_info.height / 2;
+       sh_css_sp_group.sp_out_crop_pos_x = binary->info->left_cropping;
+       sh_css_sp_group.sp_out_crop_pos_y = binary->info->top_cropping;
+}
+
+static void
+sh_css_sp_configure_dvs(const struct sh_css_binary *binary,
+                       const struct sh_css_binary_args *args)
+{
+       unsigned int crop_x = 0,
+                    crop_y = 0,
+                    uds_xc = 0,
+                    uds_yc = 0,
+                    env_width, env_height;
+       int half_env_x, half_env_y,
+           motion_x = args->dvs_vector_x,
+           motion_y = args->dvs_vector_y;
+
+       if (binary->info->enable_uds) {
+               /* we calculate with the envelope that we can actually use,
+                  the min dvs envelope is for the filter initialization. */
+               env_width  = binary->dvs_envelope_width -
+                               SH_CSS_MIN_DVS_ENVELOPE;
+               env_height = binary->dvs_envelope_height -
+                               SH_CSS_MIN_DVS_ENVELOPE;
+               half_env_x = env_width / 2;
+               half_env_y = env_height / 2;
+               /* for digital zoom, we use the dvs envelope and make sure
+                  that we don't include the 8 leftmost pixels or 8 topmost
+                  rows. */
+               uds_xc = (binary->out_frame_info.width + env_width) / 2 +
+                        SH_CSS_MIN_DVS_ENVELOPE;
+               uds_yc = (binary->out_frame_info.height + env_height) / 2 +
+                        SH_CSS_MIN_DVS_ENVELOPE;
+               /* clip the motion vector to +/- half the envelope */
+               motion_x = clamp(motion_x, -half_env_x, half_env_x);
+               motion_y = clamp(motion_y, -half_env_y, half_env_y);
+               uds_xc += motion_x;
+               uds_yc += motion_y;
+       } else if (binary->info->enable_ds) {
+               env_width  = binary->dvs_envelope_width;
+               env_height = binary->dvs_envelope_height;
+               half_env_x = env_width / 2;
+               half_env_y = env_height / 2;
+               /* clip the motion vector to +/- half the envelope */
+               motion_x = clamp(motion_x, -half_env_x, half_env_x);
+               motion_y = clamp(motion_y, -half_env_y, half_env_y);
+               /* for video with downscaling, the envelope is included in
+                  the input resolution. */
+               uds_xc = binary->in_frame_info.width/2 + motion_x;
+               uds_yc = binary->in_frame_info.height/2 + motion_y;
+               crop_x = binary->info->left_cropping;
+               crop_y = binary->info->top_cropping;
+       } else {
+               /* video nodz: here we can only crop. We make sure we crop at
+                  least the first 8x8 pixels away. */
+               env_width  = binary->dvs_envelope_width -
+                               SH_CSS_MIN_DVS_ENVELOPE;
+               env_height = binary->dvs_envelope_height -
+                               SH_CSS_MIN_DVS_ENVELOPE;
+               half_env_x = env_width / 2;
+               half_env_y = env_height / 2;
+               motion_x = clamp(motion_x, -half_env_x, half_env_x);
+               motion_y = clamp(motion_y, -half_env_y, half_env_y);
+               crop_x = SH_CSS_MIN_DVS_ENVELOPE + half_env_x + motion_x;
+               crop_y = SH_CSS_MIN_DVS_ENVELOPE + half_env_y + motion_y;
+       }
+
+       /* Must enforce that the crop position is even */
+       crop_x = EVEN_FLOOR(crop_x);
+       crop_y = EVEN_FLOOR(crop_y);
+       uds_xc = EVEN_FLOOR(uds_xc);
+       uds_yc = EVEN_FLOOR(uds_yc);
+
+       sh_css_sp_group.sp_uds_xc = uds_xc;
+       sh_css_sp_group.sp_uds_yc = uds_yc;
+       sh_css_sp_group.sp_out_crop_pos_x = crop_x;
+       sh_css_sp_group.sp_out_crop_pos_y = crop_y;
+}
+
+static void
+sh_css_sp_set_vf_zoom_position(const struct sh_css_binary *binary, bool zoom)
+{
+       /* for down scaling, we always use the center of the image */
+       unsigned uds_xc = 0;
+       unsigned uds_yc = 0;
+       if (zoom) {
+               uds_xc = (binary->in_frame_info.width) / 2;
+               uds_yc = (binary->in_frame_info.height) / 2;
+       }
+       sh_css_sp_group.sp_uds_xc = uds_xc;
+       sh_css_sp_group.sp_uds_yc = uds_yc;
+       sh_css_sp_group.sp_out_crop_pos_x = binary->info->left_cropping;
+       sh_css_sp_group.sp_out_crop_pos_y = binary->info->top_cropping;
+}
+
+void
+sh_css_sp_set_if_configs(const struct sh_css_if_config *config_a,
+                        const struct sh_css_if_config *config_b)
+{
+       bool block_a = config_a->block_no_reqs,
+            block_b = false;
+       if (config_b)
+               block_b = config_b->block_no_reqs;
+       sh_css_hrt_if_reset();
+       sh_css_hrt_if_set_block_fifo_no_reqs(block_a, block_b);
+       store_sp_int(sp_if_a_changed, 1);
+       store_sp_var(sp_if_a, (void *)config_a, sizeof(*config_a));
+
+       if (config_b) {
+               store_sp_int(sp_if_b_changed, 1);
+               store_sp_var(sp_if_b, (void *)config_b, sizeof(*config_b));
+       }
+}
+
+void
+sh_css_sp_program_input_circuit(int fmt_type,
+                               int ch_id,
+                               enum sh_css_input_mode input_mode)
+{
+       store_sp_int(sp_no_side_band, 0);
+       store_sp_int(sp_fmt_type, fmt_type);
+       store_sp_int(sp_ch_id, ch_id);
+       store_sp_int(sp_input_mode, input_mode);
+       store_sp_int(sp_program_input_circuit, 1);
+}
+
+void
+sh_css_sp_configure_sync_gen(int width, int height,
+                            int hblank_cycles,
+                            int vblank_cycles)
+{
+       store_sp_int(sp_sync_gen_width, width);
+       store_sp_int(sp_sync_gen_height, height);
+       store_sp_int(sp_sync_gen_hblank_cycles, hblank_cycles);
+       store_sp_int(sp_sync_gen_vblank_cycles, vblank_cycles);
+}
+
+void
+sh_css_sp_configure_tpg(int x_mask,
+                       int y_mask,
+                       int x_delta,
+                       int y_delta,
+                       int xy_mask)
+{
+       store_sp_int(sp_tpg_x_mask, x_mask);
+       store_sp_int(sp_tpg_y_mask, y_mask);
+       store_sp_int(sp_tpg_x_delta, x_delta);
+       store_sp_int(sp_tpg_y_delta, y_delta);
+       store_sp_int(sp_tpg_xy_mask, xy_mask);
+}
+
+void
+sh_css_sp_configure_prbs(int seed)
+{
+       store_sp_int(sp_prbs_seed, seed);
+}
+
+static enum sh_css_err
+sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
+{
+       enum sh_css_err err = sh_css_success;
+       if (args->in_frame)
+               err = set_input_frame_buffer(args->in_frame);
+       if (err == sh_css_success && args->in_ref_frame)
+               err = set_ref_in_frame_buffer(args->in_ref_frame);
+       if (err == sh_css_success && args->in_tnr_frame)
+               err = set_tnr_in_frame_buffer(args->in_tnr_frame);
+       if (err == sh_css_success && args->out_vf_frame)
+               err = set_view_finder_buffer(args->out_vf_frame);
+       if (err == sh_css_success && args->extra_frame)
+               err = set_capture_pp_frame_buffer(args->extra_frame);
+       if (err == sh_css_success && args->out_ref_frame)
+               err = set_ref_out_frame_buffer(args->out_ref_frame);
+       if (err == sh_css_success && args->out_tnr_frame)
+               err = set_tnr_out_frame_buffer(args->out_tnr_frame);
+       if (err == sh_css_success && args->out_frame)
+               err = set_output_frame_buffer(args->out_frame);
+       return err;
+}
+
+static void
+sh_css_sp_compute_overlay(const struct sh_css_overlay *overlay,
+                         struct sh_css_sp_overlay *sp_overlay)
+{
+       if (overlay == NULL) {
+               sp_overlay->overlay_width  = 0;
+               sp_overlay->overlay_height = 0;
+       } else {
+               int blend_shift,
+                   ratio100,
+                   blend_input_y,
+                   blend_input_u,
+                   blend_input_v,
+                   blend_overlay_y, blend_overlay_u, blend_overlay_v;
+
+               blend_shift = 12;
+               ratio100 = 1 << blend_shift;
+               blend_input_y =
+                   (ratio100 * overlay->blend_input_perc_y + 50) / 100;
+               blend_input_u =
+                   (ratio100 * overlay->blend_input_perc_u + 50) / 100;
+               blend_input_v =
+                   (ratio100 * overlay->blend_input_perc_v + 50) / 100;
+               blend_overlay_y =
+                   (ratio100 * overlay->blend_overlay_perc_y + 50) / 100;
+               blend_overlay_u =
+                   (ratio100 * overlay->blend_overlay_perc_u + 50) / 100;
+               blend_overlay_v =
+                   (ratio100 * overlay->blend_overlay_perc_v + 50) / 100;
+               sp_overlay->bg_y = (int) overlay->bg_y;
+               sp_overlay->bg_u = (int) overlay->bg_u;
+               sp_overlay->bg_v = (int) overlay->bg_v;
+               sp_overlay->blend_shift = blend_shift;
+               sp_overlay->blend_input_y = blend_input_y;
+               sp_overlay->blend_input_u = blend_input_u;
+               sp_overlay->blend_input_v = blend_input_v;
+               sp_overlay->blend_overlay_y = blend_overlay_y;
+               sp_overlay->blend_overlay_u = blend_overlay_u;
+               sp_overlay->blend_overlay_v = blend_overlay_v;
+               sp_overlay->overlay_width =
+                       (int) overlay->frame->info.width;
+               sp_overlay->overlay_height =
+                       (int) overlay->frame->info.height;
+               sp_overlay->overlay_start_x =
+                       (int) overlay->overlay_start_x;
+               sp_overlay->overlay_start_y =
+                       (int) overlay->overlay_start_y;
+               sp_overlay->frame_ptr_overlay_y =
+                       overlay->frame->planes.yuv.y.data;
+               sp_overlay->frame_ptr_overlay_u =
+                       overlay->frame->planes.yuv.u.data;
+               sp_overlay->frame_ptr_overlay_v =
+                       overlay->frame->planes.yuv.v.data;
+       }
+}
+
+void
+sh_css_sp_set_overlay(const struct sh_css_overlay *overlay)
+{
+       struct sh_css_sp_overlay sp_overlay;
+       sh_css_sp_compute_overlay(overlay, &sp_overlay);
+       store_sp_var(sp_si, &sp_overlay, sizeof(sp_overlay));
+}
+
+enum sh_css_err
+sh_css_sp_start_isp(struct sh_css_binary *binary,
+                   const struct sh_css_binary_args *args,
+                   bool preview_mode)
+{
+       unsigned int dx, dy;
+       enum sh_css_err err = sh_css_success;
+       bool start_copy = sh_css_continuous_start_sp_copy();
+
+       if (binary->info->mode == SH_CSS_BINARY_MODE_VF_PP) {
+               bool zoom = false;
+               if (preview_mode) {
+                       sh_css_get_zoom_factor(&dx, &dy);
+                       zoom = dx != 64 || dy != 64;
+               } else {
+                       /* in non-preview modes, VF_PP does not do
+                          the zooming, capture_pp or video do. */
+                       dx = 64;
+                       dy = 64;
+               }
+               sh_css_sp_set_vf_zoom_position(binary, zoom);
+       } else {
+               sh_css_get_zoom_factor(&dx, &dy);
+       }
+
+ /* Copy the frame infos first, to be overwritten by the frames,
+          if these are present.
+       */
+       sh_css_sp_group.sp_in_frame.info = binary->in_frame_info;
+       sh_css_sp_group.sp_out_frame.info = binary->out_frame_info;
+       sh_css_sp_group.sp_internal_frame_info = binary->internal_frame_info;
+
+       sh_css_sp_group.sp_isp_binary_id         = binary->info->id;
+       sh_css_sp_group.sp_enable_xnr            = args->enable_xnr;
+       sh_css_sp_group.sp_uds_curr_dx           = dx;
+       sh_css_sp_group.sp_uds_curr_dy           = dy;
+       sh_css_sp_group.sp_input_stream_format   = binary->input_format;
+       sh_css_sp_group.isp_dvs_envelope_width   = binary->dvs_envelope_width;
+       sh_css_sp_group.isp_dvs_envelope_height  = binary->dvs_envelope_height;
+       sh_css_sp_group.isp_deci_log_factor      = binary->deci_factor_log2;
+       sh_css_sp_group.isp_vf_downscale_bits    = binary->vf_downscale_log2;
+       sh_css_sp_group.isp_online               = binary->online;
+       sh_css_sp_group.isp_copy_vf              = args->copy_vf;
+       sh_css_sp_group.isp_copy_output          = args->copy_output;
+       sh_css_sp_group.isp_2ppc                 = args->two_ppc;
+       sh_css_sp_group.sp_run_copy              = start_copy;
+       sh_css_sp_group.xmem_bin_addr            = binary->info->xmem_addr;
+       sh_css_sp_group.xmem_map_addr            =
+                                       sh_css_params_ddr_address_map();
+
+       store_sp_int(sp_isp_started, 0);
+
+       if (binary->info->enable_dvs_envelope)
+               sh_css_sp_configure_dvs(binary, args);
+       else if (binary->info->mode != SH_CSS_BINARY_MODE_VF_PP)
+               sh_css_sp_configure_cropping(binary);
+       sh_css_params_set_current_binary(binary);
+       err = sh_css_params_write_to_ddr(binary);
+       if (err != sh_css_success)
+               return err;
+       err = sh_css_sp_write_frame_pointers(args);
+       if (err != sh_css_success)
+               return err;
+
+       sh_css_store_sp_group_pointer_to_sp();
+
+       sh_css_hrt_sp_start_isp();
+       return err;
+}
+
+bool
+sh_css_isp_has_started(void)
+{
+       return load_sp_uint(sp_isp_started);
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_sp.h b/drivers/media/video/atomisp/css/sh_css_sp.h
new file mode 100644 (file)
index 0000000..7acd6d1
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_SP_H_
+#define _SH_CSS_SP_H_
+
+#include "sh_css_binary.h"
+
+struct sh_css_sp_debug_state {
+       unsigned int error;
+       unsigned int debug[16];
+};
+
+struct sh_css_if_config {
+       unsigned int start_line;
+       unsigned int start_column;
+       unsigned int left_padding;
+       unsigned int cropped_height;
+       unsigned int cropped_width;
+       unsigned int deinterleaving;
+       unsigned int buf_vecs;
+       unsigned int buf_start_index;
+       unsigned int buf_increment;
+       unsigned int buf_eol_offset;
+       unsigned int yuv420;
+       unsigned int block_no_reqs;
+};
+
+/* Structure to encapsulate required arguments for
+ * initialization of SP DMEM using the SP itself
+ */
+struct sh_css_sp_init_dmem_cfg {
+       void         *ddr_data_addr;  /* data segment address in ddr  */
+       void         *dmem_data_addr; /* data segment address in dmem */
+       unsigned int  data_size;      /* data segment size            */
+       void         *dmem_bss_addr;  /* bss segment address in dmem  */
+       unsigned int  bss_size;       /* bss segment size             */
+};
+
+/* Function to initialize the bss section of the binary */
+void
+sh_css_sp_start_init_dmem(struct sh_css_sp_init_dmem_cfg *init_dmem_cfg);
+
+void
+sh_css_sp_start_histogram(struct sh_css_histogram *histogram,
+                         const struct sh_css_frame *frame);
+
+/* Start binary (jpeg) copy on the SP */
+void
+sh_css_sp_start_binary_copy(struct sh_css_frame *out_frame,
+                           unsigned two_ppc);
+
+/* Start raw copy on the SP */
+void
+sh_css_sp_start_raw_copy(struct sh_css_binary *binary,
+                        struct sh_css_frame *out_frame,
+                        unsigned two_ppc,
+                        bool start);
+
+unsigned int
+sh_css_sp_get_binary_copy_size(void);
+
+/* Return the value of a SW interrupt */
+unsigned int
+sh_css_sp_get_sw_interrupt_value(void);
+
+enum sh_css_err
+sh_css_sp_start_isp(struct sh_css_binary *binary,
+                   const struct sh_css_binary_args *args,
+                   bool preview_mode);
+
+void
+sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state);
+
+void
+sh_css_sp_set_overlay(const struct sh_css_overlay *overlay);
+
+void
+sh_css_sp_set_if_configs(const struct sh_css_if_config *config_a,
+                        const struct sh_css_if_config *config_b);
+
+void
+sh_css_sp_program_input_circuit(int fmt_type,
+                               int ch_id,
+                               enum sh_css_input_mode input_mode);
+
+void
+sh_css_sp_configure_sync_gen(int width,
+                            int height,
+                            int hblank_cycles,
+                            int vblank_cycles);
+
+void
+sh_css_sp_configure_tpg(int x_mask,
+                       int y_mask,
+                       int x_delta,
+                       int y_delta,
+                       int xy_mask);
+
+void
+sh_css_sp_configure_prbs(int seed);
+
+void
+sh_css_store_sp_group_pointer_to_sp(void);
+
+extern struct sh_css_sp_group sh_css_sp_group;
+#endif /* _SH_CSS_SP_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_sp_start.c b/drivers/media/video/atomisp/css/sh_css_sp_start.c
new file mode 100644 (file)
index 0000000..1ec6624
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#include "sh_css_sp_start.h"
+#include "sh_css_sp.h"
+#include "sh_css_hw.h"
+#include "sh_css_hrt.h"
+#include "sp.map.h"
+#include "sh_css_firmware.h"
+
+static unsigned char *sp_dmem_base_address = SP_DMEM_BASE;
+static bool invalidate_mmu;
+
+void
+sh_css_sp_invalidate_mmu(void)
+{
+       invalidate_mmu = true;
+}
+
+void
+sh_css_sp_start(unsigned int start_address)
+{
+       if (invalidate_mmu) {
+               sh_css_hrt_mmu_invalidate_cache();
+               invalidate_mmu = false;
+       }
+       /* set the start address */
+       sh_css_sp_ctrl_store(SP_START_ADDR_REG, start_address);
+       /* set the run bit and the start bit with a read-modify-write */
+       sh_css_sp_ctrl_set_bits(SP_SC_REG,
+                       1UL<<SP_START_BIT | 1UL<<SP_RUN_BIT);
+}
+
+
+       void *
+sh_css_sp_load_program(const struct sh_css_sp_fw *fw, const char *sp_prog)
+{
+       void *code_addr;
+
+       /* store code (text section) to DDR */
+       code_addr = hrt_isp_css_mm_alloc(fw->text_size);
+       hrt_isp_css_mm_store(code_addr, fw->text, fw->text_size);
+
+       /* Set the correct start address for the SP program */
+       sh_css_sp_activate_program(fw, code_addr, sp_prog);
+
+       return code_addr;
+}
+
+       void
+sh_css_sp_activate_program(const struct sh_css_sp_fw *fw,
+                               void *code_addr,
+                               const char *sp_prog)
+{
+       struct sh_css_sp_init_dmem_cfg init_dmem_cfg;
+       void *data_addr;
+       (void)sp_prog; /* not used on hardware, only for simulation */
+
+       /* now we program the base address into the icache and
+        * invalidate the cache.
+        */
+       sh_css_sp_ctrl_store(SP_ICACHE_ADDR_REG, (unsigned long)code_addr);
+       sh_css_sp_ctrl_set_bits(SP_ICACHE_INV_REG, 1UL<<SP_ICACHE_INV_BIT);
+
+       /* store data section to DDR */
+       data_addr = hrt_isp_css_mm_alloc(fw->data_size);
+       hrt_isp_css_mm_store(data_addr, fw->data, fw->data_size);
+
+       /* Configure the data structure to initialize dmem */
+       init_dmem_cfg.ddr_data_addr  = data_addr;
+       init_dmem_cfg.dmem_data_addr = (void *) fw->data_target;
+       init_dmem_cfg.data_size      = fw->data_size;
+       init_dmem_cfg.dmem_bss_addr  = (void *) fw->bss_target;
+       init_dmem_cfg.bss_size       = fw->bss_size;
+
+       /* Start function on the SP to initialize the SP DMEM */
+       sh_css_sp_start_init_dmem(&init_dmem_cfg);
+
+       hrt_isp_css_mm_free(data_addr);
+}
+
+
+unsigned int
+sh_css_sp_dmem_load_32(unsigned int address)
+{
+       unsigned long addr = (unsigned long)(sp_dmem_base_address + address);
+       return hrt_master_port_uload_32(addr);
+}
+
+void
+sh_css_sp_dmem_store_32(unsigned int address, unsigned int value)
+{
+       unsigned long addr = (unsigned long)(sp_dmem_base_address + address);
+       hrt_master_port_store_32(addr, value);
+}
+
+void
+sh_css_sp_dmem_load(unsigned int address, void *data, unsigned int bytes)
+{
+       unsigned long addr = (unsigned long)(sp_dmem_base_address + address);
+       hrt_master_port_load(addr, data, bytes);
+}
+
+void
+sh_css_sp_dmem_store(unsigned int address, const void *data, unsigned int bytes)
+{
+       unsigned long addr = (unsigned long)(sp_dmem_base_address + address);
+       hrt_master_port_store(addr, data, bytes);
+}
diff --git a/drivers/media/video/atomisp/css/sh_css_sp_start.h b/drivers/media/video/atomisp/css/sh_css_sp_start.h
new file mode 100644 (file)
index 0000000..0b79963
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_SP_START_H_
+#define _SH_CSS_SP_START_H_
+
+#include "sh_css_firmware.h"
+
+#define sh_css_sp_start_function(func) \
+       sh_css_sp_start(HIVE_ADDR_ ## func ## _entry)
+
+/* int on SP is 4 bytes */
+#define SP_INT_BYTES 4
+
+#define store_sp_int(var, value) \
+       sh_css_sp_dmem_store_32((unsigned) HIVE_ADDR_ ## var, \
+                               (unsigned int)(value))
+
+#define store_sp_ptr(var, value) \
+       sh_css_sp_dmem_store_32((unsigned) HIVE_ADDR_ ## var, \
+                               (unsigned int)(value))
+
+#define load_sp_uint(var) \
+       sh_css_sp_dmem_load_32((unsigned) HIVE_ADDR_ ## var)
+
+#define load_sp_array_uint(array, index) \
+       sh_css_sp_dmem_load_32((unsigned) HIVE_ADDR_ ## array + \
+                              (index)*SP_INT_BYTES)
+
+#define store_sp_array_uint(array, index, value) \
+       sh_css_sp_dmem_store_32((unsigned) HIVE_ADDR_ ## array + \
+                               (index)*SP_INT_BYTES, value)
+
+#define store_sp_var(var, data, bytes) \
+       sh_css_sp_dmem_store((unsigned) HIVE_ADDR_ ## var, data, bytes)
+
+#define SH_CSS_PREVENT_UNINIT_READS 0
+
+unsigned int
+sh_css_sp_dmem_load_32(unsigned int address);
+
+void
+sh_css_sp_dmem_store_32(unsigned int address, unsigned int value);
+
+void
+sh_css_sp_dmem_load(unsigned int address, void *data,
+                   unsigned int bytes);
+
+void
+sh_css_sp_dmem_store(unsigned int address, const void *data,
+                    unsigned int bytes);
+
+void
+sh_css_sp_start(unsigned int start_address);
+
+void *
+sh_css_sp_load_program(const struct sh_css_sp_fw *fw, const char *sp_prog);
+
+void
+sh_css_sp_activate_program(const struct sh_css_sp_fw *fw,
+                          void *code_addr,
+                          const char *sp_prog);
+
+void
+sh_css_sp_invalidate_mmu(void);
+
+#endif /* _SH_CSS_SP_START_H_ */
diff --git a/drivers/media/video/atomisp/css/sh_css_types.h b/drivers/media/video/atomisp/css/sh_css_types.h
new file mode 100644 (file)
index 0000000..2ffa1a6
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+* Support for Medfield PNW Camera Imaging ISP subsystem.
+*
+* Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+*
+* Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301, USA.
+*
+*/
+
+#ifndef _SH_CSS_TYPES_H_
+#define _SH_CSS_TYPES_H_
+
+/* This code is also used by Silicon Hive in a simulation environment
+ * Therefore, the following macro is used to differentiate when this
+ * code is being included from within the Linux kernel source
+ */
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>       /* for memcpy */
+#else
+#include <stdarg.h>             /* for the print function */
+#include <stdlib.h>             /* for size_t */
+#include <string.h>             /* for memcpy */
+#include "sh_css_min_max.h"
+#ifdef STDC99
+#include <stdbool.h>
+#else
+#include "sh_css_bool.h"
+#endif /* STDC99 */
+#endif
+
+#define SH_CSS_MAJOR    0
+#define SH_CSS_MINOR    2
+#define SH_CSS_REVISION 5
+
+#define SH_CSS_MACC_NUM_AXES           16
+#define SH_CSS_MACC_NUM_COEFS          4
+#define SH_CSS_MORPH_TABLE_NUM_PLANES  6
+#define SH_CSS_SC_NUM_COLORS           4
+#define SH_CSS_CTC_TABLE_SIZE          1024
+#define SH_CSS_GAMMA_TABLE_SIZE        1024
+#define SH_CSS_DIS_NUM_COEF_TYPES      6
+#define SH_CSS_DIS_COEF_TYPES_ON_DMEM  2
+#define SH_CSS_CTC_COEF_SHIFT          13
+#define SH_CSS_GAMMA_GAIN_K_SHIFT      13
+
+/* Fixed point types.
+ * NOTE: the 16 bit fixed point types actually occupy 32 bits
+ * to save on extension operations in the ISP code.
+ */
+#define u0_16 unsigned int     /* unsigned 0.16 fixed point type */
+#define u2_14 unsigned int     /* unsigned 2.14 fixed point type */
+#define u5_11 unsigned int     /* unsigned 5.11 fixed point type */
+#define u8_8  unsigned int     /* unsigned 8.8 fixed point type */
+#define s0_15 signed int       /* signed 0.15 fixed point type */
+
+/* Errors, these values are used as the return value for most
+   functions in this API. These can be translated into a human readable
+   string (see below). */
+enum sh_css_err {
+       sh_css_success,
+       sh_css_err_internal_error,
+       sh_css_err_conflicting_mipi_settings,
+       sh_css_err_unsupported_configuration,
+       sh_css_err_mode_does_not_have_viewfinder,
+       sh_css_err_input_resolution_not_set,
+       sh_css_err_unsupported_input_mode,
+       sh_css_err_cannot_allocate_memory,
+       sh_css_err_invalid_arguments,
+       sh_css_err_too_may_colors,
+       sh_css_err_overlay_frame_missing,
+       sh_css_err_overlay_frames_too_big,
+       sh_css_err_unsupported_frame_format,
+       sh_css_err_frames_mismatch,
+       sh_css_err_overlay_not_set,
+       sh_css_err_not_implemented,
+       sh_css_err_invalid_frame_format,
+       sh_css_err_unsupported_resolution,
+       sh_css_err_scaling_factor_out_of_range,
+       sh_css_err_cannot_obtain_shading_table,
+       sh_css_err_interrupt_error,
+       sh_css_err_unexpected_interrupt,
+       sh_css_err_interrupts_not_enabled,
+       sh_css_err_system_not_idle,
+       sh_css_err_unsupported_input_format,
+       sh_css_err_not_enough_input_lines,
+       sh_css_err_not_enough_input_columns,
+       sh_css_err_illegal_resolution,
+       sh_css_err_effective_input_resolution_not_set,
+       sh_css_err_viewfinder_resolution_too_wide,
+       sh_css_err_viewfinder_resolution_exceeds_output,
+       sh_css_err_mode_does_not_have_grid,
+       sh_css_err_mode_does_not_have_raw_output
+};
+
+/* Input modes, these enumerate all supported input modes:
+ *  - Sensor: data from a sensor coming into the MIPI interface
+ *  - FIFO:   data from the host coming into the GP FIFO
+ *  - TPG:    data coming from the test pattern generator
+ *  - PRBS:   data coming from the Pseudo Random Bit Sequence
+ *  - Memory: data coming from DDR
+ */
+enum sh_css_input_mode {
+       SH_CSS_INPUT_MODE_SENSOR,
+       SH_CSS_INPUT_MODE_FIFO,
+       SH_CSS_INPUT_MODE_TPG,
+       SH_CSS_INPUT_MODE_PRBS,
+       SH_CSS_INPUT_MODE_MEMORY
+};
+
+/* The MIPI interface can be used in two modes, one with one
+ * lane and one with 4 lanes.
+ */
+enum sh_css_mipi_port {
+       SH_CSS_MIPI_PORT_1LANE,
+       SH_CSS_MIPI_PORT_4LANE
+};
+
+/* The MIPI interface supports 2 types of compression or can
+ * be run without compression.
+ */
+enum sh_css_mipi_compression {
+       SH_CSS_MIPI_COMPRESSION_NONE,
+       SH_CSS_MIPI_COMPRESSION_1,
+       SH_CSS_MIPI_COMPRESSION_2
+};
+
+/* The ISP streaming input interface supports the following formats.
+ * These match the corresponding MIPI formats.
+ */
+enum sh_css_input_format {
+       SH_CSS_INPUT_FORMAT_YUV420_8_LEGACY,    /* 8 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_YUV420_8,   /* 8 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_YUV420_10,  /* 10 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_YUV422_8,   /* UYVY..UVYV, 8 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_YUV422_10,  /* UYVY..UVYV, 10 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_RGB_444,    /* BGR..BGR, 4 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_RGB_555,    /* BGR..BGR, 5 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_RGB_565,    /* BGR..BGR, 5 bits B and $, 6 bits G */
+       SH_CSS_INPUT_FORMAT_RGB_666,    /* BGR..BGR, 6 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_RGB_888,    /* BGR..BGR, 8 bits per subpixel */
+       SH_CSS_INPUT_FORMAT_RAW_6,      /* RAW data, 6 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_7,      /* RAW data, 7 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_8,      /* RAW data, 8 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_10,     /* RAW data, 10 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_12,     /* RAW data, 12 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_14,     /* RAW data, 14 bits per pixel */
+       SH_CSS_INPUT_FORMAT_RAW_16,     /* RAW data, 16 bits per pixel */
+       SH_CSS_INPUT_FORMAT_BINARY_8,   /* Binary byte stream. */
+};
+
+/* Specify the capture mode, this can be RAW (simply copy sensor input to DDR),
+ * Primary ISP or the Advanced ISP.
+ */
+enum sh_css_capture_mode {
+       SH_CSS_CAPTURE_MODE_RAW,        /* no processing, only copy input to
+                                          output, no viewfinder output */
+       SH_CSS_CAPTURE_MODE_PRIMARY,    /* primary ISP */
+       SH_CSS_CAPTURE_MODE_ADVANCED,   /* advanced ISP */
+       SH_CSS_CAPTURE_MODE_LOW_LIGHT,   /* low light ISP */
+};
+
+/* Interrupt info enumeration.
+ * This lists all possible interrupts for use by the appliation layer.
+ * Note that the sh_css API uses some internal interrupts, these are not listed
+ * here.
+ */
+enum sh_css_interrupt_info {
+       /* the current frame is done and a new one can be started */
+       SH_CSS_IRQ_INFO_FRAME_DONE = 1 << 0,
+       /* another stage (ISP binary) needs to be started. */
+       SH_CSS_IRQ_INFO_START_NEXT_STAGE = 1 << 1,
+       /* 3A + DIS statistics are ready. */
+       SH_CSS_IRQ_INFO_STATISTICS_READY = 1 << 2,
+       /* the css receiver has encountered an error */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_ERROR = 1 << 3,
+       /* the FIFO in the csi receiver has overflown */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_FIFO_OVERFLOW = 1 << 4,
+       /* the css receiver received the start of frame */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_SOF = 1 << 5,
+       /* the css receiver received the end of frame */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_EOF = 1 << 6,
+       /* the css receiver received the start of line */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_SOL = 1 << 7,
+       /* the css receiver received the end of line */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_EOL = 1 << 8,
+       /* the css receiver received a change in side band signals */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_SIDEBAND_CHANGED = 1 << 9,
+       /* generic short packets (0) */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_0 = 1 << 10,
+       /* generic short packets (1) */
+       SH_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_1 = 1 << 11,
+       /* the primary input formatter (A) has encountered an error */
+       SH_CSS_IRQ_INFO_IF_PRIM_ERROR = 1 << 12,
+       /* the primary input formatter (B) has encountered an error */
+       SH_CSS_IRQ_INFO_IF_PRIM_B_ERROR = 1 << 13,
+       /* the secondary input formatter has encountered an error */
+       SH_CSS_IRQ_INFO_IF_SEC_ERROR = 1 << 14,
+       /* the stream-to-memory device has encountered an error */
+       SH_CSS_IRQ_INFO_STREAM_TO_MEM_ERROR = 1 << 15,
+       /* A firmware accelerator has terminated */
+       SH_CSS_IRQ_INFO_FW_ACC_DONE = 1 << 16,
+       /* software interrupts */
+       SH_CSS_IRQ_INFO_SW_0 = 1 << 17,
+       SH_CSS_IRQ_INFO_SW_1 = 1 << 18,
+       SH_CSS_IRQ_INFO_SW_2 = 1 << 19,
+};
+
+enum sh_css_rx_irq_info {
+       SH_CSS_RX_IRQ_INFO_BUFFER_OVERRUN   = 1 << 0,
+       SH_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE = 1 << 1,
+       SH_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE  = 1 << 2,
+       SH_CSS_RX_IRQ_INFO_ECC_CORRECTED    = 1 << 3,
+       SH_CSS_RX_IRQ_INFO_ERR_SOT          = 1 << 4,
+       SH_CSS_RX_IRQ_INFO_ERR_SOT_SYNC     = 1 << 5,
+       SH_CSS_RX_IRQ_INFO_ERR_CONTROL      = 1 << 6,
+       SH_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE   = 1 << 7,
+       SH_CSS_RX_IRQ_INFO_ERR_CRC          = 1 << 8,
+       SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID   = 1 << 9,
+       SH_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC   = 1 << 10,
+       SH_CSS_RX_IRQ_INFO_ERR_FRAME_DATA   = 1 << 11,
+       SH_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT = 1 << 12,
+       SH_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC  = 1 << 13,
+       SH_CSS_RX_IRQ_INFO_ERR_LINE_SYNC    = 1 << 14,
+};
+
+/* Enumeration used to select whether interrupts should be used, and if so,
+ * whether they are edge or pulse triggered.
+ * If interrupts are not used, the blocking function
+ * sh_css_wait_for_completion() must be used.
+ */
+enum sh_css_interrupt_setting {
+       SH_CSS_INTERRUPT_SETTING_EDGE,
+       SH_CSS_INTERRUPT_SETTING_PULSE
+};
+
+/* Frame formats, some of these come from fourcc.org, others are
+   better explained by video4linux2. The NV11 seems to be described only
+   on MSDN pages, but even those seem to be gone now.
+   Frames can come in many forms, the main categories are RAW, RGB and YUV
+   (or YCbCr). The YUV frames come in 4 flavors, determined by how the U and V
+   values are subsampled:
+   1. YUV420: hor = 2, ver = 2
+   2. YUV411: hor = 4, ver = 1
+   3. YUV422: hor = 2, ver = 1
+   4. YUV444: hor = 1, ver = 1
+ */
+enum sh_css_frame_format {
+       SH_CSS_FRAME_FORMAT_NV11,       /* 12 bit YUV 411, Y, UV plane */
+       SH_CSS_FRAME_FORMAT_NV12,       /* 12 bit YUV 420, Y, UV plane */
+       SH_CSS_FRAME_FORMAT_NV16,       /* 16 bit YUV 422, Y, UV plane */
+       SH_CSS_FRAME_FORMAT_NV21,       /* 12 bit YUV 420, Y, VU plane */
+       SH_CSS_FRAME_FORMAT_NV61,       /* 16 bit YUV 422, Y, VU plane */
+       SH_CSS_FRAME_FORMAT_YV12,       /* 12 bit YUV 420, Y, V, U plane */
+       SH_CSS_FRAME_FORMAT_YV16,       /* 16 bit YUV 422, Y, V, U plane */
+       SH_CSS_FRAME_FORMAT_YUV420,     /* 12 bit YUV 420, Y, U, V plane */
+       SH_CSS_FRAME_FORMAT_YUV420_16,  /* yuv420, 16 bits per subpixel */
+       SH_CSS_FRAME_FORMAT_YUV422,     /* 16 bit YUV 422, Y, U, V plane */
+       SH_CSS_FRAME_FORMAT_YUV422_16,  /* yuv422, 16 bits per subpixel */
+       SH_CSS_FRAME_FORMAT_UYVY,       /* 16 bit YUV 422, UYVY interleaved */
+       SH_CSS_FRAME_FORMAT_YUYV,       /* 16 bit YUV 422, YUYV interleaved */
+       SH_CSS_FRAME_FORMAT_YUV444,     /* 24 bit YUV 444, Y, U, V plane */
+       SH_CSS_FRAME_FORMAT_YUV_LINE,   /* Internal format, e.g. for VBF frame.
+                                          2 y lines followed by a uv
+                                          interleaved line */
+       SH_CSS_FRAME_FORMAT_RAW,        /* RAW, 1 plane */
+       SH_CSS_FRAME_FORMAT_RGB565,     /* 16 bit RGB, 1 plane. Each 3 sub
+                                          pixels are packed into one 16 bit
+                                          value, 5 bits for R, 6 bits for G
+                                          and 5 bits for B. */
+       SH_CSS_FRAME_FORMAT_PLANAR_RGB888, /* 24 bit RGB, 3 planes */
+       SH_CSS_FRAME_FORMAT_RGBA888,    /* 32 bit RGBA, 1 plane, A=Alpha unused
+                                        */
+       SH_CSS_FRAME_FORMAT_QPLANE6,    /* Internal, for advanced ISP */
+       SH_CSS_FRAME_FORMAT_BINARY_8,   /* byte stream, used for jpeg. For
+                                          frames of this type, we set the
+                                          height to 1 and the width to the
+                                          number of allocated bytes. */
+};
+
+struct sh_css_frame_plane {
+       unsigned int height;    /* height of a plane in lines */
+       unsigned int width;     /* width of a line, in DMA elements, note that
+                                  for RGB565 the three subpixels are stored in
+                                  one element. For all other formats this is
+                                  the number of subpixels per line. */
+       unsigned int stride;    /* stride of a line in bytes */
+       void *data;             /* pointer that points into frame data */
+};
+
+struct sh_css_frame_binary_plane {
+       unsigned int size;
+       struct sh_css_frame_plane data;
+};
+
+struct sh_css_frame_yuv_planes {
+       struct sh_css_frame_plane y;
+       struct sh_css_frame_plane u;
+       struct sh_css_frame_plane v;
+};
+
+struct sh_css_frame_nv_planes {
+       struct sh_css_frame_plane y;
+       struct sh_css_frame_plane uv;
+};
+
+struct sh_css_frame_rgb_planes {
+       struct sh_css_frame_plane r;
+       struct sh_css_frame_plane g;
+       struct sh_css_frame_plane b;
+};
+
+struct sh_css_frame_plane6_planes {
+       struct sh_css_frame_plane r;
+       struct sh_css_frame_plane r_at_b;
+       struct sh_css_frame_plane gr;
+       struct sh_css_frame_plane gb;
+       struct sh_css_frame_plane b;
+       struct sh_css_frame_plane b_at_r;
+};
+
+/* For RAW input, the bayer order needs to be specified separately. There
+   are 4 possible orders. The name is constructed by taking the first two
+   colors on the first line and the first two colors from the second line.
+grbg: GRGRGRGR
+      BGBGBGBG
+rgbg: RGRGRGRG
+      GBGBGBGB
+bggr: BGBGBGBG
+      GRGRGRGR
+gbrg: GBGBGBGB
+      RGRGRGRG
+ */
+enum sh_css_bayer_order {
+       sh_css_bayer_order_grbg,
+       sh_css_bayer_order_rggb,
+       sh_css_bayer_order_bggr,
+       sh_css_bayer_order_gbrg
+};
+
+/* Frame info struct:
+   This structure describes a frame. It contains the resolution and strides.
+ */
+struct sh_css_frame_info {
+       /* width in valid data in pixels (not subpixels) */
+       unsigned int width;
+       /* height in lines of valid image data */
+       unsigned int height;
+       /* width of a line in memory, in pixels */
+       unsigned int padded_width;
+       /* format of the data in this frame */
+       enum sh_css_frame_format format;
+       /* number of valid bits per pixel, only valid for raw frames. */
+       unsigned int raw_bit_depth;
+       /* bayer order of raw data, only valid for raw frames. */
+       enum sh_css_bayer_order raw_bayer_order;
+};
+
+struct sh_css_frame {
+       struct sh_css_frame_info info;
+       /* pointer to start of image data in memory */
+       void *data;
+       /* size of data pointer in bytes */
+       unsigned int data_bytes;
+       /* indicate whether memory is allocated physically contiguously */
+       bool contiguous;
+       union {
+               struct sh_css_frame_plane raw;
+               struct sh_css_frame_plane rgb;
+               struct sh_css_frame_rgb_planes planar_rgb;
+               struct sh_css_frame_plane yuyv;
+               struct sh_css_frame_yuv_planes yuv;
+               struct sh_css_frame_nv_planes nv;
+               struct sh_css_frame_plane6_planes plane6;
+               struct sh_css_frame_binary_plane binary;
+       } planes;
+};
+
+/* Histogram. This contains num_elements values of type unsigned int.
+ * The data pointer is a DDR pointer (virtual address).
+ */
+struct sh_css_histogram {
+       unsigned int num_elements;
+       void *data;
+};
+
+/* Overlay:
+ * this is the structure describing the entire overlay.
+ * An overlay consists of a frame (of type sh_css_frame_format_yuv420),
+ * the background color (yuv) and the blending ratios for the subpixels
+ * of the input data and the overlay data.
+ * All pixels in the overlay that are not equal to the background are
+ * overlaid, taking their blending ratio into account. The blending ratio
+ * should be specified between 0 and 100.
+ */
+struct sh_css_overlay {
+       /* the frame containing the overlay data The overlay frame width should
+        * be the multiples of 2*ISP_VEC_NELEMS. The overlay frame height
+        * should be the multiples of 2.
+        */
+       struct sh_css_frame *frame;
+       /* Y value of overlay background */
+       unsigned char bg_y;
+       /* U value of overlay background */
+       char bg_u;
+       /* V value of overlay background */
+       char bg_v;
+       /* the blending percent of input data for Y subpixels */
+       unsigned char blend_input_perc_y;
+       /* the blending percent of input data for U subpixels */
+       unsigned char blend_input_perc_u;
+       /* the blending percent of input data for V subpixels */
+       unsigned char blend_input_perc_v;
+       /* the blending percent of overlay data for Y subpixels */
+       unsigned char blend_overlay_perc_y;
+       /* the blending percent of overlay data for U subpixels */
+       unsigned char blend_overlay_perc_u;
+       /* the blending percent of overlay data for V subpixels */
+       unsigned char blend_overlay_perc_v;
+       /* the overlay start x pixel position on output frame It should be the
+          multiples of 2*ISP_VEC_NELEMS. */
+       unsigned int overlay_start_x;
+       /* the overlay start y pixel position on output frame It should be the
+          multiples of 2. */
+       unsigned int overlay_start_y;
+};
+
+/* SP struct describing overlay properties */
+struct sh_css_sp_overlay {
+       int bg_y;
+       int bg_u;
+       int bg_v;
+       int blend_shift;
+       int blend_input_y;
+       int blend_input_u;
+       int blend_input_v;
+       int blend_overlay_y;
+       int blend_overlay_u;
+       int blend_overlay_v;
+       int overlay_width;
+       int overlay_height;
+       int overlay_start_x;
+       int overlay_start_y;
+       const char *frame_ptr_overlay_y;
+       const char *frame_ptr_overlay_u;
+       const char *frame_ptr_overlay_v;
+};
+
+/* structure that describes the 3A and DIS grids */
+struct sh_css_grid_info {
+       /* 3A statistics grid: */
+       unsigned int s3a_width;
+       unsigned int s3a_height;
+       unsigned int s3a_bqs_per_grid_cell;
+       /* DIS grid: */
+       unsigned int dis_width;  /* also used for vertical projections */
+       unsigned int dis_height; /* also used for horizontal projections */
+       unsigned int dis_bqs_per_grid_cell;
+       unsigned int dis_hor_coef_num;
+       unsigned int dis_ver_coef_num;
+};
+
+enum sh_css_ob_mode {
+       sh_css_ob_mode_none,
+       sh_css_ob_mode_fixed,
+       sh_css_ob_mode_raster
+};
+
+/* Shading correction */
+enum sh_css_sc_color {
+       SH_CSS_SC_COLOR_GR,
+       SH_CSS_SC_COLOR_R,
+       SH_CSS_SC_COLOR_B,
+       SH_CSS_SC_COLOR_GB
+};
+
+/* White Balance (Gain Adjust) */
+struct sh_css_wb_config {
+       unsigned int integer_bits;
+       unsigned int gr;        /* unsigned <integer_bits>.<16-integer_bits> */
+       unsigned int r;         /* unsigned <integer_bits>.<16-integer_bits> */
+       unsigned int b;         /* unsigned <integer_bits>.<16-integer_bits> */
+       unsigned int gb;        /* unsigned <integer_bits>.<16-integer_bits> */
+};
+
+/* Color Space Conversion settings */
+struct sh_css_cc_config {
+       unsigned int fraction_bits;
+       int matrix[3 * 3];      /* RGB2YUV Color matrix, signed
+                                  <13-fraction_bits>.<fraction_bits> */
+};
+
+/* Morphing table for advanced ISP.
+ * Each line of width elements takes up COORD_TABLE_EXT_WIDTH elements
+ * in memory.
+ */
+struct sh_css_morph_table {
+       unsigned int height;
+       unsigned int width;     /* number of valid elements per line */
+       unsigned short *coordinates_x[SH_CSS_MORPH_TABLE_NUM_PLANES];
+       unsigned short *coordinates_y[SH_CSS_MORPH_TABLE_NUM_PLANES];
+};
+
+struct sh_css_fpn_table {
+       short *data;
+       unsigned int width;
+       unsigned int height;
+       unsigned int shift;
+};
+
+struct sh_css_shading_table {
+       /* native sensor resolution */
+       unsigned int sensor_width;
+       unsigned int sensor_height;
+       /* number of data points per line per color (bayer quads) */
+       unsigned int width;
+       /* number of lines of data points per color (bayer quads) */
+       unsigned int height;
+       /* bits of fraction part for shading table values */
+       unsigned int fraction_bits;
+       /* one table for each color (use sh_css_sc_color to index) */
+       unsigned short *data[SH_CSS_SC_NUM_COLORS];
+};
+
+struct sh_css_gamma_table {
+       unsigned short data[SH_CSS_GAMMA_TABLE_SIZE];
+};
+
+struct sh_css_ctc_table {
+       unsigned short data[SH_CSS_CTC_TABLE_SIZE];
+};
+
+struct sh_css_macc_table {
+       short data[SH_CSS_MACC_NUM_COEFS * SH_CSS_MACC_NUM_AXES];
+};
+
+/* Temporal noise reduction configuration */
+struct sh_css_tnr_config {
+       u0_16 gain;             /* [gain] Strength of NR */
+       u0_16 threshold_y;      /* [intensity] Motion sensitivity for Y */
+       u0_16 threshold_uv;     /* [intensity] Motion sensitivity for U/V */
+};
+
+/* Optical black level configuration */
+struct sh_css_ob_config {
+       /* Obtical black level mode (Fixed / Raster) */
+       enum sh_css_ob_mode mode;
+       /* [intensity] optical black level for GR (relevant for fixed mode) */
+       u0_16 level_gr;
+       /* [intensity] optical black level for R (relevant for fixed mode) */
+       u0_16 level_r;
+       /* [intensity] optical black level for B (relevant for fixed mode) */
+       u0_16 level_b;
+       /* [intensity] optical black level for GB (relevant for fixed mode) */
+       u0_16 level_gb;
+       /* [BQ] 0..63 start position of OB area (relevant for raster mode) */
+       unsigned short start_position;
+       /* [BQ] start..63 end position of OB area (relevant for raster mode) */
+       unsigned short end_position;
+};
+
+/* Defect pixel correction configuration */
+struct sh_css_dp_config {
+       /* [intensity] The threshold of defect Pixel Correction, representing
+        * the permissible difference of intensity between one pixel and its
+        * surrounding pixels. Smaller values result in more frequent pixel
+        * corrections.
+        */
+       u0_16 threshold;
+       /* [gain] The sensitivity of mis-correction. ISP will miss a lot of
+        * defects if the value is set too large.
+        */
+       u8_8 gain;
+};
+
+/* Configuration used by Bayer noise reduction and YCC noise reduction */
+struct sh_css_nr_config {
+       /* [gain] Strength of noise reduction for both Bayer NR & YCC NR (Used
+        * by Bayer NR and YCC NR).
+        */
+       u0_16 gain;
+       /* [intensity] Sensitivity of Edge (Used by Bayer NR) */
+       u0_16 direction;
+       /* [intensity] coring threshold for Cb (Used by YCC NR) */
+       u0_16 threshold_cb;
+       /* [intensity] coring threshold for Cr (Used by YCC NR) */
+       u0_16 threshold_cr;
+};
+
+/* Edge enhancement (sharpen) configuration */
+struct sh_css_ee_config {
+       /* [gain] The strength of sharpness. */
+       u5_11 gain;
+       /* [intensity] The threshold that divides noises from edge. */
+       u8_8 threshold;
+       /* [gain] The strength of sharpness in pell-mell area. */
+       u5_11 detail_gain;
+};
+
+struct sh_css_de_config {
+       u0_16 pixelnoise;
+       u0_16 c1_coring_threshold;
+       u0_16 c2_coring_threshold;
+};
+
+struct sh_css_gc_config {
+       int gain_k1;
+       int gain_k2;
+};
+
+struct sh_css_anr_config {
+       int threshold;
+};
+
+struct sh_css_3a_config {
+       u0_16 ae_y_coef_r;      /* [gain] Weight of R for Y */
+       u0_16 ae_y_coef_g;      /* [gain] Weight of G for Y */
+       u0_16 ae_y_coef_b;      /* [gain] Weight of B for Y */
+       s0_15 af_fir1_coef[7];  /* [factor] AF FIR coefficients of fir1 */
+       s0_15 af_fir2_coef[7];  /* [factor] AF FIR coefficients of fir2 */
+};
+
+/* Workaround: hivecc complains about "tag "sh_css_3a_output" already declared"
+   without this extra decl. */
+struct sh_css_3a_output;
+
+struct sh_css_3a_output {
+       int ae_y;
+       int awb_cnt;
+       int awb_gr;
+       int awb_r;
+       int awb_b;
+       int awb_gb;
+       int af_hpf1;
+       int af_hpf2;
+};
+
+/* Descriptor of sp firmware blob */
+struct sh_css_sp_fw {
+       const void  *text;              /* Sp text section */
+       unsigned int text_source;       /* Position of text in blob */
+       unsigned int text_size;         /* Size of text section */
+       const void  *data;              /* Sp data section */
+       unsigned int data_source;       /* Position of data in blob */
+       unsigned int data_target;       /* Start position of data in SP dmem */
+       unsigned int data_size;         /* Size of text section */
+       unsigned int bss_target;        /* Start position of bss in SP dmem */
+       unsigned int bss_size;          /* Size of bss section */
+};
+
+/* this struct contains all arguments that can be passed to
+   a binary. It depends on the binary which ones are used. */
+struct sh_css_binary_args {
+       struct sh_css_frame *cc_frame;       /* continuous capture frame */
+       struct sh_css_frame *in_frame;       /* input frame */
+       struct sh_css_frame *in_ref_frame;   /* reference input frame */
+       struct sh_css_frame *in_tnr_frame;   /* tnr input frame */
+       struct sh_css_frame *out_frame;      /* output frame */
+       struct sh_css_frame *out_ref_frame;  /* reference output frame */
+       struct sh_css_frame *out_tnr_frame;  /* tnr output frame */
+       struct sh_css_frame *extra_frame;    /* intermediate frame */
+       struct sh_css_frame *out_vf_frame;   /* viewfinder output frame */
+       int                  dvs_vector_x;
+       int                  dvs_vector_y;
+       bool                 enable_xnr;
+       bool                 two_ppc;
+       bool                 copy_vf;
+       bool                 copy_output;
+       unsigned             vf_downscale_log2;
+};
+
+/* Type of acceleration */
+enum sh_css_acc_type {
+       SH_CSS_ACC_STANDALONE,  /* Stand-alone acceleration */
+       SH_CSS_ACC_OUTPUT,      /* Accelerator stage on output frame */
+       SH_CSS_ACC_VIEWFINDER   /* Accelerator stage on viewfinder frame */
+};
+
+/* Type of acceleration argument */
+enum sh_css_acc_arg_type {
+       SH_CSS_ACC_ARG_SCALAR_IN,    /* Scalar input argument */
+       SH_CSS_ACC_ARG_SCALAR_OUT,   /* Scalar output argument */
+       SH_CSS_ACC_ARG_SCALAR_IO,    /* Scalar in/output argument */
+       SH_CSS_ACC_ARG_PTR_IN,       /* Pointer input argument */
+       SH_CSS_ACC_ARG_PTR_OUT,      /* Pointer output argument */
+       SH_CSS_ACC_ARG_PTR_IO,       /* Pointer in/output argument */
+       SH_CSS_ACC_ARG_FRAME         /* Frame argument */
+};
+
+/* Descriptor for an SP argument */
+struct sh_css_sp_arg {
+       enum sh_css_acc_arg_type type;  /* Type  of SP argument */
+       void                    *value; /* Value of SP argument */
+       unsigned int             size;  /* Size  of SP argument */
+       void                    *host;  /* Private data used by host */
+};
+
+struct sh_css_acc_fw;
+
+/* Firmware descriptor */
+struct sh_css_acc_fw_hdr {
+       enum sh_css_acc_type type;      /* Type of accelerator */
+       bool                 loaded;    /* Firmware has been loaded */
+       struct sh_css_sp_arg *sp_args;  /* Current SP argument */
+       unsigned             prog_name_offset; /* offset wrt hdr in bytes */
+       unsigned             arg_types_offset; /* offset wrt hdr in bytes */
+       unsigned             sp_blob_offset;   /* offset wrt hdr in bytes */
+       unsigned             isp_blob_offset;  /* offset wrt hdr in bytes */
+       struct {
+               unsigned int         size;       /* Size of sp blob */
+               void (*init) (struct sh_css_acc_fw *); /* init for crun */
+               void                *entry;      /* Address of sp entry point */
+               unsigned int        *args;       /* Address of sp_args */
+               unsigned int         args_cnt;   /* Number  of sp_args */
+               unsigned int         args_size;  /* Size    of sp_args */
+               unsigned int        *css_abort;  /* SP dmem abort flag */
+               struct sh_css_frame *input;      /* SP dmem input frame */
+               struct sh_css_frame *output;     /* SP dmem output frame */
+               struct sh_css_frame *out_vf;     /* SP dmem vf frame */
+               struct sh_css_frame *extra;      /* SP dmem extra frame */
+               unsigned int        *vf_downscale_bits;
+               void                *isp_code;   /* SP dmem address holding xmem
+                                                   address of isp code */
+               struct sh_css_sp_fw fw;          /* SP fw descriptor */
+       } sp;
+       struct {
+               unsigned int size;       /* Size of isp blob */
+       } isp;
+};
+
+/* Firmware. Containing header and actual blobs */
+struct sh_css_acc_fw {
+       /* firmware header */
+       struct sh_css_acc_fw_hdr header;
+       /* To create a sequence of accelerators */
+       struct sh_css_acc_fw *next;
+       /* Firmware handle between user space and kernel */
+       unsigned int handle;
+       /* followed by prog_name, sp arg types, sp blob and isp blob */
+#ifdef __HIVECC
+       unsigned char            data[1]; /* Not C89 */
+#else
+       unsigned char            data[];
+#endif
+};
+
+/* Access macros for firmware */
+#define SH_CSS_ACC_OFFSET(t, f, n) ((t)((unsigned char *)(f)+(f->header.n)))
+#define SH_CSS_ACC_PROG_NAME(f)    SH_CSS_ACC_OFFSET(const char *, f, \
+                                                prog_name_offset)
+#define SH_CSS_ACC_SP_ARGS(f)      SH_CSS_ACC_OFFSET(enum sh_css_acc_arg_type*,\
+                                                f, arg_types_offset)
+#define SH_CSS_ACC_SP_CODE(f)      SH_CSS_ACC_OFFSET(unsigned char *, f, \
+                                                sp_blob_offset)
+#define SH_CSS_ACC_SP_SIZE(f)      ((f)->header.sp.size)
+#define SH_CSS_ACC_SP_DATA(f)      (SH_CSS_ACC_SP_CODE(f) + \
+                                       (f)->header.sp.fw.data_source)
+#define SH_CSS_ACC_ISP_CODE(f)     SH_CSS_ACC_OFFSET(unsigned char*, f,\
+                                                isp_blob_offset)
+#define SH_CSS_ACC_ISP_SIZE(f)     ((f)->header.isp.size)
+#define SH_CSS_ACC_SIZE(f)         ((f)->header.isp_blob_offset + \
+                                       SH_CSS_ACC_ISP_SIZE(f))
+
+#endif /* _SH_CSS_TYPES_H_ */
diff --git a/drivers/media/video/atomisp/hmm/hmm.c b/drivers/media/video/atomisp/hmm/hmm.c
new file mode 100644 (file)
index 0000000..f4fa7fa
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+/*
+ * This file contains entry functions for memory management of ISP driver
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>     /* for kmap */
+#include <linux/io.h>          /* for page_to_phys */
+
+#include "hmm/hmm.h"
+#include "hmm/hmm_bo.h"
+#include "hmm/hmm_bo_dev.h"
+
+#include "mmu/isp_mmu.h"
+#include "mmu/sh_mmu.h"
+#include "atomisp_internal.h"
+#include "asm/cacheflush.h"
+
+#ifdef USE_SSSE3
+#include <asm/ssse3.h>
+#endif
+
+static struct hmm_bo_device bo_device;
+static void *dummy_ptr;
+
+int hmm_init()
+{
+       int ret;
+
+       ret = hmm_bo_device_init(&bo_device, &sh_mmu_driver,
+                                ISP_VM_START, ISP_VM_SIZE);
+       if (ret)
+               v4l2_err(&atomisp_dev,
+                           "hmm_bo_device_init failed.\n");
+
+       /*
+        * As hmm use NULL to indicate invalid ISP virtual address,
+        * and ISP_VM_START is defined to 0 too, so we allocate
+        * one piece of dummy memory, which should return value 0,
+        * at the beginning, to avoid hmm_alloc return 0 in the
+        * further allocation.
+        */
+       dummy_ptr = hmm_alloc(1, HMM_BO_PRIVATE, 0, 0, HMM_UNCACHED);
+       return ret;
+}
+
+void hmm_cleanup()
+{
+       /*
+        * free dummy memory first
+        */
+       hmm_free(dummy_ptr);
+       dummy_ptr = NULL;
+
+       hmm_bo_device_exit(&bo_device);
+}
+
+void *hmm_alloc(size_t bytes, enum hmm_bo_type type,
+               int from_highmem, unsigned int userptr, bool cached)
+{
+       unsigned int pgnr;
+       struct hmm_buffer_object *bo;
+       int ret;
+
+       /*Get page number from size*/
+       pgnr = size_to_pgnr_ceil(bytes);
+
+       /*Buffer object structure init*/
+       bo = hmm_bo_create(&bo_device, pgnr);
+       if (!bo) {
+               v4l2_err(&atomisp_dev, "hmm_bo_create failed.\n");
+               goto create_bo_err;
+       }
+
+       /*Allocate virtual address in ISP virtual space*/
+       ret = hmm_bo_alloc_vm(bo);
+       if (ret) {
+               v4l2_err(&atomisp_dev,
+                           "hmm_bo_alloc_vm failed.\n");
+               goto alloc_vm_err;
+       }
+
+       /*Allocate pages for memory*/
+       ret = hmm_bo_alloc_pages(bo, type, from_highmem, userptr, cached);
+       if (ret) {
+               v4l2_err(&atomisp_dev,
+                           "hmm_bo_alloc_pages failed.\n");
+               goto alloc_page_err;
+       }
+
+       /*Combind the virtual address and pages togather*/
+       ret = hmm_bo_bind(bo);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "hmm_bo_bind failed.\n");
+               goto bind_err;
+       }
+
+       return (void *)bo->vm_node->start;
+
+bind_err:
+       hmm_bo_free_pages(bo);
+alloc_page_err:
+       hmm_bo_free_vm(bo);
+alloc_vm_err:
+       hmm_bo_unref(bo);
+create_bo_err:
+       return NULL;
+}
+
+void hmm_free(void *virt)
+{
+       struct hmm_buffer_object *bo;
+
+       bo = hmm_bo_device_search_start(&bo_device, (unsigned int)virt);
+
+       if (!bo) {
+               v4l2_err(&atomisp_dev,
+                           "can not find buffer object start with "
+                           "address 0x%x\n", (unsigned int)virt);
+               return;
+       }
+
+       hmm_bo_unbind(bo);
+
+       hmm_bo_free_pages(bo);
+
+       hmm_bo_free_vm(bo);
+
+       hmm_bo_unref(bo);
+}
+
+static inline int hmm_check_bo(struct hmm_buffer_object *bo, unsigned int ptr)
+{
+       if (!bo) {
+               v4l2_err(&atomisp_dev,
+                           "can not find buffer object contains "
+                           "address 0x%x\n", ptr);
+               return -EINVAL;
+       }
+
+       if (!hmm_bo_page_allocated(bo)) {
+               v4l2_err(&atomisp_dev,
+                           "buffer object has no page allocated.\n");
+               return -EINVAL;
+       }
+
+       if (!hmm_bo_vm_allocated(bo)) {
+               v4l2_err(&atomisp_dev,
+                           "buffer object has no virtual address"
+                           " space allocated.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*Read function in ISP memory management*/
+int hmm_load(void *virt, void *data, unsigned int bytes)
+{
+       unsigned int ptr;
+       struct hmm_buffer_object *bo;
+       unsigned int idx, offset, len;
+       char *src, *des;
+       int ret;
+
+       ptr = (unsigned int)virt;
+
+       bo = hmm_bo_device_search_in_range(&bo_device, ptr);
+       ret = hmm_check_bo(bo, ptr);
+       if (ret)
+               return ret;
+
+       des = (char *)data;
+       while (bytes) {
+               idx = (ptr - bo->vm_node->start) >> PAGE_SHIFT;
+               offset = (ptr - bo->vm_node->start) - (idx << PAGE_SHIFT);
+
+               src = (char *)kmap(bo->pages[idx]);
+               if (!src) {
+                       v4l2_err(&atomisp_dev,
+                                   "kmap buffer object page failed: "
+                                   "pg_idx = %d\n", idx);
+                       return -EINVAL;
+               }
+
+               src += offset;
+
+               if ((bytes + offset) >= PAGE_SIZE) {
+                       len = PAGE_SIZE - offset;
+                       bytes -= len;
+               } else {
+                       len = bytes;
+                       bytes = 0;
+               }
+
+               ptr += len;     /* update ptr for next loop */
+
+#ifdef USE_SSSE3
+               _ssse3_memcpy(des, src, len);
+#else
+               memcpy(des, src, len);
+#endif
+
+               des += len;
+               clflush_cache_range(src, len);
+
+               kunmap(bo->pages[idx]);
+       }
+
+       return 0;
+}
+
+/*Write function in ISP memory management*/
+int hmm_store(void *virt, const void *data, unsigned int bytes)
+{
+       unsigned int ptr;
+       struct hmm_buffer_object *bo;
+       unsigned int idx, offset, len;
+       char *src, *des;
+       int ret;
+
+       ptr = (unsigned int)virt;
+
+       bo = hmm_bo_device_search_in_range(&bo_device, ptr);
+       ret = hmm_check_bo(bo, ptr);
+       if (ret)
+               return ret;
+
+       src = (char *)data;
+       while (bytes) {
+               idx = (ptr - bo->vm_node->start) >> PAGE_SHIFT;
+               offset = (ptr - bo->vm_node->start) - (idx << PAGE_SHIFT);
+
+               des = (char *)kmap(bo->pages[idx]);
+               if (!des) {
+                       v4l2_err(&atomisp_dev,
+                                   "kmap buffer object page failed: "
+                                   "pg_idx = %d\n", idx);
+                       return -EINVAL;
+               }
+
+               des += offset;
+
+               if ((bytes + offset) >= PAGE_SIZE) {
+                       len = PAGE_SIZE - offset;
+                       bytes -= len;
+               } else {
+                       len = bytes;
+                       bytes = 0;
+               }
+
+               ptr += len;
+
+#ifdef USE_SSSE3
+               _ssse3_memcpy(des, src, len);
+#else
+               memcpy(des, src, len);
+#endif
+               src += len;
+
+               kunmap(bo->pages[idx]);
+       }
+
+       return 0;
+}
+
+/*memset function in ISP memory management*/
+int hmm_set(void *virt, int c, unsigned int bytes)
+{
+       unsigned int ptr;
+       struct hmm_buffer_object *bo;
+       unsigned int idx, offset, len;
+       char *des;
+       int ret;
+
+       ptr = (unsigned int)virt;
+
+       bo = hmm_bo_device_search_in_range(&bo_device, ptr);
+       ret = hmm_check_bo(bo, ptr);
+       if (ret)
+               return ret;
+
+       while (bytes) {
+               idx = (ptr - bo->vm_node->start) >> PAGE_SHIFT;
+               offset = (ptr - bo->vm_node->start) - (idx << PAGE_SHIFT);
+
+               des = (char *)kmap(bo->pages[idx]);
+               if (!des) {
+                       v4l2_err(&atomisp_dev,
+                                   "kmap buffer object page failed: "
+                                   "pg_idx = %d\n", idx);
+                       return -EINVAL;
+               }
+               des += offset;
+
+               if ((bytes + offset) >= PAGE_SIZE) {
+                       len = PAGE_SIZE - offset;
+                       bytes -= len;
+               } else {
+                       len = bytes;
+                       bytes = 0;
+               }
+
+               ptr += len;
+
+               memset(des, c, len);
+
+               kunmap(bo->pages[idx]);
+       }
+
+       return 0;
+}
+
+/*Virtual address to physical address convert*/
+unsigned int hmm_virt_to_phys(void *virt)
+{
+       unsigned int ptr = (unsigned int)virt;
+       unsigned int idx, offset;
+       struct hmm_buffer_object *bo;
+
+       bo = hmm_bo_device_search_in_range(&bo_device, ptr);
+       if (!bo) {
+               v4l2_err(&atomisp_dev,
+                           "can not find buffer object contains "
+                           "address 0x%x\n", ptr);
+               return -1;
+       }
+
+       idx = (ptr - bo->vm_node->start) >> PAGE_SHIFT;
+       offset = (ptr - bo->vm_node->start) - (idx << PAGE_SHIFT);
+
+       return page_to_phys(bo->pages[idx]) + offset;
+}
+
+int hmm_mmap(struct vm_area_struct *vma, void *virt)
+{
+       unsigned int ptr = (unsigned int)virt;
+       struct hmm_buffer_object *bo;
+
+       bo = hmm_bo_device_search_start(&bo_device, ptr);
+       if (!bo) {
+               v4l2_err(&atomisp_dev,
+                           "can not find buffer object start with "
+                           "address 0x%x\n", (unsigned int)virt);
+               return -EINVAL;
+       }
+
+       return hmm_bo_mmap(vma, bo);
+}
+
+/*Map ISP virtual address into IA virtual address*/
+void *hmm_vmap(void *virt)
+{
+       unsigned int ptr = (unsigned int)virt;
+       struct hmm_buffer_object *bo;
+
+       bo = hmm_bo_device_search_start(&bo_device, ptr);
+       if (!bo) {
+               v4l2_err(&atomisp_dev,
+                           "can not find buffer object start with "
+                           "address 0x%x\n", (unsigned int)virt);
+               return NULL;
+       }
+
+       return hmm_bo_vmap(bo);
+}
diff --git a/drivers/media/video/atomisp/hmm/hmm_bo.c b/drivers/media/video/atomisp/hmm/hmm_bo.c
new file mode 100644 (file)
index 0000000..7957667
--- /dev/null
@@ -0,0 +1,1077 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+/*
+ * This file contains functions for buffer object structure management
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gfp.h>         /* for GFP_ATOMIC */
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/hugetlb.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>                /* for kmalloc */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <linux/io.h>
+#include <asm/current.h>
+#include <linux/sched.h>
+#include "hmm/hmm_vm.h"
+#include "hmm/hmm_bo.h"
+#include "hmm/hmm_bo_dev.h"
+#include "hmm/hmm_common.h"
+#include "atomisp_internal.h"
+
+static inline unsigned int order_to_nr(unsigned int order)
+{
+       return 1U << order;
+}
+
+static inline unsigned int nr_to_order_ceil(unsigned int nr)
+{
+       unsigned int order = 0;
+
+       for (; nr / 2; nr = nr / 2 + nr % 2)
+               order++;
+
+       return order;
+}
+
+static inline unsigned int nr_to_order_bottom(unsigned int nr)
+{
+       unsigned int order = 0;
+
+       while (nr /= 2)
+               order++;
+
+       return order;
+}
+
+static void free_bo_internal(struct hmm_buffer_object *bo)
+{
+       kfree(bo);
+}
+
+/*
+ * use these functions to dynamically alloc hmm_buffer_object.
+ * hmm_bo_init will called for that allocated buffer object, and
+ * the release callback is set to kfree.
+ */
+struct hmm_buffer_object *hmm_bo_create(struct hmm_bo_device *bdev, int pgnr)
+{
+       struct hmm_buffer_object *bo;
+       int ret;
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+       if (!bo) {
+               v4l2_err(&atomisp_dev, "out of memory for bo\n");
+               return NULL;
+       }
+
+       ret = hmm_bo_init(bdev, bo, pgnr, free_bo_internal);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "hmm_bo_init failed\n");
+               kfree(bo);
+               return NULL;
+       }
+
+       return bo;
+}
+
+/*
+ * use this function to initialize pre-allocated hmm_buffer_object.
+ * as hmm_buffer_object may be used as an embedded object in an upper
+ * level object, a release callback must be provided. if it is
+ * embedded in upper level object, set release call back to release
+ * function of that object. if no upper level object, set release
+ * callback to NULL.
+ *
+ * bo->kref is inited to 1.
+ */
+int hmm_bo_init(struct hmm_bo_device *bdev,
+               struct hmm_buffer_object *bo,
+               unsigned int pgnr, void (*release) (struct hmm_buffer_object *))
+{
+       if (bdev == NULL) {
+               v4l2_warn(&atomisp_dev,
+                           "NULL hmm_bo_device.\n");
+               return -EINVAL;
+       }
+
+       /* hmm_bo_device must be already inited */
+       var_equal_return(hmm_bo_device_inited(bdev), 0, -EINVAL,
+                          "hmm_bo_device not inited yet.\n");
+
+       /* prevent zero size buffer object */
+       if (pgnr == 0) {
+               v4l2_err(&atomisp_dev,
+                           "0 size buffer is not allowed.\n");
+               return -EINVAL;
+       }
+
+       memset(bo, 0, sizeof(*bo));
+
+       kref_init(&bo->kref);
+
+       mutex_init(&bo->mutex);
+
+       INIT_LIST_HEAD(&bo->list);
+
+       bo->pgnr = pgnr;
+       bo->bdev = bdev;
+
+       INIT_LIST_HEAD(&bo->pgblocks);
+
+       bo->release = release;
+
+       if (!bo->release)
+               v4l2_warn(&atomisp_dev,
+                           "no release callback specified.\n");
+
+       /*
+        * add to active_bo_list
+        */
+       mutex_lock(&bdev->ablist_mutex);
+       list_add_tail(&bo->list, &bdev->active_bo_list);
+       bo->status |= HMM_BO_ACTIVE;
+       mutex_unlock(&bdev->ablist_mutex);
+
+       return 0;
+}
+
+static void hmm_bo_release(struct hmm_buffer_object *bo)
+{
+       struct hmm_bo_device *bdev;
+
+       check_bo_null_return(bo, (void)0);
+
+       bdev = bo->bdev;
+
+       /*
+        * FIX ME:
+        *
+        * how to destroy the bo when it is stilled MMAPED?
+        *
+        * ideally, this will not happened as hmm_bo_release
+        * will only be called when kref reaches 0, and in mmap
+        * operation the hmm_bo_ref will eventually be called.
+        * so, if this happened, something goes wrong.
+        */
+       if (bo->status & HMM_BO_MMAPED) {
+               v4l2_err(&atomisp_dev,
+                            "destroy bo which is MMAPED, do nothing\n");
+               goto err;
+       }
+
+       if (bo->status & HMM_BO_BINDED) {
+               v4l2_warn(&atomisp_dev,
+                            "the bo is still binded, unbind it first...\n");
+               hmm_bo_unbind(bo);
+       }
+       if (bo->status & HMM_BO_PAGE_ALLOCED) {
+               v4l2_warn(&atomisp_dev,
+                            "the pages is not freed, free pages first\n");
+               hmm_bo_free_pages(bo);
+       }
+       if (bo->status & HMM_BO_VM_ALLOCED) {
+               v4l2_warn(&atomisp_dev,
+                            "the vm is still not freed, free vm first...\n");
+               hmm_bo_free_vm(bo);
+       }
+
+       /*
+        * remove it from buffer device's buffer object list.
+        */
+       if (hmm_bo_activated(bo)) {
+               mutex_lock(&bdev->ablist_mutex);
+               list_del(&bo->list);
+               mutex_unlock(&bdev->ablist_mutex);
+       } else {
+               mutex_lock(&bdev->fblist_mutex);
+               list_del(&bo->list);
+               mutex_unlock(&bdev->fblist_mutex);
+       }
+
+       if (bo->release)
+               bo->release(bo);
+err:
+       return;
+}
+
+int hmm_bo_activated(struct hmm_buffer_object *bo)
+{
+       check_bo_null_return(bo, 0);
+
+       return bo->status & HMM_BO_ACTIVE;
+}
+
+void hmm_bo_unactivate(struct hmm_buffer_object *bo)
+{
+       struct hmm_bo_device *bdev;
+
+       check_bo_null_return(bo, (void)0);
+
+       check_bo_status_no_goto(bo, HMM_BO_ACTIVE, status_err);
+
+       bdev = bo->bdev;
+
+       mutex_lock(&bdev->ablist_mutex);
+       list_del(&bo->list);
+       mutex_unlock(&bdev->ablist_mutex);
+
+       mutex_lock(&bdev->fblist_mutex);
+       list_add_tail(&bo->list, &bdev->free_bo_list);
+       bo->status &= (~HMM_BO_ACTIVE);
+       mutex_unlock(&bdev->fblist_mutex);
+
+       return;
+
+status_err:
+       v4l2_err(&atomisp_dev,
+                       "buffer object already unactivated.\n");
+       return;
+}
+
+int hmm_bo_alloc_vm(struct hmm_buffer_object *bo)
+{
+       struct hmm_bo_device *bdev;
+
+       check_bo_null_return(bo, -EINVAL);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_no_goto(bo, HMM_BO_VM_ALLOCED, status_err);
+
+       bdev = bo->bdev;
+
+       bo->vm_node = hmm_vm_alloc_node(&bdev->vaddr_space, bo->pgnr);
+       if (unlikely(!bo->vm_node)) {
+               v4l2_err(&atomisp_dev,
+                               "hmm_vm_alloc_node err.\n");
+               goto null_vm;
+       }
+
+       bo->status |= HMM_BO_VM_ALLOCED;
+
+       mutex_unlock(&bo->mutex);
+
+       return 0;
+null_vm:
+       mutex_unlock(&bo->mutex);
+       return -ENOMEM;
+
+status_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                       "buffer object already has vm allocated.\n");
+       return -EINVAL;
+}
+
+void hmm_bo_free_vm(struct hmm_buffer_object *bo)
+{
+       struct hmm_bo_device *bdev;
+
+       check_bo_null_return(bo, (void)0);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_yes_goto(bo, HMM_BO_VM_ALLOCED, status_err);
+
+       bdev = bo->bdev;
+
+       hmm_vm_free_node(bo->vm_node);
+       bo->vm_node = NULL;
+       bo->status &= (~HMM_BO_VM_ALLOCED);
+       mutex_unlock(&bo->mutex);
+
+       return;
+
+status_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                       "buffer object has no vm allocated.\n");
+}
+
+int hmm_bo_vm_allocated(struct hmm_buffer_object *bo)
+{
+       int ret;
+
+       check_bo_null_return(bo, 0);
+
+       mutex_lock(&bo->mutex);
+
+       ret = (bo->status & HMM_BO_VM_ALLOCED);
+
+       mutex_unlock(&bo->mutex);
+
+       return ret;
+}
+
+/*Allocate pages which will be used only by ISP*/
+static int alloc_private_pages(struct hmm_buffer_object *bo, int from_highmem,
+                               bool cached)
+{
+       int ret;
+       unsigned int pgnr, order, blk_pgnr;
+       struct page *pages;
+       struct page_block *pgblk;
+       gfp_t gfp;
+       int i, j;
+
+       gfp = GFP_KERNEL;
+       if (from_highmem)
+               gfp |= __GFP_HIGHMEM;
+
+       pgnr = bo->pgnr;
+
+       bo->pages = kzalloc(sizeof(struct page *) * pgnr, GFP_KERNEL);
+       if (unlikely(!bo->pages)) {
+               v4l2_err(&atomisp_dev, "out of memory for bo->pages\n");
+               goto out_of_mem;
+       }
+
+       i = 0;
+       while (pgnr) {
+               order = nr_to_order_bottom(pgnr);
+               if (order > HMM_MAX_ORDER)
+                       order = HMM_MAX_ORDER;
+retry:
+               pages = alloc_pages(gfp, order);
+               if (unlikely(!pages)) {
+                       /*
+                        * in low memory case, if allocation page fails,
+                        * we turn to try if order=0 allocation could
+                        * succeed. if order=0 fails too, that means there is
+                        * no memory left.
+                        */
+                       if (order == HMM_MIN_ORDER) {
+                               v4l2_err(&atomisp_dev,
+                                        "out of memory in alloc_pages\n");
+                               goto out_of_mem;
+                       }
+                       v4l2_warn(&atomisp_dev,
+                                 "allocate order=%d pages failed."
+                                 "reduing page order to %d.\n",
+                                 order, HMM_MIN_ORDER);
+                       order = HMM_MIN_ORDER;
+                       goto retry;
+               } else {
+                       blk_pgnr = order_to_nr(order);
+
+                       pgblk = kzalloc(sizeof(*pgblk), GFP_KERNEL);
+                       if (unlikely(!pgblk)) {
+                               v4l2_err(&atomisp_dev,
+                                               "out of memory for pgblk\n");
+                               goto out_of_mem;
+                       }
+
+                       INIT_LIST_HEAD(&pgblk->list);
+                       pgblk->pages = pages;
+                       pgblk->order = order;
+
+                       list_add_tail(&pgblk->list, &bo->pgblocks);
+
+                       for (j = 0; j < blk_pgnr; j++)
+                               bo->pages[i++] = pages + j;
+
+                       pgnr -= blk_pgnr;
+
+                       if (!cached) {
+                               /*
+                                * set memory to uncacheable -- UC_MINUS
+                                */
+                               ret = set_pages_uc(pages, blk_pgnr);
+                               if (ret) {
+                                       v4l2_err(&atomisp_dev,
+                                                    "set page uncacheable"
+                                                       "failed.\n");
+                                       goto set_uc_mem_fail;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+set_uc_mem_fail:
+       /* FIX ME: select one better */
+       ret = -ENOMEM;
+       goto cleanup;
+out_of_mem:
+       ret = -ENOMEM;
+       goto cleanup;
+cleanup:
+       while (!list_empty(&bo->pgblocks)) {
+               pgblk = list_first_entry(&bo->pgblocks,
+                                        struct page_block, list);
+
+               list_del(&pgblk->list);
+
+               ret = set_pages_wb(pgblk->pages, order_to_nr(pgblk->order));
+               if (ret)
+                       v4l2_err(&atomisp_dev,
+                                       "set page to WB err...\n");
+
+               __free_pages(pgblk->pages, pgblk->order);
+               kfree(pgblk);
+       }
+
+       return ret;
+}
+
+static void free_private_pages(struct hmm_buffer_object *bo)
+{
+       struct page_block *pgblk;
+       int ret;
+
+       while (!list_empty(&bo->pgblocks)) {
+               pgblk = list_first_entry(&bo->pgblocks,
+                                        struct page_block, list);
+
+               list_del(&pgblk->list);
+
+               ret = set_pages_wb(pgblk->pages, order_to_nr(pgblk->order));
+               if (ret)
+                       v4l2_err(&atomisp_dev,
+                                       "set page to WB err...\n");
+
+               __free_pages(pgblk->pages, pgblk->order);
+               kfree(pgblk);
+       }
+
+       kfree(bo->pages);
+}
+
+/*
+ * Hacked from kernel function __get_user_pages in mm/memory.c
+ *
+ * Handle buffers allocated by other kernel space driver and mmaped into user
+ * space, function Ignore the VM_PFNMAP and VM_IO flag in VMA structure
+ *
+ * Get physical pages from user space virtual address and update into page list
+ */
+static int __get_pfnmap_pages(struct task_struct *tsk, struct mm_struct *mm,
+                             unsigned long start, int nr_pages,
+                             unsigned int gup_flags, struct page **pages,
+                             struct vm_area_struct **vmas)
+{
+       int i, ret;
+       unsigned long vm_flags;
+
+       if (nr_pages <= 0)
+               return 0;
+
+       VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
+
+       /*
+        * Require read or write permissions.
+        * If FOLL_FORCE is set, we only require the "MAY" flags.
+        */
+       vm_flags  = (gup_flags & FOLL_WRITE) ?
+                       (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+       vm_flags &= (gup_flags & FOLL_FORCE) ?
+                       (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+       i = 0;
+
+       do {
+               struct vm_area_struct *vma;
+
+               vma = find_vma(mm, start);
+               if (!vma) {
+                       v4l2_err(&atomisp_dev, "find_vma failed\n");
+                       return i ? : -EFAULT;
+               }
+
+               if (is_vm_hugetlb_page(vma)) {
+                       /*
+                       i = follow_hugetlb_page(mm, vma, pages, vmas,
+                                       &start, &nr_pages, i, gup_flags);
+                       */
+                       continue;
+               }
+
+               do {
+                       struct page *page;
+                       unsigned long pfn;
+
+                       /*
+                        * If we have a pending SIGKILL, don't keep faulting
+                        * pages and potentially allocating memory.
+                        */
+                       if (unlikely(fatal_signal_pending(current))) {
+                               v4l2_err(&atomisp_dev,
+                                       "fatal_signal_pending in %s\n",
+                                       __func__);
+                               return i ? i : -ERESTARTSYS;
+                       }
+
+                       ret = follow_pfn(vma, start, &pfn);
+                       if (ret) {
+                               v4l2_err(&atomisp_dev,
+                                       "follow_pfn() failed\n");
+                               return i ? : -EFAULT;
+                       }
+
+                       page = pfn_to_page(pfn);
+                       if (IS_ERR(page))
+                               return i ? i : PTR_ERR(page);
+                       if (pages) {
+                               pages[i] = page;
+
+                               flush_anon_page(vma, page, start);
+                               flush_dcache_page(page);
+                       }
+                       if (vmas)
+                               vmas[i] = vma;
+                       i++;
+                       start += PAGE_SIZE;
+                       nr_pages--;
+               } while (nr_pages && start < vma->vm_end);
+       } while (nr_pages);
+       return i;
+}
+
+static int get_pfnmap_pages(struct task_struct *tsk, struct mm_struct *mm,
+                    unsigned long start, int nr_pages, int write, int force,
+                    struct page **pages, struct vm_area_struct **vmas)
+{
+       int flags = FOLL_TOUCH;
+
+       if (pages)
+               flags |= FOLL_GET;
+       if (write)
+               flags |= FOLL_WRITE;
+       if (force)
+               flags |= FOLL_FORCE;
+
+       return __get_pfnmap_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
+}
+
+/*
+ * Convert user space virtual address into pages list
+ */
+static int alloc_user_pages(struct hmm_buffer_object *bo,
+                             unsigned int userptr, bool cached)
+{
+       unsigned int page_nr;
+       unsigned int i;
+       struct page_block *pgblk;
+       struct vm_area_struct *vma;
+       int ret;
+
+       bo->pages = kzalloc(sizeof(struct page *) * bo->pgnr, GFP_KERNEL);
+       if (unlikely(!bo->pages)) {
+               v4l2_err(&atomisp_dev, "out of memory for bo->pages...\n");
+               return -ENOMEM;
+       }
+
+       mutex_unlock(&bo->mutex);
+       down_read(&current->mm->mmap_sem);
+       vma = find_vma(current->mm, userptr);
+       up_read(&current->mm->mmap_sem);
+       if (vma == NULL) {
+               v4l2_err(&atomisp_dev, "find_vma failed\n");
+               return -EFAULT;
+       }
+       mutex_lock(&bo->mutex);
+       /*
+        * Handle frame buffer allocated in other kerenl space driver
+        * and map to user space
+        */
+       if (vma->vm_flags & (VM_IO | VM_PFNMAP)) {
+               page_nr = get_pfnmap_pages(current, current->mm,
+                                          (unsigned long)userptr,
+                                          (int)(bo->pgnr), 1, 0,
+                                          bo->pages, NULL);
+               bo->mem_type = HMM_BO_MEM_TYPE_PFN;
+       } else {
+               /*Handle frame buffer allocated in user space*/
+               mutex_unlock(&bo->mutex);
+               down_read(&current->mm->mmap_sem);
+               page_nr = get_user_pages(current, current->mm,
+                                        (unsigned long)userptr,
+                                        (int)(bo->pgnr), 1, 0, bo->pages,
+                                        NULL);
+               up_read(&current->mm->mmap_sem);
+               mutex_lock(&bo->mutex);
+               bo->mem_type = HMM_BO_MEM_TYPE_USER;
+       }
+
+       /* can be written by caller, not forced */
+       if (page_nr != bo->pgnr) {
+               v4l2_err(&atomisp_dev,
+                               "get_user_pages err: bo->pgnr = %d, "
+                               "pgnr actually pinned = %d.\n",
+                               bo->pgnr, page_nr);
+               return -ENOMEM;
+       }
+
+       pgblk = kzalloc(sizeof(*pgblk) * bo->pgnr, GFP_KERNEL);
+       if (unlikely(!pgblk)) {
+               v4l2_err(&atomisp_dev, "out of memory for pgblk\n");
+               goto out_of_mem;
+       }
+
+       for (i = 0; i < bo->pgnr; i++) {
+               INIT_LIST_HEAD(&pgblk->list);
+               pgblk->pages = bo->pages[i];
+               pgblk->order = 0;
+
+               list_add_tail(&pgblk->list, &bo->pgblocks);
+               pgblk++;
+       }
+       return 0;
+
+out_of_mem:
+       ret = -ENOMEM;
+       while (!list_empty(&bo->pgblocks)) {
+               pgblk = list_first_entry(&bo->pgblocks,
+                                        struct page_block, list);
+
+               list_del(&pgblk->list);
+
+               kfree(pgblk);
+       }
+
+       return ret;
+}
+
+static void free_user_pages(struct hmm_buffer_object *bo)
+{
+       struct page_block *pgblk, *head;
+       head = list_first_entry(&bo->pgblocks,
+                               struct page_block, list);
+
+       while (!list_empty(&bo->pgblocks)) {
+               pgblk = list_first_entry(&bo->pgblocks,
+                                        struct page_block, list);
+               if (bo->mem_type == HMM_BO_MEM_TYPE_USER)
+                       put_page(pgblk->pages);
+
+               list_del(&pgblk->list);
+       }
+
+       kfree(head);
+       kfree(bo->pages);
+}
+
+/*
+ * allocate/free physical pages for the bo.
+ *
+ * type indicate where are the pages from. currently we have 3 types
+ * of memory: HMM_BO_PRIVATE, HMM_BO_USER, HMM_BO_SHARE.
+ *
+ * from_highmem is only valid when type is HMM_BO_PRIVATE, it will
+ * try to alloc memory from highmem if from_highmem is set.
+ *
+ * userptr is only valid when type is HMM_BO_USER, it indicates
+ * the start address from user space task.
+ *
+ * from_highmem and userptr will both be ignored when type is
+ * HMM_BO_SHARE.
+ */
+int hmm_bo_alloc_pages(struct hmm_buffer_object *bo,
+                      enum hmm_bo_type type, int from_highmem,
+                      unsigned int userptr, bool cached)
+{
+       int ret;
+
+       check_bo_null_return(bo, -EINVAL);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_no_goto(bo, HMM_BO_PAGE_ALLOCED, status_err);
+
+       /*
+        * TO DO:
+        * add HMM_BO_USER type
+        */
+       if (type == HMM_BO_PRIVATE)
+               ret = alloc_private_pages(bo, from_highmem, cached);
+       else if (type == HMM_BO_USER)
+               ret = alloc_user_pages(bo, userptr, cached);
+       else {
+               v4l2_err(&atomisp_dev, "invalid buffer type.\n");
+               ret = -EINVAL;
+       }
+
+       if (ret)
+               goto alloc_err;
+
+       bo->type = type;
+
+       bo->status |= HMM_BO_PAGE_ALLOCED;
+
+       mutex_unlock(&bo->mutex);
+
+       return 0;
+
+alloc_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev, "alloc pages err...\n");
+       return ret;
+status_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                       "buffer object has already page allocated.\n");
+       return -EINVAL;
+}
+
+/*
+ * free physical pages of the bo.
+ */
+void hmm_bo_free_pages(struct hmm_buffer_object *bo)
+{
+       check_bo_null_return(bo, (void)0);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_yes_goto(bo, HMM_BO_PAGE_ALLOCED, status_err2);
+
+       if (bo->type == HMM_BO_PRIVATE)
+               free_private_pages(bo);
+       else if (bo->type == HMM_BO_USER)
+               free_user_pages(bo);
+       else
+               v4l2_err(&atomisp_dev, "invalid buffer type.\n");
+       /* clear the flag anyway. */
+       bo->status &= (~HMM_BO_PAGE_ALLOCED);
+
+       mutex_unlock(&bo->mutex);
+
+       return;
+
+status_err2:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                       "buffer object not page allocated yet.\n");
+
+}
+
+int hmm_bo_page_allocated(struct hmm_buffer_object *bo)
+{
+       int ret;
+
+       check_bo_null_return(bo, 0);
+
+       mutex_lock(&bo->mutex);
+
+       ret = bo->status & HMM_BO_PAGE_ALLOCED;
+
+       mutex_unlock(&bo->mutex);
+
+       return ret;
+}
+
+/*
+ * get physical page info of the bo.
+ */
+int hmm_bo_get_page_info(struct hmm_buffer_object *bo,
+                        struct page ***pages, int *pgnr)
+{
+       check_bo_null_return(bo, -EINVAL);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_yes_goto(bo, HMM_BO_PAGE_ALLOCED, status_err);
+
+       *pages = bo->pages;
+       *pgnr = bo->pgnr;
+
+       mutex_unlock(&bo->mutex);
+
+       return 0;
+
+status_err:
+       v4l2_err(&atomisp_dev,
+                       "buffer object not page allocated yet.\n");
+       mutex_unlock(&bo->mutex);
+       return -EINVAL;
+}
+
+/*
+ * bind the physical pages to a virtual address space.
+ */
+int hmm_bo_bind(struct hmm_buffer_object *bo)
+{
+       int ret;
+       unsigned int virt;
+       struct hmm_bo_device *bdev;
+       unsigned int i;
+
+       check_bo_null_return(bo, -EINVAL);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_yes_goto(bo,
+                                  HMM_BO_PAGE_ALLOCED | HMM_BO_VM_ALLOCED,
+                                  status_err1);
+
+       check_bo_status_no_goto(bo, HMM_BO_BINDED, status_err2);
+
+       bdev = bo->bdev;
+
+       virt = bo->vm_node->start;
+
+       for (i = 0; i < bo->pgnr; i++) {
+               ret =
+                   isp_mmu_map(&bdev->mmu, virt, page_to_phys(bo->pages[i]),
+                               1);
+               if (ret)
+                       goto map_err;
+               virt += (1 << PAGE_SHIFT);
+       }
+
+       /*
+        * flush TBL here.
+        *
+        * theoretically, we donot need to flush TLB as we didnot change
+        * any existed address mappings, but for Silicon Hive's MMU, its
+        * really a bug here. I guess when fetching PTEs (page table entity)
+        * to TLB, its MMU will fetch additional INVALID PTEs automatically
+        * for performance issue. EX, we only set up 1 page address mapping,
+        * meaning updating 1 PTE, but the MMU fetches 4 PTE at one time,
+        * so the additional 3 PTEs are invalid.
+        */
+       isp_mmu_flush_tlb_range(&bdev->mmu, bo->vm_node->start,
+                               (bo->pgnr << PAGE_SHIFT));
+
+       bo->status |= HMM_BO_BINDED;
+
+       mutex_unlock(&bo->mutex);
+
+       return 0;
+
+map_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                       "setup MMU address mapping failed.\n");
+       return ret;
+
+status_err2:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev, "buffer object already binded.\n");
+       return -EINVAL;
+status_err1:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                    "buffer object vm_node or page not allocated.\n");
+       return -EINVAL;
+}
+
+/*
+ * unbind the physical pages with related virtual address space.
+ */
+void hmm_bo_unbind(struct hmm_buffer_object *bo)
+{
+       unsigned int virt;
+       struct hmm_bo_device *bdev;
+       unsigned int i;
+
+       check_bo_null_return(bo, (void)0);
+
+       mutex_lock(&bo->mutex);
+
+       check_bo_status_yes_goto(bo,
+                                  HMM_BO_PAGE_ALLOCED |
+                                  HMM_BO_VM_ALLOCED |
+                                  HMM_BO_BINDED, status_err);
+
+       bdev = bo->bdev;
+
+       virt = bo->vm_node->start;
+
+       for (i = 0; i < bo->pgnr; i++) {
+               isp_mmu_unmap(&bdev->mmu, virt, 1);
+               virt += pgnr_to_size(1);
+       }
+
+       /*
+        * flush TLB as the address mapping has been removed and
+        * related TLBs should be invalidated.
+        */
+       isp_mmu_flush_tlb_range(&bdev->mmu, bo->vm_node->start,
+                               (bo->pgnr << PAGE_SHIFT));
+
+       bo->status &= (~HMM_BO_BINDED);
+
+       mutex_unlock(&bo->mutex);
+
+       return;
+
+status_err:
+       mutex_unlock(&bo->mutex);
+       v4l2_err(&atomisp_dev,
+                    "buffer vm or page not allocated or not binded yet.\n");
+}
+
+int hmm_bo_binded(struct hmm_buffer_object *bo)
+{
+       int ret;
+
+       check_bo_null_return(bo, 0);
+
+       mutex_lock(&bo->mutex);
+
+       ret = bo->status & HMM_BO_BINDED;
+
+       mutex_unlock(&bo->mutex);
+
+       return ret;
+}
+
+void *hmm_bo_vmap(struct hmm_buffer_object *bo)
+{
+       check_bo_null_return(bo, NULL);
+
+       return vmap(bo->pages, bo->pgnr, VM_MAP, PAGE_KERNEL_NOCACHE);
+}
+
+void hmm_bo_ref(struct hmm_buffer_object *bo)
+{
+       check_bo_null_return(bo, (void)0);
+
+       kref_get(&bo->kref);
+}
+
+static void kref_hmm_bo_release(struct kref *kref)
+{
+       if (!kref)
+               return;
+
+       hmm_bo_release(kref_to_hmm_bo(kref));
+}
+
+void hmm_bo_unref(struct hmm_buffer_object *bo)
+{
+       check_bo_null_return(bo, (void)0);
+
+       kref_put(&bo->kref, kref_hmm_bo_release);
+}
+
+static void hmm_bo_vm_open(struct vm_area_struct *vma)
+{
+       struct hmm_buffer_object *bo =
+           (struct hmm_buffer_object *)vma->vm_private_data;
+
+       check_bo_null_return(bo, (void)0);
+
+       hmm_bo_ref(bo);
+
+       mutex_lock(&bo->mutex);
+
+       bo->status |= HMM_BO_MMAPED;
+
+       bo->mmap_count++;
+
+       mutex_unlock(&bo->mutex);
+}
+
+static void hmm_bo_vm_close(struct vm_area_struct *vma)
+{
+       struct hmm_buffer_object *bo =
+           (struct hmm_buffer_object *)vma->vm_private_data;
+
+       check_bo_null_return(bo, (void)0);
+
+       hmm_bo_unref(bo);
+
+       mutex_lock(&bo->mutex);
+
+       bo->mmap_count--;
+
+       if (!bo->mmap_count) {
+               bo->status &= (~HMM_BO_MMAPED);
+               vma->vm_private_data = NULL;
+       }
+
+       mutex_unlock(&bo->mutex);
+}
+
+static const struct vm_operations_struct hmm_bo_vm_ops = {
+       .open = hmm_bo_vm_open,
+       .close = hmm_bo_vm_close,
+};
+
+/*
+ * mmap the bo to user space.
+ */
+int hmm_bo_mmap(struct vm_area_struct *vma, struct hmm_buffer_object *bo)
+{
+       unsigned int start, end;
+       unsigned int virt;
+       unsigned int pgnr, i;
+       unsigned int pfn;
+
+       check_bo_null_return(bo, -EINVAL);
+
+       check_bo_status_yes_goto(bo, HMM_BO_PAGE_ALLOCED, status_err);
+
+       pgnr = bo->pgnr;
+       start = vma->vm_start;
+       end = vma->vm_end;
+
+       /*
+        * check vma's virtual address space size and buffer object's size.
+        * must be the same.
+        */
+       if ((start + pgnr_to_size(pgnr)) != end) {
+               v4l2_warn(&atomisp_dev,
+                            "vma's address space size not equal"
+                            " to buffer object's size");
+               return -EINVAL;
+       }
+
+       virt = vma->vm_start;
+       for (i = 0; i < pgnr; i++) {
+               pfn = page_to_pfn(bo->pages[i]);
+               if (remap_pfn_range(vma, virt, pfn, PAGE_SIZE, PAGE_SHARED)) {
+                       v4l2_warn(&atomisp_dev,
+                                       "remap_pfn_range failed:"
+                                       " virt = 0x%x, pfn = 0x%x,"
+                                       " mapped_pgnr = %d\n", virt, pfn, 1);
+                       return -EINVAL;
+               }
+               virt += PAGE_SIZE;
+       }
+
+       vma->vm_private_data = bo;
+
+       vma->vm_ops = &hmm_bo_vm_ops;
+       vma->vm_flags |= (VM_RESERVED | VM_IO);
+
+       /*
+        * call hmm_bo_vm_open explictly.
+        */
+       hmm_bo_vm_open(vma);
+
+       return 0;
+
+status_err:
+       v4l2_err(&atomisp_dev,
+                       "buffer page not allocated yet.\n");
+       return -EINVAL;
+}
diff --git a/drivers/media/video/atomisp/hmm/hmm_bo_dev.c b/drivers/media/video/atomisp/hmm/hmm_bo_dev.c
new file mode 100644 (file)
index 0000000..d3e5ddf
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>          /* for GFP_ATOMIC */
+#include <linux/slab.h>                /* for kmalloc */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+
+#include "hmm/hmm_common.h"
+#include "hmm/hmm_bo_dev.h"
+#include "hmm/hmm_bo.h"
+#include "atomisp_internal.h"
+
+/*
+ * hmm_bo_device functions.
+ */
+int hmm_bo_device_init(struct hmm_bo_device *bdev,
+                      struct isp_mmu_driver *mmu_driver,
+                      unsigned int vaddr_start, unsigned int size)
+{
+       int ret;
+
+       check_bodev_null_return(bdev, -EINVAL);
+
+       ret = isp_mmu_init(&bdev->mmu, mmu_driver);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "isp_mmu_init failed.\n");
+               goto isp_mmu_init_err;
+       }
+
+       ret = hmm_vm_init(&bdev->vaddr_space, vaddr_start, size);
+       if (ret) {
+               v4l2_err(&atomisp_dev, "hmm_vm_init falied. "
+                            "vaddr_start = 0x%x, size = %d\n", vaddr_start,
+                            size);
+               goto vm_init_err;
+       }
+
+       INIT_LIST_HEAD(&bdev->free_bo_list);
+       INIT_LIST_HEAD(&bdev->active_bo_list);
+
+       mutex_init(&bdev->fblist_mutex);
+       mutex_init(&bdev->ablist_mutex);
+
+       bdev->flag = HMM_BO_DEVICE_INITED;
+
+       return 0;
+
+vm_init_err:
+       isp_mmu_exit(&bdev->mmu);
+isp_mmu_init_err:
+       return ret;
+}
+
+void hmm_bo_device_exit(struct hmm_bo_device *bdev)
+{
+       check_bodev_null_return(bdev, (void)0);
+
+       /*
+        * destroy all bos in the bo list, even they are in use.
+        */
+       if (!list_empty(&bdev->active_bo_list))
+               v4l2_warn(&atomisp_dev,
+                            "there're still activated bo in use. "
+                            "force to free them.\n");
+
+       while (!list_empty(&bdev->active_bo_list))
+               hmm_bo_unref(list_to_hmm_bo(bdev->active_bo_list.next));
+
+       if (!list_empty(&bdev->free_bo_list))
+               v4l2_warn(&atomisp_dev,
+                               "there're still bo in free_bo_list. "
+                               "force to free them.\n");
+
+       while (!list_empty(&bdev->free_bo_list))
+               hmm_bo_unref(list_to_hmm_bo(bdev->free_bo_list.next));
+
+       isp_mmu_exit(&bdev->mmu);
+       hmm_vm_clean(&bdev->vaddr_space);
+}
+
+int hmm_bo_device_inited(struct hmm_bo_device *bdev)
+{
+       check_bodev_null_return(bdev, -EINVAL);
+
+       return bdev->flag == HMM_BO_DEVICE_INITED;
+}
+
+/*
+ * find the buffer object with virtual address vaddr.
+ * return NULL if no such buffer object found.
+ */
+struct hmm_buffer_object *hmm_bo_device_search_start(struct hmm_bo_device *bdev,
+                                                    unsigned int vaddr)
+{
+       struct list_head *pos;
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, NULL);
+
+       mutex_lock(&bdev->ablist_mutex);
+       list_for_each(pos, &bdev->active_bo_list) {
+               bo = list_to_hmm_bo(pos);
+               /* pass bo which has no vm_node allocated */
+               if (!hmm_bo_vm_allocated(bo))
+                       continue;
+               if (bo->vm_node->start == vaddr)
+                       goto found;
+       }
+       mutex_unlock(&bdev->ablist_mutex);
+       return NULL;
+found:
+       mutex_unlock(&bdev->ablist_mutex);
+       return bo;
+}
+
+static int in_range(unsigned int start, unsigned int size, unsigned int addr)
+{
+       return (start <= addr) && (start + size > addr);
+}
+
+struct hmm_buffer_object *hmm_bo_device_search_in_range(struct hmm_bo_device
+                                                       *bdev,
+                                                       unsigned int vaddr)
+{
+       struct list_head *pos;
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, NULL);
+
+       mutex_lock(&bdev->fblist_mutex);
+       list_for_each(pos, &bdev->active_bo_list) {
+               bo = list_to_hmm_bo(pos);
+               /* pass bo which has no vm_node allocated */
+               if (!hmm_bo_vm_allocated(bo))
+                       continue;
+               if (in_range(bo->vm_node->start, bo->vm_node->size, vaddr))
+                       goto found;
+       }
+       mutex_unlock(&bdev->fblist_mutex);
+       return NULL;
+found:
+       mutex_unlock(&bdev->fblist_mutex);
+       return bo;
+}
+
+/*
+ * find a buffer object with pgnr pages from free_bo_list and
+ * activate it (remove from free_bo_list and add to
+ * active_bo_list)
+ *
+ * return NULL if no such buffer object found.
+ */
+struct hmm_buffer_object *hmm_bo_device_get_bo(struct hmm_bo_device *bdev,
+                                              unsigned int pgnr)
+{
+       struct list_head *pos;
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, NULL);
+
+       mutex_lock(&bdev->fblist_mutex);
+       list_for_each(pos, &bdev->free_bo_list) {
+               bo = list_to_hmm_bo(pos);
+               if (bo->pgnr == pgnr)
+                       goto found;
+       }
+       mutex_unlock(&bdev->fblist_mutex);
+       return NULL;
+found:
+       list_del(&bo->list);
+       mutex_unlock(&bdev->fblist_mutex);
+
+       mutex_lock(&bdev->ablist_mutex);
+       list_add(&bo->list, &bdev->active_bo_list);
+       mutex_unlock(&bdev->ablist_mutex);
+
+       return bo;
+}
+
+/*
+ * destroy all buffer objects in the free_bo_list.
+ */
+void hmm_bo_device_destroy_free_bo_list(struct hmm_bo_device *bdev)
+{
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, (void)0);
+
+       mutex_lock(&bdev->fblist_mutex);
+       while (!list_empty(&bdev->free_bo_list)) {
+               bo = list_first_entry(&bdev->free_bo_list,
+                                     struct hmm_buffer_object, list);
+
+               list_del(&bo->list);
+               hmm_bo_unref(bo);
+       }
+       mutex_unlock(&bdev->fblist_mutex);
+}
+
+/*
+ * destroy buffer object with start virtual address vaddr.
+ */
+void hmm_bo_device_destroy_free_bo_addr(struct hmm_bo_device *bdev,
+                                       unsigned int vaddr)
+{
+       struct list_head *pos;
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, (void)0);
+
+       mutex_lock(&bdev->fblist_mutex);
+       list_for_each(pos, &bdev->free_bo_list) {
+               bo = list_to_hmm_bo(pos);
+               /* pass bo which has no vm_node allocated */
+               if (!hmm_bo_vm_allocated(bo))
+                       continue;
+               if (bo->vm_node->start == vaddr)
+                       goto found;
+       }
+       mutex_unlock(&bdev->fblist_mutex);
+       return;
+found:
+       list_del(&bo->list);
+       mutex_unlock(&bdev->fblist_mutex);
+       hmm_bo_unref(bo);
+}
+
+/*
+ * destroy all buffer objects with pgnr pages.
+ */
+void hmm_bo_device_destroy_free_bo_size(struct hmm_bo_device *bdev,
+                                       unsigned int pgnr)
+{
+       struct list_head *pos;
+       struct hmm_buffer_object *bo;
+
+       check_bodev_null_return(bdev, (void)0);
+
+retry:
+       mutex_lock(&bdev->fblist_mutex);
+       list_for_each(pos, &bdev->free_bo_list) {
+               bo = list_to_hmm_bo(pos);
+               if (bo->pgnr == pgnr)
+                       goto found;
+       }
+       mutex_unlock(&bdev->fblist_mutex);
+       return;
+found:
+       list_del(&bo->list);
+       mutex_unlock(&bdev->fblist_mutex);
+       hmm_bo_unref(bo);
+       goto retry;
+}
diff --git a/drivers/media/video/atomisp/hmm/hmm_vm.c b/drivers/media/video/atomisp/hmm/hmm_vm.c
new file mode 100644 (file)
index 0000000..5bac810
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+/*
+ * This file contains function for ISP virtual address management in ISP driver
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/page.h>
+
+#include "mmu/isp_mmu.h"
+#include "hmm/hmm_vm.h"
+#include "hmm/hmm_common.h"
+#include "atomisp_internal.h"
+
+static unsigned int vm_node_end(unsigned int start, unsigned int pgnr)
+{
+       return start + pgnr_to_size(pgnr);
+}
+
+static int addr_in_vm_node(unsigned int addr,
+               struct hmm_vm_node *node)
+{
+       return (addr >= node->start) && (addr < (node->start + node->size));
+}
+
+int hmm_vm_init(struct hmm_vm *vm, unsigned int start,
+               unsigned int size)
+{
+       if (!vm)
+               return -1;
+
+       vm->start = start;
+       vm->pgnr = size_to_pgnr_ceil(size);
+       vm->size = pgnr_to_size(vm->pgnr);
+
+       INIT_LIST_HEAD(&vm->vm_node_list);
+       spin_lock_init(&vm->lock);
+
+       return 0;
+}
+
+void hmm_vm_clean(struct hmm_vm *vm)
+{
+       if (!vm)
+               return;
+
+       while (!list_empty(&vm->vm_node_list))
+               hmm_vm_free_node(hmm_vm_node(vm->vm_node_list.next));
+}
+
+static struct hmm_vm_node *alloc_hmm_vm_node(unsigned int start,
+                                              unsigned int pgnr,
+                                              struct hmm_vm *vm)
+{
+       struct hmm_vm_node *node;
+
+       node = kzalloc(sizeof(struct hmm_vm_node), GFP_KERNEL);
+       if (!node) {
+               v4l2_err(&atomisp_dev, "out of memory.\n");
+               return NULL;
+       }
+
+       INIT_LIST_HEAD(&node->list);
+       node->start = start;
+       node->pgnr = pgnr;
+       node->size = pgnr_to_size(pgnr);
+       node->vm = vm;
+
+       return node;
+}
+
+struct hmm_vm_node *hmm_vm_alloc_node(struct hmm_vm *vm, unsigned int pgnr)
+{
+       struct list_head *head, *p, *pos;
+       struct hmm_vm_node *node, *cur, *next;
+       unsigned int vm_start, vm_end;
+       unsigned int addr;
+       unsigned int size;
+
+       if (!vm)
+               return NULL;
+
+       vm_start = vm->start;
+       vm_end = vm_node_end(vm->start, vm->pgnr);
+       size = pgnr_to_size(pgnr);
+
+       addr = vm_start;
+       pos = head = &vm->vm_node_list;
+
+       spin_lock(&vm->lock);
+
+       /*
+        * if list is empty, the loop code will not be executed.
+        */
+       list_for_each(p, head) {
+               pos = p;
+               cur = hmm_vm_node(pos);
+               addr = vm_node_end(cur->start, cur->pgnr);
+               if (pos->next != head) {
+                       next = hmm_vm_node(pos->next);
+                       if ((next->start - addr) >= size)
+                               goto found;
+               }
+       }
+
+       if (addr + size > vm_end) {
+               v4l2_info(&atomisp_dev,
+                           "no enough virtual address space.\n");
+               goto failed;
+       }
+
+found:
+
+       spin_unlock(&vm->lock);
+       node = alloc_hmm_vm_node(addr, pgnr, vm);
+       if (!node)
+               goto failed;
+
+       spin_lock(&vm->lock);
+       list_add(&node->list, pos);
+
+       spin_unlock(&vm->lock);
+
+       return node;
+failed:
+       v4l2_err(&atomisp_dev, "failed...\n");
+       spin_unlock(&vm->lock);
+
+       return NULL;
+}
+
+void hmm_vm_free_node(struct hmm_vm_node *node)
+{
+       if (node) {
+               struct hmm_vm *vm = node->vm;
+               spin_lock(&vm->lock);
+               list_del(&node->list);
+               spin_unlock(&vm->lock);
+               kfree(node);
+       }
+}
+
+struct hmm_vm_node *hmm_vm_find_node_start(struct hmm_vm *vm, unsigned int addr)
+{
+       struct list_head *pos;
+       struct hmm_vm_node *node;
+
+       if (!vm)
+               return NULL;
+
+       spin_lock(&vm->lock);
+
+       list_for_each(pos, &vm->vm_node_list) {
+               node = hmm_vm_node(pos);
+               if (node->start == addr)
+                       goto found;
+       }
+
+       spin_unlock(&vm->lock);
+       return NULL;
+found:
+       spin_unlock(&vm->lock);
+       return node;
+}
+
+struct hmm_vm_node *hmm_vm_find_node_in_range(struct hmm_vm *vm,
+                                             unsigned int addr)
+{
+       struct list_head *pos;
+       struct hmm_vm_node *node;
+
+       if (!vm)
+               return NULL;
+
+       spin_lock(&vm->lock);
+
+       list_for_each(pos, &vm->vm_node_list) {
+               node = hmm_vm_node(pos);
+               if (addr_in_vm_node(addr, node))
+                       goto found;
+       }
+
+       spin_unlock(&vm->lock);
+       return NULL;
+found:
+       spin_unlock(&vm->lock);
+       return node;
+}
diff --git a/drivers/media/video/atomisp/hrt/hive_isp_css_custom_host_hrt.h b/drivers/media/video/atomisp/hrt/hive_isp_css_custom_host_hrt.h
new file mode 100644 (file)
index 0000000..c47ff26
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef _hive_isp_css_custom_host_hrt_h_
+#define _hive_isp_css_custom_host_hrt_h_
+
+#include "atomisp_cmd.h"
+
+
+#define _hrt_master_port_store_8(a, d) \
+       (*((__iomem s8 *)atomisp_get_io_virt_addr((unsigned int)(a))) = (d))
+
+#define _hrt_master_port_store_16(a, d) \
+       (*((__iomem s16 *)atomisp_get_io_virt_addr((unsigned int)(a))) = (d))
+
+#define _hrt_master_port_store_32(a, d) \
+       (*((__iomem s32 *)atomisp_get_io_virt_addr((unsigned int)(a))) = (d))
+
+#define _hrt_master_port_load_8(a) \
+       (*(__iomem s8  *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_load_16(a) \
+       (*(__iomem s16 *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_load_32(a) \
+       (*(__iomem s32 *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_uload_8(a) \
+       (*(__iomem u8  *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_uload_16(a) \
+       (*(__iomem u16 *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_uload_32(a) \
+       (*(__iomem u32 *)atomisp_get_io_virt_addr((unsigned int)(a)))
+
+#define _hrt_master_port_store_8_volatile(a, d)  _hrt_master_port_store_8(a, d)
+#define _hrt_master_port_store_16_volatile(a, d) _hrt_master_port_store_16(a, d)
+#define _hrt_master_port_store_32_volatile(a, d) _hrt_master_port_store_32(a, d)
+
+#define _hrt_master_port_load_8_volatile(a)      _hrt_master_port_load_8(a)
+#define _hrt_master_port_load_16_volatile(a)     _hrt_master_port_load_16(a)
+#define _hrt_master_port_load_32_volatile(a)     _hrt_master_port_load_32(a)
+
+#define _hrt_master_port_uload_8_volatile(a)     _hrt_master_port_uload_8(a)
+#define _hrt_master_port_uload_16_volatile(a)    _hrt_master_port_uload_16(a)
+#define _hrt_master_port_uload_32_volatile(a)    _hrt_master_port_uload_32(a)
+
+static inline void hrt_sleep(void)
+{
+       udelay(1);
+}
+
+static inline void *_hrt_mem_store(void *to, const void *from, size_t n)
+{
+       unsigned i;
+       unsigned int _to = (unsigned int)to;
+       const char *_from = (const char *)from;
+       for (i = 0; i < n; i++, _to++, _from++)
+               _hrt_master_port_store_8(_to, *_from);
+       return (void *)_to;
+}
+
+static inline void *_hrt_mem_load(const void *from, void *to, size_t n)
+{
+       unsigned i;
+       char *_to = (char *)to;
+       unsigned int _from = (unsigned int)from;
+       for (i = 0; i < n; i++, _to++, _from++)
+               *_to = _hrt_master_port_load_8(_from);
+       return _to;
+}
+
+static inline void *_hrt_mem_set(void *to, int c, size_t n)
+{
+       unsigned i;
+       unsigned int _to = (unsigned int)to;
+       for (i = 0; i < n; i++, _to++)
+               _hrt_master_port_store_8(_to, c);
+       return (void *)_to;
+}
+
+#endif /* _hive_isp_css_custom_host_hrt_h_ */
diff --git a/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c b/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c
new file mode 100644 (file)
index 0000000..daa076d
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <hmm/hmm.h>
+
+/* not sure if we need these two for page related macros,
+ * need to double check */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "atomisp_internal.h"
+
+#define __page_align(size)     (((size) + (PAGE_SIZE-1)) & (~(PAGE_SIZE-1)))
+
+static unsigned init_done;
+void hrt_isp_css_mm_init(void)
+{
+       hmm_init();
+       init_done = 1;
+}
+
+int hrt_isp_css_mm_set(void *virt_addr, int c, size_t bytes)
+{
+       if (virt_addr)
+               return hmm_set(virt_addr, c, bytes);
+
+       return -EINVAL;
+}
+
+int hrt_isp_css_mm_load(void *virt_addr, void *data, size_t bytes)
+{
+       if (virt_addr)
+               return hmm_load(virt_addr, data, bytes);
+       return -EINVAL;
+}
+
+int hrt_isp_css_mm_store(void *virt_addr, const void *data, size_t bytes)
+{
+       if (virt_addr)
+               return hmm_store(virt_addr, data, bytes);
+       return -EINVAL;
+}
+
+void hrt_isp_css_mm_free(void *virt_addr)
+{
+       if (virt_addr)
+               hmm_free(virt_addr);
+}
+
+void hrt_isp_css_mm_clear(void)
+{
+       if (init_done) {
+               hmm_cleanup();
+               init_done = 0;
+       }
+}
+
+static unsigned int my_userptr, my_num_pages;
+void hrt_isp_css_mm_set_user_ptr(unsigned int userptr, unsigned int num_pages)
+{
+       my_userptr = userptr;
+       my_num_pages = num_pages;
+}
+
+void *hrt_isp_css_mm_alloc(size_t bytes)
+{
+       if (!init_done)
+               hrt_isp_css_mm_init();
+
+       if (my_userptr == 0)
+               return (void *)hmm_alloc(bytes, HMM_BO_PRIVATE, 0, 0,
+                                               HMM_UNCACHED);
+       else {
+               if (my_num_pages < ((__page_align(bytes)) >> PAGE_SHIFT))
+                       v4l2_err(&atomisp_dev,
+                                       "user space memory size is less"
+                                       " than the expected size..\n");
+               else if (my_num_pages > ((__page_align(bytes)) >> PAGE_SHIFT))
+                       v4l2_err(&atomisp_dev,
+                                       "user space memory size is"
+                                       " large than the expected size..\n");
+
+               return (void *)hmm_alloc(bytes, HMM_BO_USER, 0,
+                                               my_userptr, HMM_UNCACHED);
+       }
+}
+
+void *hrt_isp_css_mm_alloc_cached(size_t bytes)
+{
+       if (!init_done)
+               hrt_isp_css_mm_init();
+
+       if (my_userptr == 0)
+               return (void *)hmm_alloc(bytes, HMM_BO_PRIVATE, 0, 0,
+                                               HMM_CACHED);
+       else {
+               if (my_num_pages < ((__page_align(bytes)) >> PAGE_SHIFT))
+                       v4l2_err(&atomisp_dev,
+                                       "user space memory size is less"
+                                       " than the expected size..\n");
+               else if (my_num_pages > ((__page_align(bytes)) >> PAGE_SHIFT))
+                       v4l2_err(&atomisp_dev,
+                                       "user space memory size is"
+                                       " large than the expected size..\n");
+
+               return (void *)hmm_alloc(bytes, HMM_BO_USER, 0,
+                                               my_userptr, HMM_CACHED);
+       }
+}
+
+void *hrt_isp_css_mm_calloc(size_t bytes)
+{
+       void *ptr = hrt_isp_css_mm_alloc(bytes);
+       if (!ptr)
+               hmm_set(ptr, 0, bytes);
+       return ptr;
+}
+
+void *hrt_isp_css_mm_calloc_cached(size_t bytes)
+{
+       void *ptr = hrt_isp_css_mm_alloc_cached(bytes);
+       if (!ptr)
+               hmm_set(ptr, 0, bytes);
+       return ptr;
+}
+
+int hrt_isp_css_mm_load_int(void *virt_addr, int *data)
+{
+       return hrt_isp_css_mm_load(virt_addr, data, sizeof(*data));
+}
+
+int hrt_isp_css_mm_load_short(void *virt_addr, short *data)
+{
+       return hrt_isp_css_mm_load(virt_addr, data, sizeof(*data));
+}
+
+int hrt_isp_css_mm_load_char(void *virt_addr, char *data)
+{
+       return hrt_isp_css_mm_load(virt_addr, data, sizeof(*data));
+}
+
+int hrt_isp_css_mm_store_char(void *virt_addr, char data)
+{
+       return hrt_isp_css_mm_store(virt_addr, &data, sizeof(data));
+}
+
+int hrt_isp_css_mm_store_short(void *virt_addr, short data)
+{
+       return hrt_isp_css_mm_store(virt_addr, &data, sizeof(data));
+}
+
+int hrt_isp_css_mm_store_int(void *virt_addr, int data)
+{
+       return hrt_isp_css_mm_store(virt_addr, &data, sizeof(data));
+}
+
+void *hrt_isp_css_virt_to_phys(void *virt_addr)
+{
+       return (void *)hmm_virt_to_phys(virt_addr);
+}
diff --git a/drivers/media/video/atomisp/include/atomisp/atomisp_internal.h b/drivers/media/video/atomisp/include/atomisp/atomisp_internal.h
new file mode 100644 (file)
index 0000000..e0b5286
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef ATOMISP_INTERNAL_H_
+#define ATOMISP_INTERNAL_H_
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h>
+#include <linux/firmware.h>
+#include <media/media-device.h>
+#include <linux/kernel.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+
+#include <linux/atomisp.h>
+#include <linux/atomisp_platform.h>
+#include <css/sh_css_types.h>
+#include "atomisp_subdev.h"
+#include "atomisp_csi2.h"
+#include "atomisp_tpg.h"
+#include "atomisp_file.h"
+
+#define MAGIC_NUMBER 0x73c5cc4
+
+#define ATOMISP_MAJOR          0
+#define ATOMISP_MINOR          5
+#define ATOMISP_PATCHLEVEL     1
+
+#define DRIVER_VERSION_STR     __stringify(ATOMISP_MAJOR) \
+       "." __stringify(ATOMISP_MINOR) "." __stringify(ATOMISP_PATCHLEVEL)
+#define DRIVER_VERSION         KERNEL_VERSION(ATOMISP_MAJOR, \
+       ATOMISP_MINOR, ATOMISP_PATCHLEVEL)
+
+#define ATOM_ISP_STEP_WIDTH    4
+#define ATOM_ISP_STEP_HEIGHT   4
+
+#define ATOM_ISP_MIN_WIDTH     4
+#define ATOM_ISP_MIN_HEIGHT    4
+#define ATOM_ISP_MAX_WIDTH     4352
+#define ATOM_ISP_MAX_HEIGHT    3264
+
+#define ATOM_ISP_MAX_WIDTH_TMP 1280
+#define ATOM_ISP_MAX_HEIGHT_TMP        720
+
+#define ATOM_ISP_I2C_BUS_1     4
+#define ATOM_ISP_I2C_BUS_2     5
+
+#define ATOM_ISP_POWER_DOWN    0
+#define ATOM_ISP_POWER_UP      1
+
+#define ATOM_ISP_MAX_INPUTS    4
+#define ATOMISP_ACC_FW_MAX     8
+
+int atomisp_video_init(struct atomisp_video_pipe *video, const char *name);
+void atomisp_video_unregister(struct atomisp_video_pipe *video);
+int atomisp_video_register(struct atomisp_video_pipe *video,
+       struct v4l2_device *vdev);
+
+struct atomisp_input_subdev {
+       unsigned int type;
+       enum atomisp_camera_port port;
+       struct v4l2_subdev *camera;
+       struct v4l2_subdev *motor;
+       struct sh_css_morph_table *morph_table;
+       struct sh_css_shading_table *shading_table;
+};
+
+struct atomisp_hw_contex {
+       /*OSPM related */
+       unsigned int apm_reg;
+       unsigned short apm_base;
+       unsigned int ospm_base;
+
+       unsigned int pcicmdsts;
+       unsigned int ispmmadr;
+       unsigned int msicap;
+       unsigned int msi_addr;
+       unsigned int msi_data;
+       unsigned int intr;
+       unsigned int interrupt_control;
+       unsigned int pmcs;
+       unsigned int cg_dis;
+       unsigned int i_control;
+       unsigned int csi_rcomp_config;
+       unsigned int csi_afe_dly;
+       unsigned int csi_control;
+       u16 pci_cmd;
+       struct pci_dev *pci_dev;
+
+       void *mmu_l1_base;
+};
+
+struct atomisp_sw_contex {
+       bool init;
+       bool probed;
+
+       bool work_queued;
+       bool sensor_streaming;
+       bool isp_streaming;
+
+       bool error;
+       bool bypass;
+       bool updating_uptr;
+       bool file_input;
+       bool grid_info_updated;
+
+       int power_state;
+       int run_mode;
+       int output_mode;
+};
+
+struct atomisp_css_params {
+       int online_process;
+       int yuv_ds_en;
+       unsigned int color_effect;
+       bool gdc_cac_en;
+       bool macc_en;
+       bool bad_pixel_en;
+       bool video_dis_en;
+       bool sc_en;
+       bool fpn_en;
+       bool xnr_en;
+       int false_color;
+       unsigned int histogram_elenum;
+
+       /* default configurations */
+       const struct sh_css_dp_config   *default_dp_config;
+       const struct sh_css_wb_config   *default_wb_config;
+       const struct sh_css_cc_config   *default_cc_config;
+       const struct sh_css_nr_config   *default_nr_config;
+       const struct sh_css_ee_config   *default_ee_config;
+       const struct sh_css_ob_config   *default_ob_config;
+       const struct sh_css_de_config   *default_de_config;
+       const struct sh_css_gc_config   *default_gc_config;
+       const struct sh_css_tnr_config  *default_tnr_config;
+       const struct sh_css_3a_config   *default_3a_config;
+       const struct sh_css_macc_table  *default_macc_table;
+       const struct sh_css_ctc_table   *default_ctc_table;
+       const struct sh_css_gamma_table *default_gamma_table;
+
+       /* current configurations */
+       struct sh_css_dp_config   dp_config;
+       struct sh_css_wb_config   wb_config;
+       struct sh_css_cc_config   cc_config;
+       struct sh_css_nr_config   nr_config;
+       struct sh_css_ee_config   ee_config;
+       struct sh_css_ob_config   ob_config;
+       struct sh_css_de_config   de_config;
+       struct sh_css_gc_config   gc_config;
+       struct sh_css_tnr_config  tnr_config;
+       struct sh_css_3a_config   s3a_config;
+       struct sh_css_gamma_table gamma_table;
+       struct sh_css_ctc_table   ctc_table;
+       struct sh_css_macc_table  macc_table;
+       struct sh_css_overlay   *vf_overlay;
+       /* Current grid info */
+       struct sh_css_grid_info curr_grid_info;
+
+       /* DIS coefficients, must remain alive during execution */
+       int dis_x;
+       int dis_y;
+
+       /* Intermediate buffers used to communicate data between
+          CSS and user space. These are needed to perform the
+          copy_to_user. */
+       struct sh_css_3a_output *s3a_output_buf;
+       int s3a_output_bytes;
+       /* DIS Coefficients */
+       short *dis_hor_coef_buf;
+       int    dis_hor_coef_bytes;
+       short *dis_ver_coef_buf;
+       int    dis_ver_coef_bytes;
+       /* DIS projections */
+       int *dis_ver_proj_buf;
+       int  dis_ver_proj_bytes;
+       int *dis_hor_proj_buf;
+       int  dis_hor_proj_bytes;
+
+       /* Flash */
+       int num_flash_frames;
+};
+
+struct atomisp_video_pipe_format {
+       struct v4l2_pix_format out;
+       struct v4l2_pix_format in;
+       unsigned int out_sh_fmt;
+};
+
+/*
+ * ci device struct
+ */
+struct atomisp_device {
+       struct pci_dev *pdev;
+       struct device *dev;
+       struct v4l2_device v4l2_dev;
+       struct media_device media_dev;
+       struct atomisp_platform_data *pdata;
+       const struct firmware *firmware;
+
+       struct sh_css_acc_fw *acc_fw[ATOMISP_ACC_FW_MAX];
+       unsigned int acc_fw_handle;
+       int acc_fw_count;
+       struct sh_css_acc_fw *marked_fw_for_unload;
+
+       /* ISP modules */
+       struct atomisp_sub_device isp_subdev;
+       struct atomisp_mipi_csi2_device csi2_4p;
+       struct atomisp_mipi_csi2_device csi2_1p;
+       struct atomisp_tpg_device tpg;
+       struct atomisp_file_device file_dev;
+
+       struct workqueue_struct *work_queue;
+       struct work_struct work;
+       struct completion wq_frame_complete;
+       struct completion dis_state_complete;
+       struct completion acc_fw_complete;
+       struct completion acc_unload_fw_complete;
+
+       spinlock_t irq_lock;
+       uint32_t irq_infos;
+       struct mutex input_lock;
+       struct mutex isp_lock;
+       struct mutex isp3a_lock;
+       struct atomisp_tvnorm *tvnorm;
+       bool isp3a_stat_ready;
+
+       struct atomisp_video_pipe_format *main_format;
+       struct atomisp_video_pipe_format *vf_format;
+       struct atomisp_video_pipe_format *input_format;
+       struct sh_css_frame *vf_frame;
+       struct sh_css_frame *regular_output_frame;
+       struct sh_css_frame *raw_output_frame;
+       enum atomisp_frame_status frame_status[VIDEO_MAX_FRAME];
+
+       int input_cnt;
+       int input_curr;
+       struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS];
+       struct v4l2_subdev *flash;
+       struct v4l2_subdev *motor;
+
+       struct atomisp_hw_contex hw_contex;
+       struct atomisp_sw_contex sw_contex;
+       struct atomisp_css_params params;
+
+       __u32 snr_max_width;
+       __u32 snr_max_height;
+       __u32 snr_pixelformat;
+};
+
+#define v4l2_dev_to_atomisp_device(dev) \
+       container_of(dev, struct atomisp_device, v4l2_dev)
+
+extern struct v4l2_device atomisp_dev;
+
+extern void hrt_isp_css_mm_set_user_ptr(unsigned int userptr,
+       unsigned int num_pages);
+
+#define FW_PATH        "shisp.bin"
+
+#endif /* ATOMISP_INTERNAL_H_ */
diff --git a/drivers/media/video/atomisp/include/atomisp/atomisp_tables.h b/drivers/media/video/atomisp/include/atomisp/atomisp_tables.h
new file mode 100644 (file)
index 0000000..ddf6b75
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef        __ATOMISP_TABLES_H__
+#define        __ATOMISP_TABLES_H__
+
+#include "sh_css_params.h"
+
+/*Sepia image effect table*/
+const struct sh_css_cc_config sepia_cc_config = {
+       .fraction_bits  = 8,
+       .matrix  = {141, 18, 68, -40, -5, -19, 35, 4, 16},
+};
+
+/*Negative image effect table*/
+const struct sh_css_cc_config nega_cc_config = {
+       .fraction_bits  = 8,
+       .matrix  = {255, 29, 120, 0, 374, 342, 0, 672, -301},
+};
+
+/*Mono image effect table*/
+const struct sh_css_cc_config mono_cc_config = {
+       .fraction_bits  = 8,
+       .matrix  = {255, 29, 120, 0, 0, 0, 0, 0, 0},
+};
+
+/*Skin whiten image effect table*/
+struct sh_css_macc_table skin_low_macc_table = {
+       .data = {
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       7129, 0, 0, 7129,
+       6684, 0, 0, 6684,
+       6684, 0, 0, 6684,
+       7129, 0, 0, 7129,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912
+       }
+};
+
+struct sh_css_macc_table skin_medium_macc_table = {
+       .data = {
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       5792, 0, 0, 5792,
+       4456, 0, 0, 4456,
+       4456, 0, 0, 4456,
+       5792, 0, 0, 5792,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912
+       }
+};
+
+struct sh_css_macc_table skin_high_macc_table = {
+       .data = {
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       4456, 0, 0, 4456,
+       2228, 0, 0, 2228,
+       2228, 0, 0, 2228,
+       4456, 0, 0, 4456,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912,
+       8912, 0, 0, 8912
+       }
+};
+
+/*Blue enhencement image effect table*/
+struct sh_css_macc_table blue_macc_table = {
+       .data = {
+       14336, -7168, 0, 10240, 13312, -5120, 2048, 6144, 8192, 0, 0,
+       8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192,
+       0, 0, 8192, 8192, 0, 0, 8192, 14336, 0, 0, 14336, 18432, 8192,
+       -4096, 6144, 8192, 0, 0, 8192, 12288, 2048, -4096, 6144, 8192,
+       0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192
+       }
+};
+
+/*Green enhencement image effect table*/
+struct sh_css_macc_table green_macc_table = {
+       .data = {
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0,
+       8192, 10240, 4096, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192,
+       8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0, 0, 8192, 8192, 0,
+       4096, 10240, 8192, 0, 0, 8192, 10240, 5120, 0, 12288, 9216,
+       7168, -4096, 20480, 12288, 0, 5120, 10240, 20480, -4096, 7168, 9216
+       }
+};
+
+/*Color enhancement image effect table*/
+struct sh_css_ctc_table vivid_ctc_table = {
+       .data = {
+       876, 872, 869, 865, 861, 858, 854, 850,
+       847, 843, 839, 835, 832, 828, 824, 821,
+       817, 813, 810, 806, 802, 799, 795, 791,
+       788, 784, 780, 777, 773, 769, 766, 762,
+       758, 754, 751, 747, 743, 740, 736, 732,
+       729, 725, 721, 718, 714, 710, 707, 703,
+       699, 696, 692, 688, 685, 681, 677, 673,
+       670, 666, 662, 659, 655, 651, 648, 644,
+       640, 637, 633, 629, 626, 622, 618, 615,
+       611, 607, 604, 600, 596, 592, 589, 585,
+       581, 578, 574, 570, 567, 563, 559, 556,
+       552, 548, 545, 541, 539, 537, 536, 534,
+       533, 531, 530, 528, 527, 525, 524, 522,
+       521, 519, 518, 516, 515, 514, 512, 511,
+       509, 508, 506, 505, 503, 502, 500, 499,
+       497, 496, 494, 493, 491, 490, 488, 487,
+       485, 484, 482, 481, 479, 478, 476, 475,
+       473, 472, 470, 469, 467, 466, 464, 463,
+       461, 460, 458, 457, 455, 454, 452, 451,
+       449, 448, 446, 445, 443, 442, 440, 439,
+       437, 436, 434, 433, 431, 430, 428, 427,
+       425, 424, 422, 421, 419, 418, 417, 415,
+       414, 412, 411, 409, 408, 406, 405, 403,
+       402, 400, 399, 397, 396, 394, 393, 392,
+       392, 391, 391, 390, 389, 389, 388, 388,
+       387, 387, 386, 385, 385, 384, 384, 383,
+       383, 382, 381, 381, 380, 380, 379, 379,
+       378, 377, 377, 376, 376, 375, 375, 374,
+       374, 373, 372, 372, 371, 371, 370, 370,
+       369, 368, 368, 367, 367, 366, 366, 365,
+       364, 364, 363, 363, 362, 362, 361, 360,
+       360, 359, 359, 358, 358, 357, 356, 356,
+       355, 355, 354, 354, 353, 352, 352, 351,
+       351, 350, 350, 349, 348, 348, 347, 347,
+       346, 346, 345, 344, 344, 343, 343, 342,
+       342, 341, 340, 340, 339, 339, 338, 338,
+       337, 336, 336, 335, 335, 334, 334, 333,
+       333, 332, 331, 331, 330, 330, 329, 329,
+       328, 327, 327, 326, 326, 325, 325, 324,
+       323, 323, 322, 322, 321, 321, 320, 319,
+       319, 318, 318, 317, 317, 316, 315, 315,
+       314, 314, 313, 313, 312, 311, 311, 310,
+       310, 309, 309, 308, 307, 307, 306, 306,
+       305, 305, 304, 303, 303, 302, 302, 301,
+       301, 300, 299, 299, 298, 298, 297, 297,
+       296, 296, 295, 294, 294, 293, 293, 292,
+       292, 291, 290, 290, 289, 289, 288, 288,
+       287, 286, 286, 285, 285, 284, 284, 283,
+       282, 282, 281, 281, 280, 280, 279, 278,
+       278, 277, 277, 276, 276, 275, 274, 274,
+       273, 273, 272, 272, 271, 270, 270, 269,
+       269, 268, 268, 267, 266, 266, 265, 265,
+       264, 264, 263, 262, 262, 261, 261, 260,
+       260, 259, 259, 258, 257, 257, 256, 256,
+       255, 255, 254, 253, 253, 252, 252, 251,
+       251, 250, 249, 249, 248, 248, 247, 247,
+       246, 245, 245, 244, 244, 243, 243, 242,
+       241, 241, 240, 240, 239, 239, 238, 237,
+       237, 236, 236, 235, 235, 234, 233, 233,
+       232, 232, 231, 231, 230, 229, 229, 228,
+       228, 227, 227, 226, 225, 225, 224, 224,
+       223, 223, 222, 221, 221, 220, 220, 219,
+       219, 218, 218, 217, 216, 216, 215, 215,
+       214, 214, 213, 212, 212, 211, 211, 210,
+       210, 209, 208, 208, 207, 207, 206, 206,
+       205, 204, 204, 203, 203, 202, 202, 201,
+       200, 200, 199, 199, 198, 198, 197, 196,
+       196, 195, 195, 194, 194, 193, 192, 192,
+       191, 191, 190, 190, 189, 188, 188, 187,
+       187, 186, 186, 185, 184, 184, 183, 183,
+       182, 182, 181, 181, 180, 179, 179, 178,
+       178, 177, 177, 176, 175, 175, 174, 174,
+       173, 173, 172, 171, 171, 170, 170, 169,
+       169, 168, 167, 167, 166, 166, 165, 165,
+       164, 163, 163, 163, 162, 162, 161, 161,
+       161, 160, 160, 159, 159, 159, 158, 158,
+       158, 157, 157, 156, 156, 156, 155, 155,
+       155, 154, 154, 153, 153, 153, 152, 152,
+       152, 151, 151, 150, 150, 150, 149, 149,
+       149, 148, 148, 147, 147, 147, 146, 146,
+       145, 145, 145, 144, 144, 144, 143, 143,
+       142, 142, 142, 141, 141, 141, 140, 140,
+       139, 139, 139, 138, 138, 138, 137, 137,
+       136, 136, 136, 135, 135, 134, 134, 134,
+       133, 133, 133, 132, 132, 131, 131, 131,
+       130, 130, 130, 129, 129, 128, 128, 128,
+       127, 127, 127, 126, 126, 125, 125, 125,
+       124, 124, 123, 123, 123, 122, 122, 122,
+       121, 121, 120, 120, 120, 119, 119, 119,
+       118, 118, 117, 117, 117, 116, 116, 116,
+       115, 115, 114, 114, 114, 113, 113, 112,
+       112, 112, 111, 111, 111, 110, 110, 109,
+       109, 109, 108, 108, 108, 107, 107, 106,
+       106, 106, 105, 105, 105, 104, 104, 103,
+       103, 103, 102, 102, 101, 101, 101, 100,
+       100, 100, 99, 99, 98, 98, 98, 97,
+       97, 97, 96, 96, 95, 95, 95, 94,
+       94, 94, 93, 93, 92, 92, 92, 91,
+       91, 91, 90, 90, 89, 89, 89, 88,
+       88, 87, 87, 87, 86, 86, 86, 85,
+       85, 84, 84, 84, 83, 83, 83, 82,
+       82, 81, 81, 81, 80, 80, 80, 79,
+       79, 78, 78, 78, 77, 77, 76, 76,
+       76, 75, 75, 75, 74, 74, 73, 73,
+       73, 72, 72, 72, 71, 71, 70, 70,
+       70, 69, 69, 69, 68, 68, 67, 67,
+       67, 66, 66, 65, 65, 65, 64, 64,
+       64, 63, 63, 61, 61, 61, 61, 61,
+       61, 60, 60, 58, 58, 58, 58, 58,
+       58, 57, 57, 56, 56, 56, 55, 55,
+       54, 54, 54, 53, 53, 53, 51, 51,
+       51, 51, 51, 50, 50, 50, 48, 48,
+       48, 48, 48, 47, 47, 47, 45, 45,
+       45, 45, 45, 44, 44, 42, 42, 42,
+       42, 42, 42, 41, 41, 40, 40, 40,
+       39, 39, 39, 38, 38, 37, 37, 37,
+       35, 35, 35, 35, 35, 34, 34, 34,
+       32, 32, 32, 32, 32, 31, 31, 31,
+       29, 29, 29, 29, 29, 28, 28, 28,
+       26, 26, 25, 25, 25, 25, 25, 25,
+       24, 24, 22, 22, 22, 22, 22, 22,
+       21, 21, 19, 19, 19, 19, 19, 18,
+       18, 18, 16, 16, 16, 16, 16, 15,
+       15, 15, 13, 13, 13, 12, 12, 12,
+       12, 12, 10, 10, 10, 9, 9, 9,
+       9, 9, 8, 8, 6, 6, 6, 6,
+       6, 6, 5, 5, 3, 3, 3, 3,
+       3, 3, 2, 2, 0, 0, 0, 0,
+       }
+};
+#endif
diff --git a/drivers/media/video/atomisp/include/atomisp/atomisp_v4l2.h b/drivers/media/video/atomisp/include/atomisp/atomisp_v4l2.h
new file mode 100644 (file)
index 0000000..9ab5c8d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef ATOMISP_V4L2_H_
+#define ATOMISP_V4L2_H_
+
+#include <linux/videodev2.h>
+
+/* SH header files */
+#include <css/sh_css_types.h>
+
+#define ATOMISP_MAJOR          0
+#define ATOMISP_MINOR          5
+#define ATOMISP_PATCHLEVEL     1
+
+#define DRIVER_VERSION_STR     __stringify(ATOMISP_MAJOR) \
+       "." __stringify(ATOMISP_MINOR) "." __stringify(ATOMISP_PATCHLEVEL)
+#define DRIVER_VERSION         KERNEL_VERSION(ATOMISP_MAJOR, \
+       ATOMISP_MINOR, ATOMISP_PATCHLEVEL)
+
+/*ISP binary running mode*/
+#define CI_MODE_PREVIEW                0x8000
+#define CI_MODE_VIDEO          0x4000
+#define CI_MODE_STILL_CAPTURE  0x2000
+#define CI_MODE_NONE           0x0000
+
+#define ATOM_ISP_STEP_WIDTH    2
+#define ATOM_ISP_STEP_HEIGHT   2
+
+#define ATOM_ISP_MIN_WIDTH     256
+#define ATOM_ISP_MIN_HEIGHT    2
+#define ATOM_ISP_MAX_WIDTH     4352
+#define ATOM_ISP_MAX_HEIGHT    3264
+
+#define ATOM_ISP_MAX_WIDTH_TMP 1280
+#define ATOM_ISP_MAX_HEIGHT_TMP        720
+
+#endif /* ATOMISP_V4L2_H_ */
diff --git a/drivers/media/video/atomisp/include/hmm/hmm.h b/drivers/media/video/atomisp/include/hmm/hmm.h
new file mode 100644 (file)
index 0000000..51c29cd
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __HMM_H__
+#define        __HMM_H__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include "hmm/hmm_bo.h"
+
+#define HMM_CACHED true
+#define HMM_UNCACHED false
+
+int hmm_init(void);
+void hmm_cleanup(void);
+
+void *hmm_alloc(size_t bytes, enum hmm_bo_type type,
+               int from_highmem, unsigned int userptr, bool cached);
+void hmm_free(void *ptr);
+int hmm_load(void *virt, void *data, unsigned int bytes);
+int hmm_store(void *virt, const void *data, unsigned int bytes);
+int hmm_set(void *virt, int c, unsigned int bytes);
+
+/*
+ * get kernel memory physical address from ISP virtual address.
+ */
+unsigned int hmm_virt_to_phys(void *virt);
+
+/*
+ * map ISP memory starts with virt to kernel virtual address
+ * by using vmap. return NULL if failed.
+ *
+ * !! user needs to use vunmap to unmap it manually before calling
+ * hmm_free to free the memory.
+ *
+ * virt must be the start address of ISP memory (return by hmm_alloc),
+ * do not pass any other address.
+ */
+void *hmm_vmap(void *virt);
+
+/*
+ * map ISP memory starts with virt to specific vma.
+ *
+ * used for mmap operation.
+ *
+ * virt must be the start address of ISP memory (return by hmm_alloc),
+ * do not pass any other address.
+ */
+int hmm_mmap(struct vm_area_struct *vma, void *virt);
+
+#endif
diff --git a/drivers/media/video/atomisp/include/hmm/hmm_bo.h b/drivers/media/video/atomisp/include/hmm/hmm_bo.h
new file mode 100644 (file)
index 0000000..951b0a8
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __HMM_BO_H__
+#define        __HMM_BO_H__
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/kref.h>
+#include "hmm_common.h"
+#include "hmm/hmm_vm.h"
+
+#define        check_bo_status_yes_goto(bo, _status, label) \
+       var_not_equal_goto((bo->status & (_status)), (_status), \
+                       label, \
+                       "HMM buffer status not contain %s.\n", \
+                       #_status)
+
+#define        check_bo_status_no_goto(bo, _status, label) \
+       var_equal_goto((bo->status & (_status)), (_status), \
+                       label, \
+                       "HMM buffer status contains %s.\n", \
+                       #_status)
+#define        list_to_hmm_bo(list_ptr)        \
+       list_entry((list_ptr), struct hmm_buffer_object, list)
+
+#define        kref_to_hmm_bo(kref_ptr)        \
+       list_entry((kref_ptr), struct hmm_buffer_object, kref)
+
+#define        check_bo_null_return(bo, exp)   \
+       check_null_return(bo, exp, "NULL hmm buffer object.\n")
+
+#define        HMM_MAX_ORDER           3
+#define        HMM_MIN_ORDER           0
+
+struct hmm_bo_device;
+
+/*
+ * buffer object type.
+ *
+ *     HMM_BO_PRIVATE:
+ *     pages are allocated by driver itself.
+ *     HMM_BO_SHARE:
+ *     pages are allocated by other component. currently: video driver.
+ *     HMM_BO_USER:
+ *     pages are allocated in user space process.
+ *
+ */
+enum hmm_bo_type {
+       HMM_BO_PRIVATE,
+       HMM_BO_SHARE,
+       HMM_BO_USER,
+};
+
+#define        HMM_BO_VM_ALLOCED       0x1
+#define        HMM_BO_PAGE_ALLOCED     0x2
+#define        HMM_BO_BINDED           0x4
+#define        HMM_BO_MMAPED           0x8
+#define        HMM_BO_ACTIVE           0x1000
+#define        HMM_BO_MEM_TYPE_USER     0x1
+#define        HMM_BO_MEM_TYPE_PFN      0x2
+
+struct page_block {
+       struct list_head        list;
+       struct page             *pages;
+       int                     order;
+};
+
+struct hmm_buffer_object {
+       struct hmm_bo_device    *bdev;
+       struct list_head        list;
+       struct kref             kref;
+
+       /* mutex protecting this BO */
+       struct mutex            mutex;
+       enum hmm_bo_type        type;
+       struct list_head        pgblocks;
+       struct page             **pages;        /* physical pages */
+       unsigned int            pgnr;   /* page number */
+       int                     from_highmem;
+       int                     mmap_count;
+       struct hmm_vm_node      *vm_node;
+       int                     status;
+       int         mem_type;
+
+       /*
+        * release callback for releasing buffer object.
+        *
+        * usually set to the release function to release the
+        * upper level buffer object which has hmm_buffer_object
+        * embedded in. if the hmm_buffer_object is dynamically
+        * created by hmm_bo_create, release will set to kfree.
+        *
+        */
+       void (*release)(struct hmm_buffer_object *bo);
+};
+
+/*
+ * use this function to initialize pre-allocated hmm_buffer_object.
+ *
+ * the hmm_buffer_object use reference count to manage its life cycle.
+ *
+ * bo->kref is inited to 1.
+ *
+ * use hmm_bo_ref/hmm_bo_unref increase/decrease the reference count,
+ * and hmm_bo_unref will free resource of buffer object (but not the
+ * buffer object itself as it can be both pre-allocated or dynamically
+ * allocated) when reference reaches 0.
+ *
+ * see detailed description of hmm_bo_ref/hmm_bo_unref below.
+ *
+ * as hmm_buffer_object may be used as an embedded object in an upper
+ * level object, a release callback must be provided. if it is
+ * embedded in upper level object, set release call back to release
+ * function of that object. if no upper level object, set release
+ * callback to NULL.
+ *
+ * ex:
+ *     struct hmm_buffer_object bo;
+ *     hmm_bo_init(bdev, &bo, pgnr, NULL);
+ *
+ * or
+ *     struct my_buffer_object {
+ *             struct hmm_buffer_object bo;
+ *             ...
+ *     };
+ *
+ *     void my_buffer_release(struct hmm_buffer_object *bo)
+ *     {
+ *             struct my_buffer_object *my_bo =
+ *                     container_of(bo, struct my_buffer_object, bo);
+ *
+ *             ...     // release resource in my_buffer_object
+ *
+ *             kfree(my_bo);
+ *     }
+ *
+ *     struct my_buffer_object *my_bo =
+ *             kmalloc(sizeof(*my_bo), GFP_KERNEL);
+ *
+ *     hmm_bo_init(bdev, &my_bo->bo, pgnr, my_buffer_release);
+ *     ...
+ *
+ *     hmm_bo_unref(&my_bo->bo);
+ */
+int hmm_bo_init(struct hmm_bo_device *bdev,
+               struct hmm_buffer_object *bo,
+               unsigned int pgnr,
+               void (*release)(struct hmm_buffer_object *));
+
+/*
+ * use these functions to dynamically alloc hmm_buffer_object.
+ *
+ * hmm_bo_init will called for that allocated buffer object, and
+ * the release callback is set to kfree.
+ *
+ * ex:
+ *     hmm_buffer_object *bo = hmm_bo_create(bdev, pgnr);
+ *     ...
+ *     hmm_bo_unref(bo);
+ */
+struct hmm_buffer_object *hmm_bo_create(struct hmm_bo_device *bdev,
+               int pgnr);
+
+/*
+ * increse buffer object reference.
+ */
+void hmm_bo_ref(struct hmm_buffer_object *bo);
+
+/*
+ * decrese buffer object reference. if reference reaches 0,
+ * release function of the buffer object will be called.
+ *
+ * this call is also used to release hmm_buffer_object or its
+ * upper level object with it embedded in. you need to call
+ * this function when it is no longer used.
+ *
+ * Note:
+ *
+ * user dont need to care about internal resource release of
+ * the buffer object in the release callback, it will be
+ * handled internally.
+ *
+ * this call will only release internal resource of the buffer
+ * object but will not free the buffer object itself, as the
+ * buffer object can be both pre-allocated statically or
+ * dynamically allocated. so user need to deal with the release
+ * of the buffer object itself manually. below example shows
+ * the normal case of using the buffer object.
+ *
+ *     struct hmm_buffer_object *bo = hmm_bo_create(bdev, pgnr);
+ *     ......
+ *     hmm_bo_unref(bo);
+ *
+ * or:
+ *
+ *     struct hmm_buffer_object bo;
+ *
+ *     hmm_bo_init(bdev, &bo, pgnr, NULL);
+ *     ...
+ *     hmm_bo_unref(&bo);
+ */
+void hmm_bo_unref(struct hmm_buffer_object *bo);
+
+
+/*
+ * put buffer object to unactivated status, meaning put it into
+ * bo->bdev->free_bo_list, but not destroy it.
+ *
+ * this can be used to instead of hmm_bo_destroy if there are
+ * lots of petential hmm_bo_init/hmm_bo_destroy operations with
+ * the same buffer object size. using this with hmm_bo_device_get_bo
+ * can improve performace as lots of memory allocation/free are
+ * avoided..
+ */
+void hmm_bo_unactivate(struct hmm_buffer_object *bo);
+int hmm_bo_activated(struct hmm_buffer_object *bo);
+
+/*
+ * allocate/free virtual address space for the bo.
+ */
+int hmm_bo_alloc_vm(struct hmm_buffer_object *bo);
+void hmm_bo_free_vm(struct hmm_buffer_object *bo);
+int hmm_bo_vm_allocated(struct hmm_buffer_object *bo);
+
+/*
+ * allocate/free physical pages for the bo. will try to alloc mem
+ * from highmem if from_highmem is set, and type indicate that the
+ * pages will be allocated by using video driver (for share buffer)
+ * or by ISP driver itself.
+ */
+int hmm_bo_alloc_pages(struct hmm_buffer_object *bo,
+               enum hmm_bo_type type, int from_highmem,
+               unsigned int userptr, bool cached);
+void hmm_bo_free_pages(struct hmm_buffer_object *bo);
+int hmm_bo_page_allocated(struct hmm_buffer_object *bo);
+
+/*
+ * get physical page info of the bo.
+ */
+int hmm_bo_get_page_info(struct hmm_buffer_object *bo,
+               struct page ***pages, int *pgnr);
+
+/*
+ * bind/unbind the physical pages to a virtual address space.
+ */
+int hmm_bo_bind(struct hmm_buffer_object *bo);
+void hmm_bo_unbind(struct hmm_buffer_object *bo);
+int hmm_bo_binded(struct hmm_buffer_object *bo);
+
+/*
+ * vmap buffer object's pages to contiguous kernel virtual address.
+ * user needs to call vunmap manually to unmap it.
+ */
+void *hmm_bo_vmap(struct hmm_buffer_object *bo);
+
+/*
+ * mmap the bo's physical pages to specific vma.
+ *
+ * vma's address space size must be the same as bo's size,
+ * otherwise it will return -EINVAL.
+ *
+ * vma->vm_flags will be set to (VM_RESERVED | VM_IO).
+ */
+int hmm_bo_mmap(struct vm_area_struct *vma,
+               struct hmm_buffer_object *bo);
+
+#endif
diff --git a/drivers/media/video/atomisp/include/hmm/hmm_bo_dev.h b/drivers/media/video/atomisp/include/hmm/hmm_bo_dev.h
new file mode 100644 (file)
index 0000000..0020d09
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __HMM_BO_DEV_H__
+#define        __HMM_BO_DEV_H__
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include "mmu/isp_mmu.h"
+#include "hmm/hmm_common.h"
+#include "hmm/hmm_vm.h"
+
+#define        check_bodev_null_return(bdev, exp)      \
+               check_null_return(bdev, exp, \
+                       "NULL hmm_bo_device.\n")
+
+#define        HMM_BO_DEVICE_INITED    0x1
+
+struct hmm_buffer_object;
+
+struct hmm_bo_device {
+       /* isp_mmu provides lock itself */
+       struct isp_mmu          mmu;
+
+       /* hmm_vm provides lock itself */
+       struct hmm_vm           vaddr_space;
+
+       struct list_head        free_bo_list;
+       struct mutex            fblist_mutex;
+       struct list_head        active_bo_list;
+       struct mutex            ablist_mutex;
+
+       int                     flag;
+};
+
+int hmm_bo_device_init(struct hmm_bo_device *bdev,
+               struct isp_mmu_driver *mmu_driver,
+               unsigned int vaddr_start, unsigned int size);
+
+/*
+ * clean up all hmm_bo_device related things.
+ */
+void hmm_bo_device_exit(struct hmm_bo_device *bdev);
+
+/*
+ * whether the bo device is inited or not.
+ */
+int hmm_bo_device_inited(struct hmm_bo_device *bdev);
+
+/*
+ * find the buffer object with virtual address vaddr.
+ * return NULL if no such buffer object found.
+ */
+struct hmm_buffer_object *hmm_bo_device_search_start(
+               struct hmm_bo_device *bdev, unsigned int vaddr);
+
+/*
+ * find the buffer object with virtual address vaddr.
+ * return NULL if no such buffer object found.
+ */
+struct hmm_buffer_object *hmm_bo_device_search_in_range(
+               struct hmm_bo_device *bdev, unsigned int vaddr);
+
+/*
+ * find a buffer object with pgnr pages from free_bo_list and
+ * activate it (remove from free_bo_list and add to
+ * active_bo_list)
+ *
+ * return NULL if no such buffer object found.
+ */
+struct hmm_buffer_object *hmm_bo_device_get_bo(
+               struct hmm_bo_device *bdev, unsigned int pgnr);
+
+/*
+ * destroy all buffer objects in the free_bo_list.
+ */
+void hmm_bo_device_destroy_free_bo_list(struct hmm_bo_device *bdev);
+/*
+ * destroy buffer object with start virtual address vaddr.
+ */
+void hmm_bo_device_destroy_free_bo_addr(struct hmm_bo_device *bdev,
+               unsigned int vaddr);
+/*
+ * destroy all buffer objects with pgnr pages.
+ */
+void hmm_bo_device_destroy_free_bo_size(struct hmm_bo_device *bdev,
+               unsigned int pgnr);
+
+#endif
diff --git a/drivers/media/video/atomisp/include/hmm/hmm_common.h b/drivers/media/video/atomisp/include/hmm/hmm_common.h
new file mode 100644 (file)
index 0000000..4b9b296
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __HMM_BO_COMMON_H__
+#define        __HMM_BO_COMMON_H__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+
+#define        HMM_BO_NAME     "HMM"
+
+/*
+ * some common use micros
+ */
+#define        var_equal_return(var1, var2, exp, fmt, arg ...) \
+       do { \
+               if ((var1) == (var2)) { \
+                       v4l2_err(&atomisp_dev, \
+                       fmt, ## arg); \
+                       return exp;\
+               } \
+       } while (0)
+
+#define        var_equal_goto(var1, var2, label, fmt, arg ...) \
+       do { \
+               if ((var1) == (var2)) { \
+                       v4l2_err(&atomisp_dev, \
+                       fmt, ## arg); \
+                       goto label;\
+               } \
+       } while (0)
+
+#define        var_not_equal_goto(var1, var2, label, fmt, arg ...)     \
+       do { \
+               if ((var1) != (var2)) { \
+                       v4l2_err(&atomisp_dev, \
+                       fmt, ## arg); \
+                       goto label;\
+               } \
+       } while (0)
+
+#define        check_null_return(ptr, exp, fmt, arg ...)       \
+               var_equal_return(ptr, NULL, exp, fmt, ## arg)
+
+#endif
diff --git a/drivers/media/video/atomisp/include/hmm/hmm_vm.h b/drivers/media/video/atomisp/include/hmm/hmm_vm.h
new file mode 100644 (file)
index 0000000..260cb90
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef        __HMM_VM_H__
+#define        __HMM_VM_H__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+
+struct hmm_vm {
+       unsigned int start;
+       unsigned int pgnr;
+       unsigned int size;
+       struct list_head vm_node_list;
+       spinlock_t lock;
+};
+
+struct hmm_vm_node {
+       struct list_head list;
+       unsigned int start;
+       unsigned int pgnr;
+       unsigned int size;
+       struct hmm_vm *vm;
+};
+
+#define        hmm_vm_node(list_ptr)   \
+       list_entry((list_ptr), struct hmm_vm_node, list)
+
+int hmm_vm_init(struct hmm_vm *vm, unsigned int start,
+               unsigned int size);
+
+void hmm_vm_clean(struct hmm_vm *vm);
+
+struct hmm_vm_node *hmm_vm_alloc_node(struct hmm_vm *vm,
+               unsigned int pgnr);
+
+void hmm_vm_free_node(struct hmm_vm_node *node);
+
+struct hmm_vm_node *hmm_vm_find_node_start(struct hmm_vm *vm,
+               unsigned int addr);
+
+struct hmm_vm_node *hmm_vm_find_node_in_range(struct hmm_vm *vm,
+               unsigned int addr);
+
+#endif
diff --git a/drivers/media/video/atomisp/include/mmu/isp_mmu.h b/drivers/media/video/atomisp/include/mmu/isp_mmu.h
new file mode 100644 (file)
index 0000000..a01c19b
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+/*
+ * ISP MMU driver for classic two-level page tables
+ */
+#ifndef        __ISP_MMU_H__
+#define        __ISP_MMU_H__
+
+#include <linux/mutex.h>
+
+/*
+ * do not change these values, the page size for ISP must be the
+ * same as kernel's page size.
+ */
+#define        ISP_PAGE_OFFSET         12
+#define        ISP_PAGE_SIZE           (1U << ISP_PAGE_OFFSET)
+#define        ISP_PAGE_MASK           (~(ISP_PAGE_SIZE - 1))
+
+#define        ISP_L1PT_OFFSET         22
+#define        ISP_L1PT_MASK           (~((1U << ISP_L1PT_OFFSET) - 1))
+
+#define        ISP_L2PT_OFFSET         12
+#define        ISP_L2PT_MASK           (~(ISP_L1PT_MASK|(~(ISP_PAGE_MASK))))
+
+#define        ISP_L1PT_PTES           1024
+#define        ISP_L2PT_PTES           1024
+
+#define        ISP_PTR_TO_L1_IDX(x)    ((((x) & ISP_L1PT_MASK)) \
+                                       >> ISP_L1PT_OFFSET)
+
+#define        ISP_PTR_TO_L2_IDX(x)    ((((x) & ISP_L2PT_MASK)) \
+                                       >> ISP_L2PT_OFFSET)
+
+#define        ISP_PAGE_ALIGN(x)       (((x) + (ISP_PAGE_SIZE-1)) \
+                                       & ISP_PAGE_MASK)
+
+#define        ISP_PT_TO_VIRT(l1_idx, l2_idx, offset) do {\
+               ((l1_idx) << ISP_L1PT_OFFSET) | \
+               ((l2_idx) << ISP_L2PT_OFFSET) | \
+               (offset)\
+} while (0)
+
+#define        pgnr_to_size(pgnr)      ((pgnr) << ISP_PAGE_OFFSET)
+#define        size_to_pgnr_ceil(size) (((size) + (1 << ISP_PAGE_OFFSET) - 1)\
+                                               >> ISP_PAGE_OFFSET)
+#define        size_to_pgnr_bottom(size)       ((size) >> ISP_PAGE_OFFSET)
+
+struct isp_mmu;
+
+struct isp_mmu_driver {
+       /*
+        * const value
+        *
+        * @name:
+        *      driver name
+        * @pte_valid_mask:
+        *      should be 1 bit valid data, meaning the value should
+        *      be power of 2.
+        */
+       char *name;
+       unsigned int pte_valid_mask;
+
+       /*
+        * set page directory base address (physical address).
+        *
+        * must be provided.
+        */
+       int (*set_pd_base) (struct isp_mmu *mmu,
+                       unsigned int pd_base);
+       /*
+        * callback to flush tlb.
+        *
+        * tlb_flush_range will at least flush TLBs containing
+        * address mapping from addr to addr + size.
+        *
+        * tlb_flush_all will flush all TLBs.
+        *
+        * tlb_flush_all is must be provided. if tlb_flush_range is
+        * not valid, it will set to tlb_flush_all by default.
+        */
+       void (*tlb_flush_range) (struct isp_mmu *mmu,
+                                unsigned int addr, unsigned int size);
+       void (*tlb_flush_all) (struct isp_mmu *mmu);
+
+};
+
+struct isp_mmu {
+       struct isp_mmu_driver *driver;
+       unsigned int l1_pte;
+
+       struct mutex pt_mutex;
+};
+
+/* flags for PDE and PTE */
+#define        ISP_PTE_VALID_MASK(mmu) \
+       ((mmu)->driver->pte_valid_mask)
+
+#define        ISP_PTE_VALID(mmu, pte) \
+       ((pte) & ISP_PTE_VALID_MASK(mmu))
+
+#define        UNVALID_PHYS    0xffffffff
+
+#define        NULL_PAGE       (UNVALID_PHYS & ISP_PAGE_MASK)
+#define        NULL_PTE        NULL_PAGE
+
+#define        PAGE_VALID(page)        ((page) != NULL_PAGE)
+
+/*
+ * init mmu with specific mmu driver.
+ */
+int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_driver *driver);
+/*
+ * cleanup all mmu related things.
+ */
+void isp_mmu_exit(struct isp_mmu *mmu);
+
+/*
+ * setup/remove address mapping for pgnr continous physical pages
+ * and isp_virt.
+ *
+ * map/unmap is mutex lock protected, and caller does not have
+ * to do lock/unlock operation.
+ *
+ * map/unmap will not flush tlb, and caller needs to deal with
+ * this itself.
+ */
+int isp_mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
+               unsigned int phys, unsigned int pgnr);
+
+void isp_mmu_unmap(struct isp_mmu *mmu, unsigned int isp_virt,
+                  unsigned int pgnr);
+
+static inline void isp_mmu_flush_tlb_all(struct isp_mmu *mmu)
+{
+       if (mmu->driver && mmu->driver->tlb_flush_all)
+               mmu->driver->tlb_flush_all(mmu);
+}
+
+#define isp_mmu_flush_tlb isp_mmu_flush_tlb_all
+
+static inline void isp_mmu_flush_tlb_range(struct isp_mmu *mmu,
+               unsigned int start, unsigned int size)
+{
+       if (mmu->driver && mmu->driver->tlb_flush_range)
+               mmu->driver->tlb_flush_range(mmu, start, size);
+}
+
+#endif /* ISP_MMU_H_ */
diff --git a/drivers/media/video/atomisp/include/mmu/sh_mmu.h b/drivers/media/video/atomisp/include/mmu/sh_mmu.h
new file mode 100644 (file)
index 0000000..d05aa3b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#ifndef        SH_MMU_H_
+#define        SH_MMU_H_
+
+#include <css/sh_css.h>
+#include "mmu/isp_mmu.h"
+
+
+/*
+ * include SH header file here
+ */
+
+/*
+ * set page directory base address (physical address).
+ *
+ * must be provided.
+ */
+static int sh_set_pd_base(struct isp_mmu *mmu,
+               unsigned int phys)
+{
+       sh_css_mmu_set_page_table_base_address((void *)phys);
+       return 0;
+}
+
+/*
+ * callback to flush tlb.
+ *
+ * tlb_flush_range will at least flush TLBs containing
+ * address mapping from addr to addr + size.
+ *
+ * tlb_flush_all will flush all TLBs.
+ *
+ * tlb_flush_all is must be provided. if tlb_flush_range is
+ * not valid, it will set to tlb_flush_all by default.
+ */
+static void sh_tlb_flush(struct isp_mmu *mmu)
+{
+       sh_css_mmu_invalidate_cache();
+}
+
+static struct isp_mmu_driver sh_mmu_driver = {
+       .name = "Silicon Hive ISP3000 MMU",
+       .pte_valid_mask = 0x1,
+       .set_pd_base = sh_set_pd_base,
+       .tlb_flush_all = sh_tlb_flush,
+};
+
+#define        ISP_VM_START    0x0
+#define        ISP_VM_SIZE     (1 << 30)       /* 1G address space */
+#define        ISP_PTR_NULL    NULL
+
+#endif /* SH_MMU_H_ */
+
diff --git a/drivers/media/video/atomisp/mmu/isp_mmu.c b/drivers/media/video/atomisp/mmu/isp_mmu.c
new file mode 100644 (file)
index 0000000..05ef59d
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Support for Medifield PNW Camera Imaging ISP subsystem.
+ *
+ * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
+ *
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+/*
+ * ISP MMU management wrap code
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>          /* for GFP_ATOMIC */
+#include <linux/slab.h>                /* for kmalloc */
+#include <linux/list.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include "mmu/isp_mmu.h"
+#include "atomisp_internal.h"
+
+static unsigned int atomisp_get_pte(unsigned int pt, unsigned int idx)
+{
+       unsigned int pt_virt = (unsigned int)phys_to_virt(pt);
+       return *(((unsigned int *) pt_virt) + idx);
+}
+
+static void atomisp_set_pte(unsigned int pt,
+                            unsigned int idx, unsigned int pte)
+{
+       unsigned int pt_virt = (unsigned int)phys_to_virt(pt);
+       (*(((unsigned int *) pt_virt) + idx)) = pte;
+}
+
+static void *isp_pt_phys_to_virt(unsigned int phys)
+{
+       return phys_to_virt(phys);
+}
+
+static unsigned int isp_pte_to_pgaddr(unsigned int pte)
+{
+       return (unsigned int)(pte & ISP_PAGE_MASK);
+}
+
+static unsigned int isp_pgaddr_to_pte_valid(struct isp_mmu *mmu,
+                                          unsigned int phys)
+{
+       return (unsigned int) (phys | ISP_PTE_VALID_MASK(mmu));
+}
+
+/*
+ * allocate a uncacheable page table.
+ * return physical address.
+ */
+static unsigned int alloc_page_table(void)
+{
+       int i;
+       unsigned int page;
+
+       void *virt = (void *)__get_free_page(GFP_KERNEL);
+       if (!virt)
+               return NULL_PAGE;
+
+       /*
+        * we need a uncacheable page table.
+        */
+#ifdef CONFIG_X86
+       set_memory_uc((unsigned int)virt, 1);
+#endif
+
+       page = virt_to_phys(virt);
+
+       for (i = 0; i < 1024; i++) {
+               /* NEED CHECK */
+               atomisp_set_pte(page, i, NULL_PAGE);
+       }
+
+       return page;
+}
+
+static void free_page_table(unsigned int page)
+{
+       unsigned int virt;
+       page &= ISP_PAGE_MASK;
+       /*
+        * reset the page to write back before free
+        */
+#ifdef CONFIG_X86
+       virt = (unsigned int)phys_to_virt(page);
+       set_memory_wb(virt, 1);
+#endif
+       free_page((unsigned long)phys_to_virt(page));
+}
+
+static void mmu_remap_error(struct isp_mmu *mmu,
+                             unsigned int l1_pt, unsigned int l1_idx,
+                             unsigned int l2_pt, unsigned int l2_idx,
+                             unsigned int isp_virt, unsigned int old_phys,
+                             unsigned int new_phys)
+{
+       v4l2_err(&atomisp_dev, "address remap:\n\n"
+                    "\tL1 PT: virt = 0x%x, phys = 0x%x, "
+                    "idx = %d\n"
+                    "\tL2 PT: virt = 0x%x, phys = 0x%x, "
+                    "idx = %d\n"
+                    "\told: isp_virt = 0x%x, phys = 0x%x\n"
+                    "\tnew: isp_virt = 0x%x, phys = 0x%x\n",
+                    (unsigned int)isp_pt_phys_to_virt(l1_pt),
+                    (unsigned int)(l1_pt), l1_idx,
+                    (unsigned int)isp_pt_phys_to_virt(l2_pt),
+                    (unsigned int)(l2_pt), l2_idx, (unsigned int)isp_virt,
+                    (unsigned int)old_phys, (unsigned int)isp_virt,
+                    (unsigned int)new_phys);
+}
+
+static void mmu_unmap_l2_pte_error(struct isp_mmu *mmu,
+                                    unsigned int l1_pt, unsigned int l1_idx,
+                                    unsigned int l2_pt, unsigned int l2_idx,
+                                    unsigned int isp_virt, unsigned int pte)
+{
+       v4l2_err(&atomisp_dev, "unmap unvalid L2 pte:\n\n"
+                    "\tL1 PT: virt = 0x%x, phys = 0x%x, "
+                    "idx = %d\n"
+                    "\tL2 PT: virt = 0x%x, phys = 0x%x, "
+                    "idx = %d\n"
+                    "\tisp_virt = 0x%x, pte(page phys) = 0x%x\n",
+                    (unsigned int)isp_pt_phys_to_virt(l1_pt),
+                    (unsigned int)(l1_pt), l1_idx,
+                    (unsigned int)isp_pt_phys_to_virt(l2_pt),
+                    (unsigned int)(l2_pt), l2_idx, (unsigned int)isp_virt,
+                    (unsigned int)pte);
+}
+
+static void mmu_unmap_l1_pte_error(struct isp_mmu *mmu,
+                                    unsigned int l1_pt, unsigned int l1_idx,
+                                    unsigned int isp_virt, unsigned int pte)
+{
+       v4l2_err(&atomisp_dev, "unmap unvalid L1 pte (L2 PT):\n\n"
+                    "\tL1 PT: virt = 0x%x, phys = 0x%x, "
+                    "idx = %d\n"
+                    "\tisp_virt = 0x%x, l1_pte(L2 PT) = 0x%x\n",
+                    (unsigned int)isp_pt_phys_to_virt(l1_pt),
+                    (unsigned int)(l1_pt), l1_idx, (unsigned int)isp_virt,
+                    (unsigned int)pte);
+}
+
+static void mmu_unmap_l1_pt_error(struct isp_mmu *mmu, unsigned int pte)
+{
+       v4l2_err(&atomisp_dev, "unmap unvalid L1PT:\n\n"
+                    "L1PT = 0x%x\n", (unsigned int)pte);
+}
+
+/*
+ * Update L2 page table according to isp virtual address and page physical
+ * address
+ */
+static int mmu_l2_map(struct isp_mmu *mmu, unsigned int l1_pt,
+                       unsigned int l1_idx, unsigned int l2_pt,
+                       unsigned int start, unsigned int end, unsigned int phys)
+{
+       unsigned int ptr;
+       unsigned int idx;
+       unsigned int pte;
+
+       l2_pt &= ISP_PAGE_MASK;
+
+       start = start & ISP_PAGE_MASK;
+       end = ISP_PAGE_ALIGN(end);
+       phys &= ISP_PAGE_MASK;
+
+       ptr = start;
+       do {
+               idx = ISP_PTR_TO_L2_IDX(ptr);
+
+               pte = atomisp_get_pte(l2_pt, idx);
+
+               if (ISP_PTE_VALID(mmu, pte))
+                       mmu_remap_error(mmu, l1_pt, l1_idx,
+                                         l2_pt, idx, ptr, pte, phys);
+
+               pte = isp_pgaddr_to_pte_valid(mmu, phys);
+
+               atomisp_set_pte(l2_pt, idx, pte);
+               ptr += (1U << ISP_L2PT_OFFSET);
+               phys += (1U << ISP_L2PT_OFFSET);
+       } while (ptr < end && idx < ISP_L2PT_PTES - 1);
+
+       return 0;
+}
+
+/*
+ * Update L1 page table according to isp virtual address and page physical
+ * address
+ */
+static int mmu_l1_map(struct isp_mmu *mmu, unsigned int l1_pt,
+                       unsigned int start, unsigned int end, unsigned int phys)
+{
+       unsigned int l2_pt, ptr, l1_aligned;
+       unsigned int idx;
+       unsigned int l2_pte;
+       int ret;
+
+       l1_pt &= ISP_PAGE_MASK;
+
+       start = start & ISP_PAGE_MASK;
+       end = ISP_PAGE_ALIGN(end);
+       phys &= ISP_PAGE_MASK;
+
+       ptr = start;
+       do {
+               idx = ISP_PTR_TO_L1_IDX(ptr);
+
+               l2_pte = atomisp_get_pte(l1_pt, idx);
+
+               if (!ISP_PTE_VALID(mmu, l2_pte)) {
+                       l2_pt = alloc_page_table();
+                       if (l2_pt == NULL_PAGE) {
+                               v4l2_err(&atomisp_dev,
+                                            "alloc page table fail.\n");
+                               return -ENOMEM;
+                       }
+
+                       l2_pte = isp_pgaddr_to_pte_valid(mmu, l2_pt);
+
+                       atomisp_set_pte(l1_pt, idx, l2_pte);
+               }
+
+               l2_pt = isp_pte_to_pgaddr(l2_pte);
+
+               l1_aligned = (ptr & ISP_PAGE_MASK) + (1U << ISP_L1PT_OFFSET);
+
+               if (l1_aligned < end) {
+                       ret = mmu_l2_map(mmu, l1_pt, idx,
+                                          l2_pt, ptr, l1_aligned, phys);
+                       phys += (l1_aligned - ptr);
+                       ptr = l1_aligned;
+               } else {
+                       ret = mmu_l2_map(mmu, l1_pt, idx,
+                                          l2_pt, ptr, end, phys);
+                       phys += (end - ptr);
+                       ptr = end;
+               }
+
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                   "setup mapping in L2PT fail.\n");
+                       return ret;
+               }
+       } while (ptr < end && idx < ISP_L1PT_PTES - 1);
+
+       return 0;
+}
+
+/*
+ * Update page table according to isp virtual address and page physical
+ * address
+ */
+static int mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
+                    unsigned int phys, unsigned int pgnr)
+{
+       unsigned int start, end;
+       unsigned int l1_pt;
+       int ret;
+
+       if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
+               /*
+                * allocate 1 new page for L1 page table
+                */
+               l1_pt = alloc_page_table();
+               if (l1_pt == NULL_PAGE) {
+                       v4l2_err(&atomisp_dev,
+                                   "alloc page table fail.\n");
+                       return -ENOMEM;
+               }
+
+               /*
+                * setup L1 page table physical addr to MMU
+                */
+               ret = mmu->driver->set_pd_base(mmu, l1_pt);
+               if (ret) {
+                       v4l2_err(&atomisp_dev,
+                                    "set page directory base address "
+                                    "fail.\n");
+                       return ret;
+               }
+               mmu->l1_pte = isp_pgaddr_to_pte_valid(mmu, l1_pt);
+       }
+
+       l1_pt = isp_pte_to_pgaddr(mmu->l1_pte);
+
+       start = (isp_virt) & ISP_PAGE_MASK;
+       end = start + (pgnr << ISP_PAGE_OFFSET);
+       phys &= ISP_PAGE_MASK;
+
+       ret = mmu_l1_map(mmu, l1_pt, start, end, phys);
+
+       if (ret)
+               v4l2_err(&atomisp_dev,
+                           "setup mapping in L1PT fail.\n");
+
+       return ret;
+}
+
+/*
+ * Free L2 page table according to isp virtual address and page physical
+ * address
+ */
+static void mmu_l2_unmap(struct isp_mmu *mmu, unsigned int l1_pt,
+                          unsigned int l1_idx, unsigned int l2_pt,
+                          unsigned int start, unsigned int end)
+{
+
+       unsigned int ptr;
+       unsigned int idx;
+       unsigned int pte;
+
+       l2_pt &= ISP_PAGE_MASK;
+
+       start = start & ISP_PAGE_MASK;
+       end = ISP_PAGE_ALIGN(end);
+
+       ptr = start;
+       do {
+               idx = ISP_PTR_TO_L2_IDX(ptr);
+
+               pte = atomisp_get_pte(l2_pt, idx);
+
+               if (!ISP_PTE_VALID(mmu, pte))
+                       mmu_unmap_l2_pte_error(mmu, l1_pt, l1_idx,
+                                                l2_pt, idx, ptr, pte);
+
+               atomisp_set_pte(l2_pt, idx, NULL_PTE);
+
+               ptr += (1U << ISP_L2PT_OFFSET);
+       } while (ptr < end && idx < ISP_L2PT_PTES - 1);
+}
+
+/*
+ * Free L1 page table according to isp virtual address and page physical
+ * address
+ */
+static void mmu_l1_unmap(struct isp_mmu *mmu, unsigned int l1_pt,
+                          unsigned int start, unsigned int end)
+{
+       unsigned int l2_pt, ptr, l1_aligned;
+       unsigned int idx;
+       unsigned int l2_pte;
+
+       l1_pt &= ISP_PAGE_MASK;
+
+       start = start & ISP_PAGE_MASK;
+       end = ISP_PAGE_ALIGN(end);
+
+       ptr = start;
+       do {
+               idx = ISP_PTR_TO_L1_IDX(ptr);
+
+               l2_pte = atomisp_get_pte(l1_pt, idx);
+
+               if (!ISP_PTE_VALID(mmu, l2_pte)) {
+                       mmu_unmap_l1_pte_error(mmu, l1_pt, idx, ptr, l2_pte);
+                       continue;
+               }
+
+               l2_pt = isp_pte_to_pgaddr(l2_pte);
+
+               l1_aligned = (ptr & ISP_PAGE_MASK) + (1U << ISP_L1PT_OFFSET);
+
+               if (l1_aligned < end) {
+                       mmu_l2_unmap(mmu, l1_pt, idx, l2_pt, ptr, l1_aligned);
+                       ptr = l1_aligned;
+               } else {
+                       mmu_l2_unmap(mmu, l1_pt, idx, l2_pt, ptr, end);
+                       ptr = end;
+               }
+               /*
+                * use the same L2 page next time, so we dont
+                * need to invalidate and free this PT.
+                */
+               /*      atomisp_set_pte(l1_pt, idx, NULL_PTE); */
+       } while (ptr < end && idx < ISP_L1PT_PTES - 1);
+}
+
+/*
+ * Free page table according to isp virtual address and page physical
+ * address
+ */
+static void mmu_unmap(struct isp_mmu *mmu, unsigned int isp_virt,
+                       unsigned int pgnr)
+{
+       unsigned int start, end;
+       unsigned int l1_pt;
+
+       if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
+               mmu_unmap_l1_pt_error(mmu, mmu->l1_pte);
+               return;
+       }
+
+       l1_pt = isp_pte_to_pgaddr(mmu->l1_pte);
+
+       start = (isp_virt) & ISP_PAGE_MASK;
+       end = start + (pgnr << ISP_PAGE_OFFSET);
+
+       mmu_l1_unmap(mmu, l1_pt, start, end);
+}
+
+int isp_mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
+               unsigned int phys, unsigned int pgnr)
+{
+       return mmu_map(mmu, isp_virt, phys, pgnr);
+}
+
+void isp_mmu_unmap(struct isp_mmu *mmu, unsigned int isp_virt,
+                  unsigned int pgnr)
+{
+       mmu_unmap(mmu, isp_virt, pgnr);
+}
+
+static void isp_mmu_flush_tlb_range_default(struct isp_mmu *mmu,
+                                             unsigned int start,
+                                             unsigned int size)
+{
+       isp_mmu_flush_tlb(mmu);
+}
+
+/*MMU init for internal structure*/
+int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_driver *driver)
+{
+       if (!mmu)               /* error */
+               return -EINVAL;
+       if (!driver)            /* error */
+               return -EINVAL;
+
+       if (!driver->name)
+               v4l2_warn(&atomisp_dev,
+                           "NULL name for MMU driver...\n");
+
+       mmu->driver = driver;
+
+       if (!driver->set_pd_base || !driver->tlb_flush_all) {
+               v4l2_err(&atomisp_dev,
+                           "set_pd_base or tlb_flush_all operation "
+                            "not provided.\n");
+               return -EINVAL;
+       }
+
+       if (!driver->tlb_flush_range)
+               driver->tlb_flush_range = isp_mmu_flush_tlb_range_default;
+
+       if (!driver->pte_valid_mask)
+               driver->pte_valid_mask = 0x1;
+
+       mmu->l1_pte = NULL_PTE;
+
+       mutex_init(&mmu->pt_mutex);
+
+       isp_mmu_flush_tlb(mmu);
+
+       return 0;
+}
+
+/*Free L1 and L2 page table*/
+void isp_mmu_exit(struct isp_mmu *mmu)
+{
+       unsigned int idx;
+       unsigned int pte;
+       unsigned int l1_pt, l2_pt;
+
+       if (!mmu)
+               return;
+
+       if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
+               v4l2_warn(&atomisp_dev,
+                           "invalid L1PT: pte = 0x%x\n",
+                           (unsigned int)mmu->l1_pte);
+               return;
+       }
+
+       l1_pt = isp_pte_to_pgaddr(mmu->l1_pte);
+
+       for (idx = 0; idx < ISP_L1PT_PTES; idx++) {
+               pte = atomisp_get_pte(l1_pt, idx);
+
+               if (ISP_PTE_VALID(mmu, pte)) {
+                       l2_pt = isp_pte_to_pgaddr(pte);
+
+                       free_page_table(l2_pt);
+               }
+       }
+
+       free_page_table(l1_pt);
+}