Browse Source

Linux_SDK_V0.9.5

thead_admin 1 year ago
commit
dec6356988
79 changed files with 51059 additions and 0 deletions
  1. 21 0
      .gitignore
  2. 147 0
      Makefile
  3. 10 0
      README.md
  4. 62 0
      common/log_common.c
  5. 22 0
      common/log_common.h
  6. 22 0
      doc/devicetree/bm_csi.txt
  7. 22 0
      doc/devicetree/bm_visys.txt
  8. 46 0
      driver/common/bm_printk.h
  9. 46 0
      driver/csi/Makefile
  10. 19 0
      driver/csi/bm_csi_dphy.h
  11. 509 0
      driver/csi/bm_csi_driver.c
  12. 356 0
      driver/csi/bm_csi_hw.c
  13. 85 0
      driver/csi/bm_csi_hw.h
  14. 49 0
      driver/csi/bm_csi_ioctl.h
  15. 31 0
      driver/csi/dw-csi-data.h
  16. 431 0
      driver/csi/dw-csi-plat.c
  17. 150 0
      driver/csi/dw-csi-plat.h
  18. 1176 0
      driver/csi/dw-csi-sysfs.c
  19. 36 0
      driver/csi/dw-dphy-data.h
  20. 149 0
      driver/csi/dw-dphy-plat.c
  21. 966 0
      driver/csi/dw-dphy-rx.c
  22. 224 0
      driver/csi/dw-dphy-rx.h
  23. 290 0
      driver/csi/dw-dphy-sysfs.c
  24. 104 0
      driver/csi/dw-mipi-csi-pltfrm.h
  25. 757 0
      driver/csi/dw-mipi-csi.c
  26. 317 0
      driver/csi/dw-mipi-csi.h
  27. 28 0
      driver/demo/Makefile
  28. 163 0
      driver/demo/bm_demo_driver.c
  29. 32 0
      driver/isp/Makefile
  30. 313 0
      driver/isp/bm_isp_driver.c
  31. 24 0
      driver/isp/bm_isp_ioctl.h
  32. 31 0
      driver/visys/Makefile
  33. 334 0
      driver/visys/bm_visys_driver.c
  34. 24 0
      driver/visys/bm_visys_ioctl.h
  35. 30 0
      test/csi/Makefile
  36. 99 0
      test/csi/test_csi.c
  37. 47 0
      test/isp/Makefile
  38. 124 0
      test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_16line.txt
  39. 124 0
      test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_64line.txt
  40. 177 0
      test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_frame.txt
  41. 67 0
      test/isp/isp_bm_scripts/4005_scaling_640x480.512x512.txt
  42. 26 0
      test/isp/isp_bm_scripts/isp_mem_to_mem.txt
  43. 113 0
      test/isp/isp_bm_scripts/isp_v4_mcm.txt
  44. 297 0
      test/isp/isp_run_bm_script.c
  45. 39191 0
      test/isp/resource/RAW8_20100101_005155_1920x1080.raw
  46. BIN
      test/isp/resource/RAW8_20190712_640x480.raw
  47. 30 0
      test/visys/Makefile
  48. 96 0
      test/visys/test_visys.c
  49. 47 0
      tools/reg_analyzer/Makefile
  50. 363 0
      tools/reg_analyzer/ra_common.c
  51. 100 0
      tools/reg_analyzer/ra_common.h
  52. 335 0
      tools/reg_analyzer/ra_light_isp.c
  53. 174 0
      tools/reg_analyzer/ra_light_main.c
  54. 44 0
      tools/reg_analyzer/ra_light_visys.c
  55. 51 0
      tools/reg_analyzer/ra_reg_demo.c
  56. 49 0
      tools/reg_analyzer/vsi_isp8000/isp_afm.c
  57. 48 0
      tools/reg_analyzer/vsi_isp8000/isp_compand.c
  58. 51 0
      tools/reg_analyzer/vsi_isp8000/isp_denoise3d.c
  59. 64 0
      tools/reg_analyzer/vsi_isp8000/isp_denoise3d2.c
  60. 120 0
      tools/reg_analyzer/vsi_isp8000/isp_dmsc.c
  61. 49 0
      tools/reg_analyzer/vsi_isp8000/isp_dpcc.c
  62. 50 0
      tools/reg_analyzer/vsi_isp8000/isp_ee.c
  63. 47 0
      tools/reg_analyzer/vsi_isp8000/isp_exp_bayer.c
  64. 56 0
      tools/reg_analyzer/vsi_isp8000/isp_exposure.c
  65. 61 0
      tools/reg_analyzer/vsi_isp8000/isp_hist256.c
  66. 45 0
      tools/reg_analyzer/vsi_isp8000/isp_jpe.c
  67. 49 0
      tools/reg_analyzer/vsi_isp8000/isp_lsc.c
  68. 75 0
      tools/reg_analyzer/vsi_isp8000/isp_mcm.c
  69. 71 0
      tools/reg_analyzer/vsi_isp8000/isp_pre_filt.c
  70. 238 0
      tools/reg_analyzer/vsi_isp8000/isp_stitching0.c
  71. 47 0
      tools/reg_analyzer/vsi_isp8000/isp_vsm.c
  72. 58 0
      tools/reg_analyzer/vsi_isp8000/m5_cproc.c
  73. 364 0
      tools/reg_analyzer/vsi_isp8000/m5_isp.c
  74. 63 0
      tools/reg_analyzer/vsi_isp8000/m5_isp_dpf.c
  75. 62 0
      tools/reg_analyzer/vsi_isp8000/m5_isp_is.c
  76. 57 0
      tools/reg_analyzer/vsi_isp8000/m5_isp_shutter.c
  77. 126 0
      tools/reg_analyzer/vsi_isp8000/m5_main_control.c
  78. 107 0
      tools/reg_analyzer/vsi_isp8000/m5_main_resize.c
  79. 571 0
      tools/reg_analyzer/vsi_isp8000/m5_mi.c

+ 21 - 0
.gitignore

@@ -0,0 +1,21 @@
+/.auto.deps
+/.config.cmd
+/.config.old
+/..config.tmp
+/.config
+*.tmp
+*.depend
+*.o
+*.a
+*.o.d
+*.o.cmd
+*.a.cmd
+*.ko.cmd
+*.ko
+*.mod
+*.mod.c
+*.mod.cmd
+*.order
+*.orig
+Module.symvers
+output/

+ 147 - 0
Makefile

@@ -0,0 +1,147 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+test = $(shell if [ -f "../.param" ]; then echo "exist"; else echo "noexist"; fi)
+ifeq ("$(test)", "exist")
+  include ../.param
+endif
+
+CONFIG_DRIVER_BUILD_PARAMS=KERNEL=$(LINUX_DIR) CROSS=$(CROSS_COMPILE) ARCH=$(ARCH) BOARD_NAME=$(BOARD_NAME)
+CONFIG_LIB_BUILD_PARAMS=CROSS=$(CROSS_COMPILE) ARCH=$(ARCH) BOARD_NAME=$(BOARD_NAME)
+CONFIG_TEST_BUILD_PARAMS=CROSS=$(CROSS_COMPILE) ARCH=$(ARCH) BOARD_NAME=$(BOARD_NAME)
+
+MODULE_NAME=BAREMETAL
+BUILD_LOG_START="\033[47;30m>>> $(MODULE_NAME) $@ begin\033[0m"
+BUILD_LOG_END  ="\033[47;30m<<< $(MODULE_NAME) $@ end\033[0m"
+
+DIR_TARGET_BASE=bsp/baremetal
+DIR_TARGET_LIB =bsp/baremetal/lib
+DIR_TARGET_KO  =bsp/baremetal/ko
+DIR_TARGET_TEST=bsp/baremetal/test
+DIR_TARGET_TOOLS=bsp/baremetal/tools
+
+#
+# Do a parallel build with multiple jobs, based on the number of CPUs online
+# in this system: 'make -j8' on a 8-CPU system, etc.
+#
+# (To override it, run 'make JOBS=1' and similar.)
+#
+ifeq ($(JOBS),)
+  JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
+  ifeq ($(JOBS),)
+    JOBS := 1
+  endif
+endif
+
+all:    info lib driver test tools install_local_output install_rootfs
+.PHONY: info driver lib test tools install_local_output install_rootfs \
+        clean_driver clean_lib clean_test clean_tools clean_output clean
+
+info:
+	@echo $(BUILD_LOG_START)
+	@echo "  ====== Build Info from repo project ======"
+	@echo "    BUILDROOT_DIR="$(BUILDROOT_DIR)
+	@echo "    CROSS_COMPILE="$(CROSS_COMPILE)
+	@echo "    LINUX_DIR="$(LINUX_DIR)
+	@echo "    ARCH="$(ARCH)
+	@echo "    BOARD_NAME="$(BOARD_NAME)
+	@echo "    KERNEL_ID="$(KERNELVERSION)
+	@echo "    KERNEL_DIR="$(LINUX_DIR)
+	@echo "    INSTALL_DIR_ROOTFS="$(INSTALL_DIR_ROOTFS)
+	@echo "    INSTALL_DIR_SDK="$(INSTALL_DIR_SDK)
+	@echo "    CONFIG_DRIVER_BUILD_PARAMS="$(CONFIG_DRIVER_BUILD_PARAMS)
+	@echo "    CONFIG_LIB_BUILD_PARAMS="$(CONFIG_LIB_BUILD_PARAMS)
+	@echo "    CONFIG_TEST_BUILD_PARAMS="$(CONFIG_TEST_BUILD_PARAMS)
+	@echo $(BUILD_LOG_END)
+
+driver:
+	@echo $(BUILD_LOG_START)
+	make -C driver/demo  $(CONFIG_DRIVER_BUILD_PARAMS)
+	make -C driver/visys $(CONFIG_DRIVER_BUILD_PARAMS) #BUILD_TYPE=DEBUG
+	make -C driver/isp $(CONFIG_DRIVER_BUILD_PARAMS)
+	make -C driver/csi   $(CONFIG_DRIVER_BUILD_PARAMS) BUILD_TYPE=DEBUG
+	@echo $(BUILD_LOG_END)
+
+clean_driver:
+	@echo $(BUILD_LOG_START)
+	make -C driver/demo  $(CONFIG_DRIVER_BUILD_PARAMS) clean
+	make -C driver/visys $(CONFIG_DRIVER_BUILD_PARAMS) clean
+	make -C driver/isp $(CONFIG_DRIVER_BUILD_PARAMS) clean
+	make -C driver/csi   $(CONFIG_DRIVER_BUILD_PARAMS) clean
+	@echo $(BUILD_LOG_END)
+
+lib:
+	@echo $(BUILD_LOG_START)
+	@echo $(BUILD_LOG_END)
+
+clean_lib:
+	@echo $(BUILD_LOG_START)
+	@echo $(BUILD_LOG_END)
+
+test: lib driver
+	@echo $(BUILD_LOG_START)
+	make -C test/visys
+	make -C test/csi
+	make -C test/isp
+	@echo $(BUILD_LOG_END)
+
+clean_test:
+	@echo $(BUILD_LOG_START)
+	make -C test/visys clean
+	make -C test/isp clean
+	@echo $(BUILD_LOG_END)
+
+tools:
+	@echo $(BUILD_LOG_START)
+	make -C tools/reg_analyzer -j $(JOBS)
+	@echo $(BUILD_LOG_END)
+
+clean_tools:
+	@echo $(BUILD_LOG_START)
+	make -C tools/reg_analyzer clean
+	make -C test/csi clean
+	make -C test/isp clean
+	@echo $(BUILD_LOG_END)
+
+install_local_output: driver lib test
+	@echo $(BUILD_LOG_START)
+	# driver files
+	mkdir -p ./output/rootfs/$(DIR_TARGET_KO)
+	cp -f ./driver/demo/*.ko ./output/rootfs/$(DIR_TARGET_KO)
+	cp -f ./driver/visys/*.ko ./output/rootfs/$(DIR_TARGET_KO)
+	cp -f ./driver/csi/*.ko ./output/rootfs/$(DIR_TARGET_KO)
+	cp -f ./driver/isp/*.ko ./output/rootfs/$(DIR_TARGET_KO)
+	# lib files
+	mkdir -p ./output/rootfs/$(DIR_TARGET_LIB)
+	# test files
+	mkdir -p ./output/rootfs/$(DIR_TARGET_TEST)
+	cp -rf ./test/visys/output/* ./output/rootfs/$(DIR_TARGET_TEST)
+	cp -rf ./test/isp/output/* ./output/rootfs/$(DIR_TARGET_TEST)
+	# tools files
+	mkdir -p ./output/rootfs/$(DIR_TARGET_TOOLS)
+	cp -f ./tools/reg_analyzer/output/* ./output/rootfs/$(DIR_TARGET_TOOLS)
+	cp -f ./test/csi/output/* ./output/rootfs/$(DIR_TARGET_TEST)
+	@if [ `command -v tree` != "" ]; then \
+	    tree ./output/rootfs -I 'sdk' | grep -v "\.json"; \
+	    echo "INFO: The files above, has filter out the sdk folder and .json files"; \
+	fi
+	@echo $(BUILD_LOG_END)
+
+install_rootfs: install_local_output
+	@echo $(BUILD_LOG_START)
+#	cp -rf output/rootfs/* $(INSTALL_DIR_ROOTFS)
+	@echo $(BUILD_LOG_END)
+
+clean_output:
+	@echo $(BUILD_LOG_START)
+	rm -rf ./output
+	rm -rf $(INSTALL_DIR_ROOTFS)/$(DIR_TARGET_BASE)
+	@echo $(BUILD_LOG_END)
+
+clean: clean_output clean_driver clean_lib clean_test clean_tools
+

+ 10 - 0
README.md

@@ -0,0 +1,10 @@
+# How to get the code
+- git clone git@gitlab.alibaba-inc.com:thead-linux-private/bare-metal-drivers.git
+
+# How to build
+## Build within repo project
+- XX
+## Build out of repo project
+- YY
+
+# Description of each directories

+ 62 - 0
common/log_common.c

@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "log_common.h"
+
+#define LOG_COLOR_RED_YELLO_BACK "\033[1;31;43m"
+#define LOG_COLOR_RED            "\033[2;31;49m"
+#define LOG_COLOR_YELLOW         "\033[2;33;49m"
+#define LOG_COLOR_GREEN          "\033[2;32;49m"
+#define LOG_COLOR_GRAY           "\033[1;30m"
+#define LOG_COLOR_RESET          "\033[0m"
+
+static char sprint_green_buf[1024]=LOG_COLOR_GREEN;
+int printf_green(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	int color_len = strlen(LOG_COLOR_GREEN);
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_green_buf+color_len, fmt, args);
+	va_end(args);
+
+	memcpy(sprint_green_buf+color_len+n, LOG_COLOR_RESET, strlen(LOG_COLOR_RESET)+1);
+
+	printf("%s", sprint_green_buf);
+	return n;
+}
+
+static char sprint_red_buf[1024]=LOG_COLOR_RED;
+int printf_red(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	int color_len = strlen(LOG_COLOR_RED);
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_red_buf+color_len, fmt, args);
+	va_end(args);
+
+	memcpy(sprint_red_buf+color_len+n, LOG_COLOR_RESET, strlen(LOG_COLOR_RESET));
+
+	printf("%s", sprint_red_buf);
+	return n;
+}
+

+ 22 - 0
common/log_common.h

@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#ifndef __LOG_COMMON_H__
+#define __LOG_COMMON_H__
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+int printf_green(char *fmt, ...);
+int printf_red(char *fmt, ...);
+
+#endif /* __LOG_COMMON_H__ */
+

+ 22 - 0
doc/devicetree/bm_csi.txt

@@ -0,0 +1,22 @@
+Video Input Subsystem Controller Modules device tree bindings
+--------------------------------------------
+Module Description:
+As part of the MPCore complex, Cortex-A5 and Cortex-A9 are provided
+with a Snoop Control Unit. The register range is usually 256 (0x100)
+bytes.
+
+References:
+- Light: see Reference Manual: csi_sysreg_registers_85p.xlsx
+
+- compatible : Should be:
+        "thead,light-bm-csi"
+
+- reg : Specify the base address and the size of the csi register window.
+
+Example:
+
+bm_reset: reset@ffe4100000 {
+	compatible = "thead,light-bm-csi";
+	reg = <0xff 0xe4100000 0x0 0x10000>;
+	status = "okay";
+};

+ 22 - 0
doc/devicetree/bm_visys.txt

@@ -0,0 +1,22 @@
+Video Input Subsystem Controller Modules device tree bindings
+--------------------------------------------
+Module Description:
+As part of the MPCore complex, Cortex-A5 and Cortex-A9 are provided
+with a Snoop Control Unit. The register range is usually 256 (0x100)
+bytes.
+
+References:
+- Light: see Reference Manual: visys_sysreg_registers_85p.xlsx
+
+- compatible : Should be:
+        "thead,light-bm-visys"
+
+- reg : Specify the base address and the size of the visys register window.
+
+Example:
+
+bm_reset: reset@ffe4100000 {
+	compatible = "thead,light-bm-visys";
+	reg = <0xff 0xe4100000 0x0 0x10000>;
+	status = "okay";
+};

+ 46 - 0
driver/common/bm_printk.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+#ifndef __BM_PRINTK__
+#define __BM_PRINTK__
+
+#include <stdarg.h>
+#include <linux/init.h>
+#include <linux/kern_levels.h>
+#include <linux/linkage.h>
+#include <linux/cache.h>
+
+/*
+ * These can be used to print at the various log levels.
+ * All of these will print unconditionally, although note that pr_debug()
+ * and other debug macros are compiled out unless either DEBUG is defined
+ * or CONFIG_DYNAMIC_DEBUG is set.
+ */
+#define bm_emerg(fmt, ...) \
+	printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_alert(fmt, ...) \
+	printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_crit(fmt, ...) \
+	printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_err(fmt, ...) \
+	printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_warning(fmt, ...) \
+	printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_warn pr_warning
+
+#ifdef DEBUG
+#define bm_notice(fmt, ...) \
+	printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define bm_info(fmt, ...) \
+	printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define bm_notice(fmt, ...)
+#define bm_info(fmt, ...)
+#endif
+
+#endif /* __BM_PRINTK__ */

+ 46 - 0
driver/csi/Makefile

@@ -0,0 +1,46 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+TARGET = bm_csi
+
+KBUILD_EXTRA_SYMBOLS += $(shell pwd)/../visys/Module.symvers
+
+export KBUILD_EXTRA_SYMBOLS
+
+obj-m +=$(TARGET).o
+##$(TARGET)-objs += bm_csi_dphy.o
+$(TARGET)-objs += bm_csi_driver.o
+$(TARGET)-objs += bm_csi_hw.o
+$(TARGET)-objs += dw-csi-plat.o
+$(TARGET)-objs += dw-csi-sysfs.o
+$(TARGET)-objs += dw-mipi-csi.o
+$(TARGET)-objs += dw-dphy-plat.o
+$(TARGET)-objs += dw-dphy-rx.o
+$(TARGET)-objs += dw-dphy-sysfs.o
+
+
+EXTRA_CFLAGS += -I$(PWD)/./
+EXTRA_CFLAGS += -I$(PWD)/../common
+
+#DEFS = -DCONFIG_DWC_MIPI_TC_DPHY_GEN3
+
+ifeq ($(BUILD_TYPE),DEBUG)
+	EXTRA_CFLAGS += -DDEBUG
+endif
+
+EXTRA_CFLAGS += $(DEFS)
+
+PWD :=$(shell pwd)
+
+all:
+	make -C $(KERNEL) M=$(PWD) modules
+modules_install:
+	make -C $(KERNEL_SRC) M=$(SRC) modules_install
+clean:
+	rm -rf $($(TARGET)-objs)
+	make -C $(KERNEL) M=`pwd` clean

+ 19 - 0
driver/csi/bm_csi_dphy.h

@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: liuyitong <yitong.lyt@alibaba-inc.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.
+ */
+#ifndef _BM_CSI_DPHY_H_
+#define _BM_CSI_DPHY_H_
+
+#include <linux/platform_device.h>
+
+int dw_dphy_rx_probe(struct platform_device *pdev, unsigned int dphyglueiftester, unsigned int sysreg_mipi_csi_ctrl);
+int dw_dphy_rx_remove(struct platform_device *pdev);
+
+#endif /*_BM_CSI_DPHY_H_ */
+
+

+ 509 - 0
driver/csi/bm_csi_driver.c

@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: liuyitong <yitong.lyt@alibaba-inc.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.
+ */
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/of.h>
+
+#include "bm_printk.h"
+#include "bm_csi_ioctl.h"
+#include "bm_csi_hw.h"
+#include "bm_csi_dphy.h"
+
+#define BM_DRIVER_NAME "bm_csi"
+#define BM_DRIVER_MAXCNT 3
+
+static struct class *bm_driver_class;
+static unsigned int bm_driver_major = 0;
+static unsigned int bm_driver_minor = 0;
+static unsigned int device_register_index = 0;
+
+#define check_retval(x)\
+	do {\
+		if ((x))\
+			return -EIO;\
+	} while (0)
+
+static unsigned int bm_csi_poll(struct file * filp, poll_table *wait)
+{
+	return 0;
+}
+
+void bm_csi_work(struct work_struct *work)
+{
+}
+
+irqreturn_t bm_csi_irq(int irq, void *dev_id)
+{
+	bm_info("enter %s\n", __func__);
+	return IRQ_HANDLED;
+}
+
+static int bm_csi_runtime_suspend(struct device *dev)
+{
+	struct bm_csi_drvdata *pdriver_dev = dev_get_drvdata(dev);
+	dev_info(dev, "enter %s\n", __func__);
+
+    if (pdriver_dev->pclk != NULL) {
+	    clk_disable_unprepare(pdriver_dev->pclk);
+    }
+
+    if (pdriver_dev->pixclk!= NULL) {
+	    clk_disable_unprepare(pdriver_dev->pixclk);
+    }
+
+    if (pdriver_dev->cfg_clk0!= NULL) {
+	    clk_disable_unprepare(pdriver_dev->cfg_clk0);
+    }
+
+    if (pdriver_dev->cfg_clk1!= NULL) {
+	    clk_disable_unprepare(pdriver_dev->cfg_clk1);
+    }
+
+    if (pdriver_dev->cfg_clk2!= NULL) {
+	    clk_disable_unprepare(pdriver_dev->cfg_clk2);
+    }
+
+	pr_info("exit %s\n", __func__);
+	return 0;
+}
+static int bm_csi_runtime_resume(struct device *dev)
+{
+	int ret = 0;
+	struct bm_csi_drvdata *pdriver_dev = dev_get_drvdata(dev);
+	dev_info(dev, "enter %s\n", __func__);
+
+    if (pdriver_dev->pclk != NULL) {
+	    ret = clk_prepare_enable(pdriver_dev->pclk);
+	    if (ret < 0) {
+	    	dev_err(dev, "could not prepare or enable csi pclk\n");
+	    	clk_disable_unprepare(pdriver_dev->pclk);
+            return -1;
+	    }
+    }
+
+    if (pdriver_dev->pixclk!= NULL) {
+	    ret = clk_prepare_enable(pdriver_dev->pixclk);
+	    if (ret < 0) {
+	    	dev_err(dev, "could not prepare or enable  pixclk\n");
+	    	clk_disable_unprepare(pdriver_dev->pixclk);
+            return -1;
+	    }
+    }
+
+    if (pdriver_dev->cfg_clk0 != NULL) {
+	    ret = clk_prepare_enable(pdriver_dev->cfg_clk0);
+	    if (ret < 0) {
+	    	dev_err(dev, "could not prepare or enable cfg_clk0\n");
+	    	clk_disable_unprepare(pdriver_dev->cfg_clk0);
+            return -1;
+	    }
+    }
+
+    if (pdriver_dev->cfg_clk1 != NULL) {
+	    ret = clk_prepare_enable(pdriver_dev->cfg_clk1);
+	    if (ret < 0) {
+	    	dev_err(dev, "could not prepare or enable cfg_clk1\n");
+	    	clk_disable_unprepare(pdriver_dev->cfg_clk1);
+            return -1;
+	    }
+    }
+
+    if (pdriver_dev->cfg_clk2 != NULL) {
+	    ret = clk_prepare_enable(pdriver_dev->cfg_clk2);
+	    if (ret < 0) {
+	    	dev_err(dev, "could not prepare or enable cfg_clk2\n");
+	    	clk_disable_unprepare(pdriver_dev->cfg_clk2);
+            return -1;
+	    }
+    }
+
+	pr_info("%s csi Enabled clock\n", __func__);
+	return 0;
+}
+
+static const struct dev_pm_ops bm_csi_runtime_pm_ops = {
+	SET_RUNTIME_PM_OPS(bm_csi_runtime_suspend, bm_csi_runtime_resume, NULL)
+};
+
+static int bm_csi_open(struct inode * inode, struct file * file)
+{
+    int ret = 0;
+	struct bm_csi_drvdata *drvdata;
+    struct device *dev;
+
+	bm_info("enter %s\n",  __func__);
+	dev_info(dev, "open mipi-csi dev\n");
+
+	drvdata = container_of(inode->i_cdev, struct bm_csi_drvdata, cdev);
+	file->private_data = drvdata;
+    dev = &drvdata->pdev->dev;
+	dev_info(dev, "open mipi-csi dev\n");
+    if (pm_runtime_get_sync(dev)) {
+		ret = bm_csi_runtime_resume(dev);
+		if (ret)
+			pr_err("fail to resume csi %s %d\n", __func__, __LINE__);
+	}
+
+	return 0;
+};
+
+static long bm_csi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret = 0;
+	struct bm_csi_drvdata *drvdata;
+	bm_info("enter %s\n", __func__);
+
+	drvdata = file->private_data;
+	if (drvdata == NULL) {
+		bm_err("%s:file private is null point error\n", __func__);
+		return  -ENOMEM;
+	}
+
+	mutex_lock(&drvdata->mutex);
+	switch (cmd) {
+	case BMCSI_IOC_WRITE_REG:
+		ret = bm_csi_write_reg(drvdata, (void *)arg);
+		break;
+	case BMCSI_IOC_READ_REG:
+		ret = bm_csi_read_reg(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_RESET:
+        ret = bm_csi_reset(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_POWER:
+        ret = bm_csi_set_power(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_G_POWER:
+        ret = bm_csi_get_power(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_CLOCK:
+        ret = bm_csi_set_clock(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_G_CLOCK:
+        ret = bm_csi_get_clock(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_STREAM:
+        ret = bm_csi_set_stream(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_G_STREAM:
+        ret = bm_csi_get_stream(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_FMT:
+        ret = bm_csi_set_fmt(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_G_FMT:
+        ret = bm_csi_get_fmt(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_VC_SELECT:
+        ret = bm_csi_set_vc_select(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_G_VC_SELECT:
+        ret = bm_csi_get_vc_select(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_IPI_START:
+        ret = bm_csi_ipi_enable(drvdata, (void *)arg);
+        break;
+    case BMCSI_IOC_IPI_STOP:
+        ret = bm_csi_ipi_disable(drvdata, (void *)arg);
+        break;
+    case BMCSI_IOC_S_LANE_CFG:
+        ret = bm_csi_set_lane_cfg(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_HSA_CFG:
+        ret = bm_csi_set_hsa(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_HBP_CFG:
+        ret = bm_csi_set_hbp(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_S_HSD_CFG:
+        ret = bm_csi_set_hsd(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_SET_PIXCLK:
+        ret = bm_csi_set_pixclk(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_GET_PIXCLK:
+        ret = bm_csi_get_pixclk(drvdata, (void *)arg);
+		break;
+    case BMCSI_IOC_MAX:
+		break;
+	default:
+		ret = -EPERM;
+		bm_err("%s: unsupported command %d", __func__, cmd);
+		break;
+	}
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+};
+
+static int bm_csi_release(struct inode * inode, struct file * file)
+{
+    int ret = 0;
+    struct bm_csi_drvdata *drvdata;
+    struct device *dev;
+
+	bm_info("enter %s\n", __func__);
+
+	drvdata = container_of(inode->i_cdev, struct bm_csi_drvdata, cdev);
+	file->private_data = drvdata;
+    dev = &drvdata->pdev->dev;
+	dev_info(dev, "release mipi-csi dev\n");
+    ret = bm_csi_dis_power(drvdata);
+    if (ret) {
+		pr_info("fail to disable csi power, %s %d\n", __func__, __LINE__);
+	}
+
+    ret = pm_runtime_put_sync(dev);
+	if (ret) {
+		pr_info("fail to resume csi %s %d\n", __func__, __LINE__);
+	}
+
+	return 0;
+};
+
+static int bm_csi_mmap(struct file *pFile, struct vm_area_struct *vma)
+{
+	bm_info("enter %s\n", __func__);
+	return 0;
+};
+
+struct file_operations bm_csi_fops = {
+	.owner = THIS_MODULE,
+	.open = bm_csi_open,
+	.release = bm_csi_release,
+	.unlocked_ioctl = bm_csi_ioctl,
+	.mmap = bm_csi_mmap,
+	.poll = bm_csi_poll,
+};
+
+static int bm_csi_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct bm_csi_drvdata *drvdata;
+	struct resource *iores_mem;
+    unsigned int dphyglueiftester= 0;
+    unsigned int sysreg_mipi_csi_ctrl = 0;
+	u32 value;
+
+	bm_info("enter %s\n", __func__);
+	pdev->id = device_register_index;
+	if (pdev->id >= BM_DRIVER_MAXCNT) {
+		bm_err("%s:pdev id is %d error\n", __func__, pdev->id);
+		return  -EINVAL;
+	}
+
+	drvdata = devm_kzalloc(&pdev->dev,sizeof(struct bm_csi_drvdata), GFP_KERNEL);
+	if (drvdata == NULL) {
+		bm_err("%s:alloc struct drvdata error\n", __func__);
+		return  -ENOMEM;
+	}
+
+	iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->base = devm_ioremap_resource(&pdev->dev, iores_mem);
+	bm_info("%s: [%s%d]: drvdata->base=0x%px, phy_addr base=0x%llx\n", __func__,
+		BM_DRIVER_NAME, pdev->id, drvdata->base, iores_mem->start);
+
+	drvdata->reset = NULL;
+	drvdata->device_idx = pdev->id;
+	mutex_init(&drvdata->mutex);
+	drvdata->irq_num = platform_get_irq(pdev, 0);
+	bm_info("%s:[%s%d]: pdriver_dev->irq_num=%d\n", __func__, "BM_CSI", pdev->id, drvdata->irq_num);
+
+    drvdata->pdev = pdev;
+
+    /*parse clk info from dts*/
+	drvdata->pclk = devm_clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(drvdata->pclk)) {
+		dev_err(&pdev->dev, "failed to get pclk");
+        drvdata->pclk = NULL;
+	}
+
+	drvdata->pixclk = devm_clk_get(&pdev->dev, "pixclk");
+	if (IS_ERR(drvdata->pixclk)) {
+		dev_err(&pdev->dev, "failed to get pixclk");
+        drvdata->pixclk = NULL;
+	}
+
+	drvdata->cfg_clk0 = devm_clk_get(&pdev->dev, "cfg_clk0");
+	if (IS_ERR(drvdata->cfg_clk0)) {
+		dev_err(&pdev->dev, "failed to get cfg_clk0");
+        drvdata->cfg_clk0 = NULL;
+	}
+
+    drvdata->cfg_clk1 = devm_clk_get(&pdev->dev, "cfg_clk1");
+	if (IS_ERR(drvdata->cfg_clk1)) {
+		dev_err(&pdev->dev, "failed to get cfg_clk1");
+        drvdata->cfg_clk1 = NULL;
+	}
+
+    drvdata->cfg_clk2 = devm_clk_get(&pdev->dev, "cfg_clk2");
+	if (IS_ERR(drvdata->cfg_clk2)) {
+		dev_err(&pdev->dev, "failed to get cfg_clk2");
+        drvdata->cfg_clk2 = NULL;
+	}
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (pdev->id == 0) {
+		if (bm_driver_major == 0) {
+			ret = alloc_chrdev_region(&drvdata->devt, 0, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret != 0) {
+				bm_err("%s:alloc_chrdev_region error\n", __func__);
+				return ret;
+			}
+			bm_driver_major = MAJOR(drvdata->devt);
+			bm_driver_minor = MINOR(drvdata->devt);
+		} else {
+			drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor);
+			ret = register_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret) {
+				bm_err("%s:register_chrdev_region error\n", __func__);
+				return ret;
+			}
+		}
+
+		bm_driver_class = class_create(THIS_MODULE, BM_DRIVER_NAME);
+		if (IS_ERR(bm_driver_class)) {
+			bm_err("%s[%d]:class_create error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+	}
+
+	drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor + pdev->id);
+	cdev_init(&drvdata->cdev, &bm_csi_fops);
+	ret = cdev_add(&drvdata->cdev, drvdata->devt, 1);
+	if ( ret ) {
+		bm_err("%s[%d]:cdev_add error!\n", __func__, __LINE__);
+		return ret;
+	} else {
+		bm_info("%s[%d]:cdev_add OK, major=%d, minor=%d\n", __func__, __LINE__,
+			bm_driver_major, bm_driver_minor + pdev->id);
+	}
+	drvdata->class = bm_driver_class;
+	device_create(drvdata->class, NULL, drvdata->devt,
+		      drvdata, "%s%d", BM_DRIVER_NAME, pdev->id);
+
+    /*read version*/
+	value = readl(drvdata->base + 0x0);
+	bm_info("offset=04, value is:0x%08x\n", value);
+
+    device_property_read_u32(&pdev->dev, "dphyglueiftester", &dphyglueiftester);
+	bm_info("dphyglueiftester is:0x%x\n", dphyglueiftester);
+    device_property_read_u32(&pdev->dev, "sysreg_mipi_csi_ctrl", &sysreg_mipi_csi_ctrl);
+	bm_info("sysreg_mipi_csi_ctrl is:0x%x\n", sysreg_mipi_csi_ctrl);
+
+    dw_dphy_rx_probe(pdev, dphyglueiftester, sysreg_mipi_csi_ctrl);
+    dw_csi_probe(pdev);
+
+    pm_runtime_enable(&pdev->dev);
+	ret = bm_csi_runtime_resume(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "fail to resume csi\n");
+	}
+
+	ret = bm_csi_runtime_suspend(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "fail to suspend csi\n");
+	}
+
+	device_register_index++;
+	bm_info("exit %s:[%s%d]\n", __func__, BM_DRIVER_NAME, pdev->id);
+
+	return 0;
+}
+
+static int bm_csi_remove(struct platform_device *pdev)
+{
+	struct bm_csi_drvdata *drvdata;
+
+	bm_info("enter %s\n", __func__);
+    dw_dphy_rx_remove(pdev);
+    dw_csi_remove(pdev);
+
+	device_register_index--;
+	drvdata = platform_get_drvdata(pdev);
+	free_irq(drvdata->irq_num, drvdata);
+	cdev_del(&drvdata->cdev);
+	device_destroy(drvdata->class, drvdata->devt);
+	unregister_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT);
+	mutex_destroy(&drvdata->mutex);
+	if (device_register_index == 0) {
+		class_destroy(drvdata->class);
+	}
+	devm_kfree(&pdev->dev, drvdata);
+
+	bm_info("exit %s\n", __func__);
+	return 0;
+}
+
+static const struct of_device_id bm_csi_of_match[] = {
+	{ .compatible = "thead,light-bm-csi", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bm_csi_of_match);
+
+static struct platform_driver bm_csi_driver = {
+	.probe		= bm_csi_probe,
+	.remove		= bm_csi_remove,
+	.driver = {
+		.name  = BM_DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(bm_csi_of_match),
+        .pm = &bm_csi_runtime_pm_ops,
+	}
+};
+
+static int __init bm_csi_init_module(void)
+{
+	int ret = 0;
+
+	bm_info("enter %s\n", __func__);
+	ret = platform_driver_register(&bm_csi_driver);
+	if (ret) {
+		bm_err("register platform driver failed.\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void __exit bm_csi_exit_module(void)
+{
+	bm_info("enter %s\n", __func__);
+	platform_driver_unregister(&bm_csi_driver);
+}
+
+module_init(bm_csi_init_module);
+module_exit(bm_csi_exit_module);
+
+MODULE_AUTHOR("Liu Yitong");
+MODULE_DESCRIPTION("BAREMETAL-CSI");
+MODULE_LICENSE("GPL");

+ 356 - 0
driver/csi/bm_csi_hw.c

@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: liuyitong <yitong.lyt@alibaba-inc.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.
+ */
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <linux/of.h>
+
+#include "bm_printk.h"
+#include "bm_csi_ioctl.h"
+#include "bm_csi_hw.h"
+#include "dw-dphy-rx.h"
+#include "bm_csi_dphy.h"
+
+#define check_retval(x)\
+	do {\
+		if ((x))\
+			return -EIO;\
+	} while (0)
+
+struct csi_format_context {
+    uint32_t format;
+    uint32_t width;
+    uint32_t height;
+};
+
+
+int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	struct bm_csi_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	writel(reg.value, drvdata->base + reg.offset);
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	struct bm_csi_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	reg.value = readl(drvdata->base + reg.offset);
+	check_retval(copy_to_user(args, &reg, sizeof(reg)));
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: csi reset success\n", __func__);
+    dw_csi_soc_reset();
+    dw_mipi_csi_reset(&drvdata->csi_dev);
+    dw_dphy_reset(drvdata->dphy->phy);
+	return 0;
+}
+
+static uint32_t csi_power_on_sta = 0;
+
+int bm_csi_en_power(struct bm_csi_drvdata *drvdata)
+{
+	bm_info("%s: csi set power\n", __func__);
+	csi_power_on_sta = 1;
+    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	return 0;
+}
+
+int bm_csi_dis_power(struct bm_csi_drvdata *drvdata)
+{
+	bm_info("%s: csi set power\n", __func__);
+	csi_power_on_sta = 0;
+    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	return 0;
+}
+
+int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: csi set power\n", __func__);
+	check_retval(copy_from_user(&csi_power_on_sta, args, sizeof(csi_power_on_sta)));
+    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	return 0;
+}
+
+int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: csi get power\n", __func__);
+	check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
+	return 0;
+}
+
+int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_dphy_rx *dphy = drvdata->dphy;
+    bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&dphy->dphy_freq, args, sizeof(dphy->dphy_freq)));
+
+	return 0;
+}
+
+int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_dphy_rx *dphy = drvdata->dphy;
+	bm_info("%s: \n", __func__);
+	check_retval(copy_to_user(args, &dphy->dphy_freq, sizeof(dphy->dphy_freq)));
+	return 0;
+}
+
+int bm_csi_set_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    uint32_t freq_hz = 0;
+    bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&freq_hz, args, sizeof(freq_hz)));
+    return dw_csi_set_pixclk(freq_hz);
+}
+
+int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    uint32_t freq_hz = 0;
+	bm_info("%s: \n", __func__);
+    dw_csi_get_pixclk(&freq_hz);
+	check_retval(copy_to_user(args, &freq_hz, sizeof(freq_hz)));
+    return 0;
+}
+
+int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: \n", __func__);
+	return 0;
+}
+
+int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: \n", __func__);
+	check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
+	return 0;
+}
+
+int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+    u8 dt = 0;
+    //struct csi_format_context fmt;
+	bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&dt, args, sizeof(dt)));
+/*
+    csi_dev->fmt->mbus_code = fmt.format;
+    csi_dev->fmt->width = fmt.width;
+    csi_dev->fmt->height = fmt.height;
+    */
+
+	csi_dev->ipi_dt = dt;
+    dw_mipi_csi_set_ipi_fmt(csi_dev);
+/*
+    if(fmt.height > 0 && fmt.width > 0) {
+        csi_dev->hw.ipi_color_mode = COLOR16;
+        csi_dev->hw.ipi_auto_flush = 1;
+        csi_dev->hw.ipi_adv_features = LINE_EVENT_SELECTION(EVSELAUTO);
+        csi_dev->hw.htotal = fmt.width + csi_dev->hw.hsa + csi_dev->hw.hbp + csi_dev->hw.hsd;
+        csi_dev->hw.vactive = fmt.height;
+        csi_dev->hw.output = 0;
+    }
+    */
+
+	return 0;
+}
+
+int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+    struct csi_format_context fmt;
+	bm_info("%s: \n", __func__);
+    fmt.format = csi_dev->fmt->mbus_code;
+    fmt.height = csi_dev->fmt->height;
+    fmt.width = csi_dev->fmt->width;
+
+	check_retval(copy_to_user(args, &fmt, sizeof(fmt)));
+	return 0;
+}
+
+int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct csi_vc_select_context vc;
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+	bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&vc, args, sizeof(vc)));
+
+    if (vc.ipi_idx == 1) {
+        csi_dev->hw.ipi1_en = true;
+        csi_dev->hw.virtual_ch = vc.vc_ch;
+    } else if (vc.ipi_idx == 2) {
+        csi_dev->hw.ipi2_en = true;
+        csi_dev->hw.ipi2_virtual_ch = vc.vc_ch;
+    } else if (vc.ipi_idx == 3) {
+        csi_dev->hw.ipi3_en = true;
+        csi_dev->hw.ipi3_virtual_ch = vc.vc_ch;
+    }
+
+	return 0;
+}
+
+int bm_csi_ipi_enable(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    int ipi_idx;
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+	bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
+
+    if (ipi_idx == 1) {
+        csi_dev->hw.ipi1_en = true;
+    } else if (ipi_idx == 2) {
+        csi_dev->hw.ipi2_en = true;
+    } else if (ipi_idx == 3) {
+        csi_dev->hw.ipi3_en = true;
+    }
+
+    dw_mipi_csi_start(csi_dev);
+	return 0;
+}
+
+int bm_csi_ipi_disable(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    int ipi_idx;
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+	bm_info("%s: \n", __func__);
+	check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
+
+    if (ipi_idx == 1) {
+        csi_dev->hw.ipi1_en = 0;
+    } else if (ipi_idx == 2) {
+        csi_dev->hw.ipi2_en = 0;
+    } else if (ipi_idx == 3) {
+        csi_dev->hw.ipi3_en = 0;
+    }
+
+    dw_mipi_csi_stop(csi_dev);
+	return 0;
+}
+
+int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct csi_vc_select_context vc;
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+	bm_info("%s: \n", __func__);
+
+    if (vc.ipi_idx == 1) {
+       vc.vc_ch = csi_dev->hw.virtual_ch;
+    } else if (vc.ipi_idx == 2) {
+       vc.vc_ch = csi_dev->hw.ipi2_virtual_ch;
+    } else if (vc.ipi_idx == 3) {
+       vc.vc_ch = csi_dev->hw.ipi3_virtual_ch;
+    }
+
+	check_retval(copy_to_user(args, &vc, sizeof(vc)));
+
+	return 0;
+}
+
+int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+	bm_info("%s: \n", __func__);
+
+	check_retval(copy_from_user(&csi_dev->hw.num_lanes, args, sizeof(csi_dev->hw.num_lanes)));
+
+	return 0;
+}
+
+typedef struct {
+    int ipi_idx;
+    int val;
+} dw_csi_hsx_cfg_t;
+
+int bm_csi_set_hsa(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+    dw_csi_hsx_cfg_t cfg;
+	bm_info("%s: \n", __func__);
+
+	check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
+    if (cfg.ipi_idx == 1) {
+        csi_dev->hw.hsa = cfg.val;
+    } else if(cfg.ipi_idx == 2) {
+        csi_dev->hw.ipi2_hsa = cfg.val;
+    } else if(cfg.ipi_idx == 3) {
+        csi_dev->hw.ipi3_hsa = cfg.val;
+    } else {
+        return -1;
+    }
+
+
+	return 0;
+}
+
+int bm_csi_set_hbp(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+    dw_csi_hsx_cfg_t cfg;
+	bm_info("%s: \n", __func__);
+
+    check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
+    if (cfg.ipi_idx == 1) {
+        csi_dev->hw.hbp = cfg.val;
+    } else if(cfg.ipi_idx == 2) {
+        csi_dev->hw.ipi2_hbp = cfg.val;
+    } else if(cfg.ipi_idx == 3) {
+        csi_dev->hw.ipi3_hbp = cfg.val;
+    } else {
+        return -1;
+    }
+
+	return 0;
+}
+
+int bm_csi_set_hsd(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+    struct dw_csi *csi_dev = &drvdata->csi_dev;
+    dw_csi_hsx_cfg_t cfg;
+	bm_info("%s: \n", __func__);
+
+	check_retval(copy_from_user(&cfg, args, sizeof(cfg)));
+    if (cfg.ipi_idx == 1) {
+        csi_dev->hw.hsd = cfg.val;
+    } else if(cfg.ipi_idx == 2) {
+        csi_dev->hw.ipi2_hsd = cfg.val;
+    } else if(cfg.ipi_idx == 3) {
+        csi_dev->hw.ipi3_hsd = cfg.val;
+    } else {
+        return -1;
+    }
+
+	return 0;
+}

+ 85 - 0
driver/csi/bm_csi_hw.h

@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: liuyitong <yitong.lyt@alibaba-inc.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.
+ */
+#ifndef _BM_CSI_HW_H_
+#define _BM_CSI_HW_H_
+
+#include <linux/cdev.h>
+#include <linux/ioctl.h>
+#include "dw-dphy-rx.h"
+#include "dw-mipi-csi.h"
+#include "dw-csi-data.h"
+#include "dw-dphy-data.h"
+
+struct bm_csi_drvdata {
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct mutex mutex;
+	unsigned int device_idx;
+	void __iomem *base;
+	void __iomem *reset;
+    struct dw_dphy_rx *dphy;
+    struct dw_csi csi_dev;
+	struct dw_csih_pdata csi_pdata;
+    struct dw_phy_pdata dphy_pdata;
+	int irq_num;
+	struct clk *pclk;
+    struct clk *pixclk;
+	struct clk *cfg_clk0;
+	struct clk *cfg_clk1;
+	struct clk *cfg_clk2;
+	struct platform_device *pdev;
+	void *private;	// can be bm_csi_drvdata_private, but not use now
+};
+
+struct bm_csi_drvdata_private {
+	int private_tmp;
+};
+
+int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_init(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_exit(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_en_power(struct bm_csi_drvdata *drvdata);
+int bm_csi_dis_power(struct bm_csi_drvdata *drvdata);
+int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_pixclk(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_ipi_enable(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_ipi_disable(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_hsa(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_hbp(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_set_hsd(struct bm_csi_drvdata *drvdata, void *__user args);
+
+
+/*csi dphy*/
+int bm_csi_dphy_write_reg(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_dphy_init(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_dphy_uinit(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_dphy_reset(struct bm_csi_drvdata *drvdata, void *__user args);
+
+void dw_csi_soc_reset(void);
+int dw_csi_probe(struct platform_device *pdev);
+int dw_csi_remove(struct platform_device *pdev);
+
+int dw_csi_set_pixclk(uint32_t freq_hz);
+int dw_csi_get_pixclk(uint32_t *freq_hz);
+
+#endif /* _BM_CSI_HW_H_*/

+ 49 - 0
driver/csi/bm_csi_ioctl.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: liuyitong <yitong.lyt@alibaba-inc.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.
+ */
+#ifndef _BM_CSI_IOCTL_H_
+#define _BM_CSI_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+enum {
+    BMCSI_IOC_S_RESET = 0x100,
+    BMCSI_IOC_S_POWER,
+    BMCSI_IOC_G_POWER,
+    BMCSI_IOC_S_CLOCK,
+    BMCSI_IOC_G_CLOCK,
+    BMCSI_IOC_S_STREAM,
+    BMCSI_IOC_G_STREAM,
+    BMCSI_IOC_S_FMT,
+    BMCSI_IOC_G_FMT,
+    BMCSI_IOC_S_VC_SELECT,
+    BMCSI_IOC_G_VC_SELECT,
+    BMCSI_IOC_IPI_START,
+    BMCSI_IOC_IPI_STOP,
+    BMCSI_IOC_S_LANE_CFG,
+    BMCSI_IOC_S_HSA_CFG,
+    BMCSI_IOC_S_HBP_CFG,
+    BMCSI_IOC_S_HSD_CFG,
+	BMCSI_IOC_WRITE_REG,
+	BMCSI_IOC_READ_REG,
+	BMCSI_IOC_SET_PIXCLK,
+    BMCSI_IOC_GET_PIXCLK,
+    BMCSI_IOC_MAX,
+};
+
+struct bm_csi_reg_t {
+	unsigned int offset;
+	unsigned int value;
+};
+
+struct csi_vc_select_context {
+    unsigned int ipi_idx;
+    unsigned int vc_ch;
+};
+
+#endif /* _BM_CSI_IOCTL_H_*/

+ 31 - 0
driver/csi/dw-csi-data.h

@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 platform data
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#include <linux/kernel.h>
+#include "dw-mipi-csi-pltfrm.h"
+
+#ifndef __DW_CSI_DATA__
+#define __DW_CSI_DATA__
+
+struct dw_csih_pdata {
+	u8 eotp_enabled;
+	u32 hs_freq;
+	u32 lanes;
+	u32 pclk;
+	u32 fps;
+	u32 bpp;
+	u8 id;
+};
+
+static const struct pdata_names csis[] = {
+	{ .name = "dw-csi.0", },
+	{ .name = "dw-csi.1", },
+};
+
+#endif /*__DW_CSI_DATA__ */

+ 431 - 0
driver/csi/dw-csi-plat.c

@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host controller driver.
+ * Platform driver
+ *
+ * Author: Luis Oliveira <luis.oliveira@synopsys.com>
+ */
+
+#include "dw-csi-data.h"
+#include "dw-dphy-data.h"
+#include "dw-csi-plat.h"
+
+#include "bm_csi_hw.h"
+
+const struct mipi_dt csi_dt[] = {
+	{
+		.hex = CSI_2_YUV420_8,
+		.name = "YUV420_8bits",
+	}, {
+		.hex = CSI_2_YUV420_10,
+		.name = "YUV420_10bits",
+	}, {
+		.hex = CSI_2_YUV420_8_LEG,
+		.name = "YUV420_8bits_LEGACY",
+	}, {
+		.hex = CSI_2_YUV420_8_SHIFT,
+		.name = "YUV420_8bits_SHIFT",
+	}, {
+		.hex = CSI_2_YUV420_10_SHIFT,
+		.name = "YUV420_10bits_SHIFT",
+	}, {
+		.hex = CSI_2_YUV422_8,
+		.name = "YUV442_8bits",
+	}, {
+		.hex = CSI_2_YUV422_10,
+		.name = "YUV442_10bits",
+	}, {
+		.hex = CSI_2_RGB444,
+		.name = "RGB444",
+	}, {
+		.hex = CSI_2_RGB555,
+		.name = "RGB555",
+	}, {
+		.hex = CSI_2_RGB565,
+		.name = "RGB565",
+	}, {
+		.hex = CSI_2_RGB666,
+		.name = "RGB666",
+	}, {
+		.hex = CSI_2_RGB888,
+		.name = "RGB888",
+	}, {
+		.hex = CSI_2_RAW6,
+		.name = "RAW6",
+	}, {
+		.hex = CSI_2_RAW7,
+		.name = "RAW7",
+	}, {
+		.hex = CSI_2_RAW8,
+		.name = "RAW8",
+	}, {
+		.hex = CSI_2_RAW10,
+		.name = "RAW10",
+	}, {
+		.hex = CSI_2_RAW12,
+		.name = "RAW12",
+	}, {
+		.hex = CSI_2_RAW14,
+		.name = "RAW14",
+	}, {
+		.hex = CSI_2_RAW16,
+		.name = "RAW16",
+	},
+};
+
+static struct mipi_fmt *
+find_dw_mipi_csi_format(uint32_t mbus_code)
+{
+	unsigned int i;
+
+	pr_info("%s entered mbus: 0x%x\n", __func__, mbus_code);
+
+	for (i = 0; i < ARRAY_SIZE(dw_mipi_csi_formats); i++)
+		if (mbus_code == dw_mipi_csi_formats[i].mbus_code) {
+			pr_info("Found mbus 0x%x\n", dw_mipi_csi_formats[i].mbus_code);
+			return &dw_mipi_csi_formats[i];
+		}
+	return NULL;
+}
+
+int dw_mipi_csi_enum_mbus_code(int index, uint32_t *code)
+{
+	if (index != 0)
+		return -EINVAL;
+
+	*code = dw_mipi_csi_formats[index].mbus_code;
+	return 0;
+}
+
+static struct mipi_fmt *
+dw_mipi_csi_try_format(uint32_t mbus_code)
+{
+	struct mipi_fmt *fmt;
+
+	fmt = find_dw_mipi_csi_format(mbus_code);
+	if (!fmt)
+		fmt = &dw_mipi_csi_formats[0];
+
+	return fmt;
+}
+
+struct mipi_fmt *
+dw_mipi_csi_get_format(struct dw_csi *dev)
+{
+	dev_info(dev->dev,
+		"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
+		dev->fmt->mbus_code);
+	dev_info(dev->dev,
+		"%s got width. 0x%x\n", __func__,
+		dev->fmt->width);
+	dev_info(dev->dev,
+		"%s got height. 0x%x\n", __func__,
+		dev->fmt->height);
+    return dev->fmt;
+}
+
+int
+dw_mipi_csi_set_fmt(struct platform_device *pdev,
+		    uint32_t mbus_code, uint32_t width, uint32_t height)
+{
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+    struct dw_csi *dev = &drvdata->csi_dev;
+
+	struct mipi_fmt *dev_fmt = NULL;
+	int i;
+	dev_info(dev->dev,
+		"%s got mbus_pixelcode. 0x%x\n", __func__,
+		mbus_code);
+
+	dev_fmt = dw_mipi_csi_try_format(mbus_code);
+
+	dev_info(dev->dev,
+		"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
+		dev_fmt->mbus_code);
+	if (!dev_fmt)
+		return -EINVAL;
+
+	if (dev_fmt) {
+		dev->fmt->mbus_code =  dev_fmt->mbus_code;
+        dev->fmt->width = width;
+        dev->fmt->height = height;
+		dw_mipi_csi_set_ipi_fmt(dev);
+	}
+	dev_info(dev->dev, "Width: %d, Height: %d of Demo\n", width, height);
+	if (width > 0 && height > 0) {
+        dw_mipi_csi_fill_timings(dev, width, height);
+/*
+		demo_writel(dev,
+			    DEMO_ACTIVE_WIDTH, fmt->format.width);
+		demo_writel(dev,
+			    DEMO_ACTIVE_HEIGHT, fmt->format.height);
+*/
+		dev_vdbg(dev->dev,
+			 "(core/demosaic) : width=%d/%d, height=%d/%d\n",
+			 dev->hw.htotal - (dev->hw.hbp
+					   + dev->hw.hsd
+					   + dev->hw.hsa),
+			 width,
+			 dev->hw.vactive,
+			 height);
+		dev_info(dev->dev,
+			 "(core/demosaic) : width=%d/%d, height=%d/%d\n",
+			 dev->hw.htotal - (dev->hw.hbp
+					   + dev->hw.hsd
+					   + dev->hw.hsa),
+			 width,
+			 dev->hw.vactive,
+			 height);
+
+	} else {
+		dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
+		       __func__, width);
+		dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
+		       __func__, height);
+		dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
+		       __func__, width);
+		dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
+		       __func__, height);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(csi_dt); i++)
+		if (csi_dt[i].hex == dev->ipi_dt) {
+			dev_vdbg(dev->dev, "Using data type %s\n",
+				 csi_dt[i].name);
+			dev_info(dev->dev, "Using data type %s\n",
+				 csi_dt[i].name);
+		}
+	return 0;
+}
+
+int
+dw_mipi_csi_get_fmt(struct platform_device *pdev,
+                    struct mipi_fmt *fmt)
+{
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+    struct dw_csi *dev = &drvdata->csi_dev;
+
+    struct mipi_fmt *mf = dw_mipi_csi_get_format(dev);
+	if (!mf)
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+	*fmt = *mf;
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int dw_mipi_csi_s_power(struct dw_csi *dev, int on)
+{
+	dev_info(dev->dev, "%s: on=%d\n", __func__, on);
+
+	if (on) {
+        dw_dphy_power_on(dev->phy);
+		dw_mipi_csi_hw_stdby(dev);
+		dw_mipi_csi_start(dev);
+	} else {
+		phy_power_off(dev->phy);
+		dw_mipi_csi_mask_irq_power_off(dev);
+		/* reset data type */
+		dev->ipi_dt = 0x0;
+	}
+	return 0;
+}
+
+int dw_mipi_csi_log_status(struct dw_csi *dev)
+{
+	dw_mipi_csi_dump(dev);
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_VIDEO_ADV_DEBUG)
+int
+dw_mipi_csi_g_register(struct v4l2_subdev *sd, uint32_t reg)
+{
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+    struct dw_csi *dev = &drvdata->csi_dev;
+
+	dev_vdbg(dev->dev, "%s: reg=%llu\n", __func__, reg);
+	reg->val = dw_mipi_csi_read(dev, reg);
+
+	return 0;
+}
+#endif
+
+#if  0
+static int dw_mipi_csi_init_cfg(struct v4l2_subdev *sd,
+				struct v4l2_subdev_pad_config *cfg)
+{
+	struct v4l2_mbus_framefmt *format =
+	    v4l2_subdev_get_try_format(sd, cfg, 0);
+
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+	format->code = MEDIA_BUS_FMT_RGB888_1X24;
+	format->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+#endif
+
+static irqreturn_t dw_mipi_csi_irq1(int irq, void *dev_id)
+{
+	struct dw_csi *csi_dev = dev_id;
+
+	dw_mipi_csi_irq_handler(csi_dev);
+
+	return IRQ_HANDLED;
+}
+
+extern int k_bm_visys_write_reg(uint32_t offset, uint32_t value);
+extern int k_bm_visys_read_reg(uint32_t offset, uint32_t *value);
+
+void dw_csi_soc_reset(void)
+{
+#define VISYS_SW_RST 0x100
+    uint32_t  reg_val = 0;
+    k_bm_visys_read_reg(VISYS_SW_RST, &reg_val);
+    reg_val &= ~(1 << 16);
+    k_bm_visys_write_reg(VISYS_SW_RST, reg_val);
+    reg_val |= 1 << 16;
+    k_bm_visys_write_reg(VISYS_SW_RST, reg_val);
+}
+
+#define MIPI_CSI_PIXELCLK 0x30
+#define MIPI_CSI_PIXELSRC_CLK 2376000000 //hz
+
+int dw_csi_set_pixclk(uint32_t freq_hz)
+{
+    uint32_t reg_val = 0;
+    uint32_t div = (MIPI_CSI_PIXELSRC_CLK + (MIPI_CSI_PIXELSRC_CLK % freq_hz)) / freq_hz;
+
+    if (freq_hz > MIPI_CSI_PIXELSRC_CLK || div > 0xf) {
+        return  -1;
+    }
+
+    k_bm_visys_read_reg(MIPI_CSI_PIXELCLK, &reg_val);
+    reg_val &= ~0xf;
+    reg_val |= div;
+    k_bm_visys_write_reg(MIPI_CSI_PIXELCLK, reg_val);
+
+    return 0;
+}
+
+int dw_csi_get_pixclk(uint32_t *freq_hz)
+{
+    uint32_t reg_val = 0;
+    uint32_t div = 0;
+    k_bm_visys_read_reg(MIPI_CSI_PIXELCLK, &reg_val);
+    div = reg_val & 0xf;
+    *freq_hz = MIPI_CSI_PIXELSRC_CLK / div;
+    return 0;
+}
+
+static const struct of_device_id dw_mipi_csi_of_match[];
+
+int dw_csi_probe(struct platform_device *pdev)
+{
+
+	struct device *dev = &pdev->dev;
+	struct dw_csi *csi;
+    struct dw_dphy_rx *dphy;
+    struct dw_csih_pdata *pdata;
+    struct bm_csi_drvdata *drvdata;
+	int ret;
+
+    if (!IS_ENABLED(CONFIG_OF))
+
+	dev_vdbg(dev, "Probing started\n");
+
+	/* Resource allocation */
+    drvdata  = platform_get_drvdata(pdev);
+
+    csi = &drvdata->csi_dev;
+    dphy = drvdata->dphy;
+    pdata = &drvdata->csi_pdata;
+
+	mutex_init(&csi->lock);
+	spin_lock_init(&csi->slock);
+	csi->dev = dev;
+
+    /*set csi phy*/
+    csi->phy = dphy->phy;
+	csi->base_address = drvdata->base;
+	if (IS_ERR(csi->base_address)) {
+		dev_err(dev, "base address not set.\n");
+		return PTR_ERR(csi->base_address);
+	}
+
+	csi->ctrl_irq_number = drvdata->irq_num;
+	if (csi->ctrl_irq_number < 0) {
+		dev_err(dev, "irq number %d not set.\n", csi->ctrl_irq_number);
+		ret = csi->ctrl_irq_number;
+		goto end;
+	}
+
+	ret = devm_request_irq(dev, csi->ctrl_irq_number,
+			       dw_mipi_csi_irq1, IRQF_SHARED,
+			       dev_name(dev), csi);
+	if (ret) {
+		dev_err(dev, "irq csi %d failed\n", pdata->id);
+		goto end;
+	}
+
+	csi->fmt = &dw_mipi_csi_formats[0];
+	csi->fmt->mbus_code = dw_mipi_csi_formats[0].mbus_code;
+/*
+ to do pad init
+*/
+    csi->hw.num_lanes = pdata->lanes;
+	csi->hw.pclk = pdata->pclk;
+	csi->hw.fps = pdata->fps;
+	csi->hw.dphy_freq = pdata->hs_freq;
+	csi->hw.ipi_mode = CAMERA_TIMING;
+    csi->hw.ipi_color_mode = COLOR16;
+
+    //csi soc reset
+    dw_csi_soc_reset();
+	dw_csi_create_capabilities_sysfs(pdev);
+	dw_mipi_csi_get_version(csi);
+	dw_mipi_csi_specific_mappings(csi);
+	dw_mipi_csi_mask_irq_power_off(csi);
+
+	dev_info(dev, "DW MIPI CSI-2 Host registered successfully HW v%u.%u\n",
+		 csi->hw_version_major, csi->hw_version_minor);
+
+	ret = phy_reset(csi->phy);
+    if (ret) {
+		dev_err(&csi->phy->dev, "phy init failed --> %d\n", ret);
+		goto end;
+	}
+	ret = phy_init(csi->phy);
+	if (ret) {
+		dev_err(&csi->phy->dev, "phy init failed --> %d\n", ret);
+		goto end;
+	}
+
+	return 0;
+end:
+	return ret;
+}
+
+int dw_csi_remove(struct platform_device *pdev)
+{
+    struct bm_csi_drvdata *drvdata;
+    drvdata  = platform_get_drvdata(pdev);
+    dw_csi_remove_capabilities_sysfs(pdev);
+	//struct dw_csi *mipi_csi = &drvdata->csi_dev;
+    //csi soc reset
+    dw_csi_soc_reset();
+    dev_info(&pdev->dev, "DW MIPI CSI-2 Host module removed\n");
+
+	return 0;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Luis Oliveira <luis.oliveira@synopsys.com>");
+MODULE_DESCRIPTION("Synopsys DesignWare MIPI CSI-2 Host Platform driver");

+ 150 - 0
driver/csi/dw-csi-plat.h

@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 Synopsys, Inc.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host controller driver.
+ * Supported bus formats
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#ifndef _DW_CSI_PLAT_H__
+#define _DW_CSI_PLAT_H__
+
+#include "dw-mipi-csi.h"
+
+/** Color Space Converter Block **/
+#define CSC_UNIT_NR 1
+#define CSC_COREID 0x0000
+#define CSC_CFG 0x0004
+#define CSC_COEF_A(x) (0x0008 + ((x) * 4))
+#define CSC_COEF_B(x) (0x0018 + ((x) * 4))
+#define CSC_COEF_C(x) (0x0028 + ((x) * 4))
+#define CSC_LIMIT_DN 0x0038
+#define CSC_LIMIT_UP 0x003C
+#define CSC_VID_CFG 0x0040
+
+/** Demosaic Block **/
+#define DEMO_CONTROL 0x0
+#define DEMO_GLOBAL_INT_EN 0x4
+#define DEMO_IP_INT_EN_REG 0x8
+#define DEMO_IP_INT_SATUS_REG 0xC
+#define DEMO_ACTIVE_WIDTH 0x10
+#define DEMO_ACTIVE_HEIGHT 0x18
+#define DEMO_BAYER_PHASE 0x28//0x20
+
+#define BAYER_RGGB 0x0
+#define BAYER_GRBG 0x1
+#define BAYER_GBRG 0x2
+#define BAYER_BGGR 0x3
+
+/* Video formats supported by the MIPI CSI-2 */
+static struct mipi_fmt dw_mipi_csi_formats[] = {
+	{
+		/* RAW 8 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.depth = 8,
+	}, 
+#if 0
+	{
+		/* RAW 6 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,/*modify by shenwuyi*/
+		.depth = 8,
+	}, {
+		/* RAW 7 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,/*modify by shenwuyi*/
+		.depth = 8,
+	},
+#endif
+	{
+		/* RAW 10 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.depth = 10,
+	}, {
+		/* RAW 8 */
+		.mbus_code = 0x3001,
+		.depth = 8,
+	}, {
+		/* RAW 12 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.depth = 12,
+	}, {
+		/* RAW 14 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14,
+		.depth = 14,
+	}, {
+		/* RAW 16 */
+		.mbus_code = MEDIA_BUS_FMT_SBGGR16_1X16,
+		.depth = 16,
+	}, {
+		/* RGB 666 */
+		.mbus_code = MEDIA_BUS_FMT_RGB666_1X18,
+		.depth = 18,
+	}, {
+		/* RGB 565 */
+		.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.depth = 16,
+	}, {
+		/* BGR 565 */
+		.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.depth = 16,
+	}, {
+		/* RGB 555 */
+		.mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+		.depth = 16,
+	}, {
+		/* BGR 555 */
+		.mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+		.depth = 16,
+	}, {
+		/* RGB 444 */
+		.mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE,
+		.depth = 16,
+	}, {
+		/* RGB 444 */
+		.mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+		.depth = 16,
+	}, {
+		/* RGB 888 */
+		.mbus_code = MEDIA_BUS_FMT_RGB888_2X12_LE,
+		.depth = 24,
+	}, {
+		/* BGR 888 */
+		.mbus_code = MEDIA_BUS_FMT_RGB888_2X12_BE,
+		.depth = 24,
+	}, {
+		/* BGR 888 */
+		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
+		.depth = 24,
+	}, {
+		/* YUV 422 8-bit */
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.depth = 16,
+	}, {
+		/* YUV 422 10-bit */
+		.mbus_code = MEDIA_BUS_FMT_UYVY10_1X20,
+		.depth = 24,
+	}, {
+		/* YUV 420 8-bit LEGACY */
+		.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
+		.depth = 8,
+	}, {
+		/* YUV 420 8-bit LEGACY */
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.depth = 24,
+	}, {
+		/* YUV 420 10-bit */
+		.mbus_code = MEDIA_BUS_FMT_VUY8_1X24,
+		.depth = 24,
+	}, {
+		/* YUV 420 8-bit */
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.depth = 24,
+	}, {
+		/* YUV 420 10-bit */
+		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
+		.depth = 10,
+	},
+};
+
+#endif /* _DW_CSI_PLAT_H__ */

+ 1176 - 0
driver/csi/dw-csi-sysfs.c

@@ -0,0 +1,1176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host controller driver.
+ * SysFS components for the platform driver
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#include "dw-mipi-csi.h"
+#include "bm_csi_hw.h"
+
+static ssize_t core_version_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "v.%d.%d*\n", csi_dev->hw_version_major,
+		 csi_dev->hw_version_minor);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t n_lanes_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long lanes;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &lanes);
+	if (ret < 0)
+		return ret;
+
+	if (lanes > 8) {
+		dev_err(dev, "Invalid number of lanes %lu\n", lanes);
+		return count;
+	}
+
+	dev_info(dev, "Lanes %lu\n", lanes);
+	csi_dev->hw.num_lanes = lanes;
+
+	return count;
+}
+
+static ssize_t n_lanes_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.num_lanes);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t width_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long width;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &width);
+	if (ret < 0)
+		return ret;
+
+	dev_info(dev, "width %lu\n", width);
+	csi_dev->hw.htotal = width;
+
+	return count;
+}
+
+static ssize_t width_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.htotal);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t height_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long height;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &height);
+	if (ret < 0)
+		return ret;
+
+	dev_info(dev, "hight %lu\n", height);
+	csi_dev->hw.vactive = height;
+
+	return count;
+}
+
+static ssize_t height_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.vactive);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+
+static ssize_t core_reset_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	/* Reset Controller and DPHY */
+	phy_reset(csi_dev->phy);
+	dw_mipi_csi_reset(csi_dev);
+
+	snprintf(buffer, 10, "Reset\n");
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t data_type_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	int ret;
+	unsigned long dt;
+
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &dt);
+	if (ret < 0)
+		return ret;
+
+	if (dt < 0x18 || dt > 0x2F) {
+		dev_err(dev, "Invalid data type %lx\n", dt);
+		return count;
+	}
+
+	dev_info(dev, "Data type 0x%lx\n", dt);
+	csi_dev->ipi_dt = dt;
+
+    dw_mipi_csi_set_ipi_fmt(csi_dev);
+
+	return count;
+}
+
+static ssize_t data_type_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->ipi_dt);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+/*******************************************/
+static ssize_t hsa_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsa;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsa);
+	if (ret < 0)
+		return ret;
+
+	if (hsa > 0xFFF) {
+		dev_err(dev, "Invalid HSA time %lx\n", hsa);
+		return count;
+	}
+
+	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	csi_dev->hw.hsa = hsa;
+
+	return count;
+}
+
+static ssize_t hsa_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.hsa);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t hbp_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hbp;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hbp);
+	if (ret < 0)
+		return ret;
+
+	if (hbp > 0xFFF) {
+		dev_err(dev, "Invalid HBP time %lx\n", hbp);
+		return count;
+	}
+
+	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	csi_dev->hw.hbp = hbp;
+
+	return count;
+}
+
+static ssize_t hbp_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.hbp);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t hsd_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsd;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsd);
+	if (ret < 0)
+		return ret;
+
+	if (hsd > 0xFFF) {
+		dev_err(dev, "Invalid HSD time %lx\n", hsd);
+		return count;
+	}
+
+	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	csi_dev->hw.hsd = hsd;
+
+	return count;
+}
+
+static ssize_t hsd_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.hsd);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi2_hsa_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsa;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsa);
+	if (ret < 0)
+		return ret;
+
+	if (hsa > 0xFFF) {
+		dev_err(dev, "Invalid HSA time %lx\n", hsa);
+		return count;
+	}
+
+	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	csi_dev->hw.ipi2_hsa = hsa;
+
+	return count;
+}
+
+static ssize_t ipi2_hsa_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi2_hsa);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi2_hbp_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hbp;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hbp);
+	if (ret < 0)
+		return ret;
+
+	if (hbp > 0xFFF) {
+		dev_err(dev, "Invalid HBP time %lx\n", hbp);
+		return count;
+	}
+
+	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	csi_dev->hw.ipi2_hbp = hbp;
+
+	return count;
+}
+
+static ssize_t ipi2_hbp_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi2_hbp);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi2_hsd_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsd;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsd);
+	if (ret < 0)
+		return ret;
+
+	if (hsd > 0xFFF) {
+		dev_err(dev, "Invalid HSD time %lx\n", hsd);
+		return count;
+	}
+
+	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	csi_dev->hw.ipi2_hsd = hsd;
+
+	return count;
+}
+
+static ssize_t ipi2_hsd_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi2_hsd);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi3_hsa_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsa;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsa);
+	if (ret < 0)
+		return ret;
+
+	if (hsa > 0xFFF) {
+		dev_err(dev, "Invalid HSA time %lx\n", hsa);
+		return count;
+	}
+
+	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	csi_dev->hw.ipi3_hsa = hsa;
+
+	return count;
+}
+
+static ssize_t ipi3_hsa_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi3_hsa);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi3_hbp_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hbp;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hbp);
+	if (ret < 0)
+		return ret;
+
+	if (hbp > 0xFFF) {
+		dev_err(dev, "Invalid HBP time %lx\n", hbp);
+		return count;
+	}
+
+	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	csi_dev->hw.ipi3_hbp = hbp;
+
+	return count;
+}
+
+static ssize_t ipi3_hbp_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi3_hbp);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi3_hsd_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long hsd;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &hsd);
+	if (ret < 0)
+		return ret;
+
+	if (hsd > 0xFFF) {
+		dev_err(dev, "Invalid HSD time %lx\n", hsd);
+		return count;
+	}
+
+	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	csi_dev->hw.ipi3_hsd = hsd;
+
+	return count;
+}
+
+static ssize_t ipi3_hsd_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.ipi3_hsd);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t vsa_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long vsa;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &vsa);
+	if (ret < 0)
+		return ret;
+
+	if (vsa > 0x3FF) {
+		dev_err(dev, "Invalid VSA period %lx\n", vsa);
+		return count;
+	}
+
+	dev_info(dev, "VSA period 0x%lx\n", vsa);
+	csi_dev->hw.vsa = vsa;
+
+	return count;
+}
+
+static ssize_t vsa_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.vsa);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t vbp_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long vbp;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &vbp);
+	if (ret < 0)
+		return ret;
+
+	if (vbp > 0x2FF) {
+		dev_err(dev, "Invalid VBP period %lx\n", vbp);
+		return count;
+	}
+
+	dev_info(dev, "VBP period 0x%lx\n", vbp);
+	csi_dev->hw.vbp = vbp;
+
+	return count;
+}
+
+static ssize_t vbp_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.vbp);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t vfp_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long vfp;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &vfp);
+	if (ret < 0)
+		return ret;
+
+	if (vfp > 0x3ff) {
+		dev_err(dev, "Invalid VFP period %lx\n", vfp);
+		return count;
+	}
+
+	dev_info(dev, "VFP period 0x%lx\n", vfp);
+	csi_dev->hw.vfp = vfp;
+
+	return count;
+}
+
+static ssize_t vfp_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%x\n", csi_dev->hw.vfp);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi_enable_mask_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long enable_mask;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 16, &enable_mask);
+	if (ret < 0)
+		return ret;
+
+	dev_info(dev, "enable_mask 0x%lx\n", enable_mask);
+
+    if (enable_mask & 1) {
+	    csi_dev->hw.ipi1_en = true;
+    } else {
+	    csi_dev->hw.ipi1_en = false;
+    }
+
+    if (enable_mask & 2) {
+	    csi_dev->hw.ipi2_en = true;
+    } else {
+	    csi_dev->hw.ipi2_en = false;
+    }
+
+    if (enable_mask & 4) {
+	    csi_dev->hw.ipi3_en = true;
+    } else {
+	    csi_dev->hw.ipi3_en = false;
+    }
+
+    dw_mipi_csi_start(csi_dev);
+    printk("enable mask is %lx\n", enable_mask);
+	return count;
+}
+
+static ssize_t ipi_enable_mask_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	unsigned long enable_mask = 0;
+
+
+    if (csi_dev->hw.ipi1_en == true) {
+	    enable_mask |= 1;
+    }
+
+    if (csi_dev->hw.ipi2_en == true) {
+	    enable_mask |= 2;
+    }
+
+    if (csi_dev->hw.ipi3_en == true) {
+	    enable_mask |= 4;
+    }
+
+	snprintf(buffer, 10, "%lx\n", enable_mask);
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t virtual_channel_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long virtual_ch;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &virtual_ch);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)virtual_ch < 0 || (signed int)virtual_ch > 8) {
+		dev_err(dev, "Invalid Virtual Channel %lu\n", virtual_ch);
+		return count;
+	}
+
+	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	csi_dev->hw.virtual_ch = virtual_ch;
+
+	return count;
+}
+
+static ssize_t virtual_channel_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.virtual_ch);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi2_virtual_channel_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long virtual_ch;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &virtual_ch);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)virtual_ch < 0 || (signed int)virtual_ch > 8) {
+		dev_err(dev, "Invalid Virtual Channel %lu\n", virtual_ch);
+		return count;
+	}
+
+	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	csi_dev->hw.ipi2_virtual_ch = virtual_ch;
+
+	return count;
+}
+
+static ssize_t ipi2_virtual_channel_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi2_virtual_ch);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi3_virtual_channel_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long virtual_ch;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &virtual_ch);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)virtual_ch < 0 || (signed int)virtual_ch > 8) {
+		dev_err(dev, "Invalid Virtual Channel %lu\n", virtual_ch);
+		return count;
+	}
+
+	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	csi_dev->hw.ipi3_virtual_ch = virtual_ch;
+
+	return count;
+}
+
+static ssize_t ipi3_virtual_channel_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi3_virtual_ch);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi_color_mode_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	int ret;
+	unsigned long ipi_color_mode;
+
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &ipi_color_mode);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)ipi_color_mode < 0 || (signed int)ipi_color_mode > 1) {
+		dev_err(dev,
+			"Wrong Color Mode %lu, (48 bits -> 0 or 16 bits -> 1\n",
+			ipi_color_mode);
+		return count;
+	}
+
+	dev_info(dev, "IPI Color mode %lu\n", ipi_color_mode);
+	csi_dev->hw.ipi_color_mode = ipi_color_mode;
+
+	return count;
+}
+
+static ssize_t ipi_color_mode_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_color_mode);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi_auto_flush_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	int ret;
+	unsigned long ipi_auto_flush;
+
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &ipi_auto_flush);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)ipi_auto_flush < 0 || (signed int)ipi_auto_flush > 1) {
+		dev_err(dev,
+			"Invalid Auto Flush Mode %lu, (No -> 0 or Yes -> 1\n",
+			ipi_auto_flush);
+		return count;
+	}
+
+	dev_info(dev, "IPI Auto Flush %lu\n", ipi_auto_flush);
+	csi_dev->hw.ipi_auto_flush = ipi_auto_flush;
+
+	return count;
+}
+
+static ssize_t ipi_auto_flush_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_auto_flush);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t ipi_timings_mode_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	int ret;
+	unsigned long ipi_mode;
+
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &ipi_mode);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)ipi_mode < 0 || (signed int)ipi_mode > 1) {
+		dev_err(dev,
+			"Invalid Timing Source %lu (Camera:0|Controller:1)\n",
+			ipi_mode);
+		return count;
+	}
+
+	dev_info(dev, "IPI Color mode %lu\n", ipi_mode);
+	csi_dev->hw.ipi_mode = ipi_mode;
+
+	return count;
+}
+
+static ssize_t ipi_timings_mode_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_mode);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t output_type_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long output;
+
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &output);
+	if (ret < 0)
+		return ret;
+
+	if ((signed int)output < 0 || (signed int)output > 1) {
+		dev_err(dev,
+			"Invalid Core output %lu to be used \
+			(IPI-> 0 or IDI->1 or BOTH- 2\n",
+			output);
+		return count;
+	}
+
+	dev_info(dev, "IPI Color mode %lu\n", output);
+	csi_dev->hw.output = output;
+
+	return count;
+}
+
+static ssize_t output_type_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	char buffer[10];
+
+	snprintf(buffer, 10, "%d\n", csi_dev->hw.output);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t csi_power_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+
+	int ret;
+	unsigned long on;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+
+	ret = kstrtoul(buf, 10, &on);
+	if (ret < 0)
+		return ret;
+
+    dw_mipi_csi_s_power(csi_dev, on);
+	printk("csi set power: %lu\n", on);
+
+	return count;
+}
+
+static DEVICE_ATTR_RO(core_version);
+static DEVICE_ATTR_RO(core_reset);
+static DEVICE_ATTR_RW(n_lanes);
+static DEVICE_ATTR_RW(width);
+static DEVICE_ATTR_RW(height);
+static DEVICE_ATTR_RW(data_type);
+static DEVICE_ATTR_RW(hsa);
+static DEVICE_ATTR_RW(hbp);
+static DEVICE_ATTR_RW(hsd);
+static DEVICE_ATTR_RW(vsa);
+static DEVICE_ATTR_RW(vbp);
+static DEVICE_ATTR_RW(vfp);
+static DEVICE_ATTR_RW(virtual_channel);
+static DEVICE_ATTR_RW(ipi_color_mode);
+static DEVICE_ATTR_RW(ipi_auto_flush);
+static DEVICE_ATTR_RW(ipi_timings_mode);
+static DEVICE_ATTR_RW(output_type);
+static DEVICE_ATTR_WO(csi_power);
+static DEVICE_ATTR_RW(ipi2_virtual_channel);
+static DEVICE_ATTR_RW(ipi3_virtual_channel);
+static DEVICE_ATTR_RW(ipi_enable_mask);
+static DEVICE_ATTR_RW(ipi2_hsa);
+static DEVICE_ATTR_RW(ipi2_hbp);
+static DEVICE_ATTR_RW(ipi2_hsd);
+static DEVICE_ATTR_RW(ipi3_hsa);
+static DEVICE_ATTR_RW(ipi3_hbp);
+static DEVICE_ATTR_RW(ipi3_hsd);
+
+
+int dw_csi_create_capabilities_sysfs(struct platform_device *pdev)
+{
+	device_create_file(&pdev->dev, &dev_attr_core_version);
+	device_create_file(&pdev->dev, &dev_attr_core_reset);
+	device_create_file(&pdev->dev, &dev_attr_n_lanes);
+	device_create_file(&pdev->dev, &dev_attr_height);
+	device_create_file(&pdev->dev, &dev_attr_width);
+	device_create_file(&pdev->dev, &dev_attr_data_type);
+	device_create_file(&pdev->dev, &dev_attr_hsa);
+	device_create_file(&pdev->dev, &dev_attr_hbp);
+	device_create_file(&pdev->dev, &dev_attr_hsd);
+	device_create_file(&pdev->dev, &dev_attr_vsa);
+	device_create_file(&pdev->dev, &dev_attr_vbp);
+	device_create_file(&pdev->dev, &dev_attr_vfp);
+	device_create_file(&pdev->dev, &dev_attr_virtual_channel);
+	device_create_file(&pdev->dev, &dev_attr_ipi_color_mode);
+	device_create_file(&pdev->dev, &dev_attr_ipi_auto_flush);
+	device_create_file(&pdev->dev, &dev_attr_ipi_timings_mode);
+	device_create_file(&pdev->dev, &dev_attr_output_type);
+	device_create_file(&pdev->dev, &dev_attr_csi_power);
+	device_create_file(&pdev->dev, &dev_attr_ipi2_virtual_channel);
+	device_create_file(&pdev->dev, &dev_attr_ipi3_virtual_channel);
+	device_create_file(&pdev->dev, &dev_attr_ipi_enable_mask);
+	device_create_file(&pdev->dev, &dev_attr_ipi2_hsa);
+	device_create_file(&pdev->dev, &dev_attr_ipi2_hbp);
+	device_create_file(&pdev->dev, &dev_attr_ipi2_hsd);
+	device_create_file(&pdev->dev, &dev_attr_ipi3_hsa);
+	device_create_file(&pdev->dev, &dev_attr_ipi3_hbp);
+	device_create_file(&pdev->dev, &dev_attr_ipi3_hsd);
+
+	return 0;
+}
+
+int dw_csi_remove_capabilities_sysfs(struct platform_device *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_core_version);
+	device_remove_file(&pdev->dev, &dev_attr_core_reset);
+	device_remove_file(&pdev->dev, &dev_attr_n_lanes);
+	device_remove_file(&pdev->dev, &dev_attr_height);
+	device_remove_file(&pdev->dev, &dev_attr_width);
+	device_remove_file(&pdev->dev, &dev_attr_data_type);
+	device_remove_file(&pdev->dev, &dev_attr_hsa);
+	device_remove_file(&pdev->dev, &dev_attr_hbp);
+	device_remove_file(&pdev->dev, &dev_attr_hsd);
+	device_remove_file(&pdev->dev, &dev_attr_vsa);
+	device_remove_file(&pdev->dev, &dev_attr_vbp);
+	device_remove_file(&pdev->dev, &dev_attr_vfp);
+	device_remove_file(&pdev->dev, &dev_attr_virtual_channel);
+	device_remove_file(&pdev->dev, &dev_attr_ipi_color_mode);
+	device_remove_file(&pdev->dev, &dev_attr_ipi_auto_flush);
+	device_remove_file(&pdev->dev, &dev_attr_ipi_timings_mode);
+	device_remove_file(&pdev->dev, &dev_attr_output_type);
+	device_remove_file(&pdev->dev, &dev_attr_csi_power);
+	device_remove_file(&pdev->dev, &dev_attr_ipi2_virtual_channel);
+	device_remove_file(&pdev->dev, &dev_attr_ipi3_virtual_channel);
+	device_remove_file(&pdev->dev, &dev_attr_ipi_enable_mask);
+    device_remove_file(&pdev->dev, &dev_attr_ipi2_hsa);
+	device_remove_file(&pdev->dev, &dev_attr_ipi2_hbp);
+	device_remove_file(&pdev->dev, &dev_attr_ipi2_hsd);
+    device_remove_file(&pdev->dev, &dev_attr_ipi3_hsa);
+	device_remove_file(&pdev->dev, &dev_attr_ipi3_hbp);
+	device_remove_file(&pdev->dev, &dev_attr_ipi3_hsd);
+
+	return 0;
+}

+ 36 - 0
driver/csi/dw-dphy-data.h

@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI D-PHY platform data
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#include <linux/phy/phy.h>
+#include <linux/kernel.h>
+#include <dw-mipi-csi-pltfrm.h>
+
+#ifndef __DW_DPHY_DATA_H__
+#define __DW_DPHY_DATA_H__
+
+struct dw_phy_pdata {
+	u32 dphy_frequency;
+	u8 dphy_te_len;
+	u32 config_8l;
+	u8 dphy_gen;
+	u8 phy_type;
+	u8 id;
+};
+
+static const struct pdata_names phys[] = {
+	{ .name = "phy-dw-dphy.0.0", },
+	{ .name = "phy-dw-dphy.1.1", },
+};
+
+struct dw_dphy_rx;
+
+struct plat_dw_dphy {
+	int (*get_resources)(struct device *dev, struct dw_dphy_rx *dphy);
+};
+#endif /*__DW_DPHY_DATA_H__ */

+ 149 - 0
driver/csi/dw-dphy-plat.c

@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI D-PHY controller driver.
+ * Platform driver
+ *
+ * Author: Luis Oliveira <luis.oliveira@synopsys.com>
+ */
+
+#include <dw-dphy-data.h>
+#include <dw-csi-data.h>
+#include "dw-dphy-rx.h"
+#include "bm_csi_hw.h"
+
+/* Global variable for compatibility mode, this could be override later */
+static int phy_type = 1; //Changed to fit single phy 0 - single | 1 - 8 lanes phy
+
+module_param(phy_type, int, 0664);
+MODULE_PARM_DESC(phy_type, "Disable compatibility mode for D-PHY G128");
+
+static struct phy_ops dw_dphy_ops = {
+	.init = dw_dphy_init,
+	.reset = dw_dphy_reset,
+	.power_on = dw_dphy_power_on,
+	.power_off = dw_dphy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int get_resources(struct device *dev, struct dw_dphy_rx *dphy)
+{
+	int ret = 0;
+
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
+	struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
+
+	dphy->dphy_freq = pdata->dphy_frequency;
+	dphy->dphy_te_len = pdata->dphy_te_len;
+	dphy->dphy_gen = pdata->dphy_gen;
+    drvdata->dphy = dphy;
+
+	return ret;
+}
+
+static int phy_register(struct device *dev)
+{
+	int ret = 0;
+    struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
+    struct dw_dphy_rx *dphy = drvdata->dphy;
+	struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
+
+	ret = phy_create_lookup(dphy->phy,
+					phys[pdata->id].name,
+					csis[pdata->id].name);
+	if (ret)
+		dev_err(dev, "Failed to create dphy lookup\n");
+	else
+		dev_warn(dev, "Created dphy lookup [%s] --> [%s]\n",
+		    phys[pdata->id].name, csis[pdata->id].name);
+
+
+	return ret;
+}
+
+static void phy_unregister(struct device *dev)
+{
+	if (!dev->of_node) {
+
+        struct platform_device *pdev = to_platform_device(dev);
+        struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
+        struct dw_dphy_rx *dphy = drvdata->dphy;
+	    struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
+
+		phy_remove_lookup(dphy->phy,
+				  phys[pdata->id].name, csis[pdata->id].name);
+		dev_warn(dev, "Removed dphy lookup [%s] --> [%s]\n",
+			 phys[pdata->id].name, csis[pdata->id].name);
+	}
+}
+
+#define REG_DPHY_OFFSET 0x40
+int dw_dphy_rx_probe(struct platform_device *pdev, unsigned int dphyglueiftester, unsigned int sysreg_mipi_csi_ctrl)
+{
+	struct device *dev = &pdev->dev;
+	struct dw_dphy_rx *dphy;
+    struct bm_csi_drvdata *drvdata;
+
+	dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
+	if (!dphy)
+		return -ENOMEM;
+
+	drvdata = platform_get_drvdata(pdev);
+	dphy->base_address = drvdata->base + REG_DPHY_OFFSET;
+    drvdata->dphy= dphy;
+	dphy->dphyglueiftester = dphyglueiftester;
+	dphy->sysreg_mipi_csi_ctrl = sysreg_mipi_csi_ctrl;
+
+    if (IS_ERR(dphy->base_address)) {
+		dev_err(&pdev->dev, "error requesting base address\n");
+		return PTR_ERR(dphy->base_address);
+	}
+
+	if (get_resources(dev, dphy)) {
+		dev_err(dev, "failed to parse PHY resources\n");
+		return -EINVAL;
+	}
+
+	dphy->phy = devm_phy_create(dev, NULL, &dw_dphy_ops);
+	if (IS_ERR(dphy->phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(dphy->phy);
+	}
+
+	phy_set_drvdata(dphy->phy, dphy);
+
+	if (phy_register(dev)) {
+		dev_err(dev, "failed to register PHY\n");
+		return -EINVAL;
+	}
+
+	dphy->lp_time = 1000; /* 1000 ns */
+	dphy->lanes_config = dw_dphy_setup_config(dphy);
+
+	dev_info(&dphy->phy->dev, "Probing dphy finished\n");
+
+	dw_dphy_create_capabilities_sysfs(pdev);
+
+	return 0;
+}
+
+int dw_dphy_rx_remove(struct platform_device *pdev)
+{
+    struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
+    struct dw_dphy_rx *dphy = drvdata->dphy;
+
+	dev_info(&dphy->phy->dev, "phy removed\n");
+
+	phy_reset(dphy->phy);
+	phy_unregister(&pdev->dev);
+    dw_dphy_remove_capabilities_sysfs(pdev);
+
+	return 0;
+}
+
+MODULE_DESCRIPTION("Synopsys DesignWare MIPI DPHY Rx driver");
+MODULE_AUTHOR("Luis Oliveira <lolivei@synopsys.com>");
+MODULE_LICENSE("GPL v2");

+ 966 - 0
driver/csi/dw-dphy-rx.c

@@ -0,0 +1,966 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI D-PHY controller driver
+ * Core functions
+ *
+ * Author: Luis Oliveira <luis.oliveira@synopsys.com>
+ */
+
+#include "dw-dphy-rx.h"
+#include "bm_csi_dphy.h"
+#include "bm_printk.h"
+#include <linux/io.h>
+
+struct range_dphy_gen2 {
+	u32 freq;
+	u8 hsfregrange;
+};
+
+struct range_dphy_gen2 range_gen2[] = {
+	{ 80, 0x00 }, { 90, 0x10 }, { 100, 0x20 }, { 110, 0x30 },
+	{ 120, 0x01 }, { 130, 0x11 }, { 140, 0x21 }, { 150, 0x31 },
+	{ 160, 0x02 }, { 170, 0x12 }, { 180, 0x22 }, { 190, 0x32 },
+	{ 205, 0x03 }, { 220, 0x13 }, { 235, 0x23 }, { 250, 0x33 },
+	{ 275, 0x04 }, { 300, 0x14 }, { 325, 0x05 }, { 350, 0x15 },
+	{ 400, 0x25 }, { 450, 0x06 }, { 500, 0x16 }, { 550, 0x07 },
+	{ 600, 0x17 }, { 650, 0x08 }, { 700, 0x18 }, { 750, 0x09 },
+	{ 800, 0x19 }, { 850, 0x29 }, { 900, 0x39 }, { 950, 0x0A },
+	{ 1000, 0x1A }, { 1050, 0x2A }, { 1100, 0x3A }, { 1150, 0x0B },
+	{ 1200, 0x1B }, { 1250, 0x2B }, { 1300, 0x3B }, { 1350, 0x0C },
+	{ 1400, 0x1C }, { 1450, 0x2C }, { 1500, 0x3C }, { 1550, 0x0D },
+	{ 1600, 0x1D }, { 1650, 0x2D }, { 1700, 0x0E }, { 1750, 0x1E },
+	{ 1800, 0x2E }, { 1850, 0x3E }, { 1900, 0x0F }, { 1950, 0x1F },
+	{ 2000, 0x2F },
+};
+
+struct range_dphy_gen3 {
+	u32 freq;
+	u8 hsfregrange;
+	u32 osc_freq_target;
+};
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+struct range_dphy_gen3 range_gen3[] = {
+	{ 80, 0x00, 0x1B6 }, { 90, 0x10, 0x1B6 }, { 100, 0x20, 0x1B6 },
+	{ 110, 0x30, 0x1B6 }, { 120, 0x01, 0x1B6 }, { 130, 0x11, 0x1B6 },
+	{ 140, 0x21, 0x1B6 }, { 150, 0x31, 0x1B6 }, { 160, 0x02, 0x1B6 },
+	{ 170, 0x12, 0x1B6 }, { 180, 0x22, 0x1B6 }, { 190, 0x32, 0x1B6 },
+	{ 205, 0x03, 0x1B6 }, { 220, 0x13, 0x1B6 }, { 235, 0x23, 0x1B6 },
+	{ 250, 0x33, 0x1B6 }, { 275, 0x04, 0x1B6 }, { 300, 0x14, 0x1B6 },
+	{ 325, 0x25, 0x1B6 }, { 350, 0x35, 0x1B6 }, { 400, 0x05, 0x1B6 },
+	{ 450, 0x16, 0x1B6 }, { 500, 0x26, 0x1B6 }, { 550, 0x37, 0x1B6 },
+	{ 600, 0x07, 0x1B6 }, { 650, 0x18, 0x1B6 }, { 700, 0x28, 0x1B6 },
+	{ 750, 0x39, 0x1B6 }, { 800, 0x09, 0x1B6 }, { 850, 0x19, 0x1B6 },
+	{ 900, 0x29, 0x1B6 }, { 950, 0x3A, 0x1B6 }, { 1000, 0x0A, 0x1B6 },
+	{ 1050, 0x1A, 0x1B6 }, { 1100, 0x2A, 0x1B6 }, { 1150, 0x3B, 0x1B6 },
+	{ 1200, 0x0B, 0x1B6 }, { 1250, 0x1B, 0x1B6 }, { 1300, 0x2B, 0x1B6 },
+	{ 1350, 0x3C, 0x1B6 }, { 1400, 0x0C, 0x1B6 }, { 1450, 0x1C, 0x1B6 },
+	{ 1500, 0x2C, 0x1B6 }, { 1550, 0x3D, 0x10F }, { 1600, 0x0D, 0x118 },
+	{ 1650, 0x1D, 0x121 }, { 1700, 0x2E, 0x12A }, { 1750, 0x3E, 0x132 },
+	{ 1800, 0x0E, 0x13B }, { 1850, 0x1E, 0x144 }, { 1900, 0x2F, 0x14D },
+	{ 1950, 0x3F, 0x155 }, { 2000, 0x0F, 0x15E }, { 2050, 0x40, 0x167 },
+	{ 2100, 0x41, 0x170 }, { 2150, 0x42, 0x178 }, { 2200, 0x43, 0x181 },
+	{ 2250, 0x44, 0x18A }, { 2300, 0x45, 0x193 }, { 2350, 0x46, 0x19B },
+	{ 2400, 0x47, 0x1A4 }, { 2450, 0x48, 0x1AD }, { 2500, 0x49, 0x1B6 }
+};
+#else
+//for asic
+struct range_dphy_gen3 range_gen3[] = {         //TODO 根据手册更新osc_freq_target的值。
+	{ 80, 0x00, 460 }, { 90, 0x10, 460 }, { 100, 0x20, 460 },
+	{ 110, 0x30, 460 }, { 120, 0x01, 460 }, { 130, 0x11, 460 },
+	{ 140, 0x21, 460 }, { 150, 0x31, 460 }, { 160, 0x02, 460 },
+	{ 170, 0x12, 460 }, { 180, 0x22, 460 }, { 190, 0x32, 460 },
+	{ 205, 0x03, 460 }, { 220, 0x13, 460 }, { 235, 0x23, 460 },
+	{ 250, 0x33, 460 }, { 275, 0x04, 460 }, { 300, 0x14, 460 },
+	{ 325, 0x25, 460 }, { 350, 0x35, 460 }, { 400, 0x05, 460 },
+	{ 450, 0x16, 460 }, { 500, 0x26, 460 }, { 550, 0x37, 460 },
+	{ 600, 0x07, 460 }, { 650, 0x18, 460 }, { 700, 0x28, 460 },
+	{ 750, 0x39, 460 }, { 800, 0x09, 460 }, { 850, 0x19, 460 },
+	{ 900, 0x29, 460 }, { 950, 0x3A, 460 }, { 1000, 0x0A, 460 },
+	{ 1050, 0x1A, 460 }, { 1100, 0x2A, 460 }, { 1150, 0x3B, 460 },
+	{ 1200, 0x0B, 460 }, { 1250, 0x1B, 460 }, { 1300, 0x2B, 460 },
+	{ 1350, 0x3C, 460 }, { 1400, 0x0C, 460 }, { 1450, 0x1C, 460 },
+	{ 1500, 0x2C, 460 }, { 1550, 0x3D, 285 }, { 1600, 0x0D, 295 },
+	{ 1650, 0x1D, 304 }, { 1700, 0x2E, 313 }, { 1750, 0x3E, 322 },
+	{ 1800, 0x0E, 331 }, { 1850, 0x1E, 341 }, { 1900, 0x2F, 350 },
+	{ 1950, 0x3F, 359 }, { 2000, 0x0F, 368 }, { 2050, 0x40, 377 },
+	{ 2100, 0x41, 387 }, { 2150, 0x42, 396 }, { 2200, 0x43, 405 },
+	{ 2250, 0x44, 414 }, { 2300, 0x45, 423 }, { 2350, 0x46, 432 },
+	{ 2400, 0x47, 442 }, { 2450, 0x48, 451 }, { 2500, 0x49, 460 }
+};
+#endif
+
+u8 dw_dphy_setup_config(struct dw_dphy_rx *dphy)
+{
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+#if 0
+	int ret;
+
+	if (dphy->max_lanes == CTRL_4_LANES) {
+		dev_vdbg(&dphy->phy->dev, "CONFIG 4L\n");
+		return CTRL_4_LANES;
+	}
+	if (IS_ENABLED(CONFIG_OF)) {
+		ret = gpio_request(dphy->config_8l, "config");
+		if (ret < 0) {
+			dev_vdbg(&dphy->phy->dev,
+				 "could not acquire config (err=%d)\n", ret);
+			return ret;
+		}
+		ret = gpio_get_value(dphy->config_8l);
+		gpio_free(dphy->config_8l);
+	} else {
+		ret = dphy->config_8l;
+	}
+
+	dev_vdbg(&dphy->phy->dev,
+		 "Booting in [%s] mode\n",
+		 ret == CTRL_8_LANES ? "8L" : "4+4L");
+	return ret;
+#endif
+#endif /* CONFIG_DWC_MIPI_TC_DPHY_GEN3 */
+	return CTRL_4_LANES;
+}
+
+extern int k_bm_visys_write_reg(uint32_t offset, uint32_t value);
+extern int k_bm_visys_read_reg(uint32_t offset, uint32_t *value);
+
+void dw_dphy_if_write(struct dw_dphy_rx *dphy, u32 address, u32 data)
+{
+    //writel(data, dphy->dphy1_if_addr + address);
+    k_bm_visys_write_reg(address, data);
+}
+
+u32 dw_dphy_if_read(struct dw_dphy_rx *dphy, u32 address)
+{
+	u32 if1 = 0;
+    //if1 = readl(dphy->dphy1_if_addr + address);
+    k_bm_visys_read_reg(address, &if1);
+	return if1;
+}
+
+void dw_dphy_write(struct dw_dphy_rx *dphy, u32 address, u32 data)
+{
+	writel(data, dphy->base_address + address);
+
+	if (dphy->lanes_config == CTRL_4_LANES)
+		return;
+	return;
+
+	if (address == R_CSI2_DPHY_TST_CTRL0)
+		iowrite32(data, dphy->base_address + R_CSI2_DPHY2_TST_CTRL0);
+	else if (address == R_CSI2_DPHY_TST_CTRL1)
+		iowrite32(data, dphy->base_address + R_CSI2_DPHY2_TST_CTRL1);
+}
+
+u32 dw_dphy_read(struct dw_dphy_rx *dphy, u32 address)
+{
+	int dphy1 = 0, dphy2 = 0;
+
+	dphy1 = readl(dphy->base_address + address);
+
+	if (dphy->lanes_config == CTRL_4_LANES)
+		goto end;
+
+    goto end;
+
+	if (address == R_CSI2_DPHY_TST_CTRL0)
+		dphy2 = ioread32(dphy->base_address + R_CSI2_DPHY2_TST_CTRL0);
+	else if (address == R_CSI2_DPHY_TST_CTRL1)
+		dphy2 = ioread32(dphy->base_address + R_CSI2_DPHY2_TST_CTRL1);
+	else
+		return -ENODEV;
+end:
+	return dphy1;
+}
+
+void dw_dphy_write_msk(struct dw_dphy_rx *dev, u32 address, u32 data, u8 shift,
+		       u8 width)
+{
+	u32 temp = dw_dphy_read(dev, address);
+	u32 mask = (1 << width) - 1;
+
+	temp &= ~(mask << shift);
+	temp |= (data & mask) << shift;
+	dw_dphy_write(dev, address, temp);
+}
+
+static void dw_dphy_te_12b_write(struct dw_dphy_rx *dphy, u16 addr, u8 data)
+{
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, PHY_TESTDIN, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)(addr >> 8),
+			  PHY_TESTDIN, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)addr, PHY_TESTDIN,
+			  8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)data, PHY_TESTDIN,
+			  8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+}
+
+static void dw_dphy_te_8b_write(struct dw_dphy_rx *dphy, u8 addr, u8 data)
+{
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write(dphy, R_CSI2_DPHY_TST_CTRL1, addr);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write(dphy, R_CSI2_DPHY_TST_CTRL1, data);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+}
+
+static void dw_dphy_te_write(struct dw_dphy_rx *dphy, u16 addr, u8 data)
+{
+    dphy->dphy_te_len = BIT12;
+	if (dphy->dphy_te_len == BIT12)
+		dw_dphy_te_12b_write(dphy, addr, data);
+	else
+		dw_dphy_te_8b_write(dphy, addr, data);
+}
+
+static int dw_dphy_te_12b_read(struct dw_dphy_rx *dphy, u32 addr)
+{
+	u8 ret;
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, PHY_TESTDIN, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)(addr >> 8),
+			  PHY_TESTDIN, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)addr, PHY_TESTDIN,
+			  8);
+
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, 0, PHY_TESTDIN);
+
+	ret = dw_dphy_read_msk(dphy, R_CSI2_DPHY_TST_CTRL1, PHY_TESTDOUT, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+
+	return ret;
+}
+
+static int dw_dphy_te_8b_read(struct dw_dphy_rx *dphy, u32 addr)
+{
+	u8 ret;
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, addr, PHY_TESTDIN, 8);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTDIN, 8);
+	ret = dw_dphy_read_msk(dphy, R_CSI2_DPHY_TST_CTRL1, PHY_TESTDOUT, 8);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
+
+	return ret;
+}
+
+int dw_dphy_te_read(struct dw_dphy_rx *dphy, u32 addr)
+{
+	int ret;
+
+	if (dphy->dphy_te_len == BIT12)
+		ret = dw_dphy_te_12b_read(dphy, addr);
+	else
+		ret = dw_dphy_te_12b_read(dphy, addr);
+		//ret = dw_dphy_te_8b_read(dphy, addr);
+
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+static void dw_dphy_if_init(struct dw_dphy_rx *dphy)
+{
+    bm_info("enter %s\n", __func__);
+	//dw_dphy_if_write(dphy, dphy->dphy1_if_addr, RESET);
+	//dw_dphy_if_write(dphy, dphy->dphy1_if_addr, TX_PHY);
+	//dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
+	//dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, GLUELOGIC);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RX_PHY);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
+	//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
+}
+#endif
+
+static void dw_dphy_gen3_12bit_tc_power_up(struct dw_dphy_rx *dphy, uint8_t hsfregrange)
+{
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, GLUELOGIC);  //用fpga时候是写到子板专有寄存器内,芯片要写到visys reg
+	dw_dphy_te_write(dphy, CFGCLKFREQRANGE_RX, 0x1C);   //TODO ASCI 改为通过vi sys寄存器去配置src clk
+	dw_dphy_te_write(dphy, 0x6, hsfregrange);           //TODO ASCI 改为通过vi sys寄存器去配置src clk
+#endif
+
+
+#if !IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+    u32 reg_val = 0;
+	reg_val = dw_dphy_if_read(dphy, dphy->sysreg_mipi_csi_ctrl);   //TODO ASCI 改为通过vi sys寄存器去配置src clk
+    reg_val &= ~0x3f;
+    reg_val |= 0x1c;
+	dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, reg_val);   //TODO ASCI 改为通过vi sys寄存器去配置src clk
+    reg_val &= ~(0x7f << 8);
+    reg_val |= (hsfregrange << 8);
+	dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, reg_val);   //TODO ASCI 改为通过vi sys寄存器去配置src clk
+#endif
+
+	/* CLKSEL | UPDATEPLL | SHADOW_CLEAR | SHADOW_CTRL | FORCEPLL */
+	//dw_dphy_te_write(dphy, BYPASS, 0x3F);
+	/* IO_DS3 | IO_DS2 | IO_DS1 | IO_DS0 */
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	if ((dphy->dphy_freq/1000) > 1500) {
+		dw_dphy_te_write(dphy, IO_DS, 0x0F);
+    }
+
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RX_PHY | 0x2);
+#endif
+}
+
+static void dw_dphy_gen3_8bit_tc_power_up(struct dw_dphy_rx *dphy)
+{
+	u32 input_freq = dphy->dphy_freq / 1000;
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, GLUELOGIC);
+	dw_dphy_te_write(dphy, CFGCLKFREQRANGE_RX, 0x1C);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RESET);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, RX_PHY);
+#endif
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX0_MSB, 0x03);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX0_LSB, 0x02);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX1_MSB, 0x03);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX1_LSB, 0x02);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX2_MSB, 0x03);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX2_LSB, 0x02);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX3_MSB, 0x03);
+	dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX3_LSB, 0x02);
+	dw_dphy_te_write(dphy, BANDGAP_CTRL, 0x80);
+
+	if (input_freq < 2000)
+		dw_dphy_te_write(dphy, HS_RX_CTRL_LANE0, 0xC0);
+
+	if (input_freq < 1000) {
+		dw_dphy_te_write(dphy, HS_RX_CTRL_LANE1, 0xC0);
+		dw_dphy_te_write(dphy, HS_RX_CTRL_LANE2, 0xC0);
+		dw_dphy_te_write(dphy, HS_RX_CTRL_LANE3, 0xC0);
+	}
+}
+
+int dw_dphy_g118_settle(struct dw_dphy_rx *dphy)
+{
+	u32 input_freq, total_settle, settle_time, byte_clk, lp_time;
+
+	lp_time = dphy->lp_time;
+	input_freq = dphy->dphy_freq / 1000;
+
+	settle_time = (8 * (1000000 / (input_freq))) + 115000;
+	byte_clk = (8000000 / (input_freq));
+	total_settle = (settle_time + lp_time * 1000) / byte_clk;
+
+	if (total_settle > 0xFF)
+		total_settle = 0xFF;
+
+	return total_settle;
+}
+
+static void dw_dphy_pwr_down(struct dw_dphy_rx *dphy)
+{
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
+	if (dphy->lanes_config == CTRL_8_LANES)
+		dw_dphy_write_msk(dphy, R_CSI2_DPHY2_TST_CTRL0, 0, PHY_TESTCLK, 1);
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+}
+
+static void dw_dphy_pwr_up(struct dw_dphy_rx *dphy)
+{
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
+	if (dphy->lanes_config == CTRL_8_LANES)
+		dw_dphy_write_msk(dphy, R_CSI2_DPHY2_TST_CTRL0, 1, PHY_TESTCLK,
+				  1);
+	dev_vdbg(&dphy->phy->dev, "DPHY power up.\n");
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
+    udelay(1);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+    udelay(1);
+}
+
+static int dw_dphy_gen3_12bit_configure(struct dw_dphy_rx *dphy, int abphy_flag)
+{
+	u32 input_freq = dphy->dphy_freq;
+	u8 range = 0;
+    u32 reg_val = 0;
+
+	dev_vdbg(&dphy->phy->dev, "12bit: PHY GEN 3: Freq: %u\n", input_freq);
+	for (range = 0; (range < ARRAY_SIZE(range_gen3) - 1) &&
+	     ((input_freq / 1000) > range_gen3[range].freq);
+	     range++);
+
+    input_freq  /= 1000;
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
+    udelay(1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
+
+	dw_dphy_gen3_12bit_tc_power_up(dphy, range_gen3[range].hsfregrange);
+
+	//uint8_t lp_time = dphy->lp_time;
+	//dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_17, lp_time);//SET SETTLE TIME
+
+    //位置1
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_te_write(dphy, RX_SYS_1, range_gen3[range].hsfregrange);
+	dw_dphy_te_write(dphy, RX_SYS_0, 0x20);
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_2, 0xcc);
+#else
+    //used for asic
+    if (input_freq > 1500) {
+	    dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_2, (u8)(range_gen3[range].osc_freq_target & 0xff));
+	    dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_3, (u8)(range_gen3[range].osc_freq_target >> 8));
+    }
+#endif
+
+
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, 0x21);         //TODO fpga val=0x21, chip val=0x11
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_5, 0x01);         //TODO 顺序位置配置可能需要调到位置1
+#else
+
+	reg_val = dw_dphy_te_read(dphy, RX_RX_STARTUP_OVR_4);
+    reg_val &= ~(0xf0);
+    reg_val |= (1 << 4);
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, reg_val);
+
+    if (input_freq > 1500) {
+	    reg_val = dw_dphy_te_read(dphy, RX_RX_STARTUP_OVR_4);
+        reg_val |= 1;
+	    dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, reg_val);         //TODO fpga val=0x21, chip val=0x11
+    }
+
+	reg_val = dw_dphy_te_read(dphy, RX_RX_STARTUP_OVR_5);
+    reg_val |= 1;
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_5, reg_val);         //TODO 顺序位置配置可能需要调到位置1
+
+	reg_val = dw_dphy_te_read(dphy, RX_RX_CB_1);                  //TODO used to chip
+    reg_val &= ~0x3;
+    reg_val |= 2;
+	dw_dphy_te_write(dphy, RX_RX_CB_1, reg_val);                  //TODO used to chip
+
+
+	reg_val = dw_dphy_te_read(dphy, RX_RX_CB_2);                  //TODO used to chip
+    reg_val |= (1 << 6);
+	dw_dphy_te_write(dphy, RX_RX_CB_2, reg_val);              //TODO used to chip
+
+
+    if (abphy_flag) {
+	    reg_val = dw_dphy_te_read(dphy, RX_RX_CLKLANE_LANE_6);                  //TODO used to chip
+        reg_val |= (1 << 7);
+	    dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, reg_val);    //TODO used to chip
+    }
+
+    if (input_freq <= 1500) {
+        reg_val = dw_dphy_te_read(dphy, 0x607); //TODO used to chip
+        reg_val |= 0x3f;
+	    dw_dphy_te_write(dphy, 0x607, reg_val); //TODO used to chip
+
+        reg_val = dw_dphy_te_read(dphy, 0x807); //TODO used to chip
+        reg_val |= 0x3f;
+	    dw_dphy_te_write(dphy, 0x807, reg_val); //TODO used to chip
+
+        reg_val = dw_dphy_te_read(dphy, 0xa07); //TODO used to chip
+        reg_val |= 0x3f;
+	    dw_dphy_te_write(dphy, 0xa07, reg_val); //TODO used to chip
+
+        reg_val = dw_dphy_te_read(dphy, 0xc07); //TODO used to chip
+        reg_val |= 0x3f;
+	    dw_dphy_te_write(dphy, 0xc07, reg_val);    //TODO used to chip
+    } else  {
+	    dw_dphy_te_write(dphy, RX_SYS_9, 0x43);                    //TODO used to chip
+    }
+
+    //for chip dphy->sysreg_mipi_csi_ctrl: csi2_0, csi2_1, csi2_2 -> 0x140, 0x144, 0x148
+    reg_val  = dw_dphy_if_read(dphy, dphy->sysreg_mipi_csi_ctrl);
+    reg_val |= (1 << 28) | (1 << 25) | (7 << 20);
+	dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, reg_val); //TODO set visys reg basedir_0 =1, set visys reg forcerxmode_0123=1
+#endif
+
+    udelay(1);
+
+	if (dphy->phy_type) {
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+		dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_1, 0x01);
+		dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_0, 0x80);
+#endif
+	}
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_te_write(dphy, RX_SYS_3, 0x59);
+#endif
+
+	if (dphy->phy_type || input_freq <= 1500) {
+		reg_val = dw_dphy_te_read(dphy, RX_SYS_7);
+        reg_val |= (1 << 5);
+		dw_dphy_te_write(dphy, RX_SYS_7, reg_val);
+    }
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+    udelay(1);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
+
+    udelay(600);
+
+    //TODO set visys reg mipi_csi2x2_a_forcerxmode_0=0 这个先不要配置,应该不需要设置为0
+
+    reg_val  = dw_dphy_if_read(dphy, dphy->sysreg_mipi_csi_ctrl);
+    reg_val &= ~((1 << 25) | (7 << 20));
+	dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, reg_val); //TODO set visys reg basedir_0 =1, set visys reg forcerxmode_0123=0
+	return 0;
+}
+
+static void dw_dphy_combination_4lane_switch_master(struct dw_dphy_rx *dphy)
+{
+    u32 sys_reg_val = 0;
+    sys_reg_val = dw_dphy_if_read(dphy, dphy->sysreg_mipi_csi_ctrl);
+    sys_reg_val |= 1;
+    dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, sys_reg_val);    //切换寄存器到master
+}
+
+static void dw_dphy_combination_4lane_switch_slave(struct dw_dphy_rx *dphy)
+{
+    u32 sys_reg_val = 0;
+    sys_reg_val = dw_dphy_if_read(dphy, dphy->sysreg_mipi_csi_ctrl);
+    sys_reg_val &= ~1;
+    dw_dphy_if_write(dphy, dphy->sysreg_mipi_csi_ctrl, sys_reg_val);    //切换寄存器到slave
+}
+
+#if !IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+//用于dphy 两个2lane组合成4lane的模式下phy初始化
+static int dw_dphy_12bit_combination_4lane_configure(struct dw_dphy_rx *dphy)
+{
+	u32 input_freq = dphy->dphy_freq;
+    u32 phy_reg_val = 0;
+	u8 range = 0;
+
+    dw_dphy_pwr_down(dphy);
+	dev_vdbg(&dphy->phy->dev, "12bit: PHY GEN 3: Freq: %u\n", input_freq);
+	for (range = 0; (range < ARRAY_SIZE(range_gen3) - 1) &&
+	     ((input_freq / 1000) > range_gen3[range].freq);
+	     range++);
+
+
+    //Define master PHY and slave PHY and configure each accordingly
+    //(this choice needs to be coherent with wiring connections mentioned above):
+	dw_dphy_combination_4lane_switch_master(dphy);
+    dw_dphy_te_write(dphy, RX_RX_DUAL_PHY_0, 0x01);                 //2lane合并为4lane,设置master
+	dw_dphy_combination_4lane_switch_slave(dphy);
+	dw_dphy_te_write(dphy, RX_RX_DUAL_PHY_0, 0x00);                 //2lane合并为4lane,设置slave
+
+    //Configure master PHY clock lane to drive long channel clock
+	dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, RX_RX_CLKLANE_LANE_6);
+    phy_reg_val |= (1 << 2);
+	dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, phy_reg_val);                     //2lane合并为4lane,设置master
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val &= ~(1 << 2);
+	dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    //Configure both master and slave PHY data lanes to get clock from long channel:
+	dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x508);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x508, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x508);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x508, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x708);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x708, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x708);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x708, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x908);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x908, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x908);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0x908, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0xB08);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0xB08, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0xB08);
+    phy_reg_val |= (1 << 5);
+	dw_dphy_te_write(dphy, 0xB08, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    //Configure slave PHY clock lane to bypass long channel clock to DDR clock:
+    dw_dphy_combination_4lane_switch_master(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x308);
+    phy_reg_val &= ~(1 << 3);
+	dw_dphy_te_write(dphy, 0x308, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x308);
+    phy_reg_val |= (1 << 3);
+	dw_dphy_te_write(dphy, 0x308, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    //Override slave PHY DDR clock lane enable (DPHYHSRX_div124 module):
+	dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x0e1);
+    phy_reg_val |= (1 << 1);
+	dw_dphy_te_write(dphy, 0x0e1, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    phy_reg_val = dw_dphy_te_read(dphy, RX_RX_CLKLANE_LANE_6);
+    phy_reg_val |= (1 << 3);
+	dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+    //Turn off slave PHY LP-RX clock lane:
+    dw_dphy_combination_4lane_switch_slave(dphy);
+    phy_reg_val = dw_dphy_te_read(dphy, 0x304);
+    phy_reg_val &= ~0x1f;
+    phy_reg_val |= 0xa;
+	dw_dphy_te_write(dphy, 0x304, phy_reg_val);                     //2lane合并为4lane,设置slave
+
+
+    //Configure both PHYs as described in“Start-Up Sequence” on page 81
+    //until step enable_n and enableclk=1'b1 (skip step Configure register
+    //0x307 to set rxclk_rxhs_pull_long_channel_if_rw signal (bit 8) to 1'b1).
+    dw_dphy_gen3_12bit_configure(dphy, 1);
+
+
+    //Set shutdownz=1'b1 in master and slave PHYs.
+    dw_dphy_combination_4lane_switch_master(dphy);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
+    dw_dphy_combination_4lane_switch_slave(dphy);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
+
+    //Release reset for master PHY (rstz=1'b1).
+    dw_dphy_combination_4lane_switch_master(dphy);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+
+    udelay(1);
+    //Release reset for slave PHY (rstz=1'b1).
+    dw_dphy_combination_4lane_switch_slave(dphy);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+
+    udelay(600);
+    //Set forcerxmode_n in master and slave PHY = 1'b0.
+    //???
+
+
+
+
+#if 0
+	dw_dphy_gen3_12bit_tc_power_up(dphy, range_gen3[range].hsfregrange);
+
+	//uint8_t lp_time = dphy->lp_time;
+	//dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_17, lp_time);//SET SETTLE TIME
+
+    //位置1
+	dw_dphy_te_write(dphy, RX_SYS_1, range_gen3[range].hsfregrange);
+	dw_dphy_te_write(dphy, RX_SYS_0, 0x20);
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_2, 0xcc);
+#else
+    //used for asic
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_2, (u8)(range_gen3[range].osc_freq_target & 0xff));
+#endif
+
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_3,
+			 (u8)(range_gen3[range].osc_freq_target >> 8));
+
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, 0x21);         //TODO fpga val=0x21, chip val=0x11
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_5, 0x01);         //TODO 顺序位置配置可能需要调到位置1
+#else
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, 0x11);         //TODO fpga val=0x21, chip val=0x11
+	dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_5, 0x01);         //TODO 顺序位置配置可能需要调到位置1
+	dw_dphy_te_write(dphy, RX_RX_CB_1, 0x02);                  //TODO used to chip
+	dw_dphy_te_write(dphy, RX_RX_CB_2, 0x1 << 6);              //TODO used to chip
+	dw_dphy_te_write(dphy, RX_SYS_9, 0x43);                    //TODO used to chip
+	dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, 0x1 << 7);    //TODO used to chip
+
+    //for chip dphy->dphyglueiftester : csi2_0, csi2_1, csi2_2 -> 0x140, 0x144, 0x148
+    reg_val  = dw_dphy_if_read(dphy, dphy->dphyglueiftester);
+    reg_val |= (1 << 28) | (1 << 25);
+	dw_dphy_if_write(dphy, dphy->dphyglueiftester, reg_val); //TODO set visys reg basedir_0 =1, set visys reg forcerxmode_0=1
+#endif
+
+	if (dphy->phy_type) {
+		dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_1, 0x01);
+		dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_0, 0x80);
+	}
+
+	dw_dphy_te_write(dphy, RX_SYS_3, 0x59);
+
+	dw_dphy_te_write(dphy, RX_SYS_7, 0x38);
+	if (dphy->phy_type || input_freq <= 1500)
+		dw_dphy_te_write(dphy, RX_SYS_7, 0x38);
+
+    //TODO set visys reg mipi_csi2x2_a_forcerxmode_0=0 这个先不要配置,应该不需要设置为0
+    //reg_val &= ~(1 << 25);
+	//dw_dphy_if_write(dphy, dphy->dphyglueiftester, reg_val);
+#endif
+	return 0;
+}
+#endif
+
+
+static int dw_dphy_gen3_8bit_configure(struct dw_dphy_rx *dphy)
+{
+	u32 input_freq = dphy->dphy_freq;
+	u8 data;
+	u8 range = 0;
+
+	dev_vdbg(&dphy->phy->dev, "8bit: PHY GEN 3: Freq: %u\n", input_freq);
+	for (range = 0; (range < ARRAY_SIZE(range_gen3) - 1) &&
+	     ((input_freq / 1000) > range_gen3[range].freq);
+	     range++)
+		;
+
+	dw_dphy_te_write(dphy, RX_SKEW_CAL, dw_dphy_g118_settle(dphy));
+	data = 1 << 7 | range_gen3[range].hsfregrange;
+	dw_dphy_te_write(dphy, HSFREQRANGE_8BIT, data);
+	dw_dphy_gen3_8bit_tc_power_up(dphy);
+
+	return 0;
+}
+
+static int dw_dphy_gen2_configure(struct dw_dphy_rx *dphy)
+{
+	u32 input_freq = dphy->dphy_freq;
+	u8 data;
+	u8 range = 0;
+
+	/* provide an initial active-high test clear pulse in TESTCLR  */
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
+	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
+
+	dev_vdbg(&dphy->phy->dev, "PHY GEN 2: Freq: %u\n", input_freq);
+	for (range = 0; (range < ARRAY_SIZE(range_gen2) - 1) &&
+	     ((input_freq / 1000) > range_gen2[range].freq); range++)
+		;
+
+	data = range_gen2[range].hsfregrange << 1;
+	dw_dphy_te_write(dphy, HSFREQRANGE_8BIT, data);
+
+	return 0;
+}
+
+static int dw_dphy_configure(struct dw_dphy_rx *dphy)
+{
+
+    bm_info("enter %s\n", __func__);
+	dw_dphy_pwr_down(dphy);
+    dphy->dphy_gen = GEN3;
+	if (dphy->dphy_gen == GEN3) {
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+		dw_dphy_if_init(dphy);
+#endif
+        dphy->dphy_te_len = BIT12;
+		if (dphy->dphy_te_len == BIT12)
+			dw_dphy_gen3_12bit_configure(dphy, 1);
+		else
+			dw_dphy_gen3_8bit_configure(dphy);
+	} else {
+		dw_dphy_gen2_configure(dphy);
+	}
+	dw_dphy_pwr_up(dphy);
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+
+#if 0
+int dw_dphy_if_set_idelay(struct dw_dphy_rx *dphy, u8 dly, u8 cells)
+{
+	u32 val = 0;
+
+	dw_dphy_if_write(dphy, IDLYCFG, 0);
+	dw_dphy_if_write(dphy, IDLYSEL, cells);
+	dw_dphy_if_write(dphy, IDLYCNTINVAL, dly);
+
+	/* Pulse Value Set */
+	dw_dphy_if_write(dphy, IDLYCFG, 1);
+	usleep_range(10, 20);
+	dw_dphy_if_write(dphy, IDLYCFG, 0);
+
+	/* Pulse IDELAY CTRL Reset */
+	dw_dphy_if_write(dphy, DPHY1REGRSTN, 0);
+	usleep_range(10, 20);
+	dw_dphy_if_write(dphy, DPHY1REGRSTN, 1);
+
+	/* Get Value*/
+	val = dw_dphy_if_read(dphy, IDLYCNTOUTVAL);
+
+	if (val != dly) {
+		dev_vdbg(&dphy->phy->dev,
+			 "odelay config failed, set %d get %d", dly, val);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int dw_dphy_if_get_idelay(struct dw_dphy_rx *dphy)
+{
+	return dw_dphy_if_read(dphy, IDLYCNTOUTVAL);
+}
+
+int dw_dphy_if_set_idelay_lane(struct dw_dphy_rx *dphy, u8 dly, u8 lane)
+{
+	int cell;
+
+	switch (lane) {
+	case 0:
+		for (cell = 3; cell <= 10; cell++)
+			dw_dphy_if_set_idelay(dphy, dly, cell);
+		break;
+	case 1:
+		for (cell = 14; cell <= 21; cell++)
+			dw_dphy_if_set_idelay(dphy, dly, cell);
+		break;
+	case 2:
+		for (cell = 24; cell <= 31; cell++)
+			dw_dphy_if_set_idelay(dphy, dly, cell);
+		break;
+	case 3:
+		for (cell = 34; cell <= 41; cell++)
+			dw_dphy_if_set_idelay(dphy, dly, cell);
+		break;
+	case 4: /* ALL */
+		dw_dphy_if_set_idelay(dphy, dly, 0x7F);
+		break;
+	default:
+		dev_err(&dphy->phy->dev, "Lane Value not recognized\n");
+		return -1;
+	}
+	return 0;
+}
+#endif
+#endif
+
+int dw_dphy_init(struct phy *phy)
+{
+	struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
+
+	dev_warn(&dphy->phy->dev, "Init DPHY.\n");
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+
+	return 0;
+}
+
+static int dw_dphy_set_phy_state(struct dw_dphy_rx *dphy, u32 on)
+{
+
+	u8 hs_freq;
+
+    bm_info("enter %s\n", __func__);
+	dphy->lanes_config = dw_dphy_setup_config(dphy);
+
+	if (dphy->dphy_te_len == BIT12)
+		hs_freq = RX_SYS_1;
+	else
+		hs_freq = HSFREQRANGE_8BIT;
+
+	if (on) {
+		dw_dphy_configure(dphy);
+		dev_info(&dphy->phy->dev,
+			 "HS Code: 0X%x\n", dw_dphy_te_read(dphy, hs_freq));
+	} else {
+		dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+		dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	}
+
+	return 0;
+}
+
+int dw_dphy_power_on(struct phy *phy)
+{
+	struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
+
+	dev_info(&dphy->phy->dev, "DPHY Power ON\n");
+    bm_info("enter %s\n", __func__);
+
+    dphy->phy_type = 1;
+	return dw_dphy_set_phy_state(dphy, 1);
+}
+
+int dw_dphy_power_off(struct phy *phy)
+{
+	struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
+
+	return dw_dphy_set_phy_state(dphy, 0);
+}
+
+int dw_dphy_reset(struct phy *phy)
+{
+	struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	usleep_range(100, 200);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+
+	return 0;
+}

+ 224 - 0
driver/csi/dw-dphy-rx.h

@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI D-PHY controller driver
+ *
+ * Author: Luis Oliveira <luis.oliveira@synopsys.com>
+ */
+
+#ifndef __PHY_SNPS_DPHY_RX_H__
+#define __PHY_SNPS_DPHY_RX_H__
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* DPHY interface register bank*/
+
+#define R_CSI2_DPHY_SHUTDOWNZ 0x0
+#define R_CSI2_DPHY_RSTZ 0x4
+#define R_CSI2_DPHY_RX 0x8
+#define	R_CSI2_DPHY_STOPSTATE 0xC
+#define R_CSI2_DPHY_TST_CTRL0 0x10
+#define R_CSI2_DPHY_TST_CTRL1 0x14
+#define R_CSI2_DPHY2_TST_CTRL0 0x18
+#define R_CSI2_DPHY2_TST_CTRL1 0x1C
+
+enum dphy_id_mask {
+	DPHY_ID_LANE_SUPPORT = 0,
+	DPHY_ID_IF = 4,
+	DPHY_ID_GEN = 8,
+};
+
+enum dphy_gen_values {
+	GEN1,
+	GEN2,
+	GEN3,
+};
+
+enum dphy_interface_length {
+	BIT8 = 8,
+	BIT12 = 12,
+};
+
+enum tst_ctrl0 {
+	PHY_TESTCLR,
+	PHY_TESTCLK,
+};
+
+enum tst_ctrl1 {
+	PHY_TESTDIN = 0,
+	PHY_TESTDOUT = 8,
+	PHY_TESTEN = 16,
+};
+
+enum lanes_config_values {
+	CTRL_4_LANES,
+	CTRL_8_LANES,
+};
+
+enum dphy_tc {
+	CFGCLKFREQRANGE_TX = 0x02,
+	CFGCLKFREQRANGE_RX = 0x05,
+	BYPASS = 0x20,
+	IO_DS = 0x30,
+};
+
+enum dphy_8bit_interface_addr {
+	BANDGAP_CTRL = 0x24,
+	HS_RX_CTRL_LANE0 = 0x42,
+	HSFREQRANGE_8BIT = 0x44,
+	OSC_FREQ_TARGET_RX0_LSB	= 0x4e,
+	OSC_FREQ_TARGET_RX0_MSB	= 0x4f,
+	HS_RX_CTRL_LANE1 = 0x52,
+	OSC_FREQ_TARGET_RX1_LSB	= 0x5e,
+	OSC_FREQ_TARGET_RX1_MSB	= 0x5f,
+	RX_SKEW_CAL = 0x7e,
+	HS_RX_CTRL_LANE2 = 0x82,
+	OSC_FREQ_TARGET_RX2_LSB	= 0x8e,
+	OSC_FREQ_TARGET_RX2_MSB	= 0x8f,
+	HS_RX_CTRL_LANE3 = 0x92,
+	OSC_FREQ_TARGET_RX3_LSB	= 0x9e,
+	OSC_FREQ_TARGET_RX3_MSB	= 0x9f,
+};
+
+enum dphy_12bit_interface_addr {
+	RX_SYS_0 = 0x01,
+	RX_SYS_1 = 0x02,
+	RX_SYS_3 = 0x05,
+	RX_SYS_7 = 0x08,
+    RX_SYS_9 = 0x0a,
+	RX_RX_STARTUP_OVR_0 = 0xe0,
+	RX_RX_STARTUP_OVR_1 = 0xe1,
+	RX_RX_STARTUP_OVR_2 = 0xe2,
+	RX_RX_STARTUP_OVR_3 = 0xe3,
+	RX_RX_STARTUP_OVR_4 = 0xe4,
+    RX_RX_STARTUP_OVR_5 = 0xe5,
+	RX_RX_STARTUP_OVR_17 = 0xf1,
+    RX_RX_DUAL_PHY_0 = 0x133,
+    RX_RX_CB_1 = 0x1ab,
+    RX_RX_CB_2 = 0x1ac,
+    RX_RX_CLKLANE_LANE_6 = 0x307,
+};
+
+//#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+/* Testchip interface register bank */
+#define IDLYCFG	0x00
+#define IDLYSEL	0x04
+#define IDLYCNTINVAL 0x08
+#define IDLYCNTOUTVAL 0x0c
+#define DPHY1REGRSTN 0x10
+#define DPHYZCALSTAT 0x14
+#define DPHYZCALCTRL 0x18
+#define DPHYLANE0STAT 0x1c
+#define DPHYLANE1STAT 0x20
+#define DPHYLANE2STAT 0x24
+#define DPHYLANE3STAT 0x28
+#define DPHYCLKSTAT 0x2c
+#define DPHYZCLKCTRL 0x30
+#define TCGENPURPOSOUT 0x34
+#define TCGENPURPOSIN 0x38
+#define DPHYGENERICOUT 0x3c
+#define DPHYGENERICIN 0x40
+
+#define DPHYGLUEIFTESTER 0x180
+#define DPHYID 0x100
+
+#define DPHY_DEFAULT_FREQ 300000
+
+enum glueiftester {
+	RESET = 0,
+	TX_PHY = 0x100 | (0x1 << 4),
+	RX_PHY = 0x100 | (0x2 << 4),
+	GLUELOGIC = 0x100 | (0x4 << 4),
+};
+//#endif
+
+/**
+ * struct phy		specifies associated phy component
+ * struct cfg		to pass mipi dphy specific configurations
+ * @lanes_config	lanes configuration
+ * @dphy_freq		operating frequency of the d-phy (mbps)
+ * @phy_type		dphy can be of two types, passed here
+ * @dphy_gen		dphy can be of three generations, passed here
+ * @dphy_te_len		bus width
+ * @max_lanes		maximum number of lanes
+ * @lp_time		time in low-power
+ * @base_address	memmory address of dphy test interface
+ * @dphy1_if_addr	gluelogic dphy 1 memmory address of interface
+ * @dphy2_if_addr	gluelogic dphy 2 memmory address of interface
+ * @config_8l		eight lanes configuration
+ */
+
+struct dw_dphy_rx {
+	struct phy *phy;
+	struct phy_configure_opts_mipi_dphy *cfg;
+	u32 lanes_config;
+	u32 dphy_freq;  //MBPS
+	u32 phy_type;
+	u32 dphy_gen;
+	u32 dphy_te_len;
+	u32 max_lanes;
+	u32 lp_time;
+	u32 dphyglueiftester;
+	u32 sysreg_mipi_csi_ctrl;
+	void __iomem *base_address;
+//#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+	void __iomem *dphy1_if_addr;
+	void __iomem *dphy2_if_addr;
+	u8 config_8l;
+	u8 (*get_config_8l)(struct device *dev, struct dw_dphy_rx *dphy);
+//#endif
+	u8 (*phy_register)(struct device *dev);
+	void (*phy_unregister)(struct device *dev);
+};
+
+int dw_dphy_init(struct phy *phy);
+int dw_dphy_reset(struct phy *phy);
+int dw_dphy_power_off(struct phy *phy);
+int dw_dphy_power_on(struct phy *phy);
+u8 dw_dphy_setup_config(struct dw_dphy_rx *dphy);
+void dw_dphy_write(struct dw_dphy_rx *dphy, u32 address, u32 data);
+u32 dw_dphy_read(struct dw_dphy_rx *dphy, u32 address);
+int dw_dphy_te_read(struct dw_dphy_rx *dphy, u32 addr);
+
+//#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+u32 dw_dphy_if_read(struct dw_dphy_rx *dphy, u32 address);
+int dw_dphy_if_get_idelay(struct dw_dphy_rx *dphy);
+int dw_dphy_if_set_idelay_lane(struct dw_dphy_rx *dphy, u8 dly, u8 lane);
+int dw_dphy_create_capabilities_sysfs(struct platform_device *pdev);
+int dw_dphy_remove_capabilities_sysfs(struct platform_device *pdev);
+
+static inline
+u32 dw_dphy_if_read_msk(struct dw_dphy_rx *dphy,
+			u32 address, u8 shift, u8 width)
+{
+	return (dw_dphy_if_read(dphy, address) >> shift) & ((1 << width) - 1);
+}
+//#endif /*IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)*/
+
+static inline struct phy *dw_dphy_xlate(struct device *dev,
+					struct of_phandle_args *args)
+{
+	struct dw_dphy_rx *dphy = dev_get_drvdata(dev);
+
+	return dphy->phy;
+}
+
+static inline
+u32 dw_dphy_read_msk(struct dw_dphy_rx *dev, u32 address, u8 shift,  u8 width)
+{
+	return (dw_dphy_read(dev, address) >> shift) & ((1 << width) - 1);
+}
+#endif /*__PHY_SNPS_DPHY_RX_H__*/

+ 290 - 0
driver/csi/dw-dphy-sysfs.c

@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI D-PHY controller driver.
+ * SysFS components for the platform driver
+ *
+ * Author: Luis Oliveira <luis.oliveira@synopsys.com>
+ */
+
+//#define DEBUG    1
+#include "dw-dphy-rx.h"
+#include "bm_csi_hw.h"
+
+static ssize_t dphy_reset_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[15];
+
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
+	usleep_range(100, 200);
+	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t dphy_freq_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf,
+			       size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+
+	ret = kstrtoul(buf, 10, &freq);
+	if (ret < 0)
+		return ret;
+
+	if (freq > 2500) {
+		dev_info(dev, "Freq must be under 2500 Mhz\n");
+		return count;
+	}
+	if (freq < 80) {
+		dev_info(dev, "Freq must be over 80 Mhz\n");
+		return count;
+	}
+
+	dev_vdbg(dev, "Data Rate %lu Mbps\n", freq);
+	dphy->dphy_freq = freq*1000;
+
+	return count;
+}
+
+static ssize_t dphy_freq_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[15];
+
+	snprintf(buffer,
+		 sizeof(buffer),
+		 "Freq %d\n", dphy->dphy_freq);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t dphy_addr_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[100];
+    unsigned long addr;
+    unsigned long data;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &addr);
+	if (ret < 0) {
+		return ret;
+    }
+
+    data = dw_dphy_read(dphy, addr);
+
+    snprintf(buffer,
+		 sizeof(buffer),
+		 "reg_0x%x = 0x%x\n", addr, data);
+
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+
+static ssize_t dphy_addr_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf,
+			       size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	unsigned long addr;
+    unsigned long data;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &addr);
+
+	if (ret < 0) {
+		return ret;
+    }
+
+    data = addr & 0xff;
+    addr &= 0xfff00;
+    addr = addr >> 8;
+
+	dw_dphy_write(dphy, addr, data);
+    printk("dphy write reg_0x%x = 0x%x", addr, data);
+
+
+	return count;
+}
+
+
+
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+#if 0
+static ssize_t idelay_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[15];
+
+	snprintf(buffer,
+		 sizeof(buffer), "idelay %d\n", dw_dphy_if_get_idelay(dphy));
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t idelay_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	unsigned long val;
+	u8 lane, delay;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret < 0)
+		return ret;
+
+	lane = (u8)val;
+	delay = (u8)(val >> 8);
+
+	dev_vdbg(dev, "Lanes %u\n", lane);
+	dev_vdbg(dev, "Delay %u\n", delay);
+
+	dw_dphy_if_set_idelay_lane(dphy, delay, lane);
+
+	return count;
+}
+#endif
+#endif
+
+static ssize_t len_config_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	unsigned long length;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &length);
+	if (ret < 0)
+		return ret;
+
+	if (length == BIT8)
+		dev_vdbg(dev, "Configured for 8-bit interface\n");
+	else if (length == BIT12)
+		dev_vdbg(dev, "Configured for 12-bit interface\n");
+	else
+		return count;
+
+	dphy->dphy_te_len = length;
+
+	return count;
+}
+
+static ssize_t len_config_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[20];
+
+	snprintf(buffer, sizeof(buffer), "Length %d\n", dphy->dphy_te_len);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static ssize_t dw_dphy_g118_settle_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	unsigned long lp_time;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &lp_time);
+	if (ret < 0)
+		return ret;
+
+	if (lp_time > 1 && lp_time < 10000) {
+		dphy->lp_time = lp_time;
+	} else {
+		dev_vdbg(dev, "Invalid Value configuring for 1000 ns\n");
+		dphy->lp_time = 1000;
+	}
+
+	dphy->lp_time = lp_time;
+
+	return count;
+}
+
+static ssize_t dw_dphy_g118_settle_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+    struct bm_csi_drvdata *drvdata  = platform_get_drvdata(pdev);
+	struct dw_dphy_rx *dphy = drvdata->dphy;
+	char buffer[10];
+
+	snprintf(buffer, sizeof(buffer), "Settle %d ns\n", dphy->lp_time);
+
+	return strlcpy(buf, buffer, PAGE_SIZE);
+}
+
+static DEVICE_ATTR_RO(dphy_reset);
+static DEVICE_ATTR_RW(dphy_freq);
+static DEVICE_ATTR_RW(dphy_addr);
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+//static DEVICE_ATTR_RW(idelay);
+#endif
+static DEVICE_ATTR_RW(len_config);
+static DEVICE_ATTR_RW(dw_dphy_g118_settle);
+
+int dw_dphy_create_capabilities_sysfs(struct platform_device *pdev)
+{
+	device_create_file(&pdev->dev, &dev_attr_dphy_reset);
+	device_create_file(&pdev->dev, &dev_attr_dphy_freq);
+	device_create_file(&pdev->dev, &dev_attr_dphy_addr);
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+//	device_create_file(&pdev->dev, &dev_attr_idelay);
+#endif
+	device_create_file(&pdev->dev, &dev_attr_len_config);
+	device_create_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
+	return 0;
+}
+
+int dw_dphy_remove_capabilities_sysfs(struct platform_device *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_dphy_reset);
+	device_remove_file(&pdev->dev, &dev_attr_dphy_freq);
+	device_remove_file(&pdev->dev, &dev_attr_dphy_addr);
+#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+//	device_create_file(&pdev->dev, &dev_attr_idelay);
+#endif
+	device_remove_file(&pdev->dev, &dev_attr_len_config);
+	device_remove_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
+	return 0;
+}

+ 104 - 0
driver/csi/dw-mipi-csi-pltfrm.h

@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host media entities
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#ifndef __DW_MIPI_CSI_PLTFRM_INCLUDES_H_
+#define __DW_MIPI_CSI_PLTFRM_INCLUDES_H_
+
+#include <media/media-entity.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+#define MAX_WIDTH	3280
+#define MAX_HEIGHT	1852
+
+/* The subdevices' group IDs. */
+#define GRP_ID_SENSOR		(10)
+#define GRP_ID_CSI		(20)
+#define GRP_ID_VIF		(30)
+#define GRP_ID_VIDEODEV		(40)
+
+#define CSI_MAX_ENTITIES	(2)
+#define VIF_MAX_ENTITIES	(2)
+#define PLAT_MAX_SENSORS	(2)
+
+struct pdata_names {
+	char *name;
+};
+
+enum video_dev_pads {
+	VIDEO_DEV_SD_PAD_SINK_VIF1,
+	VIDEO_DEV_SD_PAD_SINK_VIF2,
+	VIDEO_DEV_SD_PAD_SOURCE_DMA,
+	VIDEO_DEV_SD_PADS_NUM,
+};
+
+enum vif_pads {
+	VIF_PAD_SINK_CSI,
+	VIF_PAD_SOURCE_DMA,
+	VIF_PADS_NUM,
+};
+
+enum mipi_csi_pads {
+	CSI_PAD_SINK,
+	CSI_PAD_SOURCE,
+	CSI_PADS_NUM,
+};
+
+struct plat_csi_source_info {
+	u16 flags;
+	u16 mux_id;
+};
+
+struct plat_csi_fmt {
+	char *name;
+	u32 mbus_code;
+	u32 fourcc;
+	u8 depth;
+};
+
+struct plat_csi_media_pipeline;
+
+/*
+ * Media pipeline operations to be called from within a video node,  i.e. the
+ * last entity within the pipeline. Implemented by related media device driver.
+ */
+struct plat_csi_media_pipeline_ops {
+	int (*prepare)(struct plat_csi_media_pipeline *p,
+		       struct media_entity *me);
+	int (*unprepare)(struct plat_csi_media_pipeline *p);
+	int (*open)(struct plat_csi_media_pipeline *p, struct media_entity *me,
+		    bool resume);
+	int (*close)(struct plat_csi_media_pipeline *p);
+	int (*set_stream)(struct plat_csi_media_pipeline *p, bool state);
+	int (*set_format)(struct plat_csi_media_pipeline *p,
+			  struct v4l2_subdev_format *fmt);
+};
+
+struct plat_csi_video_entity {
+	struct video_device vdev;
+	struct plat_csi_media_pipeline *pipe;
+};
+
+struct plat_csi_media_pipeline {
+	struct media_pipeline mp;
+	const struct plat_csi_media_pipeline_ops *ops;
+};
+
+static inline struct plat_csi_video_entity
+*vdev_to_plat_csi_video_entity(struct video_device *vdev)
+{
+	return container_of(vdev, struct plat_csi_video_entity, vdev);
+}
+
+#define plat_csi_pipeline_call(ent, op, args...)			  \
+	(!(ent) ? -ENOENT : (((ent)->pipe->ops && (ent)->pipe->ops->op) ? \
+	(ent)->pipe->ops->op(((ent)->pipe), ##args) : -ENOIOCTLCMD))	  \
+
+#endif /* __DW_MIPI_CSI_PLTFRM_INCLUDES_H_ */

+ 757 - 0
driver/csi/dw-mipi-csi.c

@@ -0,0 +1,757 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host controller driver
+ * Core MIPI CSI-2 functions
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#include "dw-mipi-csi.h"
+
+static struct R_CSI2 reg = {
+	.VERSION = 0x00,
+	.N_LANES = 0x04,
+	.CTRL_RESETN = 0x08,
+	.INTERRUPT = 0x0C,
+	.DATA_IDS_1 = 0x10,
+	.DATA_IDS_2 = 0x14,
+	.IPI_MODE = 0x80,
+	.IPI_VCID = 0x84,
+	.IPI_DATA_TYPE = 0x88,
+	.IPI_MEM_FLUSH = 0x8C,
+	.IPI_HSA_TIME = 0x90,
+	.IPI_HBP_TIME = 0x94,
+	.IPI_HSD_TIME = 0x98,
+	.IPI_HLINE_TIME = 0x9C,
+	.IPI_SOFTRSTN = 0xA0,
+	.IPI_ADV_FEATURES = 0xAC,
+	.IPI_VSA_LINES = 0xB0,
+	.IPI_VBP_LINES = 0xB4,
+	.IPI_VFP_LINES = 0xB8,
+	.IPI_VACTIVE_LINES = 0xBC,
+	.INT_PHY_FATAL = 0xe0,
+	.MASK_INT_PHY_FATAL = 0xe4,
+	.FORCE_INT_PHY_FATAL = 0xe8,
+	.INT_PKT_FATAL = 0xf0,
+	.MASK_INT_PKT_FATAL = 0xf4,
+	.FORCE_INT_PKT_FATAL = 0xf8,
+	.INT_PHY = 0x110,
+	.MASK_INT_PHY = 0x114,
+	.FORCE_INT_PHY = 0x118,
+	.INT_LINE = 0x130,
+	.MASK_INT_LINE = 0x134,
+	.FORCE_INT_LINE = 0x138,
+	.INT_IPI = 0x140,
+	.MASK_INT_IPI = 0x144,
+	.FORCE_INT_IPI = 0x148,
+	.IPI2_MODE = 0x200,
+	.IPI3_MODE = 0x220,
+	.IPI2_VCID = 0x204,
+	.IPI3_VCID = 0x224,
+	.IPI2_DATA_TYPE = 0x208,
+	.IPI3_DATA_TYPE = 0x228,
+	.IPI2_MEM_FLUSH = 0x20c,
+	.IPI3_MEM_FLUSH = 0x22c,
+    .IPI2_HSA_TIME = 0x210,
+	.IPI2_HBP_TIME = 0x214,
+	.IPI2_HSD_TIME = 0x218,
+    .IPI3_HSA_TIME = 0x230,
+	.IPI3_HBP_TIME = 0x234,
+	.IPI3_HSD_TIME = 0x238,
+	.IPI2_ADV_FEATURES = 0x21c,
+	.IPI3_ADV_FEATURES = 0x23c,
+	.IPI2_INT_PHY_FATAL = 0x150,
+	.IPI3_INT_PHY_FATAL = 0x160,
+	.IPI2_MASK_INT_PHY_FATAL = 0x154,
+	.IPI3_MASK_INT_PHY_FATAL = 0x164,
+};
+
+struct interrupt_type csi_int = {
+	.PHY_FATAL = BIT(0),
+	.PKT_FATAL = BIT(1),
+	.PHY = BIT(16),
+};
+
+#define dw_print(VAR) \
+	dev_info(csi_dev->dev, "%s: 0x%x: %X\n", "##VAR##",\
+	VAR, dw_mipi_csi_read(csi_dev, VAR))
+
+void dw_mipi_csi_write_part(struct dw_csi *dev, u32 address, u32 data,
+			    u8 shift, u8 width)
+{
+	u32 mask = (1 << width) - 1;
+	u32 temp = dw_mipi_csi_read(dev, address);
+
+	temp &= ~(mask << shift);
+	temp |= (data & mask) << shift;
+	dw_mipi_csi_write(dev, address, temp);
+}
+
+void dw_mipi_csi_reset(struct dw_csi *csi_dev)
+{
+	dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 0);
+	usleep_range(100, 200);
+	dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 1);
+}
+
+int dw_mipi_csi_mask_irq_power_off(struct dw_csi *csi_dev)
+{
+	if (csi_dev->hw_version_major == 1) {
+		/* set only one lane (lane 0) as active (ON) */
+		dw_mipi_csi_write(csi_dev, reg.N_LANES, 0);
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY_FATAL, 0);
+		dw_mipi_csi_write(csi_dev, reg.IPI2_MASK_INT_PHY_FATAL, 0);
+		dw_mipi_csi_write(csi_dev, reg.IPI3_MASK_INT_PHY_FATAL, 0);
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PKT_FATAL, 0);
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY, 0);
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_LINE, 0);
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_IPI, 0);
+
+		/* only for version 1.30 */
+		if (csi_dev->hw_version_minor == 30)
+			dw_mipi_csi_write(csi_dev,
+					  reg.MASK_INT_FRAME_FATAL, 0);
+
+		dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 0);
+
+		/* only for version 1.40 */
+		if (csi_dev->hw_version_minor == 40) {
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_BNDRY_FRAME_FATAL, 0);
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_SEQ_FRAME_FATAL, 0);
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_CRC_FRAME_FATAL, 0);
+			dw_mipi_csi_write(csi_dev, reg.MSK_PLD_CRC_FATAL, 0);
+			dw_mipi_csi_write(csi_dev, reg.MSK_DATA_ID, 0);
+			dw_mipi_csi_write(csi_dev, reg.MSK_ECC_CORRECT, 0);
+		}
+	}
+
+	return 0;
+}
+
+int dw_mipi_csi_hw_stdby(struct dw_csi *csi_dev)
+{
+	if (csi_dev->hw_version_major == 1) {
+		/* set only one lane (lane 0) as active (ON) */
+		dw_mipi_csi_reset(csi_dev);
+		dw_mipi_csi_write(csi_dev, reg.N_LANES, 0);
+		phy_init(csi_dev->phy);
+
+		/* only for version 1.30 */
+		if (csi_dev->hw_version_minor == 30)
+			dw_mipi_csi_write(csi_dev,
+					  reg.MASK_INT_FRAME_FATAL,
+					  GENMASK(31, 0));
+
+		/* common */
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY_FATAL,
+				  GENMASK(8, 0));
+
+		dw_mipi_csi_write(csi_dev, reg.IPI2_MASK_INT_PHY_FATAL,
+				  GENMASK(8, 0));
+
+		dw_mipi_csi_write(csi_dev, reg.IPI3_MASK_INT_PHY_FATAL,
+				  GENMASK(8, 0));
+
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PKT_FATAL,
+				  GENMASK(1, 0));
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY, GENMASK(23, 0));
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_LINE, GENMASK(23, 0));
+		dw_mipi_csi_write(csi_dev, reg.MASK_INT_IPI, GENMASK(5, 0));
+
+		/* only for version 1.40 */
+		if (csi_dev->hw_version_minor == 40) {
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_BNDRY_FRAME_FATAL,
+					  GENMASK(31, 0));
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_SEQ_FRAME_FATAL,
+					  GENMASK(31, 0));
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_CRC_FRAME_FATAL,
+					  GENMASK(31, 0));
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_PLD_CRC_FATAL,
+					  GENMASK(31, 0));
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_DATA_ID, GENMASK(31, 0));
+			dw_mipi_csi_write(csi_dev,
+					  reg.MSK_ECC_CORRECT, GENMASK(31, 0));
+		}
+	}
+	return 0;
+}
+
+void dw_mipi_csi_set_ipi_fmt(struct dw_csi *csi_dev)
+{
+	struct device *dev = csi_dev->dev;
+
+	if (csi_dev->ipi_dt) {
+		dw_mipi_csi_write(csi_dev, reg.IPI_DATA_TYPE, csi_dev->ipi_dt);
+		dw_mipi_csi_write(csi_dev, reg.IPI2_DATA_TYPE, csi_dev->ipi_dt);
+		dw_mipi_csi_write(csi_dev, reg.IPI3_DATA_TYPE, csi_dev->ipi_dt);
+
+		/*switch (csi_dev->ipi_dt) {
+		case CSI_2_YUV420_8:
+		//case CSI_2_YUV420_8_LEG:
+		case CSI_2_YUV420_8_SHIFT:
+		break;
+		case CSI_2_YUV420_10:
+		case CSI_2_YUV420_10_SHIFT:
+		break;
+		}*/
+	} else {
+		switch (csi_dev->fmt->mbus_code) {
+
+		case MEDIA_BUS_FMT_RGB666_1X18:
+		csi_dev->ipi_dt =  CSI_2_RGB666;
+		break;
+
+		case MEDIA_BUS_FMT_RGB565_2X8_BE:
+		case MEDIA_BUS_FMT_RGB565_2X8_LE:
+		csi_dev->ipi_dt = CSI_2_RGB565;
+		break;
+
+		case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+		case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+		csi_dev->ipi_dt = CSI_2_RGB555;
+		break;
+
+		case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
+		case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
+		csi_dev->ipi_dt = CSI_2_RGB444;
+		break;
+
+		break;
+		case MEDIA_BUS_FMT_RGB888_2X12_LE:
+		case MEDIA_BUS_FMT_RGB888_2X12_BE:
+		csi_dev->ipi_dt = CSI_2_RGB888;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR10_1X10:
+		case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+		csi_dev->ipi_dt = CSI_2_RAW10;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR12_1X12:
+		csi_dev->ipi_dt = CSI_2_RAW12;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR14_1X14:
+		csi_dev->ipi_dt = CSI_2_RAW14;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR16_1X16:
+		csi_dev->ipi_dt = CSI_2_RAW16;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR8_1X8:
+		csi_dev->ipi_dt = CSI_2_RAW8;
+		break;
+
+		case MEDIA_BUS_FMT_YVYU8_1X16:
+		csi_dev->ipi_dt = CSI_2_YUV422_8;
+		break;
+
+		case MEDIA_BUS_FMT_VYUY8_1X16:
+		csi_dev->ipi_dt = CSI_2_YUV422_8;
+		break;
+
+		case MEDIA_BUS_FMT_UYVY10_1X20:
+		csi_dev->ipi_dt = CSI_2_YUV422_10;
+		break;
+
+		case MEDIA_BUS_FMT_YUYV8_1X16:
+		csi_dev->ipi_dt = CSI_2_YUV420_8_LEG;
+		break;
+
+		case MEDIA_BUS_FMT_UYVY8_1X16:
+		csi_dev->ipi_dt = CSI_2_YUV420_8;
+		break;
+
+		case MEDIA_BUS_FMT_VUY8_1X24:
+		csi_dev->ipi_dt = CSI_2_YUV420_10;
+		break;
+
+		case MEDIA_BUS_FMT_Y8_1X8:
+		csi_dev->ipi_dt = CSI_2_RAW8;
+		break;
+
+		case MEDIA_BUS_FMT_Y10_1X10:
+		csi_dev->ipi_dt = CSI_2_RAW8;
+		break;
+#if 0/*modify by wuyi*/
+		case MEDIA_BUS_FMT_SBGGR6_1X8:
+		csi_dev->ipi_dt = CSI_2_RAW6;
+		break;
+
+		case MEDIA_BUS_FMT_SBGGR7_1X8:
+		csi_dev->ipi_dt = CSI_2_RAW7;
+		break;
+#endif
+		default:
+		break;
+		}
+		dw_mipi_csi_write(csi_dev, reg.IPI_DATA_TYPE, csi_dev->ipi_dt);
+		dw_mipi_csi_write(csi_dev, reg.IPI2_DATA_TYPE, csi_dev->ipi_dt);
+		dw_mipi_csi_write(csi_dev, reg.IPI3_DATA_TYPE, csi_dev->ipi_dt);
+	}
+	dev_info(dev, "Selected IPI Data Type 0x%X\n", csi_dev->ipi_dt);
+}
+
+void dw_mipi_csi_fill_timings(struct dw_csi *dev, uint32_t width, uint32_t height)
+{
+	dev->hw.virtual_ch = 0;
+	dev->hw.ipi_color_mode = COLOR48;
+	dev->hw.ipi_auto_flush = 1;
+	dev->hw.ipi_mode = CAMERA_TIMING;
+	dev->hw.ipi_cut_through = CTINACTIVE;
+	dev->hw.ipi_adv_features = LINE_EVENT_SELECTION(EVSELAUTO);
+	dev->hw.htotal = width + dev->hw.hsa +
+			 dev->hw.hbp + dev->hw.hsd;
+	dev->hw.vactive = height;
+	dev->hw.output = 2;
+    dev->hw.ipi1_en = false;
+
+    dev_dbg(dev->dev, "*********** timings *********\n");
+	dev_dbg(dev->dev, "Horizontal Sync Active: %d\n", dev->hw.hsa);
+	dev_dbg(dev->dev, "Horizontal Back Porch: %d\n", dev->hw.hbp);
+	dev_dbg(dev->dev, "Horizontal Width: %d\n", width);
+	dev_dbg(dev->dev, "Horizontal Total: %d\n", dev->hw.htotal);
+	dev_dbg(dev->dev, "Vertical Sync Active: %d\n", dev->hw.vsa);
+	dev_dbg(dev->dev, "Vertical Back Porch: %d\n", dev->hw.vbp);
+	dev_dbg(dev->dev, "Vertical Front Porch: %d\n", dev->hw.vfp);
+	dev_dbg(dev->dev, "Vertical Active: %d\n", dev->hw.vactive);
+}
+
+void dw_mipi_csi_stop(struct dw_csi *csi_dev)
+{
+	/*  address | data, | shift | width */
+        if (csi_dev->hw.ipi1_en == 0) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI_MODE, 0, 24, 1);
+        }
+
+        if (csi_dev->hw.ipi2_en == 0) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI2_MODE, 0, 24, 1);
+        }
+
+        if (csi_dev->hw.ipi3_en == 0) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI3_MODE, 0, 24, 1);
+        }
+}
+
+void dw_mipi_csi_start(struct dw_csi *csi_dev)
+{
+	struct device *dev = csi_dev->dev;
+
+	dw_mipi_csi_write(csi_dev, reg.N_LANES, (csi_dev->hw.num_lanes - 1));
+	dev_info(dev, "number of lanes: %d\n", csi_dev->hw.num_lanes);
+
+	/* IPI Related Configuration */
+	if (csi_dev->hw.output == IPI_OUT || csi_dev->hw.output == BOTH_OUT) {
+		if (csi_dev->hw_version_major >= 1) {
+			if (csi_dev->hw_version_minor >= 21) {
+				dw_mipi_csi_write(csi_dev,
+						  reg.IPI_ADV_FEATURES,
+						  csi_dev->hw.ipi_adv_features);
+                dw_mipi_csi_write(csi_dev,
+						  reg.IPI2_ADV_FEATURES,
+						  csi_dev->hw.ipi_adv_features);
+                dw_mipi_csi_write(csi_dev,
+						  reg.IPI3_ADV_FEATURES,
+						  csi_dev->hw.ipi_adv_features);
+
+            }
+
+			if (csi_dev->hw_version_minor >= 30) {
+				dw_mipi_csi_write(csi_dev,
+						  reg.IPI_SOFTRSTN, 0x1 | (0x1 << 4) | (0x1 << 8));
+            }
+		}
+		/*  address | data, | shift | width */
+        if (csi_dev->hw.ipi1_en) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI_MODE, 1, 24, 1);
+        }
+
+        if (csi_dev->hw.ipi2_en) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI2_MODE, 1, 24, 1);
+        }
+
+        if (csi_dev->hw.ipi3_en) {
+		    dw_mipi_csi_write_part(csi_dev, reg.IPI3_MODE, 1, 24, 1);
+        }
+
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI_MODE,
+				       csi_dev->hw.ipi_mode,
+				       0, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI2_MODE,
+				       csi_dev->hw.ipi_mode,
+				       0, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI3_MODE,
+				       csi_dev->hw.ipi_mode,
+				       0, 1);
+
+		if (csi_dev->hw.ipi_mode == CAMERA_TIMING) {
+			dw_mipi_csi_write(csi_dev,
+					  reg.IPI_ADV_FEATURES,
+					  LINE_EVENT_SELECTION(EVSELPROG) |
+					  EN_VIDEO);
+                      /*
+					  EN_VIDEO |
+					  EN_LINE_START |
+					  EN_NULL |
+					  EN_BLANKING |
+					  EN_EMBEDDED);
+                      */
+
+            dw_mipi_csi_write(csi_dev,
+					  reg.IPI2_ADV_FEATURES,
+					  LINE_EVENT_SELECTION(EVSELPROG) |
+					  EN_VIDEO |
+					  EN_LINE_START |
+					  EN_NULL |
+					  EN_BLANKING |
+					  EN_EMBEDDED);
+
+            dw_mipi_csi_write(csi_dev,
+					  reg.IPI3_ADV_FEATURES,
+					  LINE_EVENT_SELECTION(EVSELPROG) |
+					  EN_VIDEO |
+					  EN_LINE_START |
+					  EN_NULL |
+					  EN_BLANKING |
+					  EN_EMBEDDED);
+		}
+
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI_MODE,
+				       csi_dev->hw.ipi_color_mode,
+				       8, 1);
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI_MODE,
+				       csi_dev->hw.ipi_cut_through,
+				       16, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI2_MODE,
+				       csi_dev->hw.ipi_color_mode,
+				       8, 1);
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI2_MODE,
+				       csi_dev->hw.ipi_cut_through,
+				       16, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI3_MODE,
+				       csi_dev->hw.ipi_color_mode,
+				       8, 1);
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI3_MODE,
+				       csi_dev->hw.ipi_cut_through,
+				       16, 1);
+
+
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI_VCID,
+				       csi_dev->hw.virtual_ch,
+				       0, 2);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI2_VCID,
+				       csi_dev->hw.ipi2_virtual_ch,
+				       0, 2);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI3_VCID,
+				       csi_dev->hw.ipi3_virtual_ch,
+				       0, 2);
+
+		dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI_MEM_FLUSH,
+				       csi_dev->hw.ipi_auto_flush,
+				       8, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI2_MEM_FLUSH,
+				       csi_dev->hw.ipi_auto_flush,
+				       8, 1);
+        dw_mipi_csi_write_part(csi_dev,
+				       reg.IPI3_MEM_FLUSH,
+				       csi_dev->hw.ipi_auto_flush,
+				       8, 1);
+
+		dev_vdbg(dev, "*********** config *********\n");
+		dev_vdbg(dev, "IPI enable: %s\n",
+			 csi_dev->hw.output ? "YES" : "NO");
+		dev_vdbg(dev, "video mode transmission type: %s timming\n",
+			 csi_dev->hw.ipi_mode ? "controller" : "camera");
+		dev_vdbg(dev, "Color Mode: %s\n",
+			 csi_dev->hw.ipi_color_mode ? "16 bits" : "48 bits");
+		dev_vdbg(dev, "Cut Through Mode: %s\n",
+			 csi_dev->hw.ipi_cut_through ? "enable" : "disable");
+		dev_vdbg(dev, "IPI1 Virtual Channel: %d\n",
+			 csi_dev->hw.virtual_ch);
+        dev_vdbg(dev, "IPI2 Virtual Channel: %d\n",
+			 csi_dev->hw.ipi2_virtual_ch);
+        dev_vdbg(dev, "IPI3 Virtual Channel: %d\n",
+			 csi_dev->hw.ipi3_virtual_ch);
+
+		dev_vdbg(dev, "Auto-flush: %d\n",
+			 csi_dev->hw.ipi_auto_flush);
+		dw_mipi_csi_write(csi_dev, reg.IPI_SOFTRSTN, 0x1 | (0x1 << 4) | (0x1 << 8));
+
+		if (csi_dev->hw.ipi_mode == AUTO_TIMING)
+			phy_power_on(csi_dev->phy);
+
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_HSA_TIME, csi_dev->hw.hsa);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_HBP_TIME, csi_dev->hw.hbp);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_HSD_TIME, csi_dev->hw.hsd);
+
+        dw_mipi_csi_write(csi_dev,
+				  reg.IPI2_HSA_TIME, csi_dev->hw.ipi2_hsa);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI2_HBP_TIME, csi_dev->hw.ipi2_hbp);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI2_HSD_TIME, csi_dev->hw.ipi2_hsd);
+
+        dw_mipi_csi_write(csi_dev,
+				  reg.IPI3_HSA_TIME, csi_dev->hw.ipi3_hsa);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI3_HBP_TIME, csi_dev->hw.ipi3_hbp);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI3_HSD_TIME, csi_dev->hw.ipi3_hsd);
+
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_HLINE_TIME, csi_dev->hw.htotal);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_VSA_LINES, csi_dev->hw.vsa);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_VBP_LINES, csi_dev->hw.vbp);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_VFP_LINES, csi_dev->hw.vfp);
+		dw_mipi_csi_write(csi_dev,
+				  reg.IPI_VACTIVE_LINES, csi_dev->hw.vactive);
+	}
+	phy_power_on(csi_dev->phy);
+}
+
+int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev)
+{
+	struct device *dev = csi_dev->dev;
+	u32 global_int_status, i_sts;
+	unsigned long flags;
+
+	spin_lock_irqsave(&csi_dev->slock, flags);
+	global_int_status = dw_mipi_csi_read(csi_dev, reg.INTERRUPT);
+
+	if (global_int_status & csi_int.PHY_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY_FATAL);
+		dev_err_ratelimited(dev, "int %08X: PHY FATAL: %08X\n",
+				    reg.INT_PHY_FATAL, i_sts);
+
+        i_sts = dw_mipi_csi_read(csi_dev, reg.IPI2_INT_PHY_FATAL);
+		dev_err_ratelimited(dev, "int %08X: IPI2 PHY FATAL: %08X\n",
+				    reg.IPI2_INT_PHY_FATAL, i_sts);
+
+        i_sts = dw_mipi_csi_read(csi_dev, reg.IPI3_INT_PHY_FATAL);
+		dev_err_ratelimited(dev, "int %08X: IPI2 PHY FATAL: %08X\n",
+				    reg.IPI3_INT_PHY_FATAL, i_sts);
+
+	}
+
+	if (global_int_status & csi_int.PKT_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT_FATAL);
+		dev_err_ratelimited(dev, "int %08X: PKT FATAL: %08X\n",
+				    reg.INT_PKT_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.FRAME_FATAL &&
+	    csi_dev->hw_version_major == 1 &&
+	    csi_dev->hw_version_minor == 30) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_FRAME_FATAL);
+		dev_err_ratelimited(dev, "int %08X: FRAME FATAL: %08X\n",
+				    reg.INT_FRAME_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.PHY) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY);
+		dev_err_ratelimited(dev, "int %08X: PHY: %08X\n",
+				    reg.INT_PHY, i_sts);
+	}
+
+	if (global_int_status & csi_int.PKT &&
+	    csi_dev->hw_version_major == 1 &&
+	    csi_dev->hw_version_minor <= 30) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT);
+		dev_err_ratelimited(dev, "int %08X: PKT: %08X\n",
+				    reg.INT_PKT, i_sts);
+	}
+
+	if (global_int_status & csi_int.LINE) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_LINE);
+		dev_err_ratelimited(dev, "int %08X: LINE: %08X\n",
+				    reg.INT_LINE, i_sts);
+	}
+
+	if (global_int_status & csi_int.IPI) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_IPI);
+		dev_err_ratelimited(dev, "int %08X: IPI: %08X\n",
+				    reg.INT_IPI, i_sts);
+	}
+
+	if (global_int_status & csi_int.BNDRY_FRAME_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_BNDRY_FRAME_FATAL);
+		dev_err_ratelimited(dev,
+				    "int %08X: ST_BNDRY_FRAME_FATAL: %08X\n",
+				    reg.ST_BNDRY_FRAME_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.SEQ_FRAME_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_SEQ_FRAME_FATAL);
+		dev_err_ratelimited(dev,
+				    "int %08X: ST_SEQ_FRAME_FATAL: %08X\n",
+				    reg.ST_SEQ_FRAME_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.CRC_FRAME_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_CRC_FRAME_FATAL);
+		dev_err_ratelimited(dev,
+				    "int %08X: ST_CRC_FRAME_FATAL: %08X\n",
+				    reg.ST_CRC_FRAME_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.PLD_CRC_FATAL) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_PLD_CRC_FATAL);
+		dev_err_ratelimited(dev,
+				    "int %08X: ST_PLD_CRC_FATAL: %08X\n",
+				    reg.ST_PLD_CRC_FATAL, i_sts);
+	}
+
+	if (global_int_status & csi_int.DATA_ID) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_DATA_ID);
+		dev_err_ratelimited(dev, "int %08X: ST_DATA_ID: %08X\n",
+				    reg.ST_DATA_ID, i_sts);
+	}
+
+	if (global_int_status & csi_int.ECC_CORRECTED) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_ECC_CORRECT);
+		dev_err_ratelimited(dev, "int %08X: ST_ECC_CORRECT: %08X\n",
+				    reg.ST_ECC_CORRECT, i_sts);
+	}
+
+	spin_unlock_irqrestore(&csi_dev->slock, flags);
+
+	return 1;
+}
+
+void dw_mipi_csi_get_version(struct dw_csi *csi_dev)
+{
+	u32 hw_version;
+
+	hw_version = dw_mipi_csi_read(csi_dev, reg.VERSION);
+	csi_dev->hw_version_major = (u8)((hw_version >> 24) - '0');
+	csi_dev->hw_version_minor = (u8)((hw_version >> 16) - '0');
+	csi_dev->hw_version_minor = csi_dev->hw_version_minor * 10;
+	csi_dev->hw_version_minor += (u8)((hw_version >> 8) - '0');
+}
+
+int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev)
+{
+	struct device *dev = csi_dev->dev;
+
+	if (csi_dev->hw_version_major == 1) {
+		if (csi_dev->hw_version_minor == 30) {
+			/*
+			 * Hardware registers that were
+			 * exclusive to version < 1.40
+			 */
+			reg.INT_FRAME_FATAL = 0x100;
+			reg.MASK_INT_FRAME_FATAL = 0x104;
+			reg.FORCE_INT_FRAME_FATAL = 0x108;
+			reg.INT_PKT = 0x120;
+			reg.MASK_INT_PKT = 0x124;
+			reg.FORCE_INT_PKT = 0x128;
+
+			/* interrupt source present until this release */
+			csi_int.PKT = BIT(17);
+			csi_int.LINE = BIT(18);
+			csi_int.IPI = BIT(19);
+			csi_int.FRAME_FATAL = BIT(2);
+
+		} else if (csi_dev->hw_version_minor == 40) {
+			/*
+			 * HW registers that were added
+			 * to version 1.40
+			 */
+			reg.ST_BNDRY_FRAME_FATAL = 0x280;
+			reg.MSK_BNDRY_FRAME_FATAL = 0x284;
+			reg.FORCE_BNDRY_FRAME_FATAL = 0x288;
+			reg.ST_SEQ_FRAME_FATAL = 0x290;
+			reg.MSK_SEQ_FRAME_FATAL	= 0x294;
+			reg.FORCE_SEQ_FRAME_FATAL = 0x298;
+			reg.ST_CRC_FRAME_FATAL = 0x2a0;
+			reg.MSK_CRC_FRAME_FATAL	= 0x2a4;
+			reg.FORCE_CRC_FRAME_FATAL = 0x2a8;
+			reg.ST_PLD_CRC_FATAL = 0x2b0;
+			reg.MSK_PLD_CRC_FATAL = 0x2b4;
+			reg.FORCE_PLD_CRC_FATAL = 0x2b8;
+			reg.ST_DATA_ID = 0x2c0;
+			reg.MSK_DATA_ID = 0x2c4;
+			reg.FORCE_DATA_ID = 0x2c8;
+			reg.ST_ECC_CORRECT = 0x2d0;
+			reg.MSK_ECC_CORRECT = 0x2d4;
+			reg.FORCE_ECC_CORRECT = 0x2d8;
+			reg.DATA_IDS_VC_1 = 0x0;
+			reg.DATA_IDS_VC_2 = 0x0;
+			reg.VC_EXTENSION = 0x0;
+
+			/* interrupts map were changed */
+			csi_int.LINE = BIT(17);
+			csi_int.IPI = BIT(18);
+			csi_int.BNDRY_FRAME_FATAL = BIT(2);
+			csi_int.SEQ_FRAME_FATAL	= BIT(3);
+			csi_int.CRC_FRAME_FATAL = BIT(4);
+			csi_int.PLD_CRC_FATAL = BIT(5);
+			csi_int.DATA_ID = BIT(6);
+			csi_int.ECC_CORRECTED = BIT(7);
+
+		} else {
+			dev_info(dev, "Version minor not supported.");
+		}
+	} else {
+		dev_info(dev, "Version major not supported.");
+	}
+	return 0;
+}
+
+void dw_mipi_csi_dump(struct dw_csi *csi_dev)
+{
+	dw_print(reg.VERSION);
+	dw_print(reg.N_LANES);
+	dw_print(reg.CTRL_RESETN);
+	dw_print(reg.INTERRUPT);
+	dw_print(reg.DATA_IDS_1);
+	dw_print(reg.DATA_IDS_2);
+	dw_print(reg.IPI_MODE);
+	dw_print(reg.IPI_VCID);
+	dw_print(reg.IPI_DATA_TYPE);
+	dw_print(reg.IPI_MEM_FLUSH);
+	dw_print(reg.IPI_HSA_TIME);
+	dw_print(reg.IPI_HBP_TIME);
+	dw_print(reg.IPI_HSD_TIME);
+	dw_print(reg.IPI_HLINE_TIME);
+	dw_print(reg.IPI_SOFTRSTN);
+	dw_print(reg.IPI_ADV_FEATURES);
+	dw_print(reg.IPI_VSA_LINES);
+	dw_print(reg.IPI_VBP_LINES);
+	dw_print(reg.IPI_VFP_LINES);
+	dw_print(reg.IPI_VACTIVE_LINES);
+	dw_print(reg.IPI_DATA_TYPE);
+	dw_print(reg.VERSION);
+	dw_print(reg.IPI_ADV_FEATURES);
+}

+ 317 - 0
driver/csi/dw-mipi-csi.h

@@ -0,0 +1,317 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 Host controller driver
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
+ */
+
+#ifndef _DW_MIPI_CSI_H__
+#define _DW_MIPI_CSI_H__
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/ratelimit.h>
+#include <linux/reset.h>
+#include <linux/videodev2.h>
+#include <linux/wait.h>
+#include <dw-mipi-csi-pltfrm.h>
+
+/* Advanced features */
+#define IPI_DT_OVERWRITE BIT(0)
+#define DATA_TYPE_OVERWRITE(dt) (((dt) & GENMASK(5, 0)) << 8)
+#define LINE_EVENT_SELECTION(n) ((n) << 16)
+
+enum line_event {
+	EVSELAUTO = 0,
+	EVSELPROG = 1,
+};
+
+#define EN_VIDEO BIT(17)
+#define EN_LINE_START BIT(18)
+#define EN_NULL BIT(19)
+#define EN_BLANKING BIT(20)
+#define EN_EMBEDDED BIT(21)
+#define IPI_SYNC_EVENT_MODE(n) ((n) << 24)
+
+enum sync_event {
+	SYNCEVFSN = 0,
+	SYNCEVFS = 1,
+};
+
+/* DW MIPI CSI-2 register addresses*/
+
+struct R_CSI2 {
+	u16 VERSION;
+	u16 N_LANES;
+	u16 CTRL_RESETN;
+	u16 INTERRUPT;
+	u16 DATA_IDS_1;
+	u16 DATA_IDS_2;
+	u16 DATA_IDS_VC_1;
+	u16 DATA_IDS_VC_2;
+	u16 IPI_MODE;
+	u16 IPI_VCID;
+	u16 IPI_DATA_TYPE;
+	u16 IPI_MEM_FLUSH;
+	u16 IPI_HSA_TIME;
+	u16 IPI_HBP_TIME;
+	u16 IPI_HSD_TIME;
+	u16 IPI_HLINE_TIME;
+	u16 IPI_SOFTRSTN;
+	u16 IPI_ADV_FEATURES;
+	u16 IPI_VSA_LINES;
+	u16 IPI_VBP_LINES;
+	u16 IPI_VFP_LINES;
+	u16 IPI_VACTIVE_LINES;
+	u16 VC_EXTENSION;
+	u16 INT_PHY_FATAL;
+	u16 MASK_INT_PHY_FATAL;
+	u16 FORCE_INT_PHY_FATAL;
+	u16 INT_PKT_FATAL;
+	u16 MASK_INT_PKT_FATAL;
+	u16 FORCE_INT_PKT_FATAL;
+	u16 INT_FRAME_FATAL;
+	u16 MASK_INT_FRAME_FATAL;
+	u16 FORCE_INT_FRAME_FATAL;
+	u16 INT_PHY;
+	u16 MASK_INT_PHY;
+	u16 FORCE_INT_PHY;
+	u16 INT_PKT;
+	u16 MASK_INT_PKT;
+	u16 FORCE_INT_PKT;
+	u16 INT_LINE;
+	u16 MASK_INT_LINE;
+	u16 FORCE_INT_LINE;
+	u16 INT_IPI;
+	u16 MASK_INT_IPI;
+	u16 FORCE_INT_IPI;
+	u16 ST_BNDRY_FRAME_FATAL;
+	u16 MSK_BNDRY_FRAME_FATAL;
+	u16 FORCE_BNDRY_FRAME_FATAL;
+	u16 ST_SEQ_FRAME_FATAL;
+	u16 MSK_SEQ_FRAME_FATAL;
+	u16 FORCE_SEQ_FRAME_FATAL;
+	u16 ST_CRC_FRAME_FATAL;
+	u16 MSK_CRC_FRAME_FATAL;
+	u16 FORCE_CRC_FRAME_FATAL;
+	u16 ST_PLD_CRC_FATAL;
+	u16 MSK_PLD_CRC_FATAL;
+	u16 FORCE_PLD_CRC_FATAL;
+	u16 ST_DATA_ID;
+	u16 MSK_DATA_ID;
+	u16 FORCE_DATA_ID;
+	u16 ST_ECC_CORRECT;
+	u16 MSK_ECC_CORRECT;
+	u16 FORCE_ECC_CORRECT;
+	u16 IPI2_MODE;
+	u16 IPI3_MODE;
+	u16 IPI2_VCID;
+	u16 IPI3_VCID;
+	u16 IPI2_DATA_TYPE;
+	u16 IPI3_DATA_TYPE;
+	u16 IPI2_MEM_FLUSH;
+	u16 IPI3_MEM_FLUSH;
+    u16 IPI2_HSA_TIME;
+	u16 IPI2_HBP_TIME;
+	u16 IPI2_HSD_TIME;
+    u16 IPI3_HSA_TIME;
+	u16 IPI3_HBP_TIME;
+	u16 IPI3_HSD_TIME;
+	u16 IPI2_ADV_FEATURES;
+	u16 IPI3_ADV_FEATURES;
+	u16 IPI2_INT_PHY_FATAL;
+	u16 IPI3_INT_PHY_FATAL;
+	u16 IPI2_MASK_INT_PHY_FATAL;
+	u16 IPI3_MASK_INT_PHY_FATAL;
+};
+
+/* Interrupt Masks */
+struct interrupt_type {
+	u32 PHY_FATAL;
+	u32 PKT_FATAL;
+	u32 FRAME_FATAL;
+	u32 PHY;
+	u32 PKT;
+	u32 LINE;
+	u32 IPI;
+	u32 BNDRY_FRAME_FATAL;
+	u32 SEQ_FRAME_FATAL;
+	u32 CRC_FRAME_FATAL;
+	u32 PLD_CRC_FATAL;
+	u32 DATA_ID;
+	u32 ECC_CORRECTED;
+};
+
+/* IPI Data Types */
+enum data_type {
+	CSI_2_YUV420_8 = 0x18,
+	CSI_2_YUV420_10 = 0x19,
+	CSI_2_YUV420_8_LEG = 0x1A,
+	CSI_2_YUV420_8_SHIFT = 0x1C,
+	CSI_2_YUV420_10_SHIFT = 0x1D,
+	CSI_2_YUV422_8 = 0x1E,
+	CSI_2_YUV422_10 = 0x1F,
+	CSI_2_RGB444 = 0x20,
+	CSI_2_RGB555 = 0x21,
+	CSI_2_RGB565 = 0x22,
+	CSI_2_RGB666 = 0x23,
+	CSI_2_RGB888 = 0x24,
+	CSI_2_RAW6 = 0x28,
+	CSI_2_RAW7 = 0x29,
+	CSI_2_RAW8 = 0x2A,
+	CSI_2_RAW10 = 0x2B,
+	CSI_2_RAW12 = 0x2C,
+	CSI_2_RAW14 = 0x2D,
+	CSI_2_RAW16 = 0x2E,
+	CSI_2_RAW20 = 0x2F,
+	USER_DEFINED_1 = 0x30,
+	USER_DEFINED_2 = 0x31,
+	USER_DEFINED_3 = 0x32,
+	USER_DEFINED_4 = 0x33,
+	USER_DEFINED_5 = 0x34,
+	USER_DEFINED_6 = 0x35,
+	USER_DEFINED_7 = 0x36,
+	USER_DEFINED_8 = 0x37,
+};
+
+/* DWC MIPI CSI-2 output types */
+enum output {
+	IPI_OUT = 0,
+	IDI_OUT = 1,
+	BOTH_OUT = 2
+};
+
+/* IPI color components */
+enum color_mode {
+	COLOR48 = 0,
+	COLOR16 = 1
+};
+
+/* IPI cut through */
+enum cut_through {
+	CTINACTIVE = 0,
+	CTACTIVE = 1
+};
+
+/* IPI output types */
+enum ipi_output {
+	CAMERA_TIMING = 0,
+	AUTO_TIMING = 1
+};
+
+/* Format template */
+struct mipi_fmt {
+	u32 mbus_code;
+	u8 depth;
+    u32 width;
+    u32 height;
+};
+
+struct mipi_dt {
+	u32 hex;
+	char *name;
+};
+
+/* CSI specific configuration */
+struct csi_data {
+	u32 num_lanes;
+	u32 dphy_freq; //MBPS
+	u32 pclk;
+	u32 fps;
+	u32 bpp;
+	u32 output;
+    bool ipi1_en;
+    bool ipi2_en;
+    bool ipi3_en;
+	u32 ipi_mode;
+	u32 ipi_adv_features;
+	u32 ipi_cut_through;
+	u32 ipi_color_mode;
+	u32 ipi_auto_flush;
+	u32 virtual_ch;
+	u32 ipi2_virtual_ch;
+	u32 ipi3_virtual_ch;
+	u32 hsa;
+	u32 hbp;
+	u32 hsd;
+    u32 ipi2_hsa;
+	u32 ipi2_hbp;
+	u32 ipi2_hsd;
+    u32 ipi3_hsa;
+	u32 ipi3_hbp;
+	u32 ipi3_hsd;
+	u32 htotal;
+	u32 vsa;
+	u32 vbp;
+	u32 vfp;
+	u32 vactive;
+};
+
+/* Structure to embed device driver information */
+struct dw_csi {
+	//struct v4l2_subdev sd;
+	//struct video_device vdev;
+	//struct v4l2_device v4l2_dev;
+	struct device *dev;
+	//struct media_pad pads[CSI_PADS_NUM];
+	struct mipi_fmt *fmt;
+	//struct v4l2_mbus_framefmt format;
+	void __iomem *base_address;
+	void __iomem *demo;
+	void __iomem *csc;
+	int ctrl_irq_number;
+	int demosaic_irq;
+	struct csi_data hw;
+	struct reset_control *rst;
+	struct phy *phy;
+	struct dw_csih_pdata *config;
+	struct mutex lock; /* protect resources sharing */
+	spinlock_t slock; /* interrupt handling lock */
+	u8 ipi_dt;
+	u8 index;
+	u8 hw_version_major;
+	u16 hw_version_minor;
+};
+
+void dw_mipi_csi_reset(struct dw_csi *csi_dev);
+int dw_mipi_csi_mask_irq_power_off(struct dw_csi *csi_dev);
+int dw_mipi_csi_hw_stdby(struct dw_csi *csi_dev);
+void dw_mipi_csi_set_ipi_fmt(struct dw_csi *csi_dev);
+void dw_mipi_csi_start(struct dw_csi *csi_dev);
+void dw_mipi_csi_stop(struct dw_csi *csi_dev);
+int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev);
+void dw_mipi_csi_get_version(struct dw_csi *csi_dev);
+int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev);
+void dw_mipi_csi_fill_timings(struct dw_csi *dev, uint32_t width, uint32_t height);
+void dw_mipi_csi_dump(struct dw_csi *csi_dev);
+
+//#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
+int dw_csi_create_capabilities_sysfs(struct platform_device *pdev);
+int dw_csi_remove_capabilities_sysfs(struct platform_device *pdev);
+//#endif
+
+int dw_mipi_csi_s_power(struct dw_csi *dev, int on);
+int dw_mipi_csi_log_status(struct dw_csi *dev);
+
+static inline void dw_mipi_csi_write(struct dw_csi *dev,
+				     u32 address, u32 data)
+{
+	writel(data, dev->base_address + address);
+}
+
+static inline u32 dw_mipi_csi_read(struct dw_csi *dev, u32 address)
+{
+	return readl(dev->base_address + address);
+}
+
+#endif /*_DW_MIPI_CSI_H__ */

+ 28 - 0
driver/demo/Makefile

@@ -0,0 +1,28 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+TARGET = bm_demo
+
+obj-m +=$(TARGET).o
+$(TARGET)-objs += bm_demo_driver.o
+
+EXTRA_CFLAGS += -I$(PWD)/./
+EXTRA_CFLAGS += -I$(PWD)/../common/include
+
+
+PWD :=$(shell pwd)
+
+all:
+	make   -C $(KERNEL) M=$(PWD)  modules
+modules_install:
+	make -C $(KERNEL_SRC) M=$(SRC) modules_install
+clean:
+	rm -rf $($(TARGET)-objs)
+	if [ -d "$(KERNEL)" ]; then \
+		make -C $(KERNEL) M=`pwd` clean; \
+	fi

+ 163 - 0
driver/demo/bm_demo_driver.c

@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <linux/of.h>
+
+
+#define BM_DEMO_NAME "bm_demo"
+#define BM_DRIVER_MAXCNT 2
+
+struct bm_demo_driver_dev
+{
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct mutex vvmutex;
+	unsigned int device_idx;
+	struct work_struct demo_wq;
+	wait_queue_head_t demo_wait;
+	int irq_num;
+	void *private;
+};
+
+#if 0
+struct work_struct* pWorkQueue = NULL;
+static unsigned int bm_demo_major = 0;
+static unsigned int bm_demo_minor = 0;
+struct class *bm_demo_class;
+static unsigned int devise_register_index = 0;
+static bool bm_demo_irq = false;
+#endif
+
+static unsigned int bm_demo_poll(struct file * filp, poll_table *wait)
+{
+	return 0;
+}
+
+void bm_demo_work(struct work_struct *work)
+{
+}
+
+irqreturn_t bm_demo_irq(int irq, void *dev_id)
+{
+	pr_info("enter %s\n", __func__);
+	return IRQ_HANDLED;
+}
+
+static int bm_demo_open(struct inode * inode, struct file * file)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+};
+
+static long bm_demo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+};
+
+static int bm_demo_release(struct inode * inode, struct file * file)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+};
+
+static int bm_demo_mmap(struct file *pFile, struct vm_area_struct *vma)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+};
+
+struct file_operations bm_demo_fops = {
+	.owner = THIS_MODULE,
+	.open = bm_demo_open,
+	.release = bm_demo_release,
+	.unlocked_ioctl = bm_demo_ioctl,
+	.mmap = bm_demo_mmap,
+	.poll = bm_demo_poll,
+};
+
+static int bm_demo_probe(struct platform_device *pdev)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+}
+
+static int bm_demo_remove(struct platform_device *pdev)
+{
+	pr_info("enter %s\n", __func__);
+	return 0;
+}
+
+static const struct of_device_id bm_demo_of_match[] = {
+	{ .compatible = "thead,bm-demo", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bm_demo_of_match);
+
+static struct platform_driver bm_demo_driver = {
+	.probe		= bm_demo_probe,
+	.remove		= bm_demo_remove,
+	.driver = {
+		.name  = BM_DEMO_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(bm_demo_of_match),
+	}
+};
+
+static int __init bm_demo_init_module(void)
+{
+	int ret = 0;
+
+	pr_info("enter %s\n", __func__);
+	ret = platform_driver_register(&bm_demo_driver);
+	if (ret) {
+		pr_err("register platform driver failed.\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void __exit bm_demo_exit_module(void)
+{
+	pr_info("enter %s\n", __func__);
+	platform_driver_unregister(&bm_demo_driver);
+}
+
+module_init(bm_demo_init_module);
+module_exit(bm_demo_exit_module);
+
+MODULE_AUTHOR("Lu Chongzhi");
+MODULE_DESCRIPTION("BAREMETAL-DEMO");
+MODULE_LICENSE("GPL");

+ 32 - 0
driver/isp/Makefile

@@ -0,0 +1,32 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+TARGET = bm_isp
+
+
+obj-m +=$(TARGET).o
+$(TARGET)-objs += bm_isp_driver.o
+
+EXTRA_CFLAGS += -I$(PWD)/./
+EXTRA_CFLAGS += -I$(PWD)/../common
+KBUILD_CFLAGS += -O0
+ifeq ($(BUILD_TYPE),DEBUG)
+	EXTRA_CFLAGS += -DDEBUG
+endif
+
+PWD :=$(shell pwd)
+
+all:
+	make -C $(KERNEL) M=$(PWD) modules
+modules_install:
+	make -C $(KERNEL_SRC) M=$(SRC) modules_install
+clean:
+	rm -rf $($(TARGET)-objs)
+	if [ -d "$(KERNEL)" ]; then \
+		make -C $(KERNEL) M=`pwd` clean; \
+	fi

+ 313 - 0
driver/isp/bm_isp_driver.c

@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <linux/of.h>
+
+#include "bm_printk.h"
+#include "bm_isp_ioctl.h"
+
+#define BM_DRIVER_NAME "bm_isp"
+#define BM_DRIVER_MAXCNT 3
+
+struct bm_isp_drvdata {
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct mutex mutex;
+	unsigned int device_idx;
+	void __iomem *base;
+	void __iomem *reset;
+	//int irq_num;
+	void *private;	// can be bm_isp_drvdata_private, but not use now
+};
+
+struct bm_isp_drvdata_private {
+	int private_tmp;
+};
+
+static struct class *bm_driver_class;
+static unsigned int bm_driver_major = 0;
+static unsigned int bm_driver_minor = 0;
+static unsigned int device_register_index = 0;
+
+#define check_retval(x)\
+	do {\
+		if ((x))\
+			return -EIO;\
+	} while (0)
+
+static unsigned int bm_isp_poll(struct file * filp, poll_table *wait)
+{
+	return 0;
+}
+
+void bm_isp_work(struct work_struct *work)
+{
+}
+
+irqreturn_t bm_isp_irq(int irq, void *dev_id)
+{
+	bm_info("enter %s\n", __func__);
+	return IRQ_HANDLED;
+}
+
+static int bm_isp_open(struct inode * inode, struct file * file)
+{
+	struct bm_isp_drvdata *drvdata;
+
+	bm_info("enter %s\n", __func__);
+
+	drvdata = container_of(inode->i_cdev, struct bm_isp_drvdata, cdev);
+	file->private_data = drvdata;
+
+	return 0;
+};
+
+static int bm_isp_write_reg(struct bm_isp_drvdata *drvdata, void *__user args)
+{
+	struct bm_isp_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	writel(reg.value, drvdata->base + reg.offset);
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+static int bm_isp_read_reg(struct bm_isp_drvdata *drvdata, void *__user args)
+{
+	struct bm_isp_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	reg.value = readl(drvdata->base + reg.offset);
+	check_retval(copy_to_user(args, &reg, sizeof(reg)));
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+static long bm_isp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret = 0;
+	struct bm_isp_drvdata *drvdata;
+	bm_info("enter %s\n", __func__);
+
+	drvdata = file->private_data;
+	if (drvdata == NULL) {
+		bm_err("%s:file private is null point error\n", __func__);
+		return  -ENOMEM;
+	}
+
+	mutex_lock(&drvdata->mutex);
+	switch (cmd) {
+	case BMISPIOC_WRITE_REG:
+		ret = bm_isp_write_reg(drvdata, (void *)arg);
+		break;
+	case BMISPIOC_READ_REG:
+		ret = bm_isp_read_reg(drvdata, (void *)arg);
+		break;
+	default:
+		ret = -EPERM;
+		bm_err("%s: unsupported command %d", __func__, cmd);
+		break;
+	}
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+};
+
+static int bm_isp_release(struct inode * inode, struct file * file)
+{
+	bm_info("enter %s\n", __func__);
+	return 0;
+};
+
+static int bm_isp_mmap(struct file *pFile, struct vm_area_struct *vma)
+{
+	bm_info("enter %s\n", __func__);
+	return 0;
+};
+
+struct file_operations bm_isp_fops = {
+	.owner = THIS_MODULE,
+	.open = bm_isp_open,
+	.release = bm_isp_release,
+	.unlocked_ioctl = bm_isp_ioctl,
+	.mmap = bm_isp_mmap,
+	.poll = bm_isp_poll,
+};
+
+static int bm_isp_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct bm_isp_drvdata *drvdata;
+	struct resource *iores_mem;
+	u32 value;
+
+	bm_info("enter %s\n", __func__);
+	pdev->id = device_register_index;
+	if (pdev->id >= BM_DRIVER_MAXCNT) {
+		bm_err("%s:pdev id is %d error\n", __func__, pdev->id);
+		return  -EINVAL;
+	}
+
+	drvdata = devm_kzalloc(&pdev->dev,sizeof(struct bm_isp_drvdata), GFP_KERNEL);
+	if (drvdata == NULL) {
+		bm_err("%s:alloc struct drvdata error\n", __func__);
+		return  -ENOMEM;
+	}
+
+	iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->base = devm_ioremap_resource(&pdev->dev, iores_mem);
+	bm_info("%s: [%s%d]: drvdata->base=0x%px, phy_addr base=0x%llx\n", __func__,
+		BM_DRIVER_NAME, pdev->id, drvdata->base, iores_mem->start);
+	drvdata->reset = NULL;
+	drvdata->device_idx = pdev->id;
+	mutex_init(&drvdata->mutex);
+	//drvdata->irq_num = platform_get_irq(pdev, 0);
+	//bm_info("%s:[%s%d]: pdriver_dev->irq_num=%d\n", __func__,
+	//	BM_ISP_NAME, pdev->id, drvdata->irq_num);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (pdev->id == 0) {
+		if (bm_driver_major == 0) {
+			ret = alloc_chrdev_region(&drvdata->devt, 0, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret != 0) {
+				bm_err("%s:alloc_chrdev_region error\n", __func__);
+				return ret;
+			}
+			bm_driver_major = MAJOR(drvdata->devt);
+			bm_driver_minor = MINOR(drvdata->devt);
+		} else {
+			drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor);
+			ret = register_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret) {
+				bm_err("%s:register_chrdev_region error\n", __func__);
+				return ret;
+			}
+		}
+
+		bm_driver_class = class_create(THIS_MODULE, BM_DRIVER_NAME);
+		if (IS_ERR(bm_driver_class)) {
+			bm_err("%s[%d]:class_create error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+	}
+
+	drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor + pdev->id);
+	cdev_init(&drvdata->cdev, &bm_isp_fops);
+	ret = cdev_add(&drvdata->cdev, drvdata->devt, 1);
+	if ( ret ) {
+		bm_err("%s[%d]:cdev_add error!\n", __func__, __LINE__);
+		return ret;
+	} else {
+		bm_info("%s[%d]:cdev_add OK, major=%d, minor=%d\n", __func__, __LINE__,
+			bm_driver_major, bm_driver_minor + pdev->id);
+	}
+	drvdata->class = bm_driver_class;
+	device_create(drvdata->class, NULL, drvdata->devt,
+		      drvdata, "%s%d", BM_DRIVER_NAME, pdev->id);
+
+	value = readl(drvdata->base+0x4);
+	bm_info("offset=04, value is:0x%08x\n", value);
+
+	device_register_index++;
+	bm_info("exit %s:[%s%d]\n", __func__, BM_DRIVER_NAME, pdev->id);
+
+	return 0;
+
+//err_register:
+	// When error occore, should free memory, destory device, unregister ...
+	// but now, ignore it
+//	return ret;
+}
+
+static int bm_isp_remove(struct platform_device *pdev)
+{
+	struct bm_isp_drvdata *drvdata;
+
+	bm_info("enter %s\n", __func__);
+	device_register_index--;
+
+	drvdata = platform_get_drvdata(pdev);
+	//free_irq(drvdata->irq_num, drvdata);
+	cdev_del(&drvdata->cdev);
+	device_destroy(drvdata->class, drvdata->devt);
+	unregister_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT);
+	mutex_destroy(&drvdata->mutex);
+	if (device_register_index == 0) {
+		class_destroy(drvdata->class);
+	}
+	devm_kfree(&pdev->dev, drvdata);
+
+	bm_info("exit %s\n", __func__);
+	return 0;
+}
+
+static const struct of_device_id bm_isp_of_match[] = {
+	{ .compatible = "thead,light-bm-isp", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bm_isp_of_match);
+
+static struct platform_driver bm_isp_driver = {
+	.probe		= bm_isp_probe,
+	.remove		= bm_isp_remove,
+	.driver = {
+		.name  = BM_DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(bm_isp_of_match),
+	}
+};
+
+static int __init bm_isp_init_module(void)
+{
+	int ret = 0;
+
+	bm_info("enter %s\n", __func__);
+	ret = platform_driver_register(&bm_isp_driver);
+	if (ret) {
+		bm_err("register platform driver failed.\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void __exit bm_isp_exit_module(void)
+{
+	bm_info("enter %s\n", __func__);
+	platform_driver_unregister(&bm_isp_driver);
+}
+
+module_init(bm_isp_init_module);
+module_exit(bm_isp_exit_module);
+
+MODULE_AUTHOR("Lu Chongzhi");
+MODULE_DESCRIPTION("BAREMETAL-ISP");
+MODULE_LICENSE("GPL");

+ 24 - 0
driver/isp/bm_isp_ioctl.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+#ifndef _BM_ISP_IOCTL_H_
+#define _BM_ISP_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+enum {
+	BMISPIOC_WRITE_REG = 0x100,
+	BMISPIOC_READ_REG,
+};
+
+struct bm_isp_reg_t {
+	unsigned int offset;
+	unsigned int value;
+};
+
+#endif /* _BM_ISP_IOCTL_H_ */

+ 31 - 0
driver/visys/Makefile

@@ -0,0 +1,31 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+TARGET = bm_visys
+
+
+obj-m +=$(TARGET).o
+$(TARGET)-objs += bm_visys_driver.o
+
+EXTRA_CFLAGS += -I$(PWD)/./
+EXTRA_CFLAGS += -I$(PWD)/../common
+ifeq ($(BUILD_TYPE),DEBUG)
+	EXTRA_CFLAGS += -DDEBUG
+endif
+
+PWD :=$(shell pwd)
+
+all:
+	make -C $(KERNEL) M=$(PWD) modules
+modules_install:
+	make -C $(KERNEL_SRC) M=$(SRC) modules_install
+clean:
+	rm -rf $($(TARGET)-objs)
+	if [ -d "$(KERNEL)" ]; then \
+		make -C $(KERNEL) M=`pwd` clean; \
+	fi

+ 334 - 0
driver/visys/bm_visys_driver.c

@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <linux/of.h>
+
+#include "bm_printk.h"
+#include "bm_visys_ioctl.h"
+
+#define BM_DRIVER_NAME "bm_visys"
+#define BM_DRIVER_MAXCNT 1
+
+struct bm_visys_drvdata {
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct mutex mutex;
+	unsigned int device_idx;
+	void __iomem *base;
+	void __iomem *reset;
+	//int irq_num;
+	void *private;	// can be bm_visys_drvdata_private, but not use now
+};
+
+struct bm_visys_drvdata_private {
+	int private_tmp;
+};
+
+static struct class *bm_driver_class;
+static unsigned int bm_driver_major = 0;
+static unsigned int bm_driver_minor = 0;
+static unsigned int device_register_index = 0;
+
+static struct bm_visys_drvdata *g_pdrvdata;
+
+#define check_retval(x)\
+	do {\
+		if ((x))\
+			return -EIO;\
+	} while (0)
+
+static unsigned int bm_visys_poll(struct file * filp, poll_table *wait)
+{
+	return 0;
+}
+
+void bm_visys_work(struct work_struct *work)
+{
+}
+
+irqreturn_t bm_visys_irq(int irq, void *dev_id)
+{
+	bm_info("enter %s\n", __func__);
+	return IRQ_HANDLED;
+}
+
+static int bm_visys_open(struct inode * inode, struct file * file)
+{
+	struct bm_visys_drvdata *drvdata;
+
+	bm_info("enter %s\n", __func__);
+
+	drvdata = container_of(inode->i_cdev, struct bm_visys_drvdata, cdev);
+	file->private_data = drvdata;
+
+	return 0;
+};
+
+int k_bm_visys_write_reg(uint32_t offset, uint32_t value)
+{
+	writel(value, g_pdrvdata->base + offset);
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, offset, value);
+	return 0;
+}
+
+int k_bm_visys_read_reg(uint32_t offset, uint32_t *value)
+{
+	*value = readl(g_pdrvdata->base + offset);
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, offset, *value);
+	return 0;
+}
+
+EXPORT_SYMBOL(k_bm_visys_write_reg);
+EXPORT_SYMBOL(k_bm_visys_read_reg);
+
+static int bm_visys_write_reg(struct bm_visys_drvdata *drvdata, void *__user args)
+{
+	struct bm_visys_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	writel(reg.value, drvdata->base + reg.offset);
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+static int bm_visys_read_reg(struct bm_visys_drvdata *drvdata, void *__user args)
+{
+	struct bm_visys_reg_t reg;
+	check_retval(copy_from_user(&reg, args, sizeof(reg)));
+	reg.value = readl(drvdata->base + reg.offset);
+	check_retval(copy_to_user(args, &reg, sizeof(reg)));
+	bm_info("%s  addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
+	return 0;
+}
+
+static long bm_visys_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret = 0;
+	struct bm_visys_drvdata *drvdata;
+	bm_info("enter %s\n", __func__);
+
+	drvdata = file->private_data;
+	if (drvdata == NULL) {
+		bm_err("%s:file private is null point error\n", __func__);
+		return  -ENOMEM;
+	}
+
+	mutex_lock(&drvdata->mutex);
+	switch (cmd) {
+	case BMVISYSIOC_WRITE_REG:
+		ret = bm_visys_write_reg(drvdata, (void *)arg);
+		break;
+	case BMVISYSIOC_READ_REG:
+		ret = bm_visys_read_reg(drvdata, (void *)arg);
+		break;
+	default:
+		ret = -EPERM;
+		bm_err("%s: unsupported command %d", __func__, cmd);
+		break;
+	}
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+};
+
+static int bm_visys_release(struct inode * inode, struct file * file)
+{
+	bm_info("enter %s\n", __func__);
+	return 0;
+};
+
+static int bm_visys_mmap(struct file *pFile, struct vm_area_struct *vma)
+{
+	bm_info("enter %s\n", __func__);
+	return 0;
+};
+
+struct file_operations bm_visys_fops = {
+	.owner = THIS_MODULE,
+	.open = bm_visys_open,
+	.release = bm_visys_release,
+	.unlocked_ioctl = bm_visys_ioctl,
+	.mmap = bm_visys_mmap,
+	.poll = bm_visys_poll,
+};
+
+static int bm_visys_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct bm_visys_drvdata *drvdata;
+	struct resource *iores_mem;
+	u32 value;
+
+	bm_info("enter %s\n", __func__);
+	pdev->id = device_register_index;
+	if (pdev->id >= BM_DRIVER_MAXCNT) {
+		bm_err("%s:pdev id is %d error\n", __func__, pdev->id);
+		return  -EINVAL;
+	}
+
+	drvdata = devm_kzalloc(&pdev->dev,sizeof(struct bm_visys_drvdata), GFP_KERNEL);
+	if (drvdata == NULL) {
+		bm_err("%s:alloc struct drvdata error\n", __func__);
+		return  -ENOMEM;
+	}
+
+    g_pdrvdata = drvdata;
+
+	iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->base = devm_ioremap_resource(&pdev->dev, iores_mem);
+	bm_info("%s: [%s%d]: drvdata->base=0x%px, phy_addr base=0x%llx\n", __func__,
+		BM_DRIVER_NAME, pdev->id, drvdata->base, iores_mem->start);
+	drvdata->reset = NULL;
+	drvdata->device_idx = pdev->id;
+	mutex_init(&drvdata->mutex);
+	//drvdata->irq_num = platform_get_irq(pdev, 0);
+	//bm_info("%s:[%s%d]: pdriver_dev->irq_num=%d\n", __func__,
+	//	BM_VISYS_NAME, pdev->id, drvdata->irq_num);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (pdev->id == 0) {
+		if (bm_driver_major == 0) {
+			ret = alloc_chrdev_region(&drvdata->devt, 0, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret != 0) {
+				bm_err("%s:alloc_chrdev_region error\n", __func__);
+				return ret;
+			}
+			bm_driver_major = MAJOR(drvdata->devt);
+			bm_driver_minor = MINOR(drvdata->devt);
+		} else {
+			drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor);
+			ret = register_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
+			if (ret) {
+				bm_err("%s:register_chrdev_region error\n", __func__);
+				return ret;
+			}
+		}
+
+		bm_driver_class = class_create(THIS_MODULE, BM_DRIVER_NAME);
+		if (IS_ERR(bm_driver_class)) {
+			bm_err("%s[%d]:class_create error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+	}
+
+	drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor + pdev->id);
+	cdev_init(&drvdata->cdev, &bm_visys_fops);
+	ret = cdev_add(&drvdata->cdev, drvdata->devt, 1);
+	if ( ret ) {
+		bm_err("%s[%d]:cdev_add error!\n", __func__, __LINE__);
+		return ret;
+	} else {
+		bm_info("%s[%d]:cdev_add OK, major=%d, minor=%d\n", __func__, __LINE__,
+			bm_driver_major, bm_driver_minor + pdev->id);
+	}
+	drvdata->class = bm_driver_class;
+	device_create(drvdata->class, NULL, drvdata->devt,
+		      drvdata, "%s%d", BM_DRIVER_NAME, pdev->id);
+
+	value = readl(drvdata->base+0x4);
+	bm_info("offset=04, value is:0x%08x\n", value);
+
+	device_register_index++;
+	bm_info("exit %s:[%s%d]\n", __func__, BM_DRIVER_NAME, pdev->id);
+
+	return 0;
+
+//err_register:
+	// When error occore, should free memory, destory device, unregister ...
+	// but now, ignore it
+//	return ret;
+}
+
+static int bm_visys_remove(struct platform_device *pdev)
+{
+	struct bm_visys_drvdata *drvdata;
+
+	bm_info("enter %s\n", __func__);
+	device_register_index--;
+
+	drvdata = platform_get_drvdata(pdev);
+	//free_irq(drvdata->irq_num, drvdata);
+	cdev_del(&drvdata->cdev);
+	device_destroy(drvdata->class, drvdata->devt);
+	unregister_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT);
+	mutex_destroy(&drvdata->mutex);
+	if (device_register_index == 0) {
+		class_destroy(drvdata->class);
+	}
+	devm_kfree(&pdev->dev, drvdata);
+
+	bm_info("exit %s\n", __func__);
+	return 0;
+}
+
+static const struct of_device_id bm_visys_of_match[] = {
+	{ .compatible = "thead,light-bm-visys", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bm_visys_of_match);
+
+static struct platform_driver bm_visys_driver = {
+	.probe		= bm_visys_probe,
+	.remove		= bm_visys_remove,
+	.driver = {
+		.name  = BM_DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(bm_visys_of_match),
+	}
+};
+
+static int __init bm_visys_init_module(void)
+{
+	int ret = 0;
+
+	bm_info("enter %s\n", __func__);
+	ret = platform_driver_register(&bm_visys_driver);
+	if (ret) {
+		bm_err("register platform driver failed.\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void __exit bm_visys_exit_module(void)
+{
+	bm_info("enter %s\n", __func__);
+	platform_driver_unregister(&bm_visys_driver);
+}
+
+module_init(bm_visys_init_module);
+module_exit(bm_visys_exit_module);
+
+MODULE_AUTHOR("Lu Chongzhi");
+MODULE_DESCRIPTION("BAREMETAL-VISYS");
+MODULE_LICENSE("GPL");

+ 24 - 0
driver/visys/bm_visys_ioctl.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+#ifndef _BM_VISYS_IOCTL_H_
+#define _BM_VISYS_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+enum {
+	BMVISYSIOC_WRITE_REG = 0x100,
+	BMVISYSIOC_READ_REG,
+};
+
+struct bm_visys_reg_t {
+	unsigned int offset;
+	unsigned int value;
+};
+
+#endif /* _BM_VISYS_IOCTL_H_ */

+ 30 - 0
test/csi/Makefile

@@ -0,0 +1,30 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+SOURCES = test_csi.c
+OBJECTS := $(SOURCES:.c=.o)
+EXEC = output/test_csi
+CFLAGS = -O0 -Wall -g -lm -I../../driver/csi
+
+all: $(EXEC)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(INCLUDES) $<
+
+$(EXEC): $(OBJECTS)
+	mkdir -p output
+	$(CC) $(CFLAGS) -o $(EXEC) $(OBJECTS) -pthread
+
+clean:
+	rm -f *.o $(EXEC)
+	rm -rf output
+
+install:
+
+.PHONY: clean all
+

+ 99 - 0
test/csi/test_csi.c

@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#include "bm_csi_ioctl.h"
+
+#define DEV_PATHNAME "/dev/bm_csi0"
+
+typedef struct _csi_ctx
+{
+	int dev_fd;
+} csi_ctx_t;
+static csi_ctx_t csi_ctx;
+
+static int csi_init(csi_ctx_t *ctx)
+{
+	int fd;
+	memset(&csi_ctx, 0, sizeof(csi_ctx));
+
+	fd = open(DEV_PATHNAME, O_RDWR | O_NONBLOCK);
+	if (fd < 0) {
+		printf("%s:Can't open %s: %d(%s)\n", __func__,
+			DEV_PATHNAME, errno, strerror(errno));
+		return -1;
+	}
+	ctx->dev_fd = fd;
+
+	return 0;
+}
+
+static int csi_deinit(csi_ctx_t *ctx)
+{
+	if (ctx->dev_fd >= 0) {
+		close(ctx->dev_fd);
+		ctx->dev_fd = -1;
+	}
+
+	return 0;
+}
+
+static int csi_ioctl(csi_ctx_t *ctx, unsigned int cmd, void *args)
+{
+	int ret;
+
+	if (ctx == NULL || ctx->dev_fd < 0) {
+		printf("%s:ctx is invalid\n", __func__);
+		return -1;
+	}
+
+	ret = ioctl(ctx->dev_fd, cmd, args);
+	if (ret != 0) {
+		printf("%s:ioctl failed, ret=%d(%s)\n", __func__,
+			ret, strerror(ret * -1));
+		return ret;
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	int ret;
+	struct bm_csi_reg_t reg;
+    reg.offset = 0;
+
+	ret = csi_init(&csi_ctx);
+	if (ret != 0)
+		exit(ret);
+    int cmd = BMCSI_IOC_S_RESET;
+    while(cmd < BMCSI_IOC_MAX) {
+	    ret = csi_ioctl(&csi_ctx, cmd, &reg);
+	    if (ret != 0) {
+	    	printf("!!!!!!!!!!!!!!!!!!!error\n");
+	    }
+        cmd++;
+    }
+
+	ret = csi_deinit(&csi_ctx);
+	if (ret != 0)
+		exit(ret);
+
+	exit(0);
+}
+

+ 47 - 0
test/isp/Makefile

@@ -0,0 +1,47 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+# To support host build in current path
+ifeq ($(CC),)
+  CC:=gcc
+endif
+
+CFLAGS = -O0 -Wall -g -lm
+INCLUDES = -I../../driver/isp -I../../common
+
+EXEC1 = output/isp_run_bm_script
+
+
+all: $(EXEC1)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(INCLUDES) $<
+
+prepare:
+	mkdir -p output
+
+SOURCES_COMMON = ../../common/log_common.c
+OBJECTS_COMMON = log_common.o
+common: $(SOURCES_COMMON)
+	$(CC) $(CFLAGS) -c $<
+
+SOURCES1 = isp_run_bm_script.c
+OBJECTS1 = $(SOURCES1:.c=.o)
+$(EXEC1): prepare common $(OBJECTS1)
+	@echo OBJECTS1=$(OBJECTS1)
+	$(CC) $(CFLAGS) -o $(EXEC1) $(OBJECTS_COMMON) $(OBJECTS1)
+	cp -r isp_bm_scripts ./output/
+
+clean:
+	rm -f *.o
+	rm -rf output
+
+install:
+
+.PHONY: clean all prepare common
+

+ 124 - 0
test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_16line.txt

@@ -0,0 +1,124 @@
+0 00002800 00000000
+0 00002904 00000003
+0 00002908 00000007
+0 0000290c 00001d1d
+0 00002918 00000808
+0 0000291c 00000404
+0 00002920 00000403
+0 00002924 00000a0a
+0 00002928 00002020
+0 00002910 00000707
+0 0000292c 0000100c
+0 00002930 00001810
+0 00002934 00000403
+0 00002938 00000808
+0 0000293c 00000808
+0 00002914 00001f1f
+0 00002940 00002020
+0 00002944 00000404
+0 00002948 00000403
+0 0000294c 00000806
+0 00002950 00000404
+0 00002954 00000afa
+0 00002958 00000fff
+0 00002900 00000004
+0 00001000 0000010f //global control, Vertical/Horizontal scale
+0 00002308 00000000 //H offset of output window
+0 0000230c 00000000 //V offset of output winodw
+0 00002310 00000000 //H output size
+0 00002314 00000000 //V output size
+0 00003e44 00000000
+0 00002200 00000000
+0 00000408 00000000 //H input offset
+0 0000040c 00000000 //V input offset
+0 00000410 00000780 //H input size
+0 00000414 00000438 //V input size
+0 00000594 00000000 //H offset of output window
+0 00000598 00000000 //V offset of output window
+0 0000059c 00000780 //H output size
+0 000005a0 00000438 //V output size
+0 00002308 00000000 //H offset of output window
+0 0000230c 00000000 //V offset of output window
+0 00002310 00000780 //H output size
+0 00002314 00000438 //V output size
+0 00000400 00000486 //global control, cfg_upd
+0 00000018 00001041 //data path, yuv out
+0 00002800 00000000
+0 00000400 00000486
+0 000026a0 00000000
+0 000026a0 00000000
+0 00000014 00000100
+0 00000010 0001fe7b
+0 00000200 00000010
+0 00000510 00000000
+0 0000052c 00000000
+0 00000528 00000000
+0 00000524 00000000
+0 00000514 00000000
+0 00000518 00000000
+0 0000051c 00000000
+0 00000520 00000000
+0 0000053c 01000100
+0 00000538 01000100
+0 00002f00 00000000
+0 000005bc 00000000
+0 00003e60 039c0780 //dummy pixels config
+0 00003e00 00000000
+0 00003e64 00000000
+0 00002100 00000000
+0 00002600 00000000
+0 000005bc 00000000
+0 000026a0 00000000
+0 00000510 00000000
+0 000005bc 00000000
+0 00002000 00000000
+0 000005bc 00000000
+0 00002f00 00000000
+0 000005bc 00000000
+0 00001324 d0000000 //MP, Y base address
+0 00001328 001fa400 //MP, Y size
+0 0000132c 00000000 //MP, offset counter init value
+0 00001340 d01fa400 //MP, CB base address
+0 00001344 001fa400 //MP, CB size
+0 00001348 00000000 //MP, CB offset counter init value
+0 0000134c 00000000 //MP, CR base address
+0 00001350 00000000 //MP, CR size
+0 00001354 00000000 //MP, CR offset counter init value
+0 0000160c 08000000 //MCM, AXI ID config
+0 00000404 0000405d //ACQ prop
+0 0000131c 02000100 //MP, AXI ID config
+0 00001318 00000002 //MP, AXI config
+0 00001608 00000002 //MCM, AXI config
+0 00001314 00000004 //MP, format NV12
+0 00001300 00000001
+0 00001310 0000003a //MP control, cfg_upd
+0 00000c6c 00000000 //forma conversion
+0 000016c0 0007ff3f //interuupt mask
+0 00001868 00000690
+0 0000187c 00000030
+0 00000680 00000010
+0 00000418 00000000 //number of frames to be captured, 0 for continuous
+0 000005c8 ffffffff //interrupt clear
+0 000005bc 00000023 //interrupt mask
+0 00000400 00000697
+0 00005598 c0000000 //PP, Y start
+0 0000559c 00000780 //PP, Y width
+0 000055a0 00000780 //PP, Y llength
+0 000055a4 001fa400 //PP, Y size
+0 000055bc 00000780 //PP, Y pic lval
+0 00005504 80000000 //PP, format RAW8
+0 000055c0 00000010 //PP, Y entry line number
+0 000055c4 00000438 //PP, Y buf line number
+0 000055c8 00000438 //PP, Y height
+0 000055cc 00000780 //PP, Y lval
+0 000016e8 00020000 //intr set
+0 00005500 000000fa //pp control, cfg_upd
+0 00001300 00000001
+0 00001300 00200001 //dma read trigger
+0 00000400 00000697
+msleep 1000			// sleep 1000
+1 000016d0 00000301	// MI_MIS, should get 0x00000301
+1 000016f0 00000000	// MI_MIS2, should get 0x00000000
+1 000005c0 000000ff	// ISP_RIS, Raw interrupt status, should get 0x000000ff
+1 000005c4 00000023	// ISP_MIS, Raw interrupt status, should get 0x000000ff
+1 00000400 00000096	// ISP_CTRL, should be 0x96

+ 124 - 0
test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_64line.txt

@@ -0,0 +1,124 @@
+0 00002800 00000000
+0 00002904 00000003
+0 00002908 00000007
+0 0000290c 00001d1d
+0 00002918 00000808
+0 0000291c 00000404
+0 00002920 00000403
+0 00002924 00000a0a
+0 00002928 00002020
+0 00002910 00000707
+0 0000292c 0000100c
+0 00002930 00001810
+0 00002934 00000403
+0 00002938 00000808
+0 0000293c 00000808
+0 00002914 00001f1f
+0 00002940 00002020
+0 00002944 00000404
+0 00002948 00000403
+0 0000294c 00000806
+0 00002950 00000404
+0 00002954 00000afa
+0 00002958 00000fff
+0 00002900 00000004
+0 00001000 0000010f //global control, Vertical/Horizontal scale
+0 00002308 00000000 //H offset of output window
+0 0000230c 00000000 //V offset of output winodw
+0 00002310 00000000 //H output size
+0 00002314 00000000 //V output size
+0 00003e44 00000000
+0 00002200 00000000
+0 00000408 00000000 //H input offset
+0 0000040c 00000000 //V input offset
+0 00000410 00000780 //H input size
+0 00000414 00000438 //V input size
+0 00000594 00000000 //H offset of output window
+0 00000598 00000000 //V offset of output window
+0 0000059c 00000780 //H output size
+0 000005a0 00000438 //V output size
+0 00002308 00000000 //H offset of output window
+0 0000230c 00000000 //V offset of output window
+0 00002310 00000780 //H output size
+0 00002314 00000438 //V output size
+0 00000400 00000486 //global control, cfg_upd
+0 00000018 00001041 //data path, yuv out
+0 00002800 00000000
+0 00000400 00000486
+0 000026a0 00000000
+0 000026a0 00000000
+0 00000014 00000100
+0 00000010 0001fe7b
+0 00000200 00000010
+0 00000510 00000000
+0 0000052c 00000000
+0 00000528 00000000
+0 00000524 00000000
+0 00000514 00000000
+0 00000518 00000000
+0 0000051c 00000000
+0 00000520 00000000
+0 0000053c 01000100
+0 00000538 01000100
+0 00002f00 00000000
+0 000005bc 00000000
+0 00003e60 039c0780 //dummy pixels config
+0 00003e00 00000000
+0 00003e64 00000000
+0 00002100 00000000
+0 00002600 00000000
+0 000005bc 00000000
+0 000026a0 00000000
+0 00000510 00000000
+0 000005bc 00000000
+0 00002000 00000000
+0 000005bc 00000000
+0 00002f00 00000000
+0 000005bc 00000000
+0 00001324 d0000000 //MP, Y base address
+0 00001328 001fa400 //MP, Y size
+0 0000132c 00000000 //MP, offset counter init value
+0 00001340 d01fa400 //MP, CB base address
+0 00001344 001fa400 //MP, CB size
+0 00001348 00000000 //MP, CB offset counter init value
+0 0000134c 00000000 //MP, CR base address
+0 00001350 00000000 //MP, CR size
+0 00001354 00000000 //MP, CR offset counter init value
+0 0000160c 08000000 //MCM, AXI ID config
+0 00000404 0000405d //ACQ prop
+0 0000131c 02000100 //MP, AXI ID config
+0 00001318 00000002 //MP, AXI config
+0 00001608 00000002 //MCM, AXI config
+0 00001314 00000004 //MP, format NV12
+0 00001300 00000001
+0 00001310 0000003a //MP control, cfg_upd
+0 00000c6c 00000000 //forma conversion
+0 000016c0 0007ff3f //interuupt mask
+0 00001868 00000690
+0 0000187c 00000030
+0 00000680 00000010
+0 00000418 00000000 //number of frames to be captured, 0 for continuous
+0 000005c8 ffffffff //interrupt clear
+0 000005bc 00000023 //interrupt mask
+0 00000400 00000697
+0 00005598 c0000000 //PP, Y start
+0 0000559c 00000780 //PP, Y width
+0 000055a0 00000780 //PP, Y llength
+0 000055a4 001fa400 //PP, Y size
+0 000055bc 00000780 //PP, Y pic lval
+0 00005504 80000000 //PP, format RAW8
+0 000055c0 00000040 //PP, Y entry line number
+0 000055c4 00000438 //PP, Y buf line number
+0 000055c8 00000438 //PP, Y height
+0 000055cc 00000780 //PP, Y lval
+0 000016e8 00020000 //intr set
+0 00005500 000000fa //pp control, cfg_upd
+0 00001300 00000001
+0 00001300 00200001 //dma read trigger
+0 00000400 00000697
+msleep 1000			// sleep 1000
+1 000016d0 00000301	// MI_MIS, should get 0x00000301
+1 000016f0 00000000	// MI_MIS2, should get 0x00000000
+1 000005c0 000000ff	// ISP_RIS, Raw interrupt status, should get 0x000000ff
+1 000005c4 00000023	// ISP_MIS, Raw interrupt status, should get 0x000000ff
+1 00000400 00000096	// ISP_CTRL, should be 0x96

+ 177 - 0
test/isp/isp_bm_scripts/2002_format.RAW8.YUV422.mp.00.regdump_frame.txt

@@ -0,0 +1,177 @@
+0 00002800 00000000
+1 00002900 00000004
+0 00002904 00000003
+0 00002908 00000007
+0 0000290c 00001d1d
+0 00002918 00000808
+0 0000291c 00000404
+0 00002920 00000403
+0 00002924 00000a0a
+0 00002928 00002020
+0 00002910 00000707
+0 0000292c 0000100c
+0 00002930 00001810
+0 00002934 00000403
+0 00002938 00000808
+0 0000293c 00000808
+0 00002914 00001f1f
+0 00002940 00002020
+0 00002944 00000404
+0 00002948 00000403
+0 0000294c 00000806
+0 00002950 00000404
+0 00002954 00000afa
+0 00002958 00000fff
+0 00002900 00000004
+1 00000018 00000000
+0 00002308 00000000
+0 0000230c 00000000
+0 00002310 00000000
+0 00002314 00000000
+0 00003e44 00000000
+0 00002200 00000000
+1 00000400 00000080
+1 00000400 00000480
+1 00000404 0000c05d
+0 00000408 00000000
+0 0000040c 00000000
+0 00000410 00000780
+0 00000414 00000438
+0 00000594 00000000
+0 00000598 00000000
+0 0000059c 00000780
+0 000005a0 00000438
+0 00002308 00000000
+0 0000230c 00000000
+0 00002310 00000780
+0 00002314 00000438
+0 00000400 00000486
+1 00000018 00000000
+0 00000018 00001041
+1 00002800 00000000
+0 00002800 00000000
+1 00000400 00000486
+0 00000400 00000486
+1 000026a0 00000000
+0 000026a0 00000000
+1 000026a0 00000000
+0 000026a0 00000000
+1 00000200 00000000
+1 00000010 0001ff7b
+1 00000014 00000000
+1 0000021c 0000880c
+1 00000204 00000000
+0 00000014 00000100
+0 00000010 0001fe7b
+0 00000200 00000010
+1 00000510 00000000
+0 00000510 00000000
+0 0000052c 00000000
+0 00000528 00000000
+0 00000524 00000000
+0 00000514 00000000
+0 00000518 00000000
+0 0000051c 00000000
+0 00000520 00000000
+0 0000053c 01000100
+0 00000538 01000100
+1 00002f00 00000000
+1 000005bc 00000000
+0 00002f00 00000000
+0 000005bc 00000000
+0 00003e60 039c0780
+0 00003e00 00000000
+0 00003e64 00000000
+1 00002100 00000000
+1 000005bc 00000000
+0 00002100 00000000
+1 00002600 00000000
+1 000005bc 00000000
+0 00002600 00000000
+0 000005bc 00000000
+1 000026a0 00000000
+0 000026a0 00000000
+1 00000510 00000000
+1 000005bc 00000000
+0 00000510 00000000
+0 000005bc 00000000
+1 00002000 00000000
+1 000005bc 00000000
+0 00002000 00000000
+0 000005bc 00000000
+1 00002f00 00000000
+1 000005bc 00000000
+0 00002f00 00000000
+0 000005bc 00000000
+0 00001324 d0000000
+0 00001328 001fa400
+0 0000132c 00000000
+0 00001340 d01fa400
+0 00001344 001fa400
+0 00001348 00000000
+0 0000134c 00000000
+0 00001350 00000000
+0 00001354 00000000
+1 0000160c 00000000
+0 0000160c 08000000
+1 00001608 00000000
+1 00001300 00000000
+1 00001318 00000000
+1 00001314 00000000
+1 00000c6c 00000000
+1 00000404 0000c05d
+0 00000404 0000405d
+1 0000131c 00000000
+0 0000131c 02000100
+0 00001318 00000002
+0 00001608 00000002
+0 00001314 00000004
+0 00001300 00000001
+0 00001310 0000003a
+0 00000c6c 00000000
+1 00001608 00000002
+1 00001608 00000002
+1 00001608 00000002
+1 000016c0 00000000
+0 000016c0 0007ff3f
+1 00001868 00000000
+1 0000187c 00000000
+0 00001868 00000690
+0 0000187c 00000030
+0 00000680 00000010
+0 00000418 00000001
+1 000005bc 00000000
+0 000005c8 ffffffff
+0 000005bc 00000023
+1 00000400 00000486
+0 00000400 00000497
+0 00000400 00000697
+1 00005504 00000000
+1 000016e8 00000000
+1 00001300 00000001
+1 00005500 00000000
+0 00005598 c0000000
+0 0000559c 00000780
+0 000055a0 00000780
+0 000055a4 001fa400
+0 000055bc 00000780
+0 00005504 80000000
+0 000055c0 00000438
+0 000055c4 00000438
+0 000055c8 00000438
+0 000055cc 00000780
+0 000016e8 00020000
+0 00005500 000000fa
+0 00001300 00000001
+1 00001300 00000001
+0 00001300 00200001
+1 000016c0 0007ff3f
+1 00003700 00000000
+1 00000400 00000697
+0 00000400 00000697
+msleep 1000			// sleep 1000
+1 000016d0 00000301	// MI_MIS, should get 0x00000301
+1 000016f0 00000000	// MI_MIS2, should get 0x00000000
+1 000005c0 000000ff	// ISP_RIS, Raw interrupt status, should get 0x000000ff
+1 000005c4 00000023	// ISP_MIS, Raw interrupt status, should get 0x000000ff
+1 00000400 00000096	// ISP_CTRL, should be 0x96 

+ 67 - 0
test/isp/isp_bm_scripts/4005_scaling_640x480.512x512.txt

@@ -0,0 +1,67 @@
+0 00002800 00000000	// Default: disable De-noising
+0 00002900 00000000	// Default: Disable DPCC
+0 00000018 00000000	// Default: VI_DPCL (Data Path Control Register)
+0 00000400 00000000	// Disable ISP_CTRL.disable_isp_clk
+0 00001200 00000000	// Ensure ISP_MCM_CTRL.mcm_bypass_en=0, means data is coming from MCM read from DDR
+0 00000408 00000000	// ISP_ACQ_H_OFFS = 0
+0 0000040c 00000000	// ISP_ACQ_V_OFFS = 0
+0 00000410 00000280	// ISP_ACQ_H_SIZE = 0x280 = 640
+0 00000414 000001e0	// ISP_ACQ_V_SIZE = 0x1e0 = 480
+0 00000594 00000000	// ISP_OUT_H_OFFS = 0
+0 00000598 00000000	// ISP_OUT_V_OFFS = 0
+0 0000059c 00000280	// ISP_OUT_H_SIZE = 0x280 = 640
+0 000005a0 000001e0	// ISP_OUT_V_SIZE = 0x1e0 = 480
+0 00002308 00000000	// ISP_IS_H_OFFS = 0 // can't remove
+0 0000230c 00000000	// ISP_IS_V_OFFS = 0 // can't remove
+0 00002310 00000280	// ISP_IS_H_SIZE = 0 // can't remove
+0 00002314 000001e0	// ISP_IS_H_OFFS = 0 // can't remove
+0 00000018 00001041	// VI_DPCL.vi_chan_mode=Enable MP, vi_dma_switch=path to ISP, vi_mp_mux=main resize to MI
+0 00000014 00000100	// VI_IRCL, make sure ie to be reset mode
+0 00000010 0001fe7b	// VI_ICCL, make sure vi_mrsz_clk_enable (Main resize clock enable), disable ie
+0 00003e60 039c0280	// ISP_DMSC_SIZE_CTRL, set img_hsize=0x280=640
+0 00003e00 00000000	// ISP_DMSC_CTRL, keep all Demosaic control to default
+0 00001324 D0000000	// MI_MP_Y_BASE_AD_INIT, set Y output addr
+0 00001328 00040000	// MI_MP_Y_SIZE_INIT, set Y output size
+0 0000132c 00000000	// MI_MP_Y_OFFS_CNT_INIT, set Y output offset
+0 00001340 D0040000	// MI_MP_CB_BASE_AD_INIT, set Cb output addr
+0 00001344 00020000	// MI_MP_CB_SIZE_INIT, set Cb output size
+0 00001348 00000000	// MI_MP_CB_OFFS_CNT_INIT, set Cb output offset
+0 0000134c 00000000	// MI_MP_CR_BASE_AD_INIT, set Cr output addr, here it's semi-planar, it not needed
+0 00001350 00000000	// MI_MP_CR_SIZE_INIT, set Cr output size
+0 00001354 00000000	// MI_MP_CR_OFFS_CNT_INIT, set CR output offset
+0 0000160c 08000000	// MI_MCM_BUS_ID.mcm_bus_sw_en=1, and set to 1’b1 before ISP works 
+0 00000c14 00008849	// MRSZ_SCALE_VC
+0 00000c10 0000eff7	// MRSZ_SCALE_VY
+0 00000c0c 0000cca4	// MRSZ_SCALE_HCR
+0 00000c08 0000cca4	// MRSZ_SCALE_HCB
+0 00000c04 0000ccb9	// MRSZ_SCALE_HY
+0 00000c00 0000024f	// MRSZ_CTRL, scale_XX_enable
+0 00001330 00000200	// MI_MP_Y_LLENGTH, line stride=0x200=512
+0 00001334 00000200	// MI_MP_Y_PIC_WIDTH, line pixel=0x200=512
+0 00001338 00000200	// MI_MP_Y_PIC_HEIGHT, hight pixel=0x200=512
+0 0000133c 00040000	// MI_MP_Y_PIC_SIZE, Y picture size=0x40000=512*512
+0 00000404 00000058	// ISP_ACQ_PROP: conv_422, bayer_pat
+0 0000131c 02000100	// MI_MP_BUS_ID: mp_bus_sw_en, mp_wr_id_en
+0 00001314 00000000	// MI_MP_FMT, keep default: YUV420,Semi-Planar...
+0 00001300 00000001	// MI_CTRL, mp_ycbcr_path_enable before next line
+0 00001310 0000003a	// MI_MP_CTRL, update immediately
+0 00000c6c 00000000	// MRSZ_FORMAT_CONV_CTRL, it seems main format control moved to MI_MP_FMT(1314)
+0 00000418 00000001	// ISP_ACQ_NR_FRAMES, acquire only 1 frame
+0 000005c8 ffffffff	// ISP_ICR, write clean all interrupt
+0 000005bc 00000023	// ISP_IMSC, active interrupt: imsc_frame_in, imsc_frame, imsc_isp_off
+0 00000400 00000697	// ISP_CTRL: isp_enable
+0 0000166c C0000000	// MI_MCM_DMA_RAW_PIC_START_AD: input raw image address
+0 00001670 00000280	// MI_MCM_DMA_RAW_PIC_WIDTH: RAW component image width
+0 00001674 00000280	// MI_MCM_DMA_RAW_PIC_LLENGTH
+0 00001678 0004b000	// MI_MCM_DMA_RAW_PIC_SIZE
+0 00001690 00000280	// MI_MCM_DMA_RAW_PIC_LVAL
+0 00001604 00000000	// MI_MCM_FMT
+0 000016c0 0087ff3f	// MI_IMSC, Interrupt Mask, enable most of interrupt
+0 00001600 00000060	// MI_MCM_CTRL, mcm_rd_cfg_upd
+0 00001300 0000c001	// MI_CTRL, mcm_raw_rdma_path_enable mcm_raw_rdma_start
+msleep 1000			// sleep 1000
+1 000016d0 00000301	// MI_MIS, should get 0x00000301
+1 000016f0 00000000	// MI_MIS2, should get 0x00000000
+1 000005c0 000000ff	// ISP_RIS, Raw interrupt status, should get 0x000000ff
+1 000005c4 00000023	// ISP_MIS, Raw interrupt status, should get 0x000000ff
+1 00000400 00000096	// ISP_CTRL, should be 0x96 

+ 26 - 0
test/isp/isp_bm_scripts/isp_mem_to_mem.txt

@@ -0,0 +1,26 @@
+set 0x00000014 0xffffffff // reset isp -step1
+set 0x00000014 0x00000000 // reset isp -step2
+set 0x00000404 0x0000c05d // ISP_ACQ_PROP, set rgb_dma_sel, input_selection, conv_422, bayer_pat, vsync_pol, sample_edge
+set 0x0000166c 0x00000000 // for "MI_MCM_DMA_RAW_PIC_START_AD", set mcm_dma_raw_pic_start_ad=0x60000000
+set 0x00001670 0x00000280 // for "MI_MCM_DMA_RAW_PIC_WIDTH", set mcm_dma_raw_pic_width=0x280=640
+set 0x00001674 0x00000280 // for "MI_MCM_DMA_RAW_PIC_LLENGTH", set mcm_dma_raw_pic_llength=0x280=640
+set 0x00001678 0x00096000 // for "MI_MCM_DMA_RAW_PIC_SIZE", mcm_dma_raw_pic_size=0x96000=614400=480*2*640
+set 0x00001690 0x00000500 // for "MI_MCM_DMA_RAW_PIC_LVAL", set mcm_dma_raw_width_bytes=0x500=1280=2*640
+set 0x00001604 0x00000004 // for "MI_MCM_FMT", set mcm_rd_raw_bit=b'100: RAW16
+set 0x000016c0 0x01800025 // for "MI_IMSC", enable interrupt masks
+set 0x00001600 0x000000FA // for "MI_MCM_CTRL", set mcm_rd_cfg_upd=mcm_rd_auto_update=1
+set 0x00001300 0x0000c001 // for "MI_CTRL", set mcm_raw_rdma_start, mcm_raw_rdma_path_enable
+set 0x00000400 0x00000219 // for "ISP_CTRL",  inform_enable, set isp_mode, isp_enable
+get 0x00000014
+get 0x000015e0 // Read MI_SP2_DMA_RAW_STATUS
+get 0x0000168c // Read MI_MCM_DMA_STATUS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x000016e0 // Read MI_RIS
+get 0x00000400 // Read ISP_CTRL
+get 0x000016e0 // Read MI_RIS
+get 0x00000014

+ 113 - 0
test/isp/isp_bm_scripts/isp_v4_mcm.txt

@@ -0,0 +1,113 @@
+0 00000010 0001ff7b
+0 00000014 00020000
+0 00001204 04380780
+0 00001208 04380780
+0 00001280 00000003
+0 00001284 a667aba8
+0 00001288 8b34a6ce
+0 0000128c 000b3658
+0 00001200 00000240
+0 00001600 00000018
+0 00001604 0002a222
+0 00001608 0000000a
+0 0000160c 08028783
+0 00001620 00000f00
+0 00001624 00000780
+0 00001628 00000438
+0 0000162c 003f4800
+0 0000164c 00000f00
+0 00001650 00000780
+0 00001654 00000438
+0 00001658 003f4800
+0 00001614 80000000
+0 00001618 003f4800
+0 00001640 90000000
+0 00001644 003f4800
+0 00001600 0000005c
+0 00001308 6ce60608
+0 00001310 00000030
+0 00001314 00000884
+0 00001318 00000001
+0 0000131c 03a2013b
+0 00001320 00000000
+0 00001324 00000000
+0 00001328 001fa400
+0 0000132c 00000000
+0 00001330 00000780
+0 00001334 00000780
+0 00001338 00000438
+0 0000133c 001fa400
+0 00001340 001fa400
+0 00001344 001fa400
+0 00001348 00000000
+0 0000134c 003f4800
+0 00001350 0d050750
+0 00001354 00000000
+0 00001358 00000000
+0 0000135c 00000000
+0 00001360 00000000
+0 00001394 10000000
+0 00001398 003f4800
+0 0000139c 00000000
+0 000013a0 00000f00
+0 000013a4 00000780
+0 000013a8 00000438
+0 000013ac 003f4800
+0 000013c0 20000000
+0 000013c4 00001000
+0 000013c8 00000000
+0 000013cc 00001000
+0 000013d0 00000400
+0 000013d4 00000001
+0 000013d8 00001000
+0 000013ec 00000000
+0 000016c0 ffffffff
+0 00000404 00d00018
+0 00000410 00000780
+0 00000414 00000438
+0 00000400 80186006
+0 00000538 01000100
+0 0000053c 02270220
+0 00000594 00000000
+0 00000598 00000000
+0 0000059c 00000780
+0 000005a0 00000438
+0 000005bc 001effff
+0 00002310 00000780
+0 00002314 00000438
+0 00003e00 040128be
+0 00003e04 00000000
+0 00003e08 00001f08
+0 00003e0c 200003ff
+0 00003e10 0c968628
+0 00003e14 00008008
+0 00003e18 007d07d0
+0 00003e1c 301a3012
+0 00003e20 04010000
+0 00003e24 22018000
+0 00003e28 00020000
+0 00003e2c 0210210a
+0 00003e30 00102102
+0 00003e34 0000388c
+0 00003e38 00000000
+0 00003e3c 00000000
+0 00003e40 00000000
+0 00003e44 00000001
+0 00003e48 10001000
+0 00003e4c 00000000
+0 00003e50 00000000
+0 00003e54 00000000
+0 00003e58 00080010
+0 00003e5c 00080010
+0 00003e60 28310780
+0 000015bc 60000000
+0 00001568 60000000
+0 00000018 00001041
+0 00001200 00020241
+0 00001300 00004043
+0 00001310 0000003a
+0 000014e4 0000023a
+0 00001600 0000005d
+0 00000400 80100697
+
+

+ 297 - 0
test/isp/isp_run_bm_script.c

@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#include "bm_isp_ioctl.h"
+#include "log_common.h"
+
+#define DEV_PATHNAME "/dev/bm_isp0"
+#define TOOL_NAME "isp_run_bm_script"
+#define INVALID_MAGIC32 0xDEADBEEF
+
+typedef enum {
+	ISP_BM_SCRIPT_OP_REG_SET,
+	ISP_BM_SCRIPT_OP_REG_GET,
+	ISP_BM_SCRIPT_OP_MSLEEP,
+} isp_bm_script_op;
+
+typedef struct _isp_ctx {
+	int dev_fd;
+} isp_ctx_t;
+static isp_ctx_t isp_ctx;
+
+typedef struct {
+	isp_bm_script_op	op;
+	struct bm_isp_reg_t	reg;
+	unsigned int		expect;
+	unsigned int 		msleep;
+} isp_bm_script_info;
+
+typedef struct {
+	uint32_t begin_line;	// default:0
+	uint32_t end_line;	// default:-1, -1 means no limit
+	char device_name[256];
+	char bm_script_name[256];
+	uint32_t simulate;
+} cmd_param_s;
+
+static int isp_init(isp_ctx_t *ctx, char *device_name)
+{
+	int fd;
+
+	if (!device_name) {
+		printf("%s:device name is invalid\n", __func__);
+		return -1;
+	}
+
+	memset(&isp_ctx, 0, sizeof(isp_ctx));
+
+	fd = open(device_name, O_RDWR | O_NONBLOCK);
+	if (fd < 0) {
+		printf("%s:Can't open %s: %d(%s)\n", __func__,
+			device_name, errno, strerror(errno));
+		return -1;
+	}
+	ctx->dev_fd = fd;
+
+	return 0;
+}
+
+static int isp_deinit(isp_ctx_t *ctx)
+{
+	if (ctx->dev_fd >= 0) {
+		close(ctx->dev_fd);
+		ctx->dev_fd = -1;
+	}
+
+	return 0;
+}
+
+static int isp_ioctl(isp_ctx_t *ctx, unsigned int cmd, void *args)
+{
+	int ret;
+
+	if (ctx == NULL || ctx->dev_fd < 0) {
+		printf("%s:ctx is invalid\n", __func__);
+		return -1;
+	}
+
+	ret = ioctl(ctx->dev_fd, cmd, args);
+	if (ret != 0) {
+		printf("%s:ioctl failed, ret=%d(%s)\n", __func__,
+			ret, strerror(ret * -1));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int parse_script_line(isp_bm_script_info *script_info, char *script_line)
+{
+	int ret;
+	char op_str[64]="";
+	//printf("script_line=%s", script_line);
+	ret = sscanf(script_line, "%s %x %x", op_str, &script_info->reg.offset, &script_info->reg.value);
+	if (ret == 3 && (strcmp(op_str, "set") == 0 || strcmp(op_str, "0") == 0)) {
+		script_info->op = ISP_BM_SCRIPT_OP_REG_SET;
+		return 0;
+	} else if (ret >= 2 && (strcmp(op_str, "get") == 0 || strcmp(op_str, "1") == 0)) {
+		script_info->op = ISP_BM_SCRIPT_OP_REG_GET;
+		if (ret == 2)
+			script_info->expect = INVALID_MAGIC32;
+		else
+			script_info->expect = script_info->reg.value;
+		return 0;
+	} else if (ret == 2 && strcmp(op_str, "msleep") == 0) {
+		ret = sscanf(script_line, "%s %d", op_str, &script_info->msleep);
+		script_info->op = ISP_BM_SCRIPT_OP_MSLEEP;
+		return 0;
+	} else {
+		printf_red("script_line invalid:'%s'\n", script_line);
+		return -1;
+	}
+}
+
+static void help(void)
+{
+	printf("usage: %s [-d device] [-f script_file] [-s simulate]\n", TOOL_NAME);
+	printf("  example: %s -d /dev/isp0 -f isp_bm_scripts/isp_v4_mcm.txt -b 0 -e 9 -s 0\n", TOOL_NAME);
+}
+
+static void _dump_cmd_param(cmd_param_s *cmd_param)
+{
+	printf("%s -d %s -f %s -b %d -e %d -s %d\n",
+		TOOL_NAME,
+		cmd_param->device_name,
+		cmd_param->bm_script_name,
+		cmd_param->begin_line,
+		cmd_param->end_line,
+		cmd_param->simulate);
+}
+
+static int parse_cmd_params(int argc,char *argv[], cmd_param_s *cmd_param)
+{
+	int param_cnt = 1;
+	memset(cmd_param, 0, sizeof(*cmd_param));
+	cmd_param->begin_line = 0;
+	cmd_param->end_line = -1;
+
+	if (argc == 1) {
+		help();
+		return -1;
+	}
+
+	while (param_cnt < argc) {
+		if (0 == strncmp (argv[param_cnt], "-d", 2)) {
+			strncpy(cmd_param->device_name, argv[param_cnt+1], sizeof(cmd_param->bm_script_name));
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-f", 2)) {
+			strncpy(cmd_param->bm_script_name, argv[param_cnt+1], sizeof(cmd_param->bm_script_name));
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-b", 2)) {
+			cmd_param->begin_line = atoi(argv[param_cnt+1]);
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-e", 2)) {
+			cmd_param->end_line = atoi(argv[param_cnt+1]);
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-s", 2)) {
+			cmd_param->simulate = atoi(argv[param_cnt+1]);
+			param_cnt += 2;
+		} else {
+			printf("Invalid syntax.\n");
+			_dump_cmd_param(cmd_param);
+			help();
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int32_t ret = 0;
+	uint32_t current_line = 0;
+	uint32_t run_lines = 0;
+	FILE *stream;
+	char string[1024];
+
+	cmd_param_s cmd_param;
+	ret = parse_cmd_params(argc, argv, &cmd_param);
+	if (ret != 0) {
+		return ret;
+	}
+	_dump_cmd_param(&cmd_param);
+
+	if (cmd_param.simulate == 0) {
+		ret = isp_init(&isp_ctx, &(cmd_param.device_name[0]));
+		if (ret != 0) {
+			printf("isp_init failed\n");
+			exit(ret);
+		}
+	}
+	stream = fopen(cmd_param.bm_script_name, "r");
+	if(stream == NULL) {
+		printf("Open script file:'%s' failed\n", cmd_param.bm_script_name);
+		return -1;
+	}
+
+	printf(">>> Below result is run under %s:\n",
+		cmd_param.simulate ? "Simulation" : "Hardware");
+
+	fseek(stream, 0, SEEK_SET);
+	while (current_line <= cmd_param.end_line) {
+		if (fgets(string, sizeof(string), stream) == NULL) {
+			//printf("fgets script file:'%s' failed\n", cmd_param.bm_script_name);
+			break;
+		}
+
+		if (current_line >= cmd_param.begin_line &&
+		    current_line <= cmd_param.end_line) {
+			//struct bm_isp_reg_t reg;
+			isp_bm_script_info script_info;
+			ret = parse_script_line(&script_info, string);
+			if (ret != 0) {
+				//printf_red("Line-%03d is invalid:%s", current_line+1, string);
+				current_line++;
+				continue;
+			}
+
+			//printf("[line-%03d] offset=0x%08x, value=0x%08x\n",
+			//	current_line, reg.offset, reg.value);
+
+			if (cmd_param.simulate == 0) {
+				if (script_info.op == ISP_BM_SCRIPT_OP_REG_SET) {
+					ret = isp_ioctl(&isp_ctx, BMISPIOC_WRITE_REG, &script_info.reg);
+					if (ret == 0) {
+						printf("line%03d: Write reg OK, offset=0x%08x, value=0x%08x\n",
+							current_line+1, script_info.reg.offset, script_info.reg.value);
+					} else {
+						printf("line%03d: Write reg failed\n", current_line+1);
+						ret = -1;
+						break;
+					}
+				} else if (script_info.op == ISP_BM_SCRIPT_OP_REG_GET) {
+					ret = isp_ioctl(&isp_ctx, BMISPIOC_READ_REG, &script_info.reg);
+					if (ret == 0) {
+						printf("line%03d: Read  reg OK, offset=0x%08x, value=0x%08x\n",
+							current_line+1, script_info.reg.offset, script_info.reg.value);
+					} else {
+						printf("line%03d: Read  reg failed\n", current_line+1);
+						ret = -1;
+						break;
+					}
+					if (script_info.expect != INVALID_MAGIC32 &&
+					    script_info.reg.value != script_info.expect) {
+						printf_red("         Read value(0x%08x) != expect(0x%08x)\n",
+							script_info.reg.value, script_info.expect);
+					}
+				} else if (script_info.op == ISP_BM_SCRIPT_OP_MSLEEP) {
+					usleep(script_info.msleep * 1000);
+					printf("line%03d: sleep %ums finished\n", current_line+1, script_info.msleep);
+				}
+			} else {
+				if (script_info.op == ISP_BM_SCRIPT_OP_REG_SET) {
+					printf("line%03d: Write reg OK, offset=0x%08x, value=0x%08x\n",
+						current_line+1, script_info.reg.offset, script_info.reg.value);
+				} else if (script_info.op == ISP_BM_SCRIPT_OP_REG_GET) {
+					printf("line%03d: Read  reg OK, offset=0x%08x, value=0x%08x\n",
+						current_line+1, script_info.reg.offset,script_info.reg.value);
+					if (script_info.expect != INVALID_MAGIC32 &&
+					    script_info.reg.value != script_info.expect) {
+						printf_red("         Read value(0x%08x) != expect(0x%08x)\n",
+							script_info.reg.value, script_info.expect);
+					}
+				} else if (script_info.op == ISP_BM_SCRIPT_OP_MSLEEP) {
+					usleep(script_info.msleep * 1000);
+					printf("line%03d: sleep %ums finished\n", current_line+1, script_info.msleep);
+				}
+			}
+		}
+		run_lines++;
+		current_line++;
+	}
+	printf("<<< %d script lines are run\n", run_lines);
+
+	if (cmd_param.simulate == 0) {
+		isp_deinit(&isp_ctx);
+	}
+	fclose(stream);
+	return 0;
+}

File diff suppressed because it is too large
+ 39191 - 0
test/isp/resource/RAW8_20100101_005155_1920x1080.raw


BIN
test/isp/resource/RAW8_20190712_640x480.raw


+ 30 - 0
test/visys/Makefile

@@ -0,0 +1,30 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+SOURCES = test_visys.c
+OBJECTS := $(SOURCES:.c=.o)
+EXEC = output/test_visys
+CFLAGS = -O0 -Wall -g -lm -I../../driver/visys
+
+all: $(EXEC)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(INCLUDES) $<
+
+$(EXEC): $(OBJECTS)
+	mkdir -p output
+	$(CC) $(CFLAGS) -o $(EXEC) $(OBJECTS) -pthread
+
+clean:
+	rm -f *.o $(EXEC)
+	rm -rf output
+
+install:
+
+.PHONY: clean all
+

+ 96 - 0
test/visys/test_visys.c

@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#include "bm_visys_ioctl.h"
+
+#define DEV_PATHNAME "/dev/bm_visys0"
+typedef struct _visys_ctx
+{
+	int dev_fd;
+} visys_ctx_t;
+static visys_ctx_t visys_ctx;
+
+static int visys_init(visys_ctx_t *ctx)
+{
+	int fd;
+	memset(&visys_ctx, 0, sizeof(visys_ctx));
+
+	fd = open(DEV_PATHNAME, O_RDWR | O_NONBLOCK);
+	if (fd < 0) {
+		printf("%s:Can't open %s: %d(%s)\n", __func__,
+			DEV_PATHNAME, errno, strerror(errno));
+		return -1;
+	}
+	ctx->dev_fd = fd;
+
+	return 0;
+}
+
+static int visys_deinit(visys_ctx_t *ctx)
+{
+	if (ctx->dev_fd >= 0) {
+		close(ctx->dev_fd);
+		ctx->dev_fd = -1;
+	}
+
+	return 0;
+}
+
+static int visys_ioctl(visys_ctx_t *ctx, unsigned int cmd, void *args)
+{
+	int ret;
+
+	if (ctx == NULL || ctx->dev_fd < 0) {
+		printf("%s:ctx is invalid\n", __func__);
+		return -1;
+	}
+
+	ret = ioctl(ctx->dev_fd, cmd, args);
+	if (ret != 0) {
+		printf("%s:ioctl failed, ret=%d(%s)\n", __func__,
+			ret, strerror(ret * -1));
+		return ret;
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	int ret;
+	struct bm_visys_reg_t reg;
+
+	ret = visys_init(&visys_ctx);
+	if (ret != 0)
+		exit(ret);
+
+	reg.offset = 0x4;	// should be 0x5000008b in reset
+	ret = visys_ioctl(&visys_ctx, BMVISYSIOC_READ_REG, &reg);
+	if (ret == 0) {
+		printf("%s:Read reg OK, offset=0x%08x, value=0x%08x\n", __func__,
+			reg.offset, reg.value);
+	}
+
+	ret = visys_deinit(&visys_ctx);
+	if (ret != 0)
+		exit(ret);
+
+	exit(0);
+}
+

+ 47 - 0
tools/reg_analyzer/Makefile

@@ -0,0 +1,47 @@
+##
+ # Copyright (C) 2021 Alibaba Group Holding Limited
+ #
+ # 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.
+##
+
+# To support host build in current path
+ifeq ($(CC),)
+  CC:=gcc
+endif
+
+CFLAGS = -O0 -Wall -g -lm
+INCLUDES = -I../../common -I./
+
+SOURCES := ../../common/log_common.c
+SOURCES += ra_common.c
+SOURCES += ra_light_main.c
+SOURCES += ra_reg_demo.c
+SOURCES += ra_light_visys.c
+SOURCES += ra_light_isp.c
+SOURCES += $(wildcard vsi_isp8000/*.c)
+
+
+OBJECTS := $(SOURCES:.c=.o)
+EXEC = output/reg_analyzer
+CFLAGS = -O0 -g -Wall -lm
+
+all: $(EXEC)
+
+$(EXEC): $(OBJECTS)
+	@mkdir -p output
+	$(CC) $(CFLAGS) -o $(EXEC) .obj/*.o
+
+$(OBJECTS):%.o:%.c
+	@mkdir -p .obj
+	$(CC) -c $(CFLAGS) $(INCLUDES) -o .obj/$(notdir $@) $<
+
+clean:
+	rm -rf .obj
+	rm -rf output
+
+install:
+
+.PHONY: clean all
+

+ 363 - 0
tools/reg_analyzer/ra_common.c

@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "log_common.h"
+#include "ra_common.h"
+
+static char reg_desc_tmp[4096];
+
+int ra_dump_reg_fields(reg_analyzer_info_s *ra_info,
+			const reg_field_s reg_field[], const uint32_t reg_field_count)
+{
+	int i = 0, pos=-1;
+	int has_meet = 0;
+	char *reg_name;
+	char *reg_desc;
+	uint32_t reg_reset_val;
+	uint32_t reg_offset = ra_info->reg_offset;
+	uint32_t reg_val = ra_info->reg_value;
+
+	if (strlen(ra_info->reg_name) == 0 && ra_info->reg_offset == INVALID_MAGIC32) {
+		printf("Invalid reg_name('%s') or reg_offset(0x%08x)\n",
+			ra_info->reg_name, ra_info->reg_offset);
+		return -1;
+	}
+
+	for (i = 0; i < reg_field_count; i++) {
+		if (ra_info->reg_offset == reg_field[i].offset ||
+		    (reg_field[i].reg_name != NULL &&
+		     strncmp(reg_field[i].reg_name, ra_info->reg_name, strlen(reg_field[i].reg_name))==0)) {
+			pos = i;
+			reg_offset = reg_field[pos].offset;
+			reg_desc = reg_field[pos].reg_desc;
+			reg_name = reg_field[pos].reg_name;
+			reg_reset_val = reg_field[pos].reset_value;
+			break;
+		}
+	}
+	if (pos < 0) {
+		//printf_red("Can't find register offset=0x%x\n", reg_offset);
+		return -1;
+	}
+
+	printf("\n%-24s %-10s  %10s  %10s  %s\n", "  Register Name", "Offset", "ResetValue", "CurrentVal", "Description");
+	printf("===================================================================================\n");
+	printf("%-24s 0x%08x  0x%08x  ", reg_name, reg_offset, reg_reset_val);
+	if (reg_reset_val != reg_val)
+		printf_green("0x%08x", reg_val);
+	else
+		printf("0x%08x", reg_val);
+	printf("  %s\n", reg_desc);
+
+	printf("\nBit[s]  Len  ResetValue  CurrentValue(Hex/Dec)  FieldName                Description\n");
+	printf("===================================================================================\n");
+
+	for (i = pos; i < reg_field_count; i++) {
+		if (reg_field[i].offset != reg_offset) {
+			if (has_meet == 1) {
+				break;
+			}
+			continue;
+		}
+
+		uint32_t msb = reg_field[i].msb;
+		uint32_t lsb = reg_field[i].lsb;
+		uint32_t curr_field_val = reg_val;
+		if (msb != 31 || lsb != 0) {
+			curr_field_val = (reg_val >> lsb) & (~(0xffffffff << (msb - lsb + 1)));
+		}
+		uint32_t reset_field_val;
+		uint32_t field_len = msb - lsb + 1;
+
+		reset_field_val = (reg_reset_val >> lsb) & (~(0xffffffff << (msb - lsb + 1)));
+
+		if (field_len == 1) {
+			printf(" %5d ", lsb);
+		}
+		else {
+			printf(" %2d:%2d ", msb, reg_field[i].lsb);
+		}
+		printf("%4d  ", field_len);
+		printf("0x%-9x ", reset_field_val);
+		if (curr_field_val != reset_field_val) {
+			printf_green("0x%-8x/", curr_field_val);
+			printf_green("%10u  ", curr_field_val);
+		} else {
+			printf("0x%-8x/", curr_field_val);
+			printf("%10u  ", curr_field_val);
+		}
+
+		if (reg_field[i].field_name != NULL)
+			printf("%-24s:", reg_field[i].field_name);
+		else
+			printf("%-24s", "");
+
+		if (reg_field[i].field_desc != NULL) {
+			if (strstr(reg_field[i].field_desc, LINE_PADDING_6TAB)) {
+				strncpy(reg_desc_tmp, reg_field[i].field_desc, sizeof(reg_desc_tmp));
+				char *p = strstr(reg_desc_tmp, LINE_PADDING_6TAB);
+				while (p) {
+					str_replace(p, strlen(LINE_PADDING_6TAB), LINE_PADDING_9TAB);
+					p = p+strlen(LINE_PADDING_9TAB);
+					p = strstr(p, LINE_PADDING_6TAB);
+				}
+				printf("%-s\n", reg_desc_tmp);
+			} else {
+				printf("%-s\n", reg_field[i].field_desc);
+			}
+		}
+		else
+			printf("%-s\n", "");
+
+		if (has_meet == 0) {
+			has_meet = 1;
+		}
+	}
+	printf("\n");
+
+	if (has_meet !=0 )
+		return 0;
+	else
+		return -1;
+}
+
+int ra_dump_reg_define(reg_analyzer_info_s *ra_info,
+			const reg_field_s reg_field[], const uint32_t reg_field_count)
+{
+	int i = 0, pos=-1;
+	int has_meet = 0;
+	char *reg_desc;
+	uint32_t reg_offset;
+	uint32_t reg_reset_val;
+
+	if (strlen(ra_info->reg_name) == 0 && ra_info->reg_offset == INVALID_MAGIC32) {
+		printf("Invalid reg_name('%s') or reg_offset(0x%08x)\n",
+			ra_info->reg_name, ra_info->reg_offset);
+		return -1;
+	}
+
+	for (i = 0; i < reg_field_count; i++) {
+		if (ra_info->reg_offset == reg_field[i].offset ||
+		    (reg_field[i].reg_name != NULL &&
+		     strncmp(reg_field[i].reg_name, ra_info->reg_name, strlen(reg_field[i].reg_name))==0)) {
+			pos = i;
+			reg_offset = reg_field[pos].offset;
+			reg_desc = reg_field[pos].reg_desc;
+			reg_reset_val = reg_field[pos].reset_value;
+			break;
+		}
+	}
+	if (pos < 0) {
+		//printf_red("Can't find register offset=0x%x\n", reg_offset);
+		return -1;
+	}
+
+	printf("\n%-24s %-10s  %10s  %s\n", "Register Name", "Offset", "ResetValue", "Description");
+	printf("===================================================================================\n");
+	printf("%-24s 0x%08x  0x%08x  %s\n", reg_field[pos].reg_name, reg_offset, reg_reset_val, reg_desc);
+
+
+	printf("\nBit[s]  Len  ResetValue  FieldName               Description\n");
+	printf("===================================================================================\n");
+
+	for (i = pos; i < reg_field_count; i++) {
+		if (reg_field[i].offset != reg_offset) {
+			if (has_meet == 1) {
+				break;
+			}
+			continue;
+		}
+
+		uint32_t msb = reg_field[i].msb;
+		uint32_t lsb = reg_field[i].lsb;
+
+		uint32_t reset_field_val;
+		uint32_t field_len = msb - lsb + 1;
+
+		reset_field_val = (reg_reset_val >> lsb) & (~(0xffffffff << (msb - lsb + 1)));
+
+		if (field_len == 1) {
+			printf(" %5d ", lsb);
+		}
+		else {
+			printf(" %2d:%2d ", msb, reg_field[i].lsb);
+		}
+		printf("%4d  ", field_len);
+		printf("0x%-9x ", reset_field_val);
+
+		if (reg_field[i].field_name != NULL)
+			printf("%-23s:", reg_field[i].field_name);
+		else
+			printf("%-23s", "");
+
+		if (reg_field[i].field_desc != NULL)
+			printf("%-s\n", reg_field[i].field_desc);
+		else
+			printf("%-s\n", "");
+
+		if (has_meet == 0) {
+			has_meet = 1;
+		}
+	}
+	printf("\n");
+
+	if (has_meet !=0 )
+		return 0;
+	else
+		return -1;
+
+}
+
+int ra_dump_reg_find(reg_analyzer_info_s *ra_info,
+		     const reg_field_s reg_field[], const uint32_t reg_field_count)
+{
+	int i = 0;
+	char *last_reg_name = NULL;
+	if (ra_info == NULL || ra_info->reg_name == NULL) {
+		printf("ra_info or ra_info->reg_name is invalid\n");
+		return -1;
+	}
+
+	for (i = 0; i < reg_field_count; i++) {
+		const reg_field_s *pfield = &reg_field[i];
+		if (last_reg_name == pfield->reg_name || pfield->reg_name == NULL)
+			continue;
+
+		if (stristr(pfield->reg_name, ra_info->reg_name) != NULL) {
+			printf("Find register:  offset=0x%08x, name='%s'\n",
+				pfield->offset, pfield->reg_name);
+		}
+		last_reg_name = pfield->reg_name;
+	}
+	return 0;
+}
+
+void _dump_ra_info(reg_analyzer_info_s *ra_info)
+{
+	printf("input params: [-m %s] [-o 0x%08X] [-r %s] [-v 0x%08x], op=%d\n",
+		ra_info->module_name, ra_info->reg_offset, ra_info->reg_name,
+		ra_info->reg_value, ra_info->operate);
+}
+
+char *strlwr(char *str)
+{
+	char *orign = str;
+	for (; *str != '\0'; str++)
+		*str = tolower(*str);
+	return orign;
+}
+
+void str_replace(char * cp, int n, char * str)
+{
+	int lenofstr;
+	char * tmp;
+	lenofstr = strlen(str);
+	//str3比str2短,往前移动
+	if(lenofstr < n)
+	{
+		tmp = cp+n;
+		while(*tmp)
+		{
+			*(tmp-(n-lenofstr)) = *tmp; //n-lenofstr是移动的距离
+			tmp++;
+		}
+		*(tmp-(n-lenofstr)) = *tmp; //move '\0'
+	}
+	else
+	        //str3比str2长,往后移动
+		if(lenofstr > n)
+		{
+			tmp = cp;
+			while(*tmp) tmp++;
+			while(tmp>=cp+n)
+			{
+				*(tmp+(lenofstr-n)) = *tmp;
+				tmp--;
+			}
+		}
+	strncpy(cp,str,lenofstr);
+}
+
+// compare string Ignore case
+int stricmp(const char* p1, const char* p2)
+{
+	while (*p1 && *p2)
+	{
+		char c1 = *p1;
+		char c2 = *p2;
+		if (c1 >= 'A' && c1 <= 'Z')
+		{
+			c1 += 'a' - 'A';
+		}
+		if (c2 >= 'A' && c2 <= 'Z')
+		{
+			c2 += 'a' - 'A';
+		}
+		if (c1 != c2)
+		{
+			return c1 - c2;
+		}
+		p1++;
+		p2++;
+	}
+	return *p1 - *p2;
+}
+
+// find string Ignore case
+char* stristr(const char* haystack, const char* needle)
+{
+	char* char1 = NULL;
+	char* char2  = NULL;
+	if ((haystack  == NULL) || (needle  == NULL) || (strlen(haystack) < strlen(needle))){
+		return NULL;
+	}
+
+	for (char1  = (char*)haystack; (*char1) != '\0'; ++char1) {
+		char* char3  = char1;
+		for (char2  = (char*)needle; (*char2) != '\0' && (*char1) != '\0'; ++char2, ++char1)	{
+			char c1  = (*char1) & 0xDF;
+			char c2  = (*char2) & 0xDF;
+			if ((c1  != c2) || (((c1 > 0x5A) || (c1 < 0x41)) && (*char1  != *char2)))
+				break;
+		}
+
+		if ((*char2) == '\0')
+			return char3;
+
+		char1 = char3;
+	}
+	return NULL;
+}
+
+int ra_search_reg_by_offset(reg_analyzer_info_s *ra_info)
+{
+	if (ra_info->reg_offset == INVALID_MAGIC32) {
+		return -1;
+	}
+
+	return 0;
+}
+
+int ra_search_reg_by_name(reg_analyzer_info_s *ra_info)
+{
+	if (strlen(ra_info->module_name) == 0) {
+		return -1;
+	}
+
+	return 0;
+}
+

+ 100 - 0
tools/reg_analyzer/ra_common.h

@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#ifndef __RA_COMMON_H__
+#define __RA_COMMON_H__
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#define INVALID_MAGIC32 0xDEADBEEF
+
+#define LINE_PADDING_6TAB "\n\t\t\t\t\t\t "
+#define LINE_PADDING_9TAB "\n\t\t\t\t\t\t\t\t\t "
+
+typedef struct {
+	char     *reg_name;	/* Register name, can be null if it exists above, should <=24 chars */
+	char     *reg_desc;	/* Register description, can be null if not exists */
+	uint32_t  offset;	/* Register offset address */
+	uint32_t  reset_value;	/* Register reset value */
+	uint32_t  msb;		/* MSB for this field [31..0] */
+	uint32_t  lsb;		/* LSB for this field [31..0] */
+	char     *field_name;	/* Register field name */
+	char     *field_desc;	/* Field description */
+} reg_field_s;
+
+/*
+For example:
+static const reg_field_s demo_reg_desc[] = {
+	{"Demo reg", 	0x10, "Demo field1", 15, 0,  "This is demo reg's demo field1"},
+	{NULL, 		0x10, "Demo field2", 31, 16, "This is demo reg's demo field2"},
+};
+*/
+
+typedef struct {
+	char    *ip_name;
+	uint64_t ip_phy_addr;
+} ip_phy_addr_s;
+
+typedef enum {
+	RA_OP_INVALID = -1,
+	RA_OP_SHOW_DUMP = 0,
+	RA_OP_SHOW_REG_DEFINE,
+	RA_OP_FIND_REG,
+} ra_op_e;
+
+typedef struct {
+	char module_name[64];
+	uint32_t reg_offset;
+	uint32_t reg_value;
+	char reg_name[128];
+	char field_name[128];
+	ra_op_e operate;
+} reg_analyzer_info_s;
+
+void _dump_ra_info(reg_analyzer_info_s *ra_info);
+
+int ra_dump_reg_fields(reg_analyzer_info_s *ra_info,
+			const reg_field_s reg_field[], const uint32_t reg_field_count);
+
+int ra_dump_reg_define(reg_analyzer_info_s *ra_info,
+			const reg_field_s reg_field[], const uint32_t reg_field_count);
+
+int ra_dump_reg_find(reg_analyzer_info_s *ra_info,
+		     const reg_field_s reg_field[], const uint32_t reg_field_count);
+
+///////////////////////////////////////
+
+
+typedef int (*module_reg_dump)(reg_analyzer_info_s *ra_info);
+typedef int (*module_reg_define)(reg_analyzer_info_s *ra_info);
+typedef int (*module_reg_find)(reg_analyzer_info_s *ra_info);
+
+typedef struct {
+	const char		*module_name;
+	module_reg_dump		reg_dump;
+	module_reg_define	reg_define;
+	module_reg_find		reg_find;
+} module_instance_t;
+
+int ra_search_reg_by_offset(reg_analyzer_info_s *ra_info);
+int ra_search_reg_by_name(reg_analyzer_info_s *ra_info);
+
+//////////////////////////////////////
+
+
+
+char *strlwr(char *str);
+void str_replace(char * cp, int n, char * str);
+int stricmp(const char* p1, const char* p2);
+char* stristr(const char* haystack, const char* needle);
+#endif /* __RA_COMMON_H__ */
+

+ 335 - 0
tools/reg_analyzer/ra_light_isp.c

@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "log_common.h"
+#include "ra_common.h"
+
+extern int light_isp_main_control_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x0000
+extern int light_isp_main_control_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_main_control_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_isp_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_isp_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_isp_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_mcm_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_mcm_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_mcm_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_sitching0_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_sitching0_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_sitching0_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_exp_bayer_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_exp_bayer_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_exp_bayer_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_is_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_is_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_is_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_cproc_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_cproc_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_cproc_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_main_resize_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_main_resize_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_main_resize_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_denoise3d_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_denoise3d_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_denoise3d_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_dpf_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_dpf_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_dpf_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_denoise3d2_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_denoise3d2_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_denoise3d2_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_dpcc_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_dpcc_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_dpcc_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_compand_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_compand_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_compand_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_shutter_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x0680
+extern int light_isp_shutter_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_shutter_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_mi_reg_dump(reg_analyzer_info_s *ra_info);		// OFFSET=0x1300
+extern int light_isp_mi_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_mi_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_jpe_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x1800
+extern int light_isp_jpe_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_jpe_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_afm_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x2000
+extern int light_isp_afm_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_afm_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_hist256_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x2100
+extern int light_isp_hist256_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_hist256_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_lsc_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x2200
+extern int light_isp_lsc_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_lsc_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_exposure_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x2600
+extern int light_isp_exposure_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_exposure_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_vsm_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x2f00
+extern int light_isp_vsm_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_vsm_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_ee_reg_dump(reg_analyzer_info_s *ra_info);		// OFFSET=0x3900
+extern int light_isp_ee_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_ee_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_dmsc_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x3e00
+extern int light_isp_dmsc_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_dmsc_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_pre_filt_reg_dump(reg_analyzer_info_s *ra_info);	// OFFSET=0x3e00
+extern int light_isp_pre_filt_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_pre_filt_reg_find(reg_analyzer_info_s *ra_info);
+
+
+int light_isp_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	if (light_isp_main_control_reg_dump(ra_info) == 0)	// OFFSET=0x0000
+		return 0;
+
+	if (light_isp_isp_reg_dump(ra_info) == 0)
+		return 0;
+
+	if (light_isp_mcm_reg_dump(ra_info) == 0)
+		return 0;
+
+
+	if (light_isp_mi_reg_dump(ra_info) == 0)
+		return 0;
+
+	if (light_isp_is_reg_dump(ra_info) == 0)
+		return 0;
+
+	if (light_isp_exp_bayer_reg_dump(ra_info) == 0)
+		return 0;
+
+	if (light_isp_sitching0_reg_dump(ra_info) == 0)
+		return 0;
+
+	if (light_isp_cproc_reg_dump(ra_info) ==0)
+		return 0;
+
+	if (light_isp_main_resize_reg_dump(ra_info)==0)
+		return 0;
+
+	if (light_isp_denoise3d_reg_dump(ra_info)==0)
+		return 0;
+
+	if(light_isp_dpf_reg_dump(ra_info)==0)
+		return 0;
+
+	if(light_isp_denoise3d2_reg_dump(ra_info)==0)
+		return 0;
+
+	if(light_isp_dpcc_reg_dump(ra_info)==0)
+		return 0;
+
+
+	if(light_isp_compand_reg_dump(ra_info)==0)
+		return 0;
+
+	if(light_isp_shutter_reg_dump(ra_info)==0)	// 0x0680
+		return 0;
+
+	if (light_isp_mi_reg_dump(ra_info) == 0)	// 0x1300
+		return 0;
+
+	if(light_isp_jpe_reg_dump(ra_info)==0)		// 0x1800
+		return 0;
+
+	if(light_isp_afm_reg_dump(ra_info)==0)		// 0x2000
+		return 0;
+
+	if(light_isp_hist256_reg_dump(ra_info)==0)	// 0x2100
+		return 0;
+
+	if(light_isp_lsc_reg_dump(ra_info)==0)		// 0x2200
+		return 0;
+
+	if(light_isp_exposure_reg_dump(ra_info)==0)	// 0x2600
+		return 0;
+
+	if(light_isp_vsm_reg_dump(ra_info)==0)		// 0x2f00
+		return 0;
+
+	if(light_isp_ee_reg_dump(ra_info)==0)		// 0x3900
+		return 0;
+
+	if (light_isp_dmsc_reg_dump(ra_info) == 0)	// 0x3e00
+		return 0;
+
+	if (light_isp_pre_filt_reg_dump(ra_info) == 0)	// 0x4000
+		return 0;
+
+	//printf_red("%s Can't find register name='%s' offset=0x%x\n",
+	//	ra_info->module_name,
+	//	ra_info->reg_name,
+	//	ra_info->reg_offset);
+	return -1;
+}
+
+int light_isp_reg_define(reg_analyzer_info_s *ra_info)
+{
+	if (light_isp_main_control_reg_define(ra_info) == 0)	// OFFSET=0x0000
+		return 0;
+
+	if (light_isp_isp_reg_define(ra_info) == 0)
+		return 0;
+
+	if (light_isp_mcm_reg_define(ra_info) == 0)
+		return 0;
+
+	if (light_isp_sitching0_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_exp_bayer_reg_define(ra_info) == 0)
+		return 0;
+
+	if (light_isp_is_reg_define(ra_info) == 0)
+		return 0;
+
+	if (light_isp_cproc_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_main_resize_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_denoise3d_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_dpf_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_denoise3d2_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_dpcc_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_compand_reg_define(ra_info) ==0)
+		return 0;
+
+	if (light_isp_shutter_reg_define(ra_info) ==0)		// 0x0680
+		return 0;
+
+	if (light_isp_mi_reg_define(ra_info) == 0)		// 0x1300
+		return 0;
+
+	if (light_isp_jpe_reg_define(ra_info) ==0)		// 0x1800
+		return 0;
+
+	if (light_isp_afm_reg_define(ra_info) ==0)		// 0x2000
+		return 0;
+
+	if (light_isp_hist256_reg_define(ra_info) ==0)		// 0x2100
+		return 0;
+
+	if (light_isp_lsc_reg_define(ra_info) ==0)		// 0x2200
+		return 0;
+
+	if (light_isp_exposure_reg_define(ra_info) ==0)		// 0x2600
+		return 0;
+
+	if (light_isp_vsm_reg_define(ra_info) ==0)		// 0x2f00
+		return 0;
+
+	if (light_isp_ee_reg_define(ra_info) ==0)		// 0x3900
+		return 0;
+
+	if (light_isp_dmsc_reg_define(ra_info) == 0)		// 0x3e00
+		return 0;
+
+	if (light_isp_pre_filt_reg_define(ra_info) == 0)	// 0x4000
+		return 0;
+
+	//printf_red("%s Can't find register name='%s' offset=0x%x\n",
+	//	ra_info->module_name,
+	//	ra_info->reg_name,
+	//	ra_info->reg_offset);
+	return -1;
+}
+
+int light_isp_reg_find(reg_analyzer_info_s *ra_info)
+{
+	light_isp_main_control_reg_find(ra_info);	// OFFSET=0x0000
+
+	light_isp_isp_reg_find(ra_info);
+
+	light_isp_mcm_reg_find(ra_info);
+
+	light_isp_sitching0_find(ra_info);
+
+	light_isp_exp_bayer_reg_find(ra_info);
+
+	light_isp_is_reg_find(ra_info);
+
+	light_isp_cproc_reg_find(ra_info);
+
+	light_isp_main_resize_reg_find(ra_info);
+
+	light_isp_denoise3d_reg_find(ra_info);
+
+	light_isp_dpf_reg_find(ra_info);
+
+	light_isp_denoise3d2_reg_find(ra_info);
+
+	light_isp_dpcc_reg_find(ra_info);
+
+	light_isp_compand_reg_find(ra_info);
+
+	light_isp_shutter_reg_find(ra_info);		// 0x0680
+
+	light_isp_mi_reg_find(ra_info);			// 0x1300
+
+	light_isp_jpe_reg_find(ra_info);		// 0x1800
+
+	light_isp_afm_reg_find(ra_info);		// 0x2000
+
+	light_isp_hist256_reg_find(ra_info);		// 0x2100
+
+	light_isp_lsc_reg_find(ra_info);		// 0x2200
+
+	light_isp_exposure_reg_find(ra_info);		// 0x2600
+
+	light_isp_vsm_reg_find(ra_info);		// 0x2f00
+
+	light_isp_ee_reg_find(ra_info);			// 0x3900
+
+	light_isp_dmsc_reg_find(ra_info);		// 0x3e00
+
+	light_isp_pre_filt_reg_find(ra_info);		// 0x4000
+
+	return 0;
+}
+

+ 174 - 0
tools/reg_analyzer/ra_light_main.c

@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "log_common.h"
+#include "ra_common.h"
+
+#define TOOL_NAME "reg_analyzer"
+
+extern int reg_demo_dump(reg_analyzer_info_s *ra_info);
+extern int reg_demo_define(reg_analyzer_info_s *ra_info);
+extern int reg_demo_find(reg_analyzer_info_s *ra_info);
+
+extern int light_visys_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_visys_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_visys_reg_find(reg_analyzer_info_s *ra_info);
+
+extern int light_isp_reg_dump(reg_analyzer_info_s *ra_info);
+extern int light_isp_reg_define(reg_analyzer_info_s *ra_info);
+extern int light_isp_reg_find(reg_analyzer_info_s *ra_info);
+
+
+static module_instance_t light_module_instance_array[] = {
+	{"demo",	reg_demo_dump,		reg_demo_define,	reg_demo_find},
+	{"visys",	light_visys_reg_dump,	light_visys_reg_define,	light_visys_reg_find},
+	{"isp0",	light_isp_reg_dump,	light_isp_reg_define,	light_isp_reg_find},
+};
+
+void show_moduel_list()
+{
+	int i;
+	int module_count = sizeof(light_module_instance_array)/sizeof(light_module_instance_array[0]);
+	for (i = 0; i < module_count; i++) {
+		printf("%s  ", light_module_instance_array[i].module_name);
+			}
+	printf("\n");
+}
+
+
+static void help(void)
+{
+	printf("usage: %s [-m module_name] [-o reg_offset] [-v reg_value] \n"
+	       "                    [-f find_reg_name]\n", TOOL_NAME);
+	printf("  example: %s -m demo -o 0x00000010\n", TOOL_NAME);
+	printf("           %s -m demo -o 0x00000010 -v 0x0001ff7b\n", TOOL_NAME);
+	printf("           %s -m demo -r DEMO_REG1\n", TOOL_NAME);
+	printf("           %s -m demo -r DEMO_REG0 -v 0x0001ff7b\n", TOOL_NAME);
+	printf("           %s -m demo -f _REG0\n", TOOL_NAME);
+}
+
+static int parse_cmd_params(int argc,char *argv[], reg_analyzer_info_s *ra_info)
+{
+	int param_cnt = 1;
+	memset(ra_info, 0, sizeof(*ra_info));
+	ra_info->operate = RA_OP_INVALID;
+	ra_info->reg_offset = INVALID_MAGIC32;
+	ra_info->reg_value = INVALID_MAGIC32;
+
+	if (argc == 1) {
+		//help();
+		return -1;
+	}
+
+	while (param_cnt < argc) {
+		//printf("argv[param_cnt]=%s\n", argv[param_cnt]);
+		if (0 == strncmp (argv[param_cnt], "-m", 2)) {
+			strncpy(ra_info->module_name, argv[param_cnt+1], sizeof(ra_info->module_name));
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-o", 2) ||
+			   0 == strncmp (argv[param_cnt], "addr", 2)) {
+			sscanf(strlwr(argv[param_cnt+1]), "%x", &ra_info->reg_offset);
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-r", 2)) {
+			sscanf(argv[param_cnt+1], "%s", ra_info->reg_name);
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-v", 2) ||
+			   0 == strncmp (argv[param_cnt], "value", 2)) {
+			sscanf(strlwr(argv[param_cnt+1]), "%x", &ra_info->reg_value);
+			param_cnt += 2;
+		} else if (0 == strncmp (argv[param_cnt], "-f", 2)) {
+			sscanf(argv[param_cnt+1], "%s", ra_info->reg_name);
+			ra_info->operate = RA_OP_FIND_REG;
+			param_cnt += 2;
+		} else {
+			return -1;
+		}
+	}
+
+	if (strlen(ra_info->module_name) == 0) {
+		printf("Please input valid module name, such as: ");
+		show_moduel_list();
+		return -1;
+	}
+
+	if (ra_info->operate == RA_OP_FIND_REG) {
+		return 0;
+	}
+
+	if (ra_info->reg_offset == INVALID_MAGIC32 && strlen(ra_info->reg_name) ==0 )
+		return -1;
+
+	if (ra_info->reg_value != INVALID_MAGIC32)
+		ra_info->operate = RA_OP_SHOW_DUMP;
+	else
+		ra_info->operate = RA_OP_SHOW_REG_DEFINE;
+
+	if (ra_info->operate == RA_OP_INVALID)
+		return -1;
+
+	return 0;
+}
+
+int main(int argc,char *argv[])
+{
+	int i, ret = 0;
+	int module_count = sizeof(light_module_instance_array)/sizeof(light_module_instance_array[0]);
+	reg_analyzer_info_s ra_info;
+	module_instance_t *module_inst = NULL;
+
+	ret = parse_cmd_params(argc, argv, &ra_info);
+	//_dump_ra_info(&ra_info);
+	if (ret != 0) {
+		printf_red("Invalid syntax.\n");
+		help();
+		return ret;
+	}
+
+	for (i = 0; i < module_count; i++) {
+		if(strcmp(light_module_instance_array[i].module_name, ra_info.module_name) == 0) {
+			module_inst = &light_module_instance_array[i];
+		}
+	}
+
+	if (module_inst == NULL) {
+		printf("Please input valid module name, such as: ");
+		show_moduel_list();
+		return -1;
+	}
+
+	if (ra_info.operate == RA_OP_SHOW_REG_DEFINE && module_inst->reg_define != NULL) {
+		ret = module_inst->reg_define(&ra_info);
+		if (ret != 0) {
+			printf_red("The register or offset can't find in defination\n");
+			return ret;
+		}
+	} else if (ra_info.operate == RA_OP_SHOW_DUMP && module_inst->reg_dump != NULL) {
+		ret = module_inst->reg_dump(&ra_info);
+		if (ret != 0) {
+			printf_red("The register or offset can't find in defination\n");
+			return ret;
+		}
+	} else if (ra_info.operate == RA_OP_FIND_REG && module_inst->reg_find != NULL) {
+		ret = module_inst->reg_find(&ra_info);
+		if (ret != 0) {
+			printf_red("The register or offset can't find in defination\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+

+ 44 - 0
tools/reg_analyzer/ra_light_visys.c

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"TEST","This is demo register-0 description",
+			0x1200, 0x00000000,  0,  0, "mcm_bypass_en",	"Bypass enable.      0: bypass disabled; 1: bypass enabled"},
+};
+
+
+int light_visys_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_visys_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_visys_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 51 - 0
tools/reg_analyzer/ra_reg_demo.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+/* usage: reg_analyzer -m demo -o 0x10 -v 0x13572468 */
+/* usage: reg_analyzer -m demo -r DEMO_REG1 */
+static const reg_field_s reg_demo_desc[] = {
+	/* structure field order
+	reg_name,  offset,reset_value,msb,lsb, field_name,     field_desc */
+	{"DEMO_REG0",	"This is demo register-0 description",
+			0x10, 0x12345678, 31, 16, "reg0 field0",	"This is demo reg0's field0"},
+	{NULL, NULL,	0x10, 0x0,        15, 0,  "reg0 field1",	"This is demo reg0's field1"},
+
+	{"DEMO_REG1",	"This is demo register-0 description",
+			0x14, 0x13572468, 31, 24, "reg1 field0",	"This is demo reg1's field0"},
+	{NULL, NULL,	0x14, 0x0,        23, 0,  "reg1 field1",	"This is demo reg1's field1 desc line1" LINE_PADDING_6TAB
+									"and reg1's field desc line 2" LINE_PADDING_6TAB
+									"and reg1's field desc line 3"},
+};
+
+int reg_demo_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_demo_desc) / sizeof(reg_demo_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_demo_desc, count);
+}
+
+int reg_demo_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_demo_desc) / sizeof(reg_demo_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_demo_desc, count);
+}
+
+int reg_demo_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_demo_desc) / sizeof(reg_demo_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_demo_desc, count);
+}
+

+ 49 - 0
tools/reg_analyzer/vsi_isp8000/isp_afm.c

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002000
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_AFM_CTRL", "Auto Focus Measurement Unit Control Register",
+			0x00002000, 0x00000000,  0,  0, "afm_en",		"AF measurement enable.  0: disable; 1: enable" LINE_PADDING_6TAB
+										"Writing a 1 to this register starts a new measurement " LINE_PADDING_6TAB
+										"and resets the afm_fin (measurement finished) interrupt to 0." LINE_PADDING_6TAB
+										"As long as the afm_en is 1, the AFM unit calculates new sharpness values for each frame."},
+};
+
+
+int light_isp_afm_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_afm_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_afm_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 48 - 0
tools/reg_analyzer/vsi_isp8000/isp_compand.c

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00003200
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_COMPAND_CTRL", "Compand Control Register",
+			0x00003200, 0x00000000,  3,  3, "compand_ctrl_bls_enable", "Enable Black Level Subtraction in the Compand module"},
+	{NULL, NULL,	0x00003200, 0x00000000,  2,  2, "compand_ctrl_soft_reset_flag", "Soft reset of compand module"},
+	{NULL, NULL,	0x00003200, 0x00000000,  0,  0, "compand_ctrl_expand_enable", "Enable Expand in the Compand module"},
+};
+
+
+int light_isp_compand_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_compand_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_compand_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 51 - 0
tools/reg_analyzer/vsi_isp8000/isp_denoise3d.c

@@ -0,0 +1,51 @@
+
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define ISP_DENOISE3D_BASE 0x3700
+#define REG_BASE ISP_DENOISE3D_BASE
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name, reg_desc,                  offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_DENOISE3D_CTRL", "Denoise3D Control Register",
+			0x00003700, 0x00000000, 10, 10, "denoise3d_read_ref_en",	"0: disable read ref data from SRAM; 1: Enable read ref data from SRAM"},
+	{NULL, NULL,	0x00003700, 0x00000000,  9,  9, "denoise3d_raw_decompress_en",	"1: decompress enable; t0: decompress disable"},
+	{NULL, NULL,	0x00003700, 0x00000000,  8,  8, "denoise3d_raw_compress_en",	"1: compress enable; 0: compress disable"},
+	{NULL, NULL,	0x00003700, 0x00000000,  7,  7, "denoise3d_write_ref_en",	"0: disable write ref data to SRAM; 1: Enable write ref data to SRAM (Default)"},
+};
+
+
+int light_isp_denoise3d_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_denoise3d_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_denoise3d_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 64 - 0
tools/reg_analyzer/vsi_isp8000/isp_denoise3d2.c

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x5300
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_DENOISE3D2_CTRL", "Denoise3D2 ctrl",
+			0x00005300, 0x00000000, 12, 12, "denoise3d_v20_soft_rst", "Denoise3D2:soft reset bit"},
+	{NULL, NULL,	0x00005300, 0x00000000, 11, 11, "denoise3d_v20_invgamma_en", "Denoise3D2: inv gamma  enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000, 10, 10, "denoise3d_v20_pregamma_en", "Denoise3D2: pregamma  enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  9,  9, "denoise3d_v20_erode_en", "Denoise3D2: motion erosion  enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  8,  8, "denoise3d_v20_motion_conv_en", "Denoise3D2: motion convergence enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  7,  7, "denoise3d_v20_inv_dgain_en", "Denoise3D2: inv digital gain enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  6,  6, "denoise3d_v20_inv_awb_gain_en", "Denoise3D2: inv awb  gain enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  5,  5, "denoise3d_v20_comp_luma_en", "Denoise3D2: luma compensation enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  4,  4, "denoise3d_v20_ref_reset", "Denoise3D2: soft reset bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  3,  3, "denoise3d_v20_motion_dilate_enable", "Denoise3D2: motion dilation enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  2,  2, "denoise3d_v20_nlm_enable", "Denoise3D2: 2dnr enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  1,  1, "denoise3d_v20_tnr_enable", "Denoise3D2: tnr enable bit"},
+	{NULL, NULL,	0x00005300, 0x00000000,  0,  0, "denoise3d_v20_enable", "Denoise3D2: enable bit"},
+
+
+	{"ISP_DENOISE3D2_PREGAMMA_Y_0", "Denoise3D2 Pregamma Y LUT Register",
+			0x00005400, 0x00000FFF, 29, 24, "denoise3d2_pregamma_y_2_a", "Denoise 3DV2 Pregamma Y 2 [11:6]"},
+	{NULL, NULL,	0x00005400, 0x00000FFF, 23, 12, "denoise3d2_pregamma_y_1", "Denoise 3DV2 Pregamma Y 1"},
+	{NULL, NULL,	0x00005400, 0x00000FFF, 11,  0, "denoise3d2_pregamma_y_0", "Denoise 3DV2 Pregamma Y 0"},
+};
+
+
+int light_isp_denoise3d2_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_denoise3d2_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_denoise3d2_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 120 - 0
tools/reg_analyzer/vsi_isp8000/isp_dmsc.c

@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00003e00
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_DMSC_CTRL", "Demosaic control register",
+			0x00003E00, 0x0400288E, 31, 24, "demosaic_thr",		"Threshold for Bayer demosaicing texture detection." LINE_PADDING_6TAB
+										" This value shifted 4-bit is compared width the different of the vertical" LINE_PADDING_6TAB
+										" and horizontal 12bit wide texture indicators, to decide if the vertical or" LINE_PADDING_6TAB
+										" horizontal texture flag must be set." LINE_PADDING_6TAB
+										"0x00: maximum edge sensitivity" LINE_PADDING_6TAB
+										"0xff: no texture detection"},
+	{NULL, NULL,	0x00003E00, 0x0400288E, 21, 16, "denoise_strength",	"green channel smoothing filter results account for the weight of the final result, the larger the blur"},
+	{NULL, NULL,	0x00003E00, 0x0400288E, 14, 14, "frame_clr_sel",	"0:frame clear by vsync. 1:frame clear by frame end"},
+	{NULL, NULL,	0x00003E00, 0x0400288E, 13, 13, "frame_end_en",		"frame clear by frame end"},
+	{NULL, NULL,	0x00003E00, 0x0400288E, 12,  8, "sharpen_size",		"green channel sharpen size, the larger the sharpen edge, the greater the graininess"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  7,  7, "vsync_pos_en",		"frame clear by VSYNC"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  6,  6, "soft_rst_inner",	"soft reset"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  5,  5, "sharpen_line_enable",	"0: disable line sharpen, 1: enable line sharpen"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  4,  4, "skin_enable",		"0: disable skin area filter, 1: enable skin area filter"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  3,  3, "depurple_enable",	"0: disable depurple, 1: enable depurple"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  2,  2, "demoire_enable",	"0: disable demoire, 1: enable demoire"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  1,  1, "sharpen_enable",	"0: disable sharpen, 1: enable sharpen"},
+	{NULL, NULL,	0x00003E00, 0x0400288E,  0,  0, "demosaic_bypass",	"0: do interpolation, 1: bypass interpolation"},
+
+
+	{"ISP_DMSC_INTP_THR", "Direction select threshold register",
+			0x00003E04, 0x00000000, 23, 12, "interplationdir_thr_max",	"direction select threshold value in bright area, the interpolation " LINE_PADDING_6TAB
+											" operation between maximum threshold and minimal threshold"},
+	{NULL, NULL,	0x00003E04, 0x00000000, 11,  0, "interplationdir_thr_min",	"direction select threshold value in dark area, the interpolation "  LINE_PADDING_6TAB
+											" operation between maximum threshold and minimal threshold"},
+
+	{"ISP_DMSC_DMOI_CTRL", "Demoire ctrl register",
+			0x00003E08, 0x00001F08, 13,  8, "demoire_area_thr", "judgment threshold of moire area"},
+	{NULL, NULL,	0x00003E08, 0x00001F08,  5,  0, "demoire_sat_shrink", "moire pixel forced saturation, 32=no color"},
+
+
+	{"ISP_DMSC_CAC_CTRL", "Control register for chromatic aberration correction",
+			0x00003E44, 0x00000000,  3,  3, "cac_h_clip_mode", 	"defines the red/blue pixel shift in horizon direction" LINE_PADDING_6TAB
+										"0:set horizon vector to +/-4 pixel" LINE_PADDING_6TAB
+										"1:set horizon vector to +/-4 or +/-5 pixel " LINE_PADDING_6TAB
+										"  depending on the position in bayer raster"},
+	{NULL, NULL,	0x00003E44, 0x00000000,  2,  1, "cac_v_clip_mode",	"defines the red/blue pixel shift in vertical direction" LINE_PADDING_6TAB
+										"00:set vertical vector to +/-2 pixel" LINE_PADDING_6TAB
+										"01:set vertical vector to +/-3 pixel" LINE_PADDING_6TAB
+										"10:set vertical vector to +/-3 or +/-4 pixel " LINE_PADDING_6TAB
+										"   depending on the position in bayer raster" LINE_PADDING_6TAB
+										"11:reserved"},
+	{NULL, NULL,	0x00003E44, 0x00000000,  0,  0, "cac_enable",		"0: chromatic aberration correction off" LINE_PADDING_6TAB
+										"1: chromatic aberration correction on"},
+
+	{"ISP_DMSC_SIZE_CTRL", "demoire size ctrl register",
+			0x00003E60, 0x01000000, 31, 16, "dummy_hblk_value", "dummy lines hblank cycles"},
+	{NULL, NULL,	0x00003E60, 0x01000000, 15,  0, "img_hsize", "dmsc process image hsize"},
+
+
+
+	{"ISP_DMSC_SHAP_FACT", "Sharpen factor register",
+			0x00003E14, 0x00008008, 20, 12, "sharpen_factor_black",	"Sharpen factor of black edge; 0 means no sharpen"},
+	{NULL, NULL,	0x00003E14, 0x00008008,  8,  0, "sharpen_factor_white",	"Sharpen factor of white edge; 0 means no sharpen"},
+
+	{"ISP_DMSC_CTRL_SHD", "Demosaic control shadow register",
+			0x00003E64, 0x0400080E, 31, 24, "demosaic_thr",		"Threshold for Bayer demosaicing texture detection." LINE_PADDING_6TAB
+										" This value shifted 4-bit is compared width the different of the vertical" LINE_PADDING_6TAB
+										" and horizontal 12bit wide texture indicators, to decide if the vertical or" LINE_PADDING_6TAB
+										" horizontal texture flag must be set." LINE_PADDING_6TAB
+										"0x00: maximum edge sensitivity" LINE_PADDING_6TAB
+										"0xff: no texture detection"},
+	{NULL, NULL,	0x00003E64, 0x0400080E, 21, 16, "denoise_strength",	"green channel smoothing filter results account for the weight of the final result, the larger the blur"},
+	{NULL, NULL,	0x00003E64, 0x0400080E, 14, 14, "frame_clr_sel",	"0:frame clear by vsync. 1:frame clear by frame end"},
+	{NULL, NULL,	0x00003E64, 0x0400080E, 13, 13, "frame_end_en",		"frame clear by frame end"},
+	{NULL, NULL,	0x00003E64, 0x0400080E, 12,  8, "sharpen_size",		"green channel sharpen size, the larger the sharpen edge, the greater the graininess"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  7,  7, "vsync_pos_en",		"frame clear by VSYNC"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  6,  6, "soft_rst_inner",	"soft reset"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  5,  5, "sharpen_line_enable",	"0: disable line sharpen, 1: enable line sharpen"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  4,  4, "skin_enable",		"0: disable skin area filter, 1: enable skin area filter"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  3,  3, "depurple_enable",	"0: disable depurple, 1: enable depurple"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  2,  2, "demoire_enable",	"0: disable demoire, 1: enable demoire"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  1,  1, "sharpen_enable",	"0: disable sharpen, 1: enable sharpen"},
+	{NULL, NULL,	0x00003E64, 0x0400080E,  0,  0, "demosaic_bypass",	"0: do interpolation, 1: bypass interpolation"},
+
+};
+
+
+int light_isp_dmsc_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_dmsc_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_dmsc_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 49 - 0
tools/reg_analyzer/vsi_isp8000/isp_dpcc.c

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002900
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_DPCC_MODE", "Global control register",
+			0x00002900, 0x00000004,  2,  2, "stage1_enable",	"0: bypass stage1; 1: enable stage1 (Default)"},
+	{NULL, NULL,	0x00002900, 0x00000004,  1,  1, "grayscale_mode",	"0: BAYER DATA INPUT (Default)"  LINE_PADDING_6TAB
+										" 1: enable gray scale data input from black and white sensors (without color filter array)"},
+	{NULL, NULL,	0x00002900, 0x00000004,  0,  0, "dpcc_enable",		"0: bypass DPCC (Default); 1: enable DPCC"},
+};
+
+
+int light_isp_dpcc_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_dpcc_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_dpcc_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 50 - 0
tools/reg_analyzer/vsi_isp8000/isp_ee.c

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00003900
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_EE_CTRL", "Edge Enhancement Control Register",
+			0x00003900, 0x00000000, 18, 11, "edge_enhancement_source_strength",	"Edge Enhancement strength of process"},
+	{NULL, NULL,	0x00003900, 0x00000000, 10,  3, "edge_enhancement_strength",		"Edge Enhancement strength of smooth filter"},
+	{NULL, NULL,	0x00003900, 0x00000000,  2,  2, "edge_enhancement_soft_reset",		"Edge Enhancement software reset.  0: release;  1: reset"},
+	{NULL, NULL,	0x00003900, 0x00000000,  1,  1, "edge_enhancement_input_sel",		"Edge Enhancement input data format select.  0: RGB;  1: YUV"},
+	{NULL, NULL,	0x00003900, 0x00000000,  0,  0, "edge_enhancement_enable",		"Enable/Disable Edge Enhancement.  0: Disable the EE;  1: Enable the EE"},
+};
+
+
+int light_isp_ee_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_ee_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_ee_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 47 - 0
tools/reg_analyzer/vsi_isp8000/isp_exp_bayer.c

@@ -0,0 +1,47 @@
+
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define ISP_EXP_BAYER_BASE 0x2680
+#define REG_BASE ISP_EXP_BAYER_BASE
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name, reg_desc,                  offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_EXP_H_SIZE_SHD",	"ISP_EXP_H_SIZE_SHD",  0x00002680, 0x00000000, 10,  0, "exp_h_size", "Shadow Horizontal size of one block in pixels."},
+};
+
+
+int light_isp_exp_bayer_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_exp_bayer_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_exp_bayer_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 56 - 0
tools/reg_analyzer/vsi_isp8000/isp_exposure.c

@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002600
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_EXP_CONF", "Exposure Control",
+			0x00002600, 0x00000000, 31, 31, "exp_alt_mode",		"0: luminance calculation according to Y=16+0.25R+0.5G+0.1094B" LINE_PADDING_6TAB
+										"1: luminance calculation according to Y=(R+G+B) x 0.332"},
+	{NULL, NULL,	0x00002600, 0x00000000,  3,  2, "exp_src_select",	"data source select  1:wdr  0:csm"},
+	{NULL, NULL,	0x00002600, 0x00000000,  1,  1, "autostop",		"0: continuous measurement; 1: stop measuring after a complete frame"},
+
+
+	{"ISP_EXPV2_CTRL", "raw exposure control",
+			0x000026A0, 0x00000000,  3,  2, "expv2_input_select",	"00: degamma output; 01: awb_gain output; 10: WDR3 output; 11: not used"},
+	{NULL, NULL,	0x000026A0, 0x00000000,  1,  1, "expv2_autostop",	"0: continous measurement; 1: stop measuring after a complete frame"},
+	{NULL, NULL,	0x000026A0, 0x00000000,  0,  0, "expv2_enable",		"1: start measuring a frame" LINE_PADDING_6TAB
+										"The exp block will reset this bit and halt after " LINE_PADDING_6TAB
+										"completing one frame if bit 'autostop' is set to 1"},
+};
+
+int light_isp_exposure_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_exposure_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_exposure_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 61 - 0
tools/reg_analyzer/vsi_isp8000/isp_hist256.c

@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002100
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_HIST256_PROP", "Histogram properties",
+			0x00002100, 0x00000000,  9,  3, "stepsize",	"Histogram pre-divider" LINE_PADDING_6TAB
+									"Process every (step size)th pixel; all other pixels are skipped" LINE_PADDING_6TAB
+									"0,1,2: not allowed" LINE_PADDING_6TAB
+									"3: process every third input pixel" LINE_PADDING_6TAB
+									"4: process every fourth input pixel" LINE_PADDING_6TAB
+									"..." LINE_PADDING_6TAB
+									"7FH: process every 127th pixel"},
+	{NULL, NULL,	0x00002100, 0x00000000,  2,  0, "hist_mode",	"Histogram mode, luminance is taken at ISP output before" LINE_PADDING_6TAB
+									" output formatter, RGB is taken at xtalk output" LINE_PADDING_6TAB
+									"0: disable, no measurements" LINE_PADDING_6TAB
+									"1: RGB combined histogram" LINE_PADDING_6TAB
+									"2: R histogram" LINE_PADDING_6TAB
+									"3: G histogram" LINE_PADDING_6TAB
+									"4: B histogram" LINE_PADDING_6TAB
+									"5: Y (luminance) histogram" LINE_PADDING_6TAB
+									"6, 7: must not be used"},
+};
+
+
+int light_isp_hist256_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_hist256_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_hist256_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 45 - 0
tools/reg_analyzer/vsi_isp8000/isp_jpe.c

@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00001800
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"JPE_ERROR_MIR", "jpe error imr",
+			0x00001868, 0x00000000, 31,   0, "Undefined in reg.xml",	"Undefined in reg.xml, but mrv_all_regs.h does"},
+};
+
+int light_isp_jpe_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_jpe_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_jpe_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 49 - 0
tools/reg_analyzer/vsi_isp8000/isp_lsc.c

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002200
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_LSC_CTRL", "Lens Shade Control Register",
+		0x00002200, 0x00000000,  0,	0, "lsc_en",	"0: activation request for lens shading correction" LINE_PADDING_6TAB
+								"1: deactivation request for lens shading correction" LINE_PADDING_6TAB
+								"Activation/Deactivation is an object of a shadowing mechanism." LINE_PADDING_6TAB
+								"The current status is visible at ISP_LSC_STATUS::lsc_enable_status"},
+};
+
+
+int light_isp_lsc_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_lsc_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_lsc_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 75 - 0
tools/reg_analyzer/vsi_isp8000/isp_mcm.c

@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+#define REG_BASE 0x1200
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"MCM_CTRL",	"MCM control register",
+			0x00001200, 0x00020000, 17, 17, "mcm_sensor_mem_bypass","0: use sensor latency memory in MCM; 1: not use sensor latency memory in MCM"},
+	{NULL, NULL,	0x00001200, 0x00020000, 16, 14, "mcm_g2_wr1_fmt",	"Controls the input format for MCM_G2 channel 1 with same definition as mcm_wr0_fmt"},
+	{NULL, NULL,	0x00001200, 0x00020000, 13, 11, "mcm_g2_wr0_fmt",	"Controls the input format for MCM_G2 channel 0 with same definition as mcm_wr0_fmt"},
+	{NULL, NULL,	0x00001200, 0x00020000, 10,  8, "mcm_wr1_fmt",		"Controls the input format for MCM channel 1 with same definition as mcm_wr0_fmt"},
+	{NULL, NULL,	0x00001200, 0x00020000,  7,  5, "mcm_wr0_fmt", 		"MCM Channel-0: 000: 8-bit; 001: 10-bit; 010: 12-bit; 011: 14-bit; 100: 16-bit; 101: 20-bit"},
+	{NULL, NULL,	0x00001200, 0x00020000,  4,  1, "mcm_bypass_switch",	"Bypass switch. 0000: sensor0 bypass; 0001: sensor1 bypass; …; 1111: sensor15 bypass if any"},
+	{NULL, NULL,	0x00001200, 0x00020000,  0,  0, "mcm_bypass_en",	"Bypass enable. 0: bypass disabled; 1: bypass enabled"},
+
+
+	{"MCM_SIZE0",	"MCM dimension register 0",
+			0x00001204, 0x00000000, 29, 16, "mcm_height0",		"Image height for write channel 0"},
+	{NULL, NULL,	0x00001204, 0x00000000, 13,  0, "mcm_width0",		"Image width for write channel 0"},
+
+	{"MCM_SIZE1",	"MCM dimension register 1",
+			0x00001208, 0x00000000, 29, 16, "mcm_height1",		"Image height for write channel 1"},
+	{NULL, NULL,	0x00001208, 0x00000000, 13,  0, "mcm_width1",		"Image width for write channel 1"},
+
+
+	{"ISP_MCM_RD_CFG",	"MCM read format register",
+			0x00001280, 0x00000000, 13,  0, "mcm_rd_fmt",		"input format for MCM read channel: " LINE_PADDING_6TAB
+										"  000:8bit, 001:10bit, 010:12bit, 011:14bit, 100:16bit, 101:20bit"},
+
+	{"MCM_RETIMING0",	"MCM retiming control register 0",
+			0x00001284, 0x00000000, 31,  8, "mcm_vsync_blank",	"Minimum count of clock from previous frame end to the vsync of the next frame"},
+	{NULL, NULL,	0x00001284, 0x00000000,  7,  0, "mcm_vsync_duration",	"Vsync active duration for retiming unit which indicate counts of clock"},
+
+	{"MCM_RETIMING1",	"MCM retiming control register 1",
+			0x00001288, 0x00000000, 31,  8, "mcm_vsync_blank",	"Minimum count of clock from previous frame end to the vsync of the next frame"},
+	{NULL, NULL,	0x00001288, 0x00000000,  7,  0, "mcm_vsync_duration",	"Vsync active duration for retiming unit which indicate counts of clock"},
+
+	{"MCM Unknown",	"What",	0x0000128C, 0x00000000, 31,  0, "unknown",	"unknown"},
+};
+
+
+int light_isp_mcm_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_mcm_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_mcm_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 71 - 0
tools/reg_analyzer/vsi_isp8000/isp_pre_filt.c

@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00004000
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_PRE_FILT_CTRL", "Pre-filter Mode control register",
+			0x00004000, 0x00C08802, 23, 23, "part_two_enable",	"pre part enable"},
+	{NULL, NULL,	0x00004000, 0x00C08802, 22, 22, "part_one_enable",	"post part enable"},
+	{NULL, NULL,	0x00004000, 0x00C08802, 21, 21, "soft_rst_pre_filt",	"Soft reset. 0: release; 1: reset"},
+	{NULL, NULL,	0x00004000, 0x00C08802, 20, 13, "demosaic_threshold",	"Threshold for Bayer demosaicing texture detection. " LINE_PADDING_6TAB
+										"This value shifted left 4 bits is compared with the " LINE_PADDING_6TAB
+										"difference of the vertical and horizontal 12 bit wide " LINE_PADDING_6TAB
+										"texture indicators, to determine if the vertical or " LINE_PADDING_6TAB
+										"horizontal texture flag must be set." LINE_PADDING_6TAB
+										"0x00: maximum edge sensitivity" LINE_PADDING_6TAB
+										"0xFF: no texture detection"},
+	{NULL, NULL,	0x00004000, 0x00C08802, 12,  9, "stage1_select",	"Green filter stage 1 select (range 0x0...0x8)" LINE_PADDING_6TAB
+										"0x0: maximum blurring; 0x4: Default; " LINE_PADDING_6TAB
+										"0x7: minimum blurring; 0x8: filter stage1 bypass" LINE_PADDING_6TAB
+										"For a detailed description refer to chapter " LINE_PADDING_6TAB
+										"'Filter (Sharpen/Blur) Programming' " LINE_PADDING_6TAB
+										"in the Programming Guide, Part 2."},
+	{NULL, NULL,	0x00004000, 0x00C08802,  8,  7, "out_rgb_bayer_pattern","0: RGGB; 1: GRBG; 2: GBRG; 3: BGGR"},
+	{NULL, NULL,	0x00004000, 0x00C08802,  6,  3, "rgbir_bayer_pattern",	"0: BGGIR/BAYER PATTERN (Default); 1: GRIRG; 2: RGGIR; 3: GBIRG;" LINE_PADDING_6TAB
+										"4: GIRRG; 5: IRGGB; 6: GIRBG; 7: IRGGR; 8: RGIRB; 9: GRBI;" LINE_PADDING_6TAB
+										"10: IRBRG; 11: BIRGR; 12: BGIRR; 13: GBRIR; 14: IRRBG; 15: RIRGB"},
+	{NULL, NULL,	0x00004000, 0x00C08802,  2,  2, "green_filt_enable",	"Enable/disable green channel filter" LINE_PADDING_6TAB
+										"0: disable green filter (Default)" LINE_PADDING_6TAB
+										"1: enable green filter"},
+	{NULL, NULL,	0x00004000, 0x00C08802,  1,  1, "green_filt_mode",	"0: green filter static mode (active filter factor = FILT_FAC_MID)" LINE_PADDING_6TAB
+										"1: dynamic noise reduction/sharpen (Default)"},
+	{NULL, NULL,	0x00004000, 0x00C08802,  0,  0, "isp_pre_filt_enable",	"0: bypass pre_filt (Default); 1: enable pre_filt"},
+};
+
+
+int light_isp_pre_filt_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_pre_filt_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_pre_filt_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 238 - 0
tools/reg_analyzer/vsi_isp8000/isp_stitching0.c

@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define ISP_STITCHING0_BASE 0x3300
+#define REG_BASE ISP_STITCHING0_BASE
+
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name, reg_desc,         offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_STITCHING0_CTRL", "HDR Stitch Control Register",
+			0x00003300, 0x00000000, 26, 26, "share_en",		"Enable/Disable share of sram.  0: Disable share sram;  1: Enable share sram"},
+	{NULL, NULL,	0x00003300, 0x00000000, 25, 25, "digital_gain_en_2",	"Enable/Disable dgain of very short frame. 0: Disable the dgain; 1: Enable the dgain"},
+	{NULL, NULL,	0x00003300, 0x00000000, 24, 24, "digital_gain_en_1",	"Enable/Disable dgain of short frame.  0: Disable the dgain; 1: Enable the dgain"},
+	{NULL, NULL,	0x00003300, 0x00000000, 23, 23, "digital_gain_en_0",	"Enable/Disable dgain of long frame.  0: Disable the dgain; 1: Enable the dgain"},
+	{NULL, NULL,	0x00003300, 0x00000000, 22, 22, "regs_inform_en",	"Enable/Disable inform module.  0: Disable the inform; 1: Enable the inform"},
+	{NULL, NULL,	0x00003300, 0x00000000, 21, 21, "vsync_pol",		"VSYNC polarity reversal"},
+	{NULL, NULL,	0x00003300, 0x00000000, 20, 20, "hsync_pol",		"HSYNC polarity reversal"},
+	{NULL, NULL,	0x00003300, 0x00000000, 19, 19, "awb_gain_enable",	"Enable/Disable AWB Gain module. 0: Disable the AWB gain; 1: Enable the AWB gain"},
+	{NULL, NULL,	0x00003300, 0x00000000, 18, 18, "cfg_upd",		"Configuration update"},
+	{NULL, NULL,	0x00003300, 0x00000000, 17, 17, "gen_cfg_upd",		"Generate configuration update"},
+	{NULL, NULL,	0x00003300, 0x00000000, 16, 16, "gen_cfg_upd_fix",	"Auto configuration update in the end of frame"},
+	{NULL, NULL,	0x00003300, 0x00000000, 14, 13, "bypass_select",	"Bypass frame select.  0: long frame; 1: short frame; 2: very short frame"},
+	{NULL, NULL,	0x00003300, 0x00000000, 12, 12, "linear_combine_enable","linear combination enable"},
+	{NULL, NULL,	0x00003300, 0x00000000, 11, 11, "base_frame_selection",	"base frame select"},
+	{NULL, NULL,	0x00003300, 0x00000000, 10,  9, "combination_mode",	"combination_mode"},
+	{NULL, NULL,	0x00003300, 0x00000000,  8,  8, "channel_config_bit",	"channel_config_bit"},
+	{NULL, NULL,	0x00003300, 0x00000000,  7,  7, "b10_enable_bit",	"10 bit enable"},
+	{NULL, NULL,	0x00003300, 0x00000000,  6,  6, "lin_enable_bit",	"reserved"},
+	{NULL, NULL,	0x00003300, 0x00000000,  5,  5, "vs_enable_bit",	"very short frame enable"},
+	{NULL, NULL,	0x00003300, 0x00000000,  4,  3, "bayer_pattern",	"bayer pattern. 00: RGGB; 01: GRBG; 10: GBRB; 11: BGGR"},
+	{NULL, NULL,	0x00003300, 0x00000000,  2,  2, "soft_reset_flag",	"Activate/deactivate Stitch software reset.  0: software reset un-active; 1: software reset active"},
+	{NULL, NULL,	0x00003300, 0x00000000,  1,  1, "mono_input_flag",	"reserved"},
+	{NULL, NULL,	0x00003300, 0x00000000,  0,  0, "combine_enable_bit",	"Enable/Disable Stitch module. 0: Disable the Stitch module; 1: Enable the Stitch module"},
+
+
+	{"ISP_STITCHING0_FRAME_WIDTH", "Stitching frame width",		0x00003304, 0x00000000, 13,  0, "stitching_frame_width",	"Frame width"},
+	{"ISP_STITCHING0_FRAME_HEIGHT","Stitching frame height",	0x00003308, 0x00000000, 13,  0, "stitching_frame_height",	"Frame height"},
+
+	{"ISP_STITCHING0_EXPOSURE_BIT", "Stitching frame data bit depth",
+			0x0000330C, 0x05050505, 31, 24, "stitching_l_bit_depth", "Exposure bit for LS; valid range: [0..255]"},
+	{NULL, NULL,	0x0000330C, 0x05050505, 23, 16, "stitching_s_bit_depth", "Exposure bit for VS; valid range: [0..255]"},
+	{NULL, NULL,	0x0000330C, 0x05050505, 15,  8, "stitching_vs_bit_depth", "Exposure bit for S; valid range: [0..255]"},
+	{NULL, NULL,	0x0000330C, 0x05050505,  7,  0, "stitching_ls_bit_depth", "Exposure bit for L; valid range: [0..255]"},
+
+	{"ISP_STITCHING0_COLOR_WEIGHT", "Channel color weight for gray computation",
+			0x00003310, 0x001D464D, 23, 16, "stitching_color_weight_2", "B color weight for Y conversion. Valid range: [0..255]"},
+	{NULL, NULL,	0x00003310, 0x001D464D, 15,  8, "stitching_color_weight_1", "G color weight for Y conversion. Valid range: [0..255]"},
+	{NULL, NULL,	0x00003310, 0x001D464D,  7,  0, "stitching_color_weight_0", "R color weight for Y conversion.. Valid range: [0..255]"},
+
+	{"ISP_STITCHING0_BLS_EXP_0_A", "Black level for exposure 0 channel A",
+			0x00003314, 0x01000000, 31, 16, "stitching_digital_gain_exp_0_r", "Digital gain value for exposure 0 red pixel"},
+	{NULL, NULL,	0x00003314, 0x01000000, 11,  0, "stitching_bls_exp_0_a", "Black level value for exposure 0 channel A"},
+
+
+	{"ISP_STITCHING0_BLS_EXP_0_B", "Black level for exposure 0 channel B",
+			0x00003318, 0x01000000, 31, 16, "stitching_digital_gain_exp_0_g", "Digital gain value for exposure 0 blue pixel"},
+	{NULL, NULL,	0x00003318, 0x01000000, 11,  0, "stitching_bls_exp_0_b", "Black level value for exposure 0 channel B"},
+
+
+
+	{"ISP_STITCHING0_RATIO_LS", "Exposure ratio between Long and Short",
+			0x00003344, 0x00400400, 23, 12, "stitching_ratio_long_short_1", "Exposure merge ratio from S to L (greater than 1)"},
+	{NULL, NULL,	0x00003344, 0x00400400, 11,  0, "stitching_ratio_long_short_0", "Exposure merge ratio from S to L (less than 1)"},
+
+
+	{"ISP_STITCHING0_LONG_EXPOSURE", "Long exposure time",			0x00003360, 0x00000040, 11,  0, "stitching_long_exposure_time", "Exposure time for long exposure frame"},
+	{"ISP_STITCHING0_SHORT_EXPOSURE", "Short exposure time",		0x00003364, 0x00000008, 11,  0, "stitching_short_exposure_time", "Exposure time for short exposure frame"},
+	{"ISP_STITCHING0_VERY_SHORT_EXPOSURE", "Very short exposure time",	0x00003368, 0x00000008, 11,  0, "stitching_very_short_exposure_time", "Exposure time for very short exposure frame"},
+	{"ISP_STITCHING0_HDR_MODE", "HDR combination mode",			0x0000336C, 0x00000000,  3,  0, "stitching_hdr_input_format_type", "Input Sensor HDR mode:" LINE_PADDING_6TAB
+														"  0: dual DCG mode 3x12-bit (default)" LINE_PADDING_6TAB
+														"  1: DOL 3 Frame 3x12-bit" LINE_PADDING_6TAB
+														"  2: 3x12-bit line by line without waiting" LINE_PADDING_6TAB
+														"  3: 16-bit compressed data + 12-bit RAW" LINE_PADDING_6TAB
+														"  4: 2x12-bit dual DCG without waiting" LINE_PADDING_6TAB
+														"  5: DOL2 frame or 1 CG+VS sx12-bit RAW" LINE_PADDING_6TAB
+														"  6: L+S 2x12-bit RAW"},
+
+	{"ISP_STITCHING0_OUT_HBLANK", "HDR blanking in horizontal direction",
+			0x00003370, 0x00100080, 31, 16, "stitching_dummy_s_hblank", "Dummy line horizontal blank for short exposure"},
+	{NULL, NULL,	0x00003370, 0x00100080, 15,  0, "stitching_out_hblank", "Output data horizontal blank time"},
+
+
+	{"ISP_STITCHING0_OUT_VBLANK", "HDR blanking in vertical direction",
+			0x00003374, 0x00100020, 31, 16, "stitching_dummy_vs_hblank", "Dummy line horizontal blank for very short exposure"},
+	{NULL, NULL,	0x00003374, 0x00100020, 15,  0, "stitching_out_vblank", "Output data vertical blank time"},
+
+
+	{"ISP_STITCHING0_INTERRUPT_STATUS", "Stitching interrupt status",	0x00003378, 0x00000000, 2,  0, "stitching_interrupt_status", "  Unknown yet"},
+	{"ISP_STITCHING0_COMPRESS_X0", "Compression LUT x index",		0x0000337C, 0x00000000, 9,  0, "compress_lut_first_valid_x", "  Compression LUT first valid x index"},
+	{"ISP_STITCHING0_COMPRESS_X0_SHD", "Compression LUT x index shadow",	0x00003380, 0x00000000, 9,  0, "compress_lut_first_valid_shd_x", "  Compression LUT first valid x index shadow"},
+
+
+	{"ISP_STITCHING0_COMPRESS_LUT_0", "Compression LUT data 0",
+			0x000033A0, 0x00000000, 29, 20, "stitching_compress_lut_2", "VS compression LUT2"},
+	{NULL, NULL,	0x000033A0, 0x00000000, 19, 10, "stitching_compress_lut_1", "VS compression LUT1"},
+	{NULL, NULL,	0x000033A0, 0x00000000,  9,  0, "stitching_compress_lut_0", "VS compression LUT0"},
+
+	{"ISP_STITCHING0_COMPRESS_LUT_1", "Compression LUT data 1",
+			0x000033A4, 0x00000000, 29, 20, "stitching_compress_lut_5", "VS compression LUT5"},
+	{NULL, NULL,	0x000033A4, 0x00000000, 19, 10, "stitching_compress_lut_4", "VS compression LUT4"},
+	{NULL,  NULL,	0x000033A4, 0x00000000,  9,  0, "stitching_compress_lut_3", "VS compression LUT3"},
+
+	{"ISP_STITCHING0_COMPRESS_LUT_4", "Compression LUT data 4",
+			0x000033B0, 0x00000000, 29, 20, "stitching_compress_lut_14", "VS compression LUT14"},
+	{NULL, NULL,	0x000033B0, 0x00000000, 19, 10, "stitching_compress_lut_13", "VS compression LUT13"},
+	{NULL, NULL,	0x000033B0, 0x00000000,  9,  0, "stitching_compress_lut_12", "VS compression LUT12"},
+
+	{"ISP_STITCHING0_COMPRESS_LUT_SHD_0", "Compression LUT data 0 shadow",
+			0x000033B4, 0x00000000, 29, 20, "stitching_compress_lut_shd_2", "Shadow of VS compression LUT2"},
+	{NULL, NULL,	0x000033B4, 0x00000000, 19, 10, "stitching_compress_lut_shd_1", "Shadow of VS compression LUT1"},
+	{NULL, NULL,	0x000033B4, 0x00000000,  9,  0, "stitching_compress_lut_shd_0", "Shadow of VS compression LUT0"},
+
+	{"ISP_STITCHING0_EXP0_AWB_GAIN_G", "AWB gain for exposure 0 channel G",
+			0x000033C8, 0x01000100, 25, 16, "stitching_exp0_awb_gain_gr", "Stitching AWB GR gain for exposure 0"},
+	{NULL, NULL,	0x000033C8, 0x01000100,  9,  0, "stitching_exp0_awb_gain_gb", "Stitching AWB GB gain for exposure 0"},
+
+	{"ISP_STITCHING0_EXP0_AWB_GAIN_RB", "AWB gain for exposure 0 channel RB",
+			0x000033CC, 0x01000100, 25, 16, "stitching_exp0_awb_gain_r", "Stitching AWB R gain for exposure 0"},
+	{NULL, NULL,	0x000033CC, 0x01000100,  9,  0, "stitching_exp0_awb_gain_b", "Stitching AWB B gain for exposure 0"},
+
+
+	{"ISP_STITCHING0_EXP1_AWB_GAIN_G", "AWB gain for exposure 1 channel G",
+			0x000033D0, 0x01000100, 25, 16, "stitching_exp1_awb_gain_gr", "Stitching AWB GR gain for exposure 1"},
+	{NULL, NULL,	0x000033D0, 0x01000100,  9,  0, "stitching_exp1_awb_gain_gb", "Stitching AWB GB gain for exposure 1"},
+
+
+	{"ISP_STITCHING0_EXP1_AWB_GAIN_RB", "AWB gain for exposure 1 channel RB",
+			0x000033D4, 0x01000100, 25, 16, "stitching_exp1_awb_gain_r", "Stitching AWB R gain for exposure 1"},
+	{NULL, NULL,	0x000033D4, 0x01000100,  9,  0, "stitching_exp1_awb_gain_b", "Stitching AWB B gain for exposure 1"},
+
+
+	{"ISP_STITCHING0_LONG_SAT_PARAMS", "Stitching saturation params for long exposure",
+			0x000033E0, 0x007FF000, 23, 12, "stitching_long_sat_thresh", "Stitching long saturation threshold"},
+	{NULL, NULL,	0x000033E0, 0x007FF000,  8,  0, "stitching_long_sat_combine_weight", "Stitching long combine weight"},
+
+	{"ISP_STITCHING0_EXP2_AWB_GAIN_G", "AWB gain for exposure 2 channel G",
+			0x000033D8, 0x01000100, 25, 16, "stitching_exp2_awb_gain_gr", "Stitching AWB GR gain for exposure 2"},
+	{NULL, NULL,	0x000033D8, 0x01000100,  9,  0, "stitching_exp2_awb_gain_gb", "Stitching AWB GB gain for exposure 2"},
+
+	{"ISP_STITCHING0_EXP2_AWB_GAIN_RB", "AWB gain for exposure 2 channel RB",
+			0x000033DC, 0x01000100, 25, 16, "stitching_exp2_awb_gain_r", "Stitching AWB R gain for exposure 2"},
+	{NULL, NULL,	0x000033DC, 0x01000100,  9,  0, "stitching_exp2_awb_gain_b", "Stitching AWB B gain for exposure 2"},
+
+	{"ISP_STITCHING0_IMSC", "IMSC Interrupt Mask",
+			0x000033E4, 0x00000000,  8,  8, "stitching_imsc_hdr_hist_irq_vs", "Stitching HDR hist VS interrupt mask"},
+	{NULL, NULL,	0x000033E4, 0x00000000,  7,  7, "stitching_imsc_hdr_hist_irq_s", "Stitching HDR hist S interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  6,  6, "stitching_imsc_hdr_hist_irq_l", "Stitching HDR hist L interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  5,  5, "stitching_imsc_hdr_exp_complete_vs", "Stitching HDR exp statistic VS interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  4,  4, "stitching_imsc_hdr_exp_complete_s", "Stitching HDR exp statistic S interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  3,  3, "stitching_imsc_hdr_exp_complete_l", "Stitching HDR exp statistic L interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  2,  2, "stitching_imsc_fifo_empty", "Stitching HDR FIFO empty L interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  1,  1, "stitching_imsc_exp_err2", "Stitching HDR very short exp time error L interrupt mask"},
+	{NULL,	NULL,	0x000033E4, 0x00000000,  0,  0, "stitching_imsc_exp_err1", "Stitching HDR short exp time error L interrupt mask"},
+
+
+	{"ISP_STITCHING0_RIS", "RIS Raw Interrupt Status",
+			0x000033E8, 0x00000000,  8,  8, "stitching_ris_hdr_hist_irq_vs", "Stitching HDR hist VS interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  7,  7, "stitching_ris_hdr_hist_irq_s", "Stitching HDR hist S interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  6,  6, "stitching_ris_hdr_hist_irq_l", "Stitching HDR hist L interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  5,  5, "stitching_ris_hdr_exp_complete_vs", "Stitching HDR exp statistic VS interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  4,  4, "stitching_ris_hdr_exp_complete_s", "Stitching HDR exp statistic S interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  3,  3, "stitching_ris_hdr_exp_complete_l", "Stitching HDR exp statistic L interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  2,  2, "stitching_ris_fifo_empty", "Stitching HDR FIFO empty L interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  1,  1, "stitching_ris_exp_err2", "Stitching HDR very short exp time error L interrupt status"},
+	{NULL, NULL,	0x000033E8, 0x00000000,  0,  0, "stitching_ris_exp_err1", "Stitching HDR short exp time error L interrupt status"},
+
+
+	{"ISP_STITCHING0_MIS", "MIS Masked Interrupt Status",
+			0x000033EC, 0x00000000,  8,  8, "stitching_mis_hdr_hist_irq_vs", "Stitching HDR hist VS interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  7,  7, "stitching_mis_hdr_hist_irq_s", "Stitching HDR hist S interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  6,  6, "stitching_mis_hdr_hist_irq_l", "Stitching HDR hist L interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  5,  5, "stitching_mis_hdr_exp_complete_vs", "Stitching HDR exp statistic VS interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  4,  4, "stitching_mis_hdr_exp_complete_s", "Stitching HDR exp statistic S interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  3,  3, "stitching_mis_hdr_exp_complete_l", "Stitching HDR exp statistic L interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  2,  2, "stitching_mis_fifo_empty", "Stitching HDR FIFO empty L interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  1,  1, "stitching_mis_exp_err2", "Stitching HDR very short exp time error\n\t L interrupt masked status"},
+	{NULL, NULL,	0x000033EC, 0x00000000,  0,  0, "stitching_mis_exp_err1", "Stitching HDR short exp time error L interrupt \n\tMasked status"},
+
+
+	{"ISP_STITCHING0_ICR", "ICR Interrupt Clear Register",
+			0x000033F0, 0x00000000,  8,  8, "stitching_icr_hdr_hist_irq_vs", "Stitching HDR hist VS interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  7,  7, "stitching_icr_hdr_hist_irq_s", "Stitching HDR hist S interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  6,  6, "stitching_icr_hdr_hist_irq_l", "Stitching HDR hist L interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  5,  5, "stitching_icr_hdr_exp_complete_vs", "Stitching HDR exp statistic VS interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  4,  4, "stitching_icr_hdr_exp_complete_s", "Stitching HDR exp statistic S interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  3,  3, "stitching_icr_hdr_exp_complete_l", "Stitching HDR exp statistic L interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  2,  2, "stitching_icr_fifo_empty", "Stitching HDR FIFO empty L interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  1,  1, "stitching_icr_exp_err2", "Stitching HDR very short exp time error L interrupt clear"},
+	{NULL, NULL,	0x000033F0, 0x00000000,  0,  0, "stitching_icr_exp_err1", "Stitching HDR short exp time error L interrupt clear"},
+
+
+	{"ISP_STITCHING0_ISR", "ISR Interrupt Set Register",
+			0x000033F4, 0x00000000,  8,  8, "stitching_isr_hdr_hist_irq_vs", "Stitching HDR hist VS interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  7,  7, "stitching_isr_hdr_hist_irq_s", "Stitching HDR hist S interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  6,  6, "stitching_isr_hdr_hist_irq_l", "Stitching HDR hist L interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  5,  5, "stitching_isr_hdr_exp_complete_vs", "Stitching HDR exp statistic VS interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  4,  4, "stitching_isr_hdr_exp_complete_s", "Stitching HDR exp statistic S interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  3,  3, "stitching_isr_hdr_exp_complete_l", "Stitching HDR exp statistic L interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  2,  2, "stitching_isr_fifo_empty", "Stitching HDR FIFO empty L interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  1,  1, "stitching_isr_exp_err2", "Stitching HDR very short exp time error L interrupt set"},
+	{NULL, NULL,	0x000033F4, 0x00000000,  0,  0, "stitching_isr_exp_err1", "Stitching HDR short exp time error L interrupt set"},
+};
+
+
+int light_isp_sitching0_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_sitching0_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_sitching0_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 47 - 0
tools/reg_analyzer/vsi_isp8000/isp_vsm.c

@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00002f00
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_VSM_MODE", "Video Stable Measure Mode",
+			0x00002f00, 0x00000000,	1,  1, "vsm_meas_irq_enable",	"1: Enable VS measurement done IRQ"},
+	{NULL, NULL,	0x00002f00, 0x00000000,  0,  0, "vsm_meas_en",		"1: Enable measurement"},
+};
+
+
+int light_isp_vsm_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_vsm_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_vsm_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 58 - 0
tools/reg_analyzer/vsi_isp8000/m5_cproc.c

@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x800
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+	{"CPROC_CTRL", "Global control register",
+			0x00000800, 0x00000000,  3,  3, "cproc_c_out_range",	"Color processing chrominance pixel clipping range at output" LINE_PADDING_6TAB
+										"  0: CbCr_out clipping range [16..240] according to ITU-R BT.601 standard" LINE_PADDING_6TAB
+										"  1: Full UV_out clipping range [0..255]"},
+	{NULL, NULL,	0x00000800, 0x00000000,  2,  2, "cproc_y_in_range",	"Color processing luminance input range (offset processing)" LINE_PADDING_6TAB
+										"  0: Y_in range [64..940] according to ITU-R BT.601 standard;" LINE_PADDING_6TAB
+										"    offset of 64 will be subtracted from Y_in" LINE_PADDING_6TAB
+										"  1: Y_in full range [0..1023]; no offset will be subtracted from Y_in"},
+	{NULL, NULL,	0x00000800, 0x00000000,  1,  1, "cproc_y_out_range",	"Color processing luminance output clipping range" LINE_PADDING_6TAB
+										"  0: Y_out clipping range [16..235];" LINE_PADDING_6TAB
+										"    offset of 16 is added to Y_out according to ITU-R BT.601 standard" LINE_PADDING_6TAB
+										"  1: Y_out clipping range [0..255]; no offset is added to Y_out"},
+	{NULL, NULL,	0x00000800, 0x00000000,  0,  0, "cproc_enable",		"Color processing enable" LINE_PADDING_6TAB
+										"  0: Color processing is bypassed" LINE_PADDING_6TAB
+										"  1: Color processing is active" LINE_PADDING_6TAB
+										"  2 * 10 bit input data are truncated to 2 * 8 bit output data" LINE_PADDING_6TAB
+										"  output data are rounded to 2 * 8 bit and clipping is active"},
+};
+
+int light_isp_cproc_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_cproc_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_cproc_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 364 - 0
tools/reg_analyzer/vsi_isp8000/m5_isp.c

@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define MRV_ISP_BASE 0x0400
+#define REG_BASE MRV_ISP_BASE
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_CTRL", "ISP Global control register",
+			0x00000400, 0x80000000, 31, 31, "disable_isp_clk",	"1: disable ISP clock of SRAM."},
+	{NULL, NULL,	0x00000400, 0x80000000, 23, 23, "pp_write_sel",		"1: select yuv output 0: select raw output"},
+	{NULL, NULL,	0x00000400, 0x80000000, 22, 22, "ir_raw_out",		"0: disable; 1: IR data output from main path"},
+	{NULL, NULL,	0x00000400, 0x80000000, 20, 20, "regs_wdrth_data_mux",	""},
+	{NULL, NULL,	0x00000400, 0x80000000, 19, 19, "digi_gain_en",		"0:digital gain disable; 1:digital gain enable"},
+	{NULL, NULL,	0x00000400, 0x80000000, 18, 18, "dpf_raw_out",		"0: Disable; 1: Enable DPF raw output (from March 2018)"},
+	{NULL, NULL,	0x00000400, 0x80000000, 17, 17, "cnr_en",		"0: Disable; 1: CNR is enabled. (from March 2018)"},
+	{NULL, NULL,	0x00000400, 0x80000000, 16, 16, "enable_12bit_unpack",	"0:disable; 1: enable 12-bit unpack for DMA read"},
+	{NULL, NULL,	0x00000400, 0x80000000, 15, 15, "enable_12bit_packed",	"0:disable; 1: enable 12-bit pack"},
+	{NULL, NULL,	0x00000400, 0x80000000, 14, 14, "csm_c_range",		"Color Space Matrix chrominance clipping range for ISP output" LINE_PADDING_6TAB
+										"0: CbCr range 64..960 [16..240] according to ITU-R BT.601 standard" LINE_PADDING_6TAB
+										"1: full UV range 0..1023 [0..255]" LINE_PADDING_6TAB
+										"Numbers in brackets are for 8 bit resolution." LINE_PADDING_6TAB
+										"This bit also configures the YCbCr sequence align block accordingly."},
+	{NULL, NULL,	0x00000400, 0x80000000, 13, 13, "csm_y_range",		"Color Space Matrix luminance clipping range for ISP output" LINE_PADDING_6TAB
+										"0: Y range 64..940 [16..235] according to ITU-R BT.601 standard" LINE_PADDING_6TAB
+										"1: full Y range 0..1023 [0..255]" LINE_PADDING_6TAB
+										"Numbers in brackets are for 8 bit resolution." LINE_PADDING_6TAB
+										"This bit also configures the YCbCr sequence align block accordingly."},
+	{NULL, NULL,	0x00000400, 0x80000000, 12, 12, "flash_mode",		"0: sensor interface works independently from flash control unit" LINE_PADDING_6TAB
+										"1: one frame is captured when signaled by flash control unit"},
+	{NULL, NULL,	0x00000400, 0x80000000, 11, 11, "gamma_out_enable",	"Gamma ON/OFF"},
+	{NULL, NULL,	0x00000400, 0x80000000, 10, 10, "gen_cfg_upd",		"1: generate frame synchronous configuration signal at the output of ISP for" LINE_PADDING_6TAB
+										"   shadow registers of the following processing modules, write only"},
+	{NULL, NULL,	0x00000400, 0x80000000,  9,  9, "cfg_upd",		"1: immediately configure (update) shadow registers, write only"},
+	{NULL, NULL,	0x00000400, 0x80000000,  8,  8, "gen_cfg_upd_fix",	"1: make gen_cfg_upd a level signal, effect since then.; " LINE_PADDING_6TAB
+										"0: gen_cfg_upd is a pulse signal, only effect for current frame."},
+	{NULL, NULL,	0x00000400, 0x80000000,  7,  7, "awb_enable",		"Auto white balance ON/OFF"},
+	{NULL, NULL,	0x00000400, 0x80000000,  6,  6, "gamma_in_enable",	"Sensor De-gamma ON/OFF"},
+	{NULL, NULL,	0x00000400, 0x80000000,  4,  4, "inform_enable",	"input formatter. 0: disabled; 1: enabled" LINE_PADDING_6TAB
+										"The ISP input formatter is enabled or disabled by this bit immediately," LINE_PADDING_6TAB
+										"But always starts or stops acquisition frame synchronously."},
+	{NULL, NULL,	0x00000400, 0x80000000,  3,  1, "isp_mode",		"000 - RAW picture with BT.601 sync (ISP bypass)" LINE_PADDING_6TAB
+										"001 - ITU-R BT.656 (YUV with embedded sync)" LINE_PADDING_6TAB
+										"010 - ITU-R BT.601 (YUV input with H/Vsync signals)" LINE_PADDING_6TAB
+										"011 - Bayer RGB processing with H/Vsync signals" LINE_PADDING_6TAB
+										"100 - data mode (ISP bypass, sync signals interpreted as data enable)" LINE_PADDING_6TAB
+										"101 - Bayer RGB processing with BT.656 synchronization" LINE_PADDING_6TAB
+										"110 - RAW picture with ITU-R BT.656 synchronization (ISP bypass)" LINE_PADDING_6TAB
+										"111 - reserved" LINE_PADDING_6TAB
+										"Side effect: If RAW, ...[Refer to Doc]"},
+	{NULL, NULL,	0x00000400, 0x80000000,  0,  0, "isp_enable", 		"ISP data output. 0: disabled ; 1: enabled" LINE_PADDING_6TAB
+										"Controls output formatter frame synchronously, if isp_gen_cfg_upd is" LINE_PADDING_6TAB
+										"Used to activate this bit. For immediate update isp_cfg_upd must be used."},
+
+
+	{"ISP_ACQ_PROP", "ISP acquisition properties",
+			0x00000404, 0x00000000, 31, 31, "hdr_en",			"in HDR mode, ISP input data bit width is 20"},
+	{NULL, NULL,	0x00000404, 0x00000000, 29, 29, "sample_edge_1",		"Sample edge control for sensor 2. " LINE_PADDING_6TAB
+											"0: use input sclk; 1: add half cycle delay of sclk"},
+	{NULL, NULL,	0x00000404, 0x00000000, 28, 28, "sample_edge_0",		"Sample edge control for sensor 1." LINE_PADDING_6TAB
+											"0: use input sclk; 1: add half cycle delay of sclk"},
+	{NULL, NULL,	0x00000404, 0x00000000, 27, 26, "two_cycle_data_sel",		"two_cycle_data_sel[2:0]. " LINE_PADDING_6TAB
+											"0:select the same bits of data0 and data1;" LINE_PADDING_6TAB
+											"1: select all bits of data0 and data1 low bits"},
+	{NULL, NULL,	0x00000404, 0x00000000, 25, 25, "change_two_cycle_data_sequence", "0: data0 is high bits, data1 is low bits;" LINE_PADDING_6TAB
+											"1: data1 is high bits, data0 is low bits"},
+	{NULL, NULL,	0x00000404, 0x00000000, 24, 24, "two_cycle_merge_enable",	"0: not merge; 1: two sequence data merge to one pixel"},
+	{NULL, NULL,	0x00000404, 0x00000000, 23, 20, "input_bayer_format",		"0: no more than bit16; 1~5: reserved; 6: bit18; 7: bit20"},
+	{NULL, NULL,	0x00000404, 0x00000000, 19, 17, "pin_mapping",			"Bit mapping from LSB to MSB:" LINE_PADDING_6TAB
+											"000 - normal 12-bit external Interface" LINE_PADDING_6TAB
+											"001 - mapping Low 10 bit to High 10 bits, append 2 zeroes as LSBs" LINE_PADDING_6TAB
+											"010 - mapping Low 8 bit to High 8 bits, append 4 zeroes as LSBs" LINE_PADDING_6TAB
+											"011 - mapping Middle 8 bit to High 8 bits, append 4 zeroes as LSBs" LINE_PADDING_6TAB
+											"100...111 - Reserved (from March 2018)"},
+	{NULL, NULL,	0x00000404, 0x00000000, 16, 16, "yuv_dma_sel", 			"0: use align or conversion data for isp_is input. " LINE_PADDING_6TAB
+											"1: use DMA yuv read data for isp_is input. (from March 2018)"},
+	{NULL, NULL,	0x00000404, 0x00000000, 15, 15, "rgb_dma_sel",			"0: use input formatter data for latency fifo. "  LINE_PADDING_6TAB
+											"1: use DMA rgb read data for latency fifo.. (from March 2018)"},
+	{NULL, NULL,	0x00000404, 0x00000000, 14, 12, "input_selection",		"It not defined in reg.xml, but defines in code:" LINE_PADDING_6TAB
+											"000- 12Bit external Interface" LINE_PADDING_6TAB
+											"001- 10Bit Interface, append 2 zeroes as LSBs" LINE_PADDING_6TAB
+											"010- 10Bit Interface, append 2 MSBs as LSBs" LINE_PADDING_6TAB
+											"011- 8Bit Interface, append 4 zeroes as LSBs" LINE_PADDING_6TAB
+											"100- 8Bit Interface, append 4 MSBs as LSBs" LINE_PADDING_6TAB
+											"101...111 reserved"},
+	{NULL, NULL,	0x00000404, 0x00000000, 11, 11, "field_inv",			"0: do not swap odd and even fields; 1: swap odd and even fields"},
+	{NULL, NULL,	0x00000404, 0x00000000, 10,  9, "field_selection",		"00- sample all fields (don't care about fields); "  LINE_PADDING_6TAB
+											"01- sample only even fields; " LINE_PADDING_6TAB
+											"10- sample only odd fields;" LINE_PADDING_6TAB
+											"11- reserved"},
+	{NULL, NULL,	0x00000404, 0x00000000,  8,  7, "ccir_seq",			"00- YCbYCr; 01- YCrYCb; 10- CbYCrY; 11- CrYCbY"},
+	{NULL, NULL,	0x00000404, 0x00000000,  6,  5, "conv_422",			"00- cosited color subsampling Y0Cb0Cr0 – Y1" LINE_PADDING_6TAB
+											"01- interleaved color subsampling Y0Cb0 – Y1Cr1 (not recommended) " LINE_PADDING_6TAB
+											"10- non-cosited color subsampling Y0Cb(0+1)/2 – Y1Cr(0+1)/2 " LINE_PADDING_6TAB
+											"11- reserved"},
+	{NULL, NULL,	0x00000404, 0x00000000,  4,  3, "bayer_pat",			"Color components from sensor, starting with top left position" LINE_PADDING_6TAB
+											"in sampled frame (reprogram with ISP_ACQ_H_OFFS, ISP_ACQ_V_OFFS)" LINE_PADDING_6TAB
+											"00- first line: RGRG..., second line: GBGB..." LINE_PADDING_6TAB
+											"01- first line: GRGR..., second line: BGBG..." LINE_PADDING_6TAB
+											"10- first line: GBGB..., second line: RGRG..." LINE_PADDING_6TAB
+											"11- first line: BGBG..., second line: GRGR..." LINE_PADDING_6TAB
+											"This configuration applies for the black level " LINE_PADDING_6TAB
+											"area after cropping by the input formatter."},
+	{NULL, NULL,	0x00000404, 0x00000000,  2,  2, "vsync_pol",			"Vertical sync polarity. 0: high active; 1: low active"},
+	{NULL, NULL,	0x00000404, 0x00000000,  1,  1, "hsync_pol",			"Horizontal sync polarity. 0: high active; 1: low active"},
+	{NULL, NULL,	0x00000404, 0x00000000,  0,  0, "sample_edge",			"0- negative edge sampling; 1- positive edge sampling"},
+
+
+
+	{"ISP_ACQ_H_OFFS", "Horizontal input offset",	0x00000408, 0x00000000, 14,  0, "acq_h_offs", "Horizontal sample offset in 8-bit samples (YUV: 4 samples = 2 pixels)"},
+	{"ISP_ACQ_H_SIZE", "Horizontal input size",	0x00000410, 0x00001000, 14,  0, "acq_h_size",	"Horizontal sample size in 12-bit samples." LINE_PADDING_6TAB
+													" YUV input: 2 samples = 1 pixel, else 1 sample = 1 pixel;[Refer doc]"},
+	{"ISP_ACQ_V_OFFS", "Vertical input offset",	0x0000040c, 0x00000000, 13,  0, "acq_v_offs", "Vertical sample offset in lines"},
+	{"ISP_ACQ_V_SIZE", "Vertical input size",	0x00000414, 0x00000C00, 13,  0, "acq_v_size",	"Vertical sample size in lines"},
+
+	{"ISP_ACQ_NR_FRAMES", "Number of frames to be captured",
+							0x00000418, 0x00000000,  9,  0, "acq_nr_frames", "Number of input frames to be sampled (0 = continuous)"},
+
+
+	{"ISP_AWB_PROP", "Auto white balance properties",
+			0x00000510, 0x00000000, 31, 31, "awb_meas_mode","0: near white discrimination mode using YCbCr color space" LINE_PADDING_6TAB
+									"1: RGB based measurement mode"},
+	{NULL, NULL,	0x00000510, 0x00000000,  2,  2, "awb_max_en",	"0: disable; 1: enable. Not valid in RGB measurement mode."},
+	{NULL, NULL,	0x00000510, 0x00000000,  1,  0, "awb_mode",	"00: no measurement"  LINE_PADDING_6TAB
+									"01: reserved" LINE_PADDING_6TAB
+									"10: measurement of YCbCr means (AWB_MEAS_MODE = 0)" LINE_PADDING_6TAB
+									"    or RGB means (AWB_MEAS_MODE = 1)" LINE_PADDING_6TAB
+									"11: reserved"},
+
+	{"ISP_AWB_GAIN_G", "Auto white balance gain green",
+			0x00000538, 0x01000100, 25, 16, "awb_gain_gr",	"Gain value for green component in red line 100h = 1, " LINE_PADDING_6TAB
+									"  Unsigned integer value, range 0 to 4 with 8 bit fractional part"},
+	{NULL, NULL,	0x00000538, 0x01000100,  9,  0, "awb_gain_gb",	"Gain value for green component in blue line 100h = 1, "  LINE_PADDING_6TAB
+									"  Unsigned integer value, range 0 to 4 with 8 bit fractional part"},
+
+	{"ISP_AWB_GAIN_RB", "Auto white balance gain red and blue",
+			0x0000053c, 0x01000100, 25, 16, "awb_gain_r",	"Gain value for red component in red line 100h = 1, " LINE_PADDING_6TAB
+									"  Unsigned integer value, range 0 to 4 with 8 bit fractional part"},
+	{NULL, NULL,	0x0000053c, 0x01000100,  9,  0, "awb_gain_b",	"Gain value for blue component in blue line 100h = 1, " LINE_PADDING_6TAB
+									"  Unsigned integer value, range 0 to 4 with 8 bit fractional part"},
+
+	{"ISP_OUT_H_OFFS", "Horizontal offset of output window",	0x00000594, 0x00000000, 13,  0, "isp_out_h_offs",	"Horizontal pic offset in lines"},
+	{"ISP_OUT_V_OFFS", "Vertical offset of output window",		0x00000598, 0x00000000, 13,  0, "isp_out_v_offs",	"Vertical pic offset in lines"},
+	{"ISP_OUT_H_SIZE", "Output horizontal picture size",		0x0000059C, 0x00000000, 14,  0, "isp_out_h_size",	"Horizontal picture size in pixel if ISP_MODE is set to: ...[Refer doc]"},
+	{"ISP_OUT_V_SIZE", "Output vertical picture size",		0x000005A0, 0x00000000, 13,  0, "isp_out_v_size",	"Vertical picture size in lines"},
+
+
+	{"ISP_DEMOSAIC", "Demosaic parameters",
+			0x000005a4, 0x00000004, 10, 10, "demosaic_bypass",	"0: normal operation for RGB Bayer Pattern input" LINE_PADDING_6TAB
+										"1: demosaicing bypass for Black&White input data"},
+	{NULL, NULL,	0x000005a4, 0x00000004,  7,  0, "demosaic_th",		"Threshold for Bayer demosaicing texture detection." LINE_PADDING_6TAB
+										"  This value shifted left 4bit is compared with the" LINE_PADDING_6TAB
+										"  difference of the vertical and horizontal 12-Bit wide" LINE_PADDING_6TAB
+										"  texture indicators, to decide if the vertical or"LINE_PADDING_6TAB
+										"  horizontal texture flag must be set." LINE_PADDING_6TAB
+										"0x00: maximum edge sensitivity" LINE_PADDING_6TAB
+										"0xFF: no texture detection"},
+
+	{"ISP_FLAGS_SHD", "Flags (current status) of certain signals and Shadow regs for enable signals",
+			0x000005a8, 0x00000000, 31, 31, "s_hsync",		"State of ISP input port s_hsync, for test purposes"},
+	{NULL, NULL,	0x000005a8, 0x00000000, 30, 30, "s_vsync",		"State of ISP input port s_vsync, for test purposes"},
+	{NULL, NULL,	0x000005a8, 0x00000000, 27, 16, "s_data",		"State of ISP input port s_data, for test purposes"},
+	{NULL, NULL,	0x000005a8, 0x00000000,  2,  2, "inform_field",		"Current field information (0=odd, 1=even)"},
+	{NULL, NULL,	0x000005a8, 0x00000000,  1,  1, "inform_en_shd",	"Input formatter enable shadow register"},
+	{NULL, NULL,	0x000005a8, 0x00000000,  0,  0, "isp_on_shd",		"ISP enable shadow register" LINE_PADDING_6TAB
+										"  Shows if ISP currently outputs data (1) or not (0)"},
+
+	{"ISP_IMSC", "Interrupt mask",
+			0x000005bc, 0x00000000, 26, 26, "imsc_sensor0_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 25, 25, "imsc_sensor1_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 24, 24, "imsc_sensor2_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 23, 23, "imsc_sensor3_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 22, 22, "imsc_ae2_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 21, 21, "imsc_awb2_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 20, 20, "imsc_tdnr", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 19, 19, "imsc_vsm_done", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 18, 18, "imsc_exp_end", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 17, 17, "imsc_fl_cap", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 16, 16, "imsc_tdnr1", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 15, 15, "imsc_hist_end", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 14, 14, "imsc_afm_fin", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 13, 13, "imsc_afm_lum_of", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 12, 12, "imsc_afm_sum_of", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 11, 11, "imsc_sh_off", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000, 10, 10, "imsc_sh_on", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  9,  9, "imsc_fl_off", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  8,  8, "imsc_fl_on", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  7,  7, "imsc_h_start", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  6,  6, "imsc_v_start", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  5,  5, "imsc_frame_in", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  4,  4, "imsc_awb_done", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  3,  3, "imsc_size_err", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  2,  2, "imsc_dataloss", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  1,  1, "imsc_frame", "0: mask out; 1: enable interrupt"},
+	{NULL, NULL,	0x000005bc, 0x00000000,  0,  0, "imsc_isp_off", "0: mask out; 1: enable interrupt"},
+
+
+	{"ISP_RIS", "Raw interrupt status",
+			0x000005c0, 0x00000000, 26, 26, "ris_sensor0_dataloss", "sensor0 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 25, 25, "ris_sensor1_dataloss", "sensor1 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 24, 24, "ris_sensor2_dataloss", "sensor2 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 23, 23, "ris_sensor3_dataloss", "sensor3 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 22, 22, "ris_ae2_dataloss", "aev2 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 21, 21, "ris_awb2_dataloss", "awb2 data loss"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 20, 20, "ris_tdnr", "TDNR reference frame FIFO empty"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 19, 19, "ris_vsm_done", "VSM module complete"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 18, 18, "ris_exp_end", "Exposure measurement complete"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 17, 17, "ris_fl_cap", "Signaling captured frame"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 16, 16, "ris_tdnr1", "write cover read"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 15, 15, "ris_hist_end", "Histogram measurement ready." LINE_PADDING_6TAB
+									"(Old or new histogram measurement)"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 14, 14, "ris_afm_fin", "AF measurement finished: this interrupt is setwhen the first" LINE_PADDING_6TAB
+									"complete frame is calculated after enabling the AF measurement"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 13, 13, "ris_afm_lum_of", "Auto focus luminance overflow"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 12, 12, "ris_afm_sum_of", "Auto focus sum overflow"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 11, 11, "ris_sh_off", "Mechanical shutter is switched off"},
+	{NULL, NULL,	0x000005c0, 0x00000000, 10, 10, "ris_sh_on", "Mechanical shutter is switched on"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  9,  9, "ris_fl_off", "Flash light is switched off"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  8,  8, "ris_fl_on", "Flash light is switched on"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  7,  7, "ris_h_start", "Start edge of h_sync"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  6,  6, "ris_v_start", "Start edge of v_sync"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  5,  5, "ris_frame_in", "Sampled input frame is complete"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  4,  4, "ris_awb_done", "White balancing measurement cycle is complete; results can be read out"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  3,  3, "ris_size_err", "Picture size violation occurred; incorrect programming"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  2,  2, "ris_dataloss", "Loss of data occurred within a line, processing failure"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  1,  1, "ris_frame", "Frame was completely put out"},
+	{NULL, NULL,	0x000005c0, 0x00000000,  0,  0, "ris_isp_off", "ISP output was disabled (vsynced) due to f_cnt reached or manual"},
+
+	{"ISP_MIS", "Masked interrupt status",	  0x000005c4, 0x00000000, 26, 26, "mis_sensor0_dataloss", "sensor0 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 25, 25, "mis_sensor1_dataloss", "sensor1 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 24, 24, "mis_sensor2_dataloss", "sensor2 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 23, 23, "mis_sensor3_dataloss", "sensor3 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 22, 22, "mis_ae2_dataloss", "aev2 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 21, 21, "mis_awb2_dataloss", "awb2 data loss"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 20, 20, "mis_tdnr", "TDNR reference frame FIFO empty"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 19, 19, "mis_vsm_done", "VSM module complete"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 18, 18, "mis_exp_end", "Exposure measurement complete"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 17, 17, "mis_fl_cap", "Signaling captured frame"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 16, 16, "mis_tdnr1", "write cover read"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 15, 15, "mis_hist_end", "Histogram measurement ready." LINE_PADDING_6TAB
+									"(Old or new histogram measurement)"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 14, 14, "mis_afm_fin", "AF measurement finished: this interrupt is set when the first" LINE_PADDING_6TAB
+									"complete frame is calculated after enabling the AF measurement"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 13, 13, "mis_afm_lum_of", "Auto focus luminance overflow"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 12, 12, "mis_afm_sum_of", "Auto focus sum overflow"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 11, 11, "mis_sh_off", "Mechanical shutter is switched off"},
+	{NULL, NULL,	0x000005c4, 0x00000000, 10, 10, "mis_sh_on", "Mechanical shutter is switched on"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  9,  9, "mis_fl_off", "Flash light is switched off"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  8,  8, "mis_fl_on", "Flash light is switched on"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  7,  7, "mis_h_start", "Start edge of h_sync"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  6,  6, "mis_v_start", "Start edge of v_sync"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  5,  5, "mis_frame_in", "Sampled input frame is complete"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  4,  4, "mis_awb_done", "White balancing measurement cycle is complete; results can be read out"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  3,  3, "mis_size_err", "Picture size violation occurred; incorrect programming"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  2,  2, "mis_dataloss", "Loss of data occurred within a line, processing failure"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  1,  1, "mis_frame", "Frame was completely put out"},
+	{NULL, NULL,	0x000005c4, 0x00000000,  0,  0, "mis_isp_off", "ISP output was disabled (vsynced) due to f_cnt reached or manual"},
+
+	{"ISP_ICR", "Interrupt clear register",
+			0x000005c8, 0x00000000, 26, 26, "icr_sensor0_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 25, 25, "icr_sensor1_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 24, 24, "icr_sensor2_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 23, 23, "icr_sensor3_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 22, 22, "icr_ae2_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 21, 21, "icr_awb2_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 20, 20, "icr_tdnr", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 19, 19, "icr_vsm_done", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 18, 18, "icr_exp_end", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 17, 17, "icr_fl_cap", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 16, 16, "icr_tdnr1", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 15, 15, "icr_hist_end", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 14, 14, "icr_afm_fin", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 13, 13, "icr_afm_lum_of", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 12, 12, "icr_afm_sum_of", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 11, 11, "icr_sh_off", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000, 10, 10, "icr_sh_on", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  9,  9, "icr_fl_off", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  8,  8, "icr_fl_on", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  7,  7, "icr_h_start", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  6,  6, "icr_v_start", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  5,  5, "icr_frame_in", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  4,  4, "icr_awb_done", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  3,  3, "icr_size_err", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  2,  2, "icr_dataloss", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  1,  1, "icr_frame", "Clear interrupt"},
+	{NULL, NULL,	0x000005c8, 0x00000000,  0,  0, "icr_isp_off", "Clear interrupt"},
+
+	{"ISP_ISR", "Interrupt set register",
+			0x000005cc, 0x00000000, 26, 26, "isr_sensor0_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 25, 25, "isr_sensor1_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 24, 24, "isr_sensor2_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 23, 23, "isr_sensor3_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 22, 22, "isr_ae2_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 21, 21, "isr_awb2_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 20, 20, "isr_tdnr", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 19, 19, "isr_vsm_done", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 18, 18, "isr_exp_end", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 17, 17, "isr_fl_cap", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 16, 16, "isr_tdnr1", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 15, 15, "isr_hist_end", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 14, 14, "isr_afm_fin", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 13, 13, "isr_afm_lum_of", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 12, 12, "isr_afm_sum_of", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 11, 11, "isr_sh_off", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000, 10, 10, "isr_sh_on", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  9,  9, "isr_fl_off", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  8,  8, "isr_fl_on", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  7,  7, "isr_h_start", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  6,  6, "isr_v_start", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  5,  5, "isr_frame_in", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  4,  4, "isr_awb_done", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  3,  3, "isr_size_err", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  2,  2, "isr_dataloss", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  1,  1, "isr_frame", "Set interrupt"},
+	{NULL, NULL,	0x000005cc, 0x00000000,  0,  0, "isr_isp_off", "Set interrupt"},
+
+	{"ISP_ERR", "ISP error register",
+			0x0000063c, 0x00000000,  2,  2, "outform_size_err",	"Size error is generated in outmux submodule"},
+	{NULL, NULL,	0x0000063c, 0x00000000,  1,  1, "is_size_err",		"Size error is generated in image stabilization submodule"},
+	{NULL, NULL,	0x0000063c, 0x00000000,  0,  0, "inform_size_err",	"Size error is generated in inform submodule"},
+
+	{"ISP_ERR_CLR", "ISP error clear register",
+			0x00000640, 0x00000000,  2,  2, "outform_size_err_clr",	"Size error is cleared"},
+	{NULL, NULL,	0x00000640, 0x00000000,  1,  1, "is_size_err_clr",	"Size error is cleared"},
+	{NULL, NULL,	0x00000640, 0x00000000,  0,  0, "inform_size_err_clr",	"Size error is cleared"},
+
+};
+
+
+
+int light_isp_isp_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_isp_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_isp_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 63 - 0
tools/reg_analyzer/vsi_isp8000/m5_isp_dpf.c

@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+#define REG_BASE 0x2800
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_DPF_MODE", "Mode Control for De-noising Pre-Filter Block",
+			0x00002800, 0x00000000,  9,  9, "use_nf_gain",		"0: DPF_NF_GAINs will not be used. (Default)" LINE_PADDING_6TAB
+										"1: DPF_NF_GAINs will be used."},
+	{NULL, NULL,	0x00002800, 0x00000000,  8,  8, "lsc_gain_en",		"0: LSC gain will not be processed. Use LSC gain factor of 1. (Default)" LINE_PADDING_6TAB
+										"1: LSC gain will be processed"},
+	{NULL, NULL,	0x00002800, 0x00000000,  7,  7, "awb_gain_en",		"Only relevant when use_nf_gain==0 and ISP_CTRL::ISP_AWB_ENABLE==1" LINE_PADDING_6TAB
+										"0: ISP_AWB gains will not be processed. Use AWB gain factor of 1. (Default)" LINE_PADDING_6TAB
+										"1: ISP_AWB gains will be processed"},
+	{NULL, NULL,	0x00002800, 0x00000000,  6,  6, "nll_equ_segm",		"0: equidistant segmentation for NLL (Default)" LINE_PADDING_6TAB
+										"1: optimized logarithmic like segmentation for Noise Level Lookup (NLL)"},
+	{NULL, NULL,	0x00002800, 0x00000000,  5,  5, "rb_filter_size9x9",	"0: Wide Red and Blue filter kernel size of 13x9 (7x5 active) pixels (Default)" LINE_PADDING_6TAB
+										"1: Red and Blue filter kernel size of 9x9 (5x5 active) pixels"},
+	{NULL, NULL,	0x00002800, 0x00000000,  4,  4, "r_filter_off",		"0: filter R pixels (Default)" LINE_PADDING_6TAB
+										"1: disable filter processing for red pixels (R)"},
+	{NULL, NULL,	0x00002800, 0x00000000,  3,  3, "gr_filter_off",	"0: filter GB pixels (Default)" LINE_PADDING_6TAB
+										"1: disable filter processing for green pixels in green/blue lines (GB)"},
+	{NULL, NULL,	0x00002800, 0x00000000,  2,  2, "gb_filter_off",	"0: filter GB pixels (Default)" LINE_PADDING_6TAB
+										"1: disable filter processing for green pixels in green/blue lines (GB)"},
+	{NULL, NULL,	0x00002800, 0x00000000,  1,  1, "b_filter_off",		"0: filter B pixels (Default); 1: disable filter processing for blue pixels (B)"},
+	{NULL, NULL,	0x00002800, 0x00000000,  0,  0, "cfg_dpf_enable",	"De-noising pre-filter; 0: Bypass DPF (Default); 1: Enable DPF"},
+};
+
+
+int light_isp_dpf_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_dpf_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_dpf_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 62 - 0
tools/reg_analyzer/vsi_isp8000/m5_isp_is.c

@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define MRV_IS_BASE 0x2300
+#define REG_BASE MRV_IS_BASE
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_IS_CTRL",	"Image Stabilization Control Register",
+		0x00002300, 0x00000000,  0,  0, "is_en",	"Image stabilization state. 0: off ; 1: on"},
+
+	{"ISP_IS_RECENTER", "Image Stabilization Re-center Register",
+		0x00002304, 0x00000000,  0,  0, "is_recenter",	"0: re-center feature switched off; 1..7: re-centering by (cur_h/v_offs-H/V_OFFS)/2^RECENTER"},
+
+	{"ISP_IS_H_OFFS", "Horizontal Offset of Output Window",
+		0x00002308, 0x00000000, 13,  0, "is_h_offs",	"Horizontal picture offset in pixels"},
+
+	{"ISP_IS_V_OFFS", "Vertical Offset of Output Window",
+		0x0000230C, 0x00000000, 13,  0, "is_v_offs",	"Vertical picture offset in lines"},
+
+	{"ISP_IS_H_SIZE", "Horizontal Output Picture Size",
+		0x00002310, 0x00001000, 13,  0, "is_h_size",	"Horizontal picture size in pixels if ISP_MODE is set to: ..."},
+
+	{"ISP_IS_V_SIZE", "Vertical Output Picture Size",
+		0x00002314, 0x00001000, 13,  0, "is_v_size",	"Vertical picture size in lines"},
+};
+
+
+int light_isp_is_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_is_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_is_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 57 - 0
tools/reg_analyzer/vsi_isp8000/m5_isp_shutter.c

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x00000680
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"ISP_SH_CTRL", "Mechanical shutter control",
+			0x00000680, 0x00000000,  4,  4, "sh_open_pol",	"Shutter_open polarity. 0: high active; 1: low active"},
+	{NULL, NULL,	0x00000680, 0x00000000,  3,  3, "sh_trig_pol",	"Mechanical shutter trigger edge." LINE_PADDING_6TAB
+									"0: use negative edge of trigger signal" LINE_PADDING_6TAB
+									"1: use positive edge of trigger signal"},
+	{NULL, NULL,	0x00000680, 0x00000000,  2,  2, "sh_trig_src",	"Mechanical shutter trigger source." LINE_PADDING_6TAB
+									"0: use “vds_vsync” for trigger event" LINE_PADDING_6TAB
+									"1: use “shutter_trig” for trigger event"},
+	{NULL, NULL,	0x00000680, 0x00000000,  1,  1, "sh_rep_en",	"Mechanical shutter repetition enable." LINE_PADDING_6TAB
+									"0: shutter is opened only once" LINE_PADDING_6TAB
+									"1: shutter is opened with the repetition rate of the trigger signal"},
+	{NULL, NULL,	0x00000680, 0x00000000,  0,  0, "sh_en",	"Mechanical shutter. 0: disable; 1: enable"},
+
+};
+
+
+int light_isp_shutter_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_shutter_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_shutter_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 126 - 0
tools/reg_analyzer/vsi_isp8000/m5_main_control.c

@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+#define REG_BASE 0x0000
+
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+
+	{"VI_CCL", "Clock Control Register",
+			0x00000000, 0x00000000,  2,  2, "vi_ccl_dis",		"Clock Control Logic disable." LINE_PADDING_6TAB
+										"  0: processing/cfg-clocks for all sub modules enabled" LINE_PADDING_6TAB
+										"  1: processing/cfg-clocks for all sub modules disabled " LINE_PADDING_6TAB
+										"     without access to ID and VI_CCL register"},
+	{NULL, NULL,	0x00000000, 0x00000000,  1,  1, "vi_ccl_dis_status",	"Status of vi_ccl[2] bit (copy of vi_ccl[2])"},
+
+	{"VI_ICCL",  "Internal Clock Control Register",
+			0x00000010, 0x000FFF7B, 19, 19, "stitch_3_clk_en", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 18, 18, "stitch_2_clk_en", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 17, 17, "reserved0", "reserved0"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 16, 16, "mcm_rd_clk_en", "MCM read clock enable; 0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 15, 15, "mcm_wr_clk_en", "0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 14, 14, "stitch_1_clk_en", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 13, 13, "stitch_0_clk_en", "stitch0 clock enable; 0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 12, 12, "vi_mipi2_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 11, 11, "vi_mipi_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B, 10, 10, "vi_smia_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  9,  9, "vi_simp_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  8,  8, "vi_ie_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  6,  6, "vi_mi_clk_enable", "Memory interface clock enable; 0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  5,  5, "vi_jpeg_clk_enable", "unused"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  4,  4, "vi_srsz_clk_enable", "Self-picture resize clock enable; 0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  3,  3, "vi_mrsz_clk_enable", "Main resize clock enable; 0: power safe; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  1,  1, "vi_cp_clk_enable", "CPROC processing clock enable; 0: power safe ; 1: processing mode"},
+	{NULL, NULL,	0x00000010, 0x000FFF7B,  0,  0, "vi_isp_clk_enable", "ISP processing clock enable; 0: power safe ; 1: processing mode"},
+
+	{"VI_IRCL",  "Internal Reset Control Register",
+			0x00000014, 0x00000000, 20, 20, "soft_rst_mi_wrapper", "mi wrapper software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000, 19, 19, "soft_rst_stitch_3", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000, 18, 18, "soft_rst_stitch_2", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000, 17, 17, "soft_rst_fe", "0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000, 16, 16, "soft_rst_mcm_rd", "0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000, 15, 15, "soft_rst_mcm_wr", "MCM write software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000, 14, 14, "soft_rst_stitch_1", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000, 13, 13, "soft_rst_stitch_0", "stitch0 software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000, 12, 12, "vi_mipi2_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000, 11, 11, "vi_mipi_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000, 10, 10, "vi_smia_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000,  9,  9, "vi_simp_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000,  8,  8, "vi_ie_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000,  7,  7, "vi_marvin_rst", "Hardware reset of entire image signal processor; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  6,  6, "vi_mi_soft_rst", "Memory interface software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  5,  5, "vi_jpeg_soft_rst", "unused"},
+	{NULL, NULL,	0x00000014, 0x00000000,  4,  4, "vi_srsz_soft_rst", "Self-picture resize software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  3,  3, "vi_mrsz_soft_rst", "Main-picture resize software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  2,  2, "vi_ycs_soft_rst", "Y/C splitter software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  1,  1, "vi_cp_soft_rst", "Color processing software reset; 0: Processing mode; 1: reset state"},
+	{NULL, NULL,	0x00000014, 0x00000000,  0,  0, "vi_isp_soft_rst", "ISP software reset; 0: Processing mode; 1: reset state"},
+
+	{"VI_DPCL", "Data Path Control Register",
+			0x00000018, 0x00000000, 27, 26, "if_select3",		"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000, 25, 24, "if_select2",		"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000, 23, 22, "next_sensor_id",	"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000, 21, 20, "sensor_id",		"Present frame id"},
+	{NULL, NULL,	0x00000018, 0x00000000, 19, 19, "reserved2",		"reserved2"},
+	{NULL, NULL,	0x00000018, 0x00000000, 18, 18, "strm_mux",		"1:raw out 0:yuv out"},
+	{NULL, NULL,	0x00000018, 0x00000000, 17, 16, "if_select1",		"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000, 15, 15, "reserved1",		"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000, 14, 12, "vi_chan_mode",		"Enable Main Path, Self Path 1, Self Path 2." LINE_PADDING_6TAB
+										"Note: More than one bit may be set to enable more than one path." LINE_PADDING_6TAB
+										"Bit 12: Enable Main Path; Bit 13: Enable Self Path 1; Bit 14: Enable Self Path 2"},
+	{NULL, NULL,	0x00000018, 0x00000000, 11, 11, "vi_dma_spmux",		"xml doc unused, but in code:" LINE_PADDING_6TAB
+										"0: data from camera interface to self resize" LINE_PADDING_6TAB
+										"1: data from DMA read port to self resize"},
+	{NULL, NULL,	0x00000018, 0x00000000, 10, 10, "vi_dma_iemux",		"xml doc unused, but in code:" LINE_PADDING_6TAB
+										"0: data from camera interface to image effects" LINE_PADDING_6TAB
+										"1: data from DMA read port to image effects"},
+	{NULL, NULL,	0x00000018, 0x00000000,  9,  8, "if_select0",		"Input interface for sensor0" LINE_PADDING_6TAB
+										"0: parallel interface; 1: SMIA-interface (Reserved); 2: Unused; 3: HDR Stitch output"},
+	{NULL, NULL,	0x00000018, 0x00000000,  6,  4, "vi_dma_switch",	"xml doc unused, but in code:" LINE_PADDING_6TAB
+										"0: path to SPMUX" LINE_PADDING_6TAB
+										"1: path to Superimpose" LINE_PADDING_6TAB
+										"2: path to Image Effects" LINE_PADDING_6TAB
+										"3: path to JPEG" LINE_PADDING_6TAB
+										"4: path to ISP"},
+	{NULL, NULL,	0x00000018, 0x00000000,  3,  2, "reserved0",		"unused"},
+	{NULL, NULL,	0x00000018, 0x00000000,  1,  0, "vi_mp_mux",		"xml doc unused, but in code:" LINE_PADDING_6TAB
+										"00: reserved (future: data from DMA read port to JPEG encoder)" LINE_PADDING_6TAB
+										"01: data from main resize to MI, uncompressed" LINE_PADDING_6TAB
+										"    (now also used for RAW data bypass)" LINE_PADDING_6TAB
+										"10: data from main resize to JPEG encoder"},
+};
+
+
+int light_isp_main_control_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_main_control_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_main_control_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 107 - 0
tools/reg_analyzer/vsi_isp8000/m5_main_resize.c

@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x800
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"MRSZ_CTRL", "Global control register",
+			0x00000c00, 0x00000000, 10, 10, "auto_upd", "0: no update; 1: update shadow registers at frame end"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  9,  9, "cfg_upd", "Write 0: nothing happens; Write 1: update shadow registers; Read: Always 0"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  8,  8, "crop_enable", "0: Bypass crop ; 1: Enable picture crop"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  7,  7, "scale_vc_up", "0: Vertical chrominance downscaling selected ; 1: Vertical chrominance upscaling selected"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  6,  6, "scale_vy_up", "0: Vertical luminance downscaling selected ; 1: Vertical luminance upscaling selected"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  5,  5, "scale_hc_up", "0: Horizontal chrominance downscaling selected ; 1: Horizontal chrominance upscaling selected"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  4,  4, "scale_hy_up", "0: Horizontal luminance downscaling selected ; 1: Horizontal luminance upscaling selected"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  3,  3, "scale_vc_enable", "Vertical chrominance scaling unit; 0: Bypass; 1: enable"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  2,  2, "scale_vy_enable", "Vertical luminance scaling unit; 0: Bypass; 1: enable"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  1,  1, "scale_hc_enable", "Horizontal chrominance scaling unit; 0: Bypass; 1: enable"},
+	{NULL, NULL,	0x00000c00, 0x00000000,  0,  0, "scale_hy_enable", "Horizontal luminance scaling unit ; 0: Bypass; 1: enable"},
+
+
+	{"MRSZ_SCALE_HY", "Horizontal luminance scale factor register",
+			0x00000c04, 0x00000000, 15,	0, "scale_hy",	"This register is set to the horizontal luminance downscale factor" LINE_PADDING_6TAB
+									"or to the reciprocal of the horizontal luminance upscale factor."},
+
+	{"MRSZ_SCALE_HCB", "Horizontal Cb scale factor register",
+			0x00000c08, 0x00000000, 15,  0, "scale_hcb",	"This register is set to the horizontal Cb downscale factor " LINE_PADDING_6TAB
+									"or to the reciprocal of the horizontal Cb upscale factor."},
+
+	{"MRSZ_SCALE_HCR", "Horizontal Cr scale factor register",
+			0x00000c0c, 0x00000000, 15,  0, "scale_hcr",	"This register is set to the horizontal Cr downscale factor " LINE_PADDING_6TAB
+									"or to the reciprocal of the horizontal Cr upscale factor."},
+
+	{"MRSZ_SCALE_VY", "Vertical luminance scale factor register",
+			0x00000c10, 0x00000000, 15,  0, "scale_vy",	"This register is set to the vertical luminance downscale factor " LINE_PADDING_6TAB
+									"or to the reciprocal of the vertical luminance upscale factor."},
+
+	{"MRSZ_SCALE_VC", "Vertical chrominance scale factor register",
+			0x00000c14, 0x00000000, 15,  0, "scale_vc",	"This register is set to the vertical chrominance downscale factor" LINE_PADDING_6TAB
+									"or to the reciprocal of the vertical chrominance upscale factor."},
+
+	{"MRSZ_FORMAT_CONV_CTRL", "Format conversion control",
+			0x00000c6c, 0x00000000, 10, 10, "rsz_pack_format",	"0: YUV422/YUV420 planar; 1: YUV422/YUV420 semi_planar"},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  9,  9, "expand_8to10_method",	"0: add two MSBs in two LSBs; 1: add zeros in two LSBs"},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  8,  8, "expand_8to10_enable",	"0: disable 10 bit (add two zeros in two LSBs); 1: enable 10 bit"},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  7,  7, "cfg_422nocosited",	"0: YCbCr422 data are co-sited (Y0 Cb0 and Cr0 are sampled at the same position)" LINE_PADDING_6TAB
+										"1: YCbCr422 data are non_co-sited (Cb and Cr samples are centered between Y samples)" LINE_PADDING_6TAB
+										"   so modified interpolation is activated" LINE_PADDING_6TAB
+										"Note: the programmed value becomes effective immediately after this register is set." LINE_PADDING_6TAB
+										"Therefore, only write to this register if no picture data is sent to the Self Path."},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  6,  6, "cfg_cbcr_full",	"0: CbCr has a compressed range of [16..240]" LINE_PADDING_6TAB
+										"1: CbCr has full range [0..255]" LINE_PADDING_6TAB
+										"Note: the programmed value becomes effective immediately after this register is set. " LINE_PADDING_6TAB
+										"Therefore, only write to this register if no picture data is sent to the Self Path."},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  5,  5, "cfg_y_full",		"0: Y has a compressed range of [16..235]" LINE_PADDING_6TAB
+										"1: Y has full range [0..255]" LINE_PADDING_6TAB
+										"Note: the programmed value becomes effective immediately after this register is set." LINE_PADDING_6TAB
+										"Therefore, only write to this register if no picture data is sent to the Self Path."},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  4,  2, "rsz_output_format",	"Main Resize output format"LINE_PADDING_6TAB
+										"000: YCbCr 4:0:0" LINE_PADDING_6TAB
+										"001: YCbCr 4:2:0" LINE_PADDING_6TAB
+										"010: YCbCr 4:2:2" LINE_PADDING_6TAB
+										"011: YCbCr 4:4:4" LINE_PADDING_6TAB
+										"100: RGB565" LINE_PADDING_6TAB
+										"101: RGB666" LINE_PADDING_6TAB
+										"110: RGB888" LINE_PADDING_6TAB
+										"Reserved"},
+	{NULL, NULL,	0x00000c6c, 0x00000000,  1,  0, "rsz_input_format",	"Main resize input format" LINE_PADDING_6TAB
+										"00: YCbCr 4:0:0" LINE_PADDING_6TAB
+										"01: YCbCr 4:2:0" LINE_PADDING_6TAB
+										"10: YCbCr 4:2:2" LINE_PADDING_6TAB
+										"11: YCbCr 4:4:4"},
+};
+
+int light_isp_main_resize_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_main_resize_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_main_resize_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

+ 571 - 0
tools/reg_analyzer/vsi_isp8000/m5_mi.c

@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ra_common.h"
+
+#define REG_BASE 0x1300
+static const reg_field_s reg_desc[] = {
+	/* structure field order
+	reg_name,                 offset,reset_value,msb,lsb, field_name,              field_desc */
+
+	{"MI_CTRL", "Global control register",
+			0x00001300, 0x00000000, 24, 24, "sp2_raw2_continuous",		"Enables continuous mode. If set to 1, the same frame is read back over and over."},
+	{NULL, NULL,	0x00001300, 0x00000000, 23, 23, "sp2_raw2_start", 		"Enables DMA access."},
+	{NULL, NULL,	0x00001300, 0x00000000, 22, 22, "pp_dma_continuous", 		"Enables continuous mode. If set to 1, the same frame is read back over and over."},
+	{NULL, NULL,	0x00001300, 0x00000000, 21, 21, "pp_dma_start",			"Enables DMA access."},
+	{NULL, NULL,	0x00001300, 0x00000000, 20, 20, "sp2_raw2_write_path_enable",	"Enables sp2_raw2_write path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 19, 19, "pp_write_path_enable", 	"Enables pp write path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 18, 18, "mcm_g2_raw1_path_enable", 	"Enables mcm_g2_raw1 path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 17, 17, "mcm_g2_raw0_path_enable", 	"Enables mcm_g2_raw0 path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 16, 16, "mcm_raw_rdma_start_con",	"Enables continuous mode. If set to 1, ... [Refer to Doc]."},
+	{NULL, NULL,	0x00001300, 0x00000000, 15, 15, "mcm_raw_rdma_start", 		"Enables DMA access."},
+	{NULL, NULL,	0x00001300, 0x00000000, 14, 14, "mcm_raw_rdma_path_enable",	"Enables mcm_raw_rdma path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 13, 13, "sp2_raw_rdma_start_con",	"Enables continuous mode. If set to 1, the same frame is read back over and over.."},
+	{NULL, NULL,	0x00001300, 0x00000000, 12, 12, "sp2_raw_rdma_start",		"Enables DMA access."},
+	{NULL, NULL,	0x00001300, 0x00000000, 11, 11, "sp2_raw_rdma_path_enable",	"Enables sp2_raw_rdma path."},
+	{NULL, NULL,	0x00001300, 0x00000000, 10, 10, "sp2_ycbcr_rdma_start_con",	"Enables continuous mode. If set to 1, the same frame is read back over and over.."},
+	{NULL, NULL,	0x00001300, 0x00000000,  9,  9, "sp2_ycbcr_rdma_start",		"Enables DMA access."},
+	{NULL, NULL,	0x00001300, 0x00000000,  8,  8, "sp2_ycbcr_rdma_path_enable",	"Enables sp2_ycbcr_rdma path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  7,  7, "mcm_raw1_path_enable",		"Enables mcm_raw1 path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  6,  6, "mcm_raw0_path_enable",		"Enables mcm_raw0 path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  5,  5, "sp2_raw_path_enable",		"Enables sp2_raw path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  4,  4, "sp2_ycbcr_path_enable",	"Enables sp2_ycbcr path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  3,  3, "sp1_ycbcr_path_enable",	"Enables sp1_ycbcr path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  2,  2, "mp_jdp_path_enable",		"Enables mp_jdp path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  1,  1, "mp_raw_path_enable",		"Enables mp_raw path."},
+	{NULL, NULL,	0x00001300, 0x00000000,  0,  0, "mp_ycbcr_path_enable",		"Enables mp_ycbcr path."},
+
+	{"MI_CTRL_SHD",  "Global control internal shadow register",
+			0x00001304, 0x00000000, 20, 20, "sp2_raw2_write_path_enable",	"Enables sp2_raw2_write path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 19, 19, "pp_write_path_enable",		"Enables pp write path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 18, 18, "mcm_g2_raw1_path_enable",	"Enables mcm_raw1 path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 17, 17, "mcm_g2_raw0_path_enable",	"Enables mcm_raw0 path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 16, 16, "mcm_raw_rdma_start_con",	"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 15, 15, "mcm_raw_rdma_start",		"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 14, 14, "mcm_raw_rdma_path_enable",	"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 13, 13, "sp2_raw_rdma_start_con",	"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 12, 12, "sp2_raw_rdma_start",		"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 11, 11, "sp2_raw_rdma_path_enable",	"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000, 10, 10, "sp2_ycbcr_rdma_start_con",	"Unused"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	9,  9, "mcm_raw1_path_enable",		"Enables mcm_raw1 path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	8,  8, "mcm_raw0_path_enable",		"Enables mcm_raw0 path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	5,  5, "sp2_raw_path_enable",		"Enables sp2_raw path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	4,  4, "sp2_ycbcr_path_enable",		"Enables sp2_ycbcr path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	3,  3, "sp1_ycbcr_path_enable",		"Enables sp1_ycbcr path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	2,  2, "mp_jdp_path_enable",		"Enables mp_jdp path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	1,  1, "mp_raw_path_enable",		"Enables mp_raw path. 0: Disabled; 1: enabled"},
+	{NULL,	NULL,  0x00001304, 0x00000000,	0,  0, "mp_ycbcr_path_enable",		"Enables mp_ycbcr path. 0: Disabled; 1: enabled"},
+
+
+
+	{"MI_QOS",  "AXI Bus QOS value configuration",
+			0x00001308, 0x00000000, 31, 28, "mcm_qos_rd", "QoS value of AXI bus for MCM read"},
+	{NULL, NULL,	0x00001308, 0x00000000, 27, 24, "mcm_qos_wr", "QoS value of AXI bus for MCM write"},
+	{NULL, NULL,	0x00001308, 0x00000000, 23, 20, "sp2_qos_rd", "QoS value of AXI bus bus for sp2 read"},
+	{NULL, NULL,	0x00001308, 0x00000000, 19, 16, "sp2_qos_wr", "QoS value of AXI bus bus for sp2 write"},
+	{NULL, NULL,	0x00001308, 0x00000000, 11,  8, "sp1_qos_wr", "QoS value of AXI bus bus for sp1 write"},
+	{NULL, NULL,	0x00001308, 0x00000000,  3,  0, "mp_qos_wr", "QoS value of AXI bus bus for mp write"},
+
+
+	{"MI_QOS2",  "AXI Bus QOS value configuration",
+			0x0000130C, 0x00000000,  7,  4, "rt_qos_rd", "QoS value of AXI bus for RT read"},
+	{NULL, NULL,	0x0000130C, 0x00000000,  3,  0, "rt_qos_wr", "QoS value of AXI bus for RT write"},
+
+
+	{"MI_MP_CTRL", "MP control register",
+			0x00001310, 0x00000000,  5,  5, "mp_init_offset_en",	"Enables updating of the offset counters shadow registers for" LINE_PADDING_6TAB
+										"main path to the programmed register init values." LINE_PADDING_6TAB
+										"MI_MP_Y/CB/CR_OFFS_CNT_INIT-> MI_MP_Y/CB/CR_OFFS_CNT_SHD" LINE_PADDING_6TAB
+										"The update will be executed either when a forced software " LINE_PADDING_6TAB
+										"update occurs (in register MI_MP_CTRL bit cfg_upd = 1) or " LINE_PADDING_6TAB
+										"when an automatic configuration update signal arrives at the MI input port. " LINE_PADDING_6TAB
+										"The latter is split into main and self picture, so only " LINE_PADDING_6TAB
+										"the corresponding main/self shadow registers are affected."},
+	{NULL, NULL,	0x00001310, 0x00000000,  4,  4, "mp_init_base_en",	"Enables updating of the base address and buffer size shadow " LINE_PADDING_6TAB
+										"registers for main picture to the programmed register init values." LINE_PADDING_6TAB
+										"MI_MP_Y/CB/CR_BASE_AD_INIT-> MI_MP_Y/CB/CR_OFFS_CNT_SHD" LINE_PADDING_6TAB
+										"MI_MP_Y/CB/CR_SIZE_INIT-> MI_MP_Y/CB/CR_SIZE_SHD" LINE_PADDING_6TAB
+										"The update will be executed either when a forced software " LINE_PADDING_6TAB
+										"update occurs (in register MI_MP_CTRL bit cfg_upd = 1) or " LINE_PADDING_6TAB
+										"when an automatic config update signal arrives at the MI input port. " LINE_PADDING_6TAB
+										"The latter is split into main and self picture. So only the " LINE_PADDING_6TAB
+										"corresponding main/self shadow registers are affected. " LINE_PADDING_6TAB
+										"After a picture skip has been performed init_offset_en " LINE_PADDING_6TAB
+										"selects between skip restart and skip init mode " LINE_PADDING_6TAB
+										"(see bit skip in register MI_MP_CTRL)."},
+	{NULL, NULL,	0x00001310, 0x00000000,  3,  3, "mp_mi_cfg_upd",	"Forced configuration update. Leads to an immediate update of the shadow " LINE_PADDING_6TAB
+										"registers. Depending on the two init enable bits in the MI_MP_CTRL register" LINE_PADDING_6TAB
+										"(init_offset_en and init_base_en) the offset counter, base address and" LINE_PADDING_6TAB
+										"buffer size shadow registers are also updated."},
+	{NULL, NULL,	0x00001310, 0x00000000,  2,  2, "mp_mi_skip",		"Skip of current or next starting main picture:" LINE_PADDING_6TAB
+										"Aborts writing of main picture image data of the current frame to RAM" LINE_PADDING_6TAB
+										"  (after the current burst transmission has been completed). " LINE_PADDING_6TAB
+										"  Further main picture data up to the end of the current frame are discarded." LINE_PADDING_6TAB
+										"No further macroblock line interrupt (mblk_line), no wrap around interrupt " LINE_PADDING_6TAB
+										"  for main picture (wrap_mp_y/cb/cr) and no fill level interrupt (fill_mp_y) are generated." LINE_PADDING_6TAB
+										"  Skip does not affect the generation of the main path frame end interrupt (mp_frame_end)." LINE_PADDING_6TAB
+										"Skip does not affect the processing of self picture and its corresponding interrupts " LINE_PADDING_6TAB
+										"  namely the self path frame end interrupt (sp_frame_end)." LINE_PADDING_6TAB
+										"The byte counter (register MI_BYTE_CNT) is not affected. " LINE_PADDING_6TAB
+										"  It produces the correct number of JPEG or RAW data bytes " LINE_PADDING_6TAB
+										"  at the end of the current (skipped) frame." LINE_PADDING_6TAB
+										"After a skip has been performed, the offset counter for the main picture " LINE_PADDING_6TAB
+										"  at the start of the following frame are set depending on the bit " LINE_PADDING_6TAB
+										"init_offset_en in register MI_MP_CTRL: " LINE_PADDING_6TAB
+										"- Skip restart mode (init_offset_en = 0)" LINE_PADDING_6TAB
+										"  The offset counters of the main picture are restarted at the old start values of " LINE_PADDING_6TAB
+										"  the previous skipped frame." LINE_PADDING_6TAB
+										"- Skip init mode (init_offset_en = 1)" LINE_PADDING_6TAB
+										"  The offset counters of the main picture are initialized with the register " LINE_PADDING_6TAB
+										"  contents of the offset counter init registers without any additional forced" LINE_PADDING_6TAB
+										"  software update or automatic config update."},
+	{NULL, NULL,	0x00001310, 0x00000000,  1,  1, "mp_auto_update",	"Automatic update of configuration registers for main path at frame end."},
+	{NULL, NULL,	0x00001310, 0x00000000,  0,  0, "mp_pingpong_enable",	"Pingpong mode of configuration registers for main path at frame end."},
+
+
+	{"MI_MP_FMT", "MI main path format",
+			0x00001314, 0x00000000, 17, 17, "mp_wr_jdp_dp_bit",		"0: 32bit; 1: 64bit;"},
+	{NULL, NULL,	0x00001314, 0x00000000, 16, 16, "mp_wr_yuv_word_aligned_msb_en","0: 10bit yuv in LSB of 16bit; 1: 10bit yuv in MSB of 16bit;"},
+	{NULL, NULL,	0x00001314, 0x00000000, 15, 15, "mp_wr_yuv_word_aligned",	"0: disable; 1:enable"},
+	{NULL, NULL,	0x00001314, 0x00000000, 14, 13, "mp_wr_yuv_nvy",		"00: Put Y first => YC1C2; 01: Put Y second => C1YC2; 10: Put Y Third => C1C2Y"},
+	{NULL, NULL,	0x00001314, 0x00000000, 12, 12, "mp_wr_yuv_nv21",		"0: Put U before V; 1: Put V before U"},
+	{NULL, NULL,	0x00001314, 0x00000000, 11, 10, "mp_wr_raw_aligned",		"00: unaligned; 01: aligned mode0; 10: aligned mode1; 11: Reserved"},
+	{NULL, NULL,	0x00001314, 0x00000000,  9,  9, "mp_wr_yuv_aligned",		"0: unaligned; 1:aligned"},
+	{NULL, NULL,	0x00001314, 0x00000000,  8,  6, "mp_wr_raw_bit",		"000: RAW8; 001: RAW10; 010: RAW12; 011: RAW14; 100: RAW16; 101: RAW20, or Reserved."},
+	{NULL, NULL,	0x00001314, 0x00000000,  5,  4, "mp_wr_yuv_str",		"00: YUV/RGB SemiPlanar; 01: YUV Interleave, RGB Raster; 10: YUV/RGB Planar; 11: Y Only"},
+	{NULL, NULL,	0x00001314, 0x00000000,  3,  2, "mp_wr_yuv_fmt",		"00: YUV420; 01: YUV422; 10: YUV444; 11: Reserved"},
+	{NULL, NULL,	0x00001314, 0x00000000,  1,  1, "mp_wr_yuv_bit",		"0: 8 bit YUV/RGB; 1: 10 bit YUV/RGB"},
+	{NULL, NULL,	0x00001314, 0x00000000,  0,  0, "mp_wr_jdp_fmt",		"Output format. 0: DPCC; 1: JPEG"},
+
+
+	{"MI_MP_BUS_CFG", "MP AXI Bus configuration",
+			0x00001318, 0x00000000, 27, 24, "mp_wr_swap_jdp",	"Same as mp_wr_swap_y"},
+	{NULL, NULL,	0x00001318, 0x00000000, 23, 20, "mp_wr_swap_raw",	"Same as mp_wr_swap_y"},
+	{NULL, NULL,	0x00001318, 0x00000000, 19, 16, "mp_wr_swap_v",		"Same as mp_wr_swap_y"},
+	{NULL, NULL,	0x00001318, 0x00000000, 15, 12, "mp_wr_swap_u",		"Same as mp_wr_swap_y"},
+	{NULL, NULL,	0x00001318, 0x00000000, 11,  8, "mp_wr_swap_y",		"Swap bits control for 16 byte data width on AXI bus;" LINE_PADDING_6TAB
+										"YUV interleave or RGB raster mode share the same bits." LINE_PADDING_6TAB
+										" Bit 0: to swap bytes" LINE_PADDING_6TAB
+										" Bit 1: to swap words" LINE_PADDING_6TAB
+										" Bit 2 to swap double words" LINE_PADDING_6TAB
+										" Bit 3 to swap four words"},
+	{NULL, NULL,	0x00001318, 0x00000000,  7,  6, "mp_rd_issue_cap",	"Unused"},
+	{NULL, NULL,	0x00001318, 0x00000000,  5,  4, "mp_wr_issue_cap",	"Maximum outstanding issue capability. 00:4; 01:8; 10:16; 11:32"},
+	{NULL, NULL,	0x00001318, 0x00000000,  3,  2, "mp_rd_burst_len",	"Unused"},
+	{NULL, NULL,	0x00001318, 0x00000000,  1,  0, "mp_wr_burst_len",	"Maximum burst length. 00:4; 01:8; 10:16; 11:32"},
+
+
+	{"MI_MP_BUS_ID", "MP AXI Bus ID configuration",
+			0x0000131c, 0x00000000, 25, 25, "mp_bus_sw_en", "Control whether BUS works, and set to 1’b1 before ISP works"},
+	{NULL, NULL,	0x0000131c, 0x00000000, 24, 24, "mp_rd_id_en", "Unused"},
+	{NULL, NULL,	0x0000131c, 0x00000000, 23, 16, "mp_rd_id_cfg", "Unused"},
+	{NULL, NULL,	0x0000131c, 0x00000000,  8,  8, "mp_wr_id_en", "MP AXI ports write ID configuration enable"},
+	{NULL, NULL,	0x0000131c, 0x00000000,  7,  0, "mp_wr_id_cfg", "MP AXI ports write ID configuration"},
+
+	{"MI_MP_BUS_TIMEO", "MP AXI Bus control register",
+			0x00001320, 0x00000000, 31, 31, "mp_bus_timeo_en", "MP AXI bus time out waiting enable"},
+	{NULL, NULL,	0x00001320, 0x00000000, 30,  0, "mp_bus_timeo", "MP AXI bus time out waiting clock cycle numbers"},
+
+
+	{"MI_MP_Y_BASE_AD_INIT", "Base address for main picture Y component",
+			0x00001324, 0x00000000, 31,  0, "mp_y_base_ad_init",	"Base address of main picture Y component ring buffer." LINE_PADDING_6TAB
+										"Programmed value becomes effective (visible in corresponding shadow register)" LINE_PADDING_6TAB
+										"after a soft reset, a forced software update or an automatic configuration update."},
+
+
+	{"MI_MP_Y_SIZE_INIT", "Size of main picture Y component in frame buffer(ring buffer)",
+			0x00001328, 0x00000000, 28,  0, "mp_y_size_init",	"Size of main picture Y component ring buffer." LINE_PADDING_6TAB
+										"Programmed value becomes effective (visible in corresponding shadow register)" LINE_PADDING_6TAB
+										"after a soft reset, a forced software update or an automatic configuration update."},
+
+	{"MI_MP_Y_OFFS_CNT_INIT", "Offset counter init value for main picture Y",
+			0x0000132c, 0x00000000, 28,  0, "mp_y_offs_cnt_init",	"Offset counter init value of main picture Y component ring buffer." LINE_PADDING_6TAB
+										"Programmed value becomes effective (visible in corresponding shadow register)" LINE_PADDING_6TAB
+										"after a soft reset, a forced software update or an automatic configuration update."},
+
+	{"MI_MP_Y_LLENGTH", "Line length of main picture Y",
+			0x00001330, 0x00000000, 31,  0, "mp_y_llengh",	"Line length of Main Path picture Y component or RGB picture in bytes, " LINE_PADDING_6TAB
+									"also known as line stride. [Refer doc]"},
+
+	{"MI_MP_Y_PIC_WIDTH", "Image width of the Y component in pixels for main path",
+			0x00001334, 0x00000000, 31,	0, "mp_y_pic_width",	"Image width of the main picture Y component or RGB picture in pixels.[Refer doc]"},
+
+	{"MI_MP_Y_PIC_HEIGHT", "Image height of the Y component in pixels for main path",
+			0x00001338, 0x00000000, 31,  0, "mp_y_pic_height",	"Image height of the y component or RGB picture in pixels.[Refer doc]"},
+
+	{"MI_MP_Y_PIC_SIZE", "Image memory size of the Y component in bytes for main path",
+			0x0000133c, 0x00000000, 31,  0, "mp_y_pic_size",	"Image size of the Y component or RGB picture in bytes.[Refer doc]"},
+
+	{"MI_MP_CB_BASE_AD_INIT", "Base address for main picture Cb component ring buffer",
+			0x00001340, 0x00000000, 31,  0, "mp_cb_base_ad_init",	"Base address of main picture Cb component ring buffer.[Refer doc]"},
+
+
+	{"MI_MP_CB_SIZE_INIT", "Size of main picture Cb component ring buffer",
+		0x00001344, 0x00000000, 27,	0, "mp_cb_size_init", "Size of main picture Cb component ring buffer.[Refer doc]"},
+
+
+	{"MI_MP_CB_OFFS_CNT_INIT", "Offset counter init value for main picture Cb component ring buffer",
+		0x00001348, 0x00000000, 27,  0, "mp_cb_offs_cnt_init", "Offset counter init value of main picture Cb component ring buffer.[Refer doc]"},
+
+
+	{"MI_MP_CR_BASE_AD_INIT", "Base address for main picture Cr component ring buffer",
+		0x0000134c, 0x00000000, 31,  0, "mp_cr_base_ad_init", "Base address of main picture Cr component ring buffer.[Refer doc]"},
+
+	{"MI_MP_CR_SIZE_INIT", "Size of main picture Cr component ring buffer",
+		REG_BASE+0x050, 0x00000000, 27,  0, "mp_cr_size_init",		"Size of main picture Cr component ring buffer.[Refer doc]"},
+
+	{"MI_MP_CR_OFFS_CNT_INIT", "Offset counter init value for main picture Cr component ring buffer",
+		0x00001354, 0x00000000, 27,  0, "mp_cr_offs_cnt_init", "Offset counter init value of main picture Cr component ring buffer.[Refer doc]"},
+
+	{"MI_MP_Y_BASE_AD_INIT2", "Base address 2 (ping pong) for main picture Y component",
+		0x00001358, 0x00000000, 31,  0, "mp_y_base_ad_init2", "Second ping pong base address of main picture Y component buffer.[Refer doc]"},
+
+	{"MI_MP_CB_BASE_AD_INIT2",	"Base address 2 (pingpong) for main picture Cb component ring buffer",
+		0x0000135C, 0x00000000, 31,  0, "mp_cb_base_ad_init2",	"Second ping pong base address of main picture Cb component buffer[Refer doc]"},
+
+	{"MI_MP_CR_BASE_AD_INIT2",	"Base address 2 (pingpong) for main picture Cr component ring buffer",
+		0x00001360, 0x00000000, 31,  0, "mp_cr_base_ad_init2",	"Second ping pong base address of main picture Cr component buffer.[Refer doc]"},
+
+	{"MI_MP_Y_BASE_AD_SHD", "Base address shadow register for main picture Y component ring buffer",
+		0x00001370, 0x00000000, 31,  0, "mp_y_base_ad", "Shadow Base address of main picture Y component ring buffer."},
+
+	{"MI_MP_RAW_BASE_AD_INIT","Follow Y",	0x00001394, 0x00000000, 31,  0, "mp_raw_base_ad_init",	"Base address of main picture RAW component ring buffer.[Refer doc]"},
+	{"MI_MP_RAW_SIZE_INIT", "Follow Y",	0x00001398, 0x00000000, 28,  0, "mp_raw_size_init", "Size of main picture RAW data ring buffer.[Refer doc]"},
+	{"MI_MP_RAW_OFFS_CNT_INIT", "Follow Y",	0x0000139c, 0x00000000, 28,  0, "mp_raw_offs_cnt_init", "Offset counter initial value of main picture RAW data ring buffer.[Refer doc]"},
+	{"MI_MP_RAW_LLENGTH", "Follow Y",	0x000013a0, 0x00000000, 31,  0, "mp_raw_llengh", "Line length of Main Path picture RAW data in bytes, also known as line stride. [Refer doc]"},
+	{"MI_MP_RAW_PIC_WIDTH", "Follow Y",	0x000013a4, 0x00000000, 31,  0, "mp_raw_pic_width", "Image width of the Main Path picture RAW component or RGB picture in pixels.[Refer doc]"},
+	{"MI_MP_RAW_PIC_HEIGHT", "Follow Y",	0x000013A8, 0x00000000, 14,  0, "mp_raw_pic_height",	"Image height of Main Path picture RAW data in pixels[Refer doc]"},
+	{"MI_MP_RAW_PIC_SIZE", "Follow Y",	0x000013AC, 0x00000000, 24,  0, "mp_raw_pic_size",	"Image size of the RAW component in bytes[Refer doc]"},
+
+	{"MI_MP_JDP_BASE_AD_INIT", "Follow Y",	0x000013C0, 0x00000000, 31,  0, "mp_jdp_base_ad_init",	"Base address of main picture jpeg or dpcc ring buffer.[Refer doc]"},
+	{"MI_MP_JDP_SIZE_INIT", "Follow Y",	0x000013C4, 0x00000000, 28,  0, "mp_jdp_size_init",	"Size of main picture jpeg or dpcc ring buffer.[Refer doc]"},
+	{"MI_MP_JDP_OFFS_CNT_INIT", "Follow Y",	0x000013C8, 0x00000000, 28,  0, "mp_jdp_offs_cnt_init",	"Offset counter init value of main picture jpeg or dpcc data ring buffer.[Refer doc]"},
+	{"MI_MP_JDP_LLENGTH", "Follow Y",	0x000013CC, 0x00000000, 31,  0, "mp_jdp_llength",	"Line length of mp picture jpeg data in pixels, also known as line stride.[Refer doc]"},
+	{"MI_MP_JDP_PIC_WIDTH", "Follow Y",	0x000013D0, 0x00000000, 14,  0, "mp_jdp_pic_width",	"Image width of the main picture JPEG component picture in pixels.[Refer doc]"},
+	{"MI_MP_JDP_PIC_HEIGHT", "Follow Y",	0x000013D4, 0x00000000, 14,  0, "mp_jdp_pic_height",	"Image height of the main picture JPEG component picture in pixels.[Refer doc]"},
+	{"MI_MP_JDP_PIC_SIZE", "Follow Y",	0x000013D8, 0x00000000, 24,  0, "mp_jdp_pic_size",	"Image size of the main picture JPEG component picture in bytes.[Refer doc]"},
+
+
+	{"MI_MP_STATUS_CLR", "FIFO full clear",
+			0x000013ec, 0x00000000,  4,  4, "mp_jdp_fifo_full", "Clear status of JDP FIFO full flag in Main path"},
+	{NULL, NULL,	0x000013ec, 0x00000000,  3,  3, "mp_raw_fifo_full", "Clear status of RAW FIFO full flag in Main path"},
+	{NULL, NULL,	0x000013ec, 0x00000000,  2,  2, "mp_cr_fifo_full", "Clear status of Cr FIFO full flag in Main path"},
+	{NULL, NULL,	0x000013ec, 0x00000000,  1,  1, "mp_cb_fifo_full", "Clear status of Cb FIFO full flag in Main path"},
+	{NULL, NULL,	0x000013ec, 0x00000000,  0,  0, "mp_y_fifo_full", "Clear status of Y FIFO full flag in Main path"},
+
+
+	{"MI_MP_CTRL_STATUS", "FIFO Full STATUS, Y,U,V,RAW,JDP",
+			0x000013f0, 0x00000000,  4,  4, "mp_jdp_fifo_full", "FIFO full flag of JDP FIFO in Main path asserted since last clear"},
+	{NULL, NULL,	0x000013f0, 0x00000000,  3,  3, "mp_raw_fifo_full", "FIFO full flag of RAW FIFO in Main path asserted since last clear"},
+	{NULL, NULL,	0x000013f0, 0x00000000,  2,  2, "mp_cr_fifo_full", "FIFO full flag of Cr FIFO in Main path asserted since last clear"},
+	{NULL, NULL,	0x000013f0, 0x00000000,  1,  1, "mp_cb_fifo_full", "FIFO full flag of Cb FIFO in Main path asserted since last clear"},
+	{NULL, NULL,	0x000013f0, 0x00000000,  0,  0, "mp_y_fifo_full", "FIFO full flag of Y FIFO in Main path asserted since last clear"},
+
+	{"MI_SP2_CTRL", "SP2 control register",
+			0x000014e4, 0x00000000,  9,  9, "sp2_rd_raw_cfg_update",	"Forced configuration update which leads to an immediate update of the shadow registers for this RAW read path."},
+	{NULL, NULL,	0x000014e4, 0x00000000,  8,  8, "sp2_rd_raw_auto_update",	"unused"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  7,  7, "sp2_rd_yuv_cfg_update",	"unused"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  6,  6, "sp2_rd_yuv_auto_update",	"unused"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  5,  5, "sp2_init_offset_en",		"Enables updating of the offset counters shadow registers [Refer doc]"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  4,  4, "sp2_init_base_en",		"Enables updating of the base address and buffer size shadow registers[Refer doc]"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  3,  3, "sp2_mi_cfg_upd",		"Forced configuration update which leads to an immediate update of the shadow registers.[Refer doc]"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  2,  2, "sp2_mi_skip",			"Skip of current or next starting main picture."},
+	{NULL, NULL,	0x000014e4, 0x00000000,  1,  1, "sp2_auto_update",		"Automatic update of configuration registers for Self Path 2 at frame end. 0: disabled; 1: enabled"},
+	{NULL, NULL,	0x000014e4, 0x00000000,  0,  0, "sp2_pingpong_enable",		"Ping-pong mode of configuration registers for Self Path 2 at frame end. 0: disabled; 1: enabled"},
+
+
+	{"MI_SP2_FMT",	"SP2 pixel format control register",
+			0x000014e8, 0x00000000, 29, 29, "sp2_wr_yuv_word_aligned_msb_en","0: 10bit yuv in LSB of 16bit;  1: 10bit yuv in MSB of 16bit;"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 28, 28, "sp2_wr_yuv_word_aligned", 	"0: disable; 1:enable"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 27, 26, "sp2_rd_yuv_nvy", 		"00: Y channel in the first position; 01: Y in the second; 10: Y in the third; 11: Reserved" LINE_PADDING_6TAB
+											"  When in YUV444 or RGB888 interleave: " LINE_PADDING_6TAB
+											"  00: Y channel in the first and third position; 01: Y channel in the second and fourth position"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 25, 25, "sp2_rd_yuv_nv21", 		"0: No swap; 1: Swap Cr and Cb channel for semi-planar and YUV444 or RGB interleave and YUV422 interleave"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 24, 23, "sp2_rd_raw_aligned",		"00: Unaligned; 01: Aligned mode0; 10: Aligned mode1; 11: Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 22, 22, "sp2_rd_yuv_aligned",		"0: Unaligned; 1: Aligned"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 21, 19, "sp2_rd_raw_bit",		"000: RAW8; 001: RAW10; 010: RAW12; 011: RAW14; 100: RAW16; 101: RAW20, or Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 18, 17, "sp2_rd_yuv_str",		"00: YUV/RGB Semi-Planar; 01: YUV Interleave, RGB Raster; 10: YUV/RGB Planar; 11: Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 16, 15, "sp2_rd_yuv_fmt",		"00: YUV420; 01: YUV422; 10: YUV444; 11: Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 14, 14, "sp2_rd_yuv_bit",		"0: 8 bit YUV/RGB; 1: 10 bit YUV/RGB"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 13, 12, "sp2_wr_yuv_nvy",		"00: Y channel in the first position; 01: Y in the second; 10: Y in the third; 11: Reserved" LINE_PADDING_6TAB
+											"  When in YUV444 or RGB888 interleave:  00:Y channel in 1st and 3rd position;  01:Y channel in the 2nd and 4th position"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 11, 11, "sp2_wr_yuv_nv21",		"0: No swap; 1: Swap Cr and Cb channel for semi-planar and YUV444 or RGB interleave and YUV422 interleave"},
+	{NULL, NULL,	0x000014e8, 0x00000000, 10,  9, "sp2_wr_raw_aligned",		"00: Unaligned; 01: Aligned mode0; 10: Aligned mode1; 11: Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000,  8,  8, "sp2_wr_yuv_aligned",		"0: Unaligned; 1:Aligned"},
+	{NULL, NULL,	0x000014e8, 0x00000000,  7,  5, "sp2_wr_raw_bit",		"000: RAW8; 001: RAW10; 010: RAW12; 011: RAW14; 100: RAW16; 101: RAW20, or Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000,  4,  3, "sp2_wr_yuv_str",		"00: YUV/RGB SemiPlanar; 01: YUV Interleave, RGB Raster; 10: YUV/RGB Planar; 11: Y Only"},
+	{NULL, NULL,	0x000014e8, 0x00000000,  2,  1, "sp2_wr_yuv_fmt",		"00: YUV420; 01: YUV422; 10: YUV444; 11: Reserved"},
+	{NULL, NULL,	0x000014e8, 0x00000000,  0,  0, "sp2_wr_yuv_bit",		"0: 8 bit YUV/RGB; 1: 10 bit YUV/RGB"},
+
+	{"MI_SP2_RAW_BASE_AD_INIT", "Follow main path RAW",
+			0x00001568, 0x00000000, 31,  0, "sp2_raw_base_ad_init",		"Base address of Self Path 2 picture RAW component ring buffer[Refer doc]"},
+	{"MI_SP2_DMA_RAW_PIC_START_AD", "RAW component image start address",
+			0x000015bc, 0x00000000, 31,  0, "sp2_dma_raw_pic_start_ad",	"Image start address of the RAW component"},
+
+	{"MI_SP2_DMA_RAW_PIC_WIDTH", "RAW component image width",
+			0x000015c0, 0x00000000, 14,  0, "sp2_dma_raw_pic_width", "Image width of the RAW component in pixels."},
+
+	{"MI_SP2_DMA_RAW_STATUS", "DMA raw status",    0x000015e0, 0x00000000,	0,  0, "sp2_dma_raw_active", "If set, DMA RAW access is active."},
+
+	{"MI_MCM_CTRL", "MCM Path MI control register",
+			0x00001600, 0x00000000,  6,  6, "mcm_rd_cfg_upd",	"Forced configuration update which leads to an immediate " LINE_PADDING_6TAB
+										"update of the shadow registers for the MCM read path."},
+	{NULL, NULL,	0x00001600, 0x00000000,  5,  5, "mcm_rd_auto_update",	"unused"},
+	{NULL, NULL,	0x00001600, 0x00000000,  4,  4, "mcm_init_offset_en",	"Enables updating of the offset counters shadow registers " LINE_PADDING_6TAB
+										"for MCM path to the programmed register init values.[Refer doc]"},
+	{NULL, NULL,	0x00001600, 0x00000000,  3,  3, "mcm_init_base_en",	"Enables updating of the base address and buffer size shadow registers" LINE_PADDING_6TAB
+										"for main picture to the programmed register init values. [Refer doc]"},
+	{NULL, NULL,	0x00001600, 0x00000000,  2,  2, "mcm_wr_cfg_upd",	"Forced configuration update which leads to an immediate " LINE_PADDING_6TAB
+										"update of the shadow registers. [Refer doc]"},
+	{NULL, NULL,	0x00001600, 0x00000000,  1,  1, "mcm_wr_skip",		"Skip of current or next starting MCM picture."},
+	{NULL, NULL,	0x00001600, 0x00000000,  0,  0, "mcm_wr_auto_update",	"Automatic update of configuration registers for Self Path 1 " LINE_PADDING_6TAB
+										"at frame end. 0: Disabled; 1: Enabled"},
+
+
+
+	{"MI_MCM_FMT", "MCM pixel format control register",
+			0x00001604, 0x00000000, 17, 16, "mcm_wr1_fmt_aligned",	"00:  unaligned, 01: aligned mode0, 10: aligned mode1, 11: Reserved"},
+	{NULL, NULL,	0x00001604, 0x00000000, 15, 14, "mcm_wr0_fmt_aligned",	"00:  unaligned, 01: aligned mode0, 10: aligned mode1, 11: Reserved"},
+	{NULL, NULL,	0x00001604, 0x00000000, 13, 12, "mcm_rd_fmt_aligned",	"00:  unaligned, 01: aligned mode0, 10: aligned mode1, 11: Reserved"},
+	{NULL, NULL,	0x00001604, 0x00000000, 11,  8, "mcm_wr1_raw_bit",	"000: RAW8, 001: RAW10, 010: RAW12, 011: RAW14, 100: RAW16, 101: RAW20 or Reserved"},
+	{NULL, NULL,	0x00001604, 0x00000000,  7,  4, "mcm_wr0_raw_bit",	"000: RAW8, 001: RAW10, 010: RAW12, 011: RAW14, 100: RAW16, 101: RAW20 or Reserved"},
+	{NULL, NULL,	0x00001604, 0x00000000,  3,  0, "mcm_rd_raw_bit",	"000: RAW8, 001: RAW10, 010: RAW12, 011: RAW14, 100: RAW16, 101: RAW20 or Reserved"},
+
+
+	{"MI_MCM_BUS_CFG", "MCM AXI Bus cfg",
+			0x00001608, 0x00000000, 19, 16, "mcm_rd_swap_raw",	"Swap bits control for 16 byte data width on AXI bus; " LINE_PADDING_6TAB
+										"YUV interleave and RGB raster mode share the same bits." LINE_PADDING_6TAB
+										"Bit 0 to swap bytes; Bit 1 to swap words; Bit 2 to swap double words; Bit 3 to swap four words"},
+	{NULL, NULL,	0x00001608, 0x00000000, 15, 12, "mcm_wr0_swap_raw",	"Same as field: mcm_rd_swap_raw"},
+	{NULL, NULL,	0x00001608, 0x00000000, 11,  8, "mcm_wr1_swap_raw",	"Same as field: mcm_rd_swap_raw"},
+	{NULL, NULL,	0x00001608, 0x00000000,  7,  6, "mcm_rd_issue_cap",	"Maximum outstanding issue capability. 00: 4; 01: 8; 10: 16; 11: 32"},
+	{NULL, NULL,	0x00001608, 0x00000000,  5,  4, "mcm_wr_issue_cap",	"Maximum outstanding issue capability. 00: 4; 01: 8; 10: 16; 11: 32"},
+	{NULL, NULL,	0x00001608, 0x00000000,  3,  2, "mcm_rd_burst_len",	"Maximum burst length. 00:4; 01:8; 10:16, 11:Reserved"},
+	{NULL, NULL,	0x00001608, 0x00000000,  1,  0, "mcm_wr_burst_len",	"Maximum burst length. 00:4; 01:8; 10:16, 11:Reserved"},
+
+	{"MI_MCM_RAW0_BASE_AD_INIT", "Follow Main Path RAW",	0x00001614, 0x00000000, 31,  0, "mcm_raw0_base_ad_init","Base address of MCM Path picture RAW0 component ring buffer[Refer doc]"},
+	{"MI_MCM_RAW0_SIZE_INIT", "Follow Main Path RAW",	0x00001618, 0x00000000, 28,  0, "mcm_raw0_size_init",	"Size of MCM Path picture RAW0 data ring buffer.[Refer doc]"},
+
+	{"MI_MCM_BUS_ID", "MCM AXI Bus ID configuration",
+			0x0000160C, 0x00000000, 27, 27, "mcm_bus_sw_en",	"Control whether BUS works, and set to 1’b1 before ISP works"},
+	{NULL, NULL,	0x0000160C, 0x00000000, 26, 26, "mcm_rd_id_en",	"MCM AXI ports read ID configuration enable"},
+	{NULL, NULL,	0x0000160C, 0x00000000, 25, 18, "mcm_rd_id_cfg",	"MCM AXI ports read ID configuration"},
+	{NULL, NULL,	0x0000160C, 0x00000000,  8,  8, "mcm_wr1_id_en",	"MCM AXI ports write1 ID configuration enable"},
+	{NULL, NULL,	0x0000160C, 0x00000000,  7,  0, "mcm_wr1_id_cfg",	"MCM AXI ports write1 ID configuration"},
+
+	{"MI_MCM_RAW0_LLENGTH", "Follow Main Path RAW",    0x00001620, 0x00000000, 31,  0, "mcm_raw0_llength",		"Line length of MCM Path picture RAW0 data in bytes, also known as line stride[Refer doc]"},
+	{"MI_MCM_RAW0_PIC_WIDTH", "Follow Main Path RAW",  0x00001624, 0x00000000, 14,  0, "mcm_raw0_pic_width",	"Image width of the MCM Path picture RAW component in pixels.[Refer doc]"},
+	{"MI_MCM_RAW0_PIC_HEIGHT", "Follow Main Path RAW", 0x00001628, 0x00000000, 14,  0, "mcm_raw0_pic_height",	"Image height of the RAW0 component in pixels.[Refer doc]"},
+	{"MI_MCM_RAW0_PIC_SIZE", "Follow Main Path RAW",   0x0000162c, 0x00000000, 24,  0, "mcm_raw0_pic_size",		"Image size of the RAW0 component in bytes(mcm_raw0_llength * mcm_raw0_pic_height).[Refer doc]"},
+
+	{"MI_MCM_RAW1_BASE_AD_INIT", "Follow Main Path RAW",	0x00001640, 0x00000000, 31,  0, "mcm_raw1_base_ad_init","Base address of MCM Path picture RAW1 component ring buffer"},
+	{"MI_MCM_RAW1_SIZE_INIT", "Follow Main Path RAW",	0x00001644, 0x00000000, 28,  0, "mcm_raw1_size_init",	"Size of MCM Path picture RAW1 data ring buffer."},
+
+	{"MI_MCM_RAW1_LLENGTH", "Follow Main Path RAW",    0x0000164c, 0x00000000, 31,  0, "mcm_raw1_llength",		"Line length of MCM Path picture RAW1 data in bytes, also known as line stride[Refer doc]"},
+	{"MI_MCM_RAW1_PIC_WIDTH", "Follow Main Path RAW",  0x00001650, 0x00000000, 14,  0, "mcm_raw1_pic_width",	"Image width of the MCM Path picture RAW1 component in pixels.[Refer doc]"},
+	{"MI_MCM_RAW1_PIC_HEIGHT", "Follow Main Path RAW", 0x00001654, 0x00000000, 14,  0, "mcm_raw1_pic_height",	"Image height of the RAW1 component in pixels.[Refer doc]"},
+	{"MI_MCM_RAW1_PIC_SIZE", "Follow Main Path RAW",   0x00001658, 0x00000000, 24,  0, "mcm_raw1_pic_size",		"Image size of the RAW1 component in bytes(mcm_raw1_llength * mcm_raw1_pic_height).[Refer doc]"},
+
+	{"MI_MCM_DMA_RAW_PIC_START_AD", "RAW component image start address",	0x0000166c, 0x00000000, 31,  0, "mcm_dma_raw_pic_start_ad",	"Image start address of the RAW component."},
+	{"MI_MCM_DMA_RAW_PIC_WIDTH", "RAW component image width",		0x00001670, 0x00000000, 14,  0, "mcm_dma_raw_pic_width",	"Image width of the RAW component in pixels."},
+	{"MI_MCM_DMA_RAW_PIC_LLENGTH", "RAW component original line length",	0x00001674, 0x00000000, 31,  0, "mcm_dma_raw_pic_llength",	"Line length of the RAW component in bytes of " LINE_PADDING_6TAB
+																		"the original image in memory.For an uncropped image, " LINE_PADDING_6TAB
+																		"where lines follow each other without offset" LINE_PADDING_6TAB
+																		"(no line stride), line length must match image width."},
+	{"MI_MCM_DMA_RAW_PIC_SIZE", "RAW component image memory size in bytes",	0x00001678, 0x00000000, 27,  0, "mcm_dma_raw_pic_size",		"Image size of the RAW component in bytes which has to be" LINE_PADDING_6TAB
+																		" the RAW line length multiplied by the RAW image height" LINE_PADDING_6TAB
+																		"(dma_raw_llength * dma_raw_pic_height)."},
+
+	{"MI_MCM_DMA_STATUS", "MCM_DMA status register",    0x0000168c, 0x00000000,  0,  0, "mcm_dma_active", "0: MCM DMA access is not active; 1: MCM DMA access is active"},
+	{"MI_MCM_DMA_RAW_PIC_LVAL", "MCM_DMA RAW Component line valid bytes number, 128 bit Alignment.",
+			0x00001690, 0x00000000, 15,  0, "mcm_dma_raw_width_bytes",	"Sizes occupied by valid data of a line; " LINE_PADDING_6TAB
+											"should be a multiple of 16" LINE_PADDING_6TAB
+											"Note: bus width=16 bytes"},
+
+	{"MI_IMSC", "Interrupt Mask",
+			0x000016c0, 0x00000000, 27, 27, "fill_mp_y", "Mask bit for fill level interrupt of main picture Y, JPEG or RAW data"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 26, 26, "mblk_line", "Mask bit for macroblock line interrupt of main picture " LINE_PADDING_6TAB
+									"(16 lines of Y, 8 lines of Cb and 8 lines of Cr are written into RAM)"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 25, 25, "mp_handshk_int", "Mask bit for handshake interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 24, 24, "mcm_dma_raw_ready", "Mask bit for mcm_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 23, 23, "sp2_dma_raw_ready", "Mask bit for sp2_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 22, 22, "sp2_dma_ycbcr_ready", "Mask bit for sp2_dma YCbCr ready interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 21, 21, "wrap_mcm_raw1", "Mask bit for MCM RAW1 address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 20, 20, "wrap_mcm_raw0", "Mask bit for MCM RAW0 address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 19, 19, "wrap_sp2_raw", "Mask bit for Self Path 2 RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 18, 18, "wrap_sp2_cr", "Mask bit for Self Path 2 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 17, 17, "wrap_sp2_cb", "Mask bit for Self Path 2 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 16, 16, "wrap_sp2_y", "Mask bit for Self Path 2 Y address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 15, 15, "wrap_sp1_cr", "Mask bit for Self Path 1 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 14, 14, "wrap_sp1_cb", "Mask bit for Self Path 1 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 13, 13, "wrap_sp1_y", "Mask bit for Self Path 1 Y address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 12, 12, "wrap_mp_jdp", "Mask bit for Main Path JDP address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 11, 11, "wrap_mp_raw", "Mask bit for Main Path RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000, 10, 10, "wrap_mp_cr", "Mask bit for Main Path Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  9,  9, "wrap_mp_cb", "Mask bit for Main Path Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  8,  8, "wrap_mp_y", "Mask bit for Main Path Y address wrap interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  7,  7, "mcm_raw1_frame_end", "Mask bit for MCM RAW1 end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  6,  6, "mcm_raw0_frame_end", "Mask bit for MCM RAW0 end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  5,  5, "sp2_raw_frame_end", "Mask bit for Self Path 2 RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  4,  4, "sp2_ycbcr_frame_end", "Mask bit for Self Path 2 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  3,  3, "sp1_ycbcr_frame_end", "Mask bit for Self Path 1 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  2,  2, "mp_jdp_frame_end", "Mask bit for Main Path JDP end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  1,  1, "mp_raw_frame_end", "Mask bit for Main Path RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016c0, 0x00000000,  0,  0, "mp_ycbcr_frame_end", "Mask bit for Main Path YCbCr end of frame interrupt." LINE_PADDING_6TAB
+										"0: Interrupt masked; 1: Interrupt active"},
+
+	{"MI_MIS", "Masked Interrupt Status",
+			0x000016d0, 0x00000000, 27, 27, "fill_mp_y",		"Masked status of fill level interrupt of main picture Y, JPEG or RAW data"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 26, 26, "mblk_line",		"Masked status of macroblock line interrupt of main picture" LINE_PADDING_6TAB
+										"(16 lines of Y, 8 lines of Cb and 8 lines of Cr are written into RAM)"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 25, 25, "mp_handshk_int",	"Masked status of handshake interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 24, 24, "mcm_dma_raw_ready",	"Masked status of mcm_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 23, 23, "sp2_dma_raw_ready",	"Masked status of sp2_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 22, 22, "sp2_dma_ycbcr_ready",	"Masked status of sp2_dma YCbCr ready interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 21, 21, "wrap_mcm_raw1",	"Masked status of MCM RAW1 address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 20, 20, "wrap_mcm_raw0",	"Masked status of MCM RAW0 address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 19, 19, "wrap_sp2_raw",		"Masked status of Self Path2 RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 18, 18, "wrap_sp2_cr",		"Masked status of Self Path2 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 17, 17, "wrap_sp2_cb",		"Masked status of Self Path2 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 16, 16, "wrap_sp2_y",		"Masked status of Self Path2 y address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 15, 15, "wrap_sp1_cr",		"Masked status of Self Path1 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 14, 14, "wrap_sp1_cb",		"Masked status of Self Path1 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 13, 13, "wrap_sp1_y",		"Masked status of Self Path1 y address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 12, 12, "wrap_mp_jdp",		"Masked status of Main Path JDP address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 11, 11, "wrap_mp_raw",		"Masked status of Main Path RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000, 10, 10, "wrap_mp_cr",		"Masked status of Main Path Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  9,  9, "wrap_mp_cb",		"Masked status of Main Path Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  8,  8, "wrap_mp_y",		"Masked status of Main Path Y address wrap interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  7,  7, "mcm_raw1_frame_end",	"Masked status of MCM RAW1 end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  6,  6, "mcm_raw0_frame_end",	"Masked status of MCM RAW0 end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  5,  5, "sp2_raw_frame_end",	"Masked status of Self Path2 RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  4,  4, "sp2_ycbcr_frame_end",	"Masked status of Self Path2 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  3,  3, "sp1_ycbcr_frame_end",	"Masked status of Self Path1 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  2,  2, "mp_jdp_frame_end",	"Masked status of Main Path JDP end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  1,  1, "mp_raw_frame_end",	"Masked status of Main Path RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016d0, 0x00000000,  0,  0, "mp_ycbcr_frame_end",	"Masked status of Main Path YCbCr end of frame interrupt"},
+
+	{"MI_ICR", "Interrupt Clear Register",
+			0x000016d8, 0x00000000, 27, 27, "fill_mp_y", "Clear fill level interrupt of main picture Y, JPEG or RAW data"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 26, 26, "mblk_line", "Clear macroblock line interrupt of main picture "  LINE_PADDING_6TAB
+									" (16 lines of Y, 8 lines of Cb and 8 lines of Cr are written into RAM)"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 25, 25, "mp_handshk_int", "Clear handshake interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 24, 24, "mcm_dma_raw_ready", "Clear mcm_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 23, 23, "sp2_dma_raw_ready", "Clear sp2_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 22, 22, "sp2_dma_ycbcr_ready", "Clear sp2_dma YCbCr ready interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 21, 21, "wrap_mcm_raw1", "Clear MCM RAW1 address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 20, 20, "wrap_mcm_raw0", "Clear MCM RAW0 address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 19, 19, "wrap_sp2_raw", "Clear Self Path2 RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 18, 18, "wrap_sp2_cr", "Clear Self Path2 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 17, 17, "wrap_sp2_cb", "Clear Self Path2 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 16, 16, "wrap_sp2_y", "Clear Self Path2 y address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 15, 15, "wrap_sp1_cr", "Clear Self Path1 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 14, 14, "wrap_sp1_cb", "Clear Self Path1 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 13, 13, "wrap_sp1_y", "Clear Self Path1 Y address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 12, 12, "wrap_mp_jdp", "Clear Main Path JDP address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 11, 11, "wrap_mp_raw", "Clear Main Path RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000, 10, 10, "wrap_mp_cr", "Clear Main Path Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  9,  9, "wrap_mp_cb", "Clear Main Path Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  8,  8, "wrap_mp_y", "Clear Main Path Y address wrap interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  7,  7, "mcm_raw1_frame_end", "Clear MCM RAW1 end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  6,  6, "mcm_raw0_frame_end", "Clear MCM RAW0 end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  5,  5, "sp2_raw_frame_end", "Clear Self Path2 RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  4,  4, "sp2_ycbcr_frame_end", "Clear Self Path2 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  3,  3, "sp1_ycbcr_frame_end", "Clear Self Path1 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  2,  2, "mp_jdp_frame_end", "Clear Main Path JDP end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  1,  1, "mp_raw_frame_end", "Clear Main Path RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016d8, 0x00000000,  0,  0, "mp_ycbcr_frame_end", "Clear Main Path YCbCr end of frame interrupt"},
+
+
+	{"MI_RIS", "Interrupt Set Register",
+			0x000016e0, 0x00000000, 27, 27, "fill_mp_y", "RAW status of fill level interrupt of main picture Y, JPEG or RAW data"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 26, 26, "mblk_line", "RAW status of macroblock line interrupt of main picture " LINE_PADDING_6TAB
+								"(16 lines of Y, 8 lines of Cb and 8 lines of Cr are written into RAM)"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 25, 25, "mp_handshk_int", "RAW status of handshake interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 24, 24, "mcm_dma_raw_ready", "RAW status of mcm_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 23, 23, "sp2_dma_raw_ready", "RAW status of sp2_dma RAW ready interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 22, 22, "sp2_dma_ycbcr_ready", "RAW status of sp2_dma YCbCr ready interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 21, 21, "wrap_mcm_raw1", "RAW status of MCM RAW1 address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 20, 20, "wrap_mcm_raw0", "RAW status of MCM RAW0 address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 19, 19, "wrap_sp2_raw", "RAW status of Self Path2 RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 18, 18, "wrap_sp2_cr", "RAW status of Self Path2 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 17, 17, "wrap_sp2_cb", "RAW status of Self Path2 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 16, 16, "wrap_sp2_y", "RAW status of Self Path2 Y address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 15, 15, "wrap_sp1_cr", "RAW status of Self Path1 Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 14, 14, "wrap_sp1_cb", "RAW status of Self Path1 Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 13, 13, "wrap_sp1_y", "RAW status of Self Path1 Y address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 12, 12, "wrap_mp_jdp", "RAW status of Main Path JDP address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 11, 11, "wrap_mp_raw", "RAW status of Main Path RAW address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000, 10, 10, "wrap_mp_cr", "RAW status of Main Path Cr address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  9,  9, "wrap_mp_cb", "RAW status of Main Path Cb address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  8,  8, "wrap_mp_y", "RAW status of Main Path Y address wrap interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  7,  7, "mcm_raw1_frame_end", "RAW status of MCM RAW1 end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  6,  6, "mcm_raw0_frame_end", "RAW status of MCM RAW0 end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  5,  5, "sp2_raw_frame_end", "RAW status of Self Path2 RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  4,  4, "sp2_ycbcr_frame_end", "RAW status of Self Path2 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  3,  3, "sp1_ycbcr_frame_end", "RAW status of Self Path1 YCbCr end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  2,  2, "mp_jdp_frame_end", "RAW status of Main Path JDP end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  1,  1, "mp_raw_frame_end", "RAW status of Main Path RAW end of frame interrupt"},
+	{NULL, NULL,	0x000016e0, 0x00000000,  0,  0, "mp_ycbcr_frame_end", "RAW status of Main Path YCbCr end of frame interrupt"},
+
+
+	{"MI_MIS2", "Interrupt Set Register",
+			0x000016f0, 0x00000000, 26, 26, "ppw_y_buf_full", "status of ppw y buf full ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 25, 25, "ppw_u_buf_full", "status of ppw u buf full ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 24, 24, "ppw_v_buf_full", "status of ppw v buf full ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 23, 23, "ppr_y_buf_full", "status of ppr y buf full ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 22, 22, "sp2_raw2_w_buf_full", "status of spw_raw2 wr buf full interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 21, 21, "sp2_raw2_r_buf_full", "status of spw_raw2 rd buf full interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 20, 20, "hdr_w_buf_full", "status of mi hdr wr buf full interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 19, 19, "hdr_r_buf_full", "status of mi hdr rd buf full interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 18, 18, "sp2_raw2_dma_ready", "status of spw_raw2 ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 17, 17, "ppr_dma_ready", "status of pp_dma yuv ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 16, 16, "wrap_sp2_raw", "status of sp2_raw2 address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 15, 15, "wrap_ppw_cr", "status of ppw_cr address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 14, 14, "wrap_ppw_cb", "status of ppw_cb address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 13, 13, "wrap_ppw_y", "status of ppw_y address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 12, 12, "sp2_raw2_frame_end", "status of spp2_raw2 end of frame interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 11, 11, "ppw_frame_end", "status of ppw end of frame interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000, 10, 10, "hdr_vs_dma_ready", "status of hdr_vs ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  9,  9, "hdr_s_dma_ready", "status of hdr_s ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  8,  8, "hdr_l_dma_ready", "status of hdr_l ready interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  7,  7, "wrap_hdr_vs", "status of hdr_vs address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  6,  6, "wrap_hdr_s", "status of hdr_s address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  5,  5, "wrap_hdr_l", "status of hdr_l address wrap interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  4,  4, "hdr_vs_frame_end", "status of hdr_vs end of frame interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  3,  3, "hdr_s_frame_end", "status of hdr_s end of frame interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  2,  2, "hdr_l_frame_end", "status of hdr_l end of frame interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  1,  1, "mi_rt_bus_buserr", "status of Memory Interface RT Path bus buserr interrupt"},
+	{NULL, NULL,	0x000016f0, 0x00000000,  0,  0, "mi_rt_bus_timeo", "status of Memory Interface RT Path bus timeout interrupt"},
+};
+
+int light_isp_mi_reg_dump(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_fields(ra_info, reg_desc, count);
+}
+
+int light_isp_mi_reg_define(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_define(ra_info, reg_desc, count);
+}
+
+int light_isp_mi_reg_find(reg_analyzer_info_s *ra_info)
+{
+	uint32_t count = sizeof(reg_desc) / sizeof(reg_desc[0]);
+	return ra_dump_reg_find(ra_info, reg_desc, count);
+}
+

Some files were not shown because too many files changed in this diff