Problems with porting AR0135 + DS90UB964 driver to Jetson TX2 (CSI/VI bind Fault?)

Hello there,

for about two weeks I’m working on porting an Aptina AR0135 driver to the Jetson TX2.
We use a DS90UB964 deserializer as CSI source on 2 lanes on a custom base board.

I’ve used the original ov5693 driver as base for my own.
I’ve removed all references inside the device tree to the ov5693 and replaced them by my ar0135 ones.

And I was refer to this topic:
https://devtalk.nvidia.com/default/topic/1016796/?comment=5223528

But I couldn’t get the /dev/vedio0 file!

Here is my hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-e3326-a00.dtsi:

/*
 * Copyright (c) 2015-2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 //#include "dt-bindings/clock/tegra186-clock.h" //zhou
 //#include <t18x-common-platforms/tegra186-quill-camera-e3326-a00.dtsi>

/ {
	host1x {
		vi@15700000 {
			status = "okay";
			num-channels = <1>;
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				status = "okay";
				port@0 {
					status = "okay";
					reg = <0>;
					e3326_vi_in0: endpoint {
						status = "okay";
						csi-port = <2>;
						bus-width = <2>;
						remote-endpoint = <&e3326_csi_out0>;
					};
				};
			};
		};

		nvcsi@150c0000 {
			status = "okay";
			num-channels = <1>;
			#address-cells = <1>;
			#size-cells = <0>;
			channel@0 {
				status = "okay";
				reg = <0>;
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					status = "okay";
					port@0 {
						status = "okay";
						reg = <0>;
						e3326_csi_in0: endpoint@0 {
							status = "okay";
							csi-port = <2>;
							bus-width = <2>;
							remote-endpoint = <&e3326_ar0135_out0>;
						};
					};
					port@1 {
						status = "okay";
						reg = <1>;
						e3326_csi_out0: endpoint@1 {
							status = "okay";
							remote-endpoint = <&e3326_vi_in0>;
						};
					};
				};
			};
		};
	};

	i2c@3180000 {
        status = "okay";
		ar0135_c@10 {
			compatible = "nvidia,ar0135";
			/* I2C device address */
			reg = <0x10>;
           

			/* V4L2 device node location */
			devnode = "video0";
			status = "okay";

			/* Physical dimensions of sensor */
			physical_w = "3.674";
			physical_h = "2.738";
			sensor_model = "ar0135";

			// clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
			// 		 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
			// clock-names = "extperiph1", "pllp_grtba";
			// mclk = "extperiph1";
			// //clock-frequency = <24000000>;
			// clock-frequency = <25000000>;

			/* Define any required hw resources needed by driver */
			/* ie. clocks, io pins, power sources */
			avdd-reg = "vana";
			iovdd-reg = "vif";

			

			/* Sensor output flip settings */
			/*vertical-flip = "true";*/

			/**
			* A modeX node is required to support v4l2 driver
			* implementation with NVIDIA camera software stack
			*
			* mclk_khz = "";
			* Standard MIPI driving clock, typically 24MHz
			*
			* num_lanes = "";
			* Number of lane channels sensor is programmed to output
			*
			* tegra_sinterface = "";
			* The base tegra serial interface lanes are connected to
			*
			* discontinuous_clk = "";
			* The sensor is programmed to use a discontinuous clock on MIPI lanes
			*
			* dpcm_enable = "true";
			* The sensor is programmed to use a DPCM modes
			*
			* cil_settletime = "";
			* MIPI lane settle time value.
			* A "0" value attempts to autocalibrate based on mclk_multiplier
			*
			*
			*
			*
			* active_w = "";
			* Pixel active region width
			*
			* active_h = "";
			* Pixel active region height
			*
			* pixel_t = "";
			* The sensor readout pixel pattern
			*
			* readout_orientation = "0";
			* Based on camera module orientation.
			* Only change readout_orientation if you specifically
			* Program a different readout order for this mode
			*
			* line_length = "";
			* Pixel line length (width) for sensor mode.
			* This is used to calibrate features in our camera stack.
			*
			* mclk_multiplier = "";
			* Multiplier to MCLK to help time hardware capture sequence
			* TODO: Assign to PLL_Multiplier as well until fixed in core
			*
			* pix_clk_hz = "";
			* Sensor pixel clock used for calculations like exposure and framerate
			*
			*
			*
			*
			* inherent_gain = "";
			* Gain obtained inherently from mode (ie. pixel binning)
			*
			* min_gain_val = ""; (floor to 6 decimal places)
			* max_gain_val = ""; (floor to 6 decimal places)
			* Gain limits for mode
			*
			* min_exp_time = ""; (ceil to integer)
			* max_exp_time = ""; (ceil to integer)
			* Exposure Time limits for mode (us)
			*
			*
			* min_hdr_ratio = "";
			* max_hdr_ratio = "";
			* HDR Ratio limits for mode
			*
			* min_framerate = "";
			* max_framerate = "";
			* Framerate limits for mode (fps)
			*/
			mode0 { // AR0135_MODE_1280X728
				mclk_khz = "25000";
				num_lanes = "2";
				tegra_sinterface = "serial_c";
				discontinuous_clk = "no";
				dpcm_enable = "false";
				cil_settletime = "0";

				active_w = "1280";
				active_h = "728";
				pixel_t = "raw12";
				readout_orientation = "90";
				line_length = "1650";
				inherent_gain = "1";
				// mclk_multiplier = "6.67";
				// pix_clk_hz = "160000000";
                                mclk_multiplier = "2.97";
                                pix_clk_hz = "74250000";

				min_gain_val = "1.0";
				max_gain_val = "16";
				min_hdr_ratio = "1";
				max_hdr_ratio = "64";
				min_framerate = "1.816577";
				max_framerate = "54";
				min_exp_time = "34";
				max_exp_time = "550385";
                                embedded_metadata_height = "2";
			};

			ports {
				#address-cells = <1>;
				#size-cells = <0>;
                                status = "okay";
				port@0 {
					status = "okay";
					reg = <0>;
					e3326_ar0135_out0: endpoint {
						status = "okay";
						csi-port = <2>;
						bus-width = <2>;
						remote-endpoint = <&e3326_csi_in0>;
					};
				};
			};
		};
	};

	e3326_lens_ar0135@P5V27C {
		min_focus_distance = "0.0";
		hyper_focal = "0.0";
		focal_length = "2.67";
		f_number = "2.0";
		aperture = "2.0";
	};

	tegra-camera-platform {
		compatible = "nvidia, tegra-camera-platform";
		/**
		* Physical settings to calculate max ISO BW
		*
		* num_csi_lanes = <>;
		* Total number of CSI lanes when all cameras are active
		*
		* max_lane_speed = <>;
		* Max lane speed in Kbit/s
		*
		* min_bits_per_pixel = <>;
		* Min bits per pixel
		*
		* vi_peak_byte_per_pixel = <>;
		* Max byte per pixel for the VI ISO case
		*
		* vi_bw_margin_pct = <>;
		* Vi bandwidth margin in percentage
		*
		* max_pixel_rate = <>;
		* Max pixel rate in Kpixel/s for the ISP ISO case
		*
		* isp_peak_byte_per_pixel = <>;
		* Max byte per pixel for the ISP ISO case
		*
		* isp_bw_margin_pct = <>;
		* Isp bandwidth margin in percentage
		*/
		num_csi_lanes = <4>;
		max_lane_speed = <1500000>;
		min_bits_per_pixel = <10>;
		vi_peak_byte_per_pixel = <2>;
		vi_bw_margin_pct = <25>;
		//max_pixel_rate = <160000>;
		isp_peak_byte_per_pixel = <5>;
		isp_bw_margin_pct = <25>;

		/**
		* The general guideline for naming badge_info contains 3 parts, and is as follows,
		* The first part is the camera_board_id for the module; if the module is in a FFD
		* platform, then use the platform name for this part.
		* The second part contains the position of the module, ex. “rear” or “front”.
		* The third part contains the last 6 characters of a part number which is found
		* in the module's specsheet from the vender.
		*/
		modules {
			module0 {
				status = "okay";
				badge = "e3326_front_P5V27C";
				position = "rear";
				orientation = "1";
				drivernode0 {
					status = "okay";
					/* Declare PCL support driver (classically known as guid)  */
					pcl_id = "v4l2_sensor";
					/* Driver v4l2 device name */
					devname = "ar0135 2-0010";
					/* Declare the device-tree hierarchy to driver instance */
					proc-device-tree = "/proc/device-tree/i2c@3180000/ar0135_c@10";
				};
				drivernode1 {
					status = "okay";
					/* Declare PCL support driver (classically known as guid)  */
					pcl_id = "v4l2_lens";
					proc-device-tree = "/proc/device-tree/e3326_lens_ar0135@P5V27C/";
				};
			};
		};
	};
};

And I was use Main Platform Device Tree File this way not plugin manager to register my device.And I was use tegra186-quill-camera-modules.dtsi as a model for generating my dtsi.Here is my hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-modules.dtsi.

/*
 * Copyright (c) 2016-2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */

//#include "t18x-common-platforms/tegra186-quill-deserializer.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-e3326-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-e3323-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-e3333-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-e3322-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-li-mipi-adpt-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-imx274-a00.dtsi"
#include "t18x-common-platforms/tegra186-quill-camera-vivid.dtsi"

#define CAM0_RST_L	TEGRA_MAIN_GPIO(R, 5)
#define CAM0_PWDN	TEGRA_MAIN_GPIO(R, 0)
#define CAM1_RST_L	TEGRA_MAIN_GPIO(R, 1)
#define CAM1_PWDN	TEGRA_MAIN_GPIO(L, 6)

/ {
	tegra-camera-platform {
		/**
		* tpg_max_iso = <>;
		* Max iso bw for 6 streams of tpg
		* streams * nvcsi_freq * PG_bitrate / RG10 * BPP
		* 6 * 102Mhz * 32 bits/ 10 bits * 2 Bps
		* = 3916.8 MBps
		*/
		tpg_max_iso = <3916800>;
	};

	/* set camera gpio direction to output */
	gpio@2200000 {
		camera-control-output-low {
			gpio-hog;
			output-low;
			gpios = <CAM0_RST_L 0 CAM0_PWDN 0
				 CAM1_RST_L 0 CAM1_PWDN 0>;
			label = "cam0-rst", "cam0-pwdn",
				"cam1-rst", "cam1-pwdn";
		};
	};

	/* all cameras are disabled by default */
	host1x {
		vi_base: vi@15700000 {
			status = "okay";
			ports {
				vi_port0: port@0 {
					status = "okay";
					vi_in0: endpoint {
						status = "okay";
					};
				};
				vi_port1: port@1 {
					status = "disabled";
					vi_in1: endpoint {
						status = "disabled";
					};
				};
				vi_port2: port@2 {
					status = "disabled";
					vi_in2: endpoint {
						status = "disabled";
					};
				};
				vi_port3: port@3 {
					status = "disabled";
					vi_in3: endpoint {
						status = "disabled";
					};
				};
				vi_port4: port@4 {
					status = "disabled";
					vi_in4: endpoint {
						status = "disabled";
					};
				};
				vi_port5: port@5 {
					status = "disabled";
					vi_in5: endpoint {
						status = "disabled";
					};
				};
			};
		};
		csi_base: nvcsi@150c0000 {
			status = "okay";
			csi_chan0: channel@0 {
				status = "okay";
				ports {
					csi_chan0_port0: port@0 {
						status = "okay";
						csi_in0: endpoint@0 {
							status = "okay";
						};
					};
					csi_chan0_port1: port@1 {
						status = "okay";
						csi_out0: endpoint@1 {
							status = "okay";
						};
					};
				};
			};
			csi_chan1: channel@1 {
				status = "disabled";
				ports {
					csi_chan1_port0: port@0 {
						status = "disabled";
						csi_in1: endpoint@2 {
							status = "disabled";
						};
					};
					csi_chan1_port1: port@1 {
						status = "disabled";
						csi_out1: endpoint@3 {
							status = "disabled";
						};
					};
				};
			};
			csi_chan2: channel@2 {
				status = "disabled";
				ports {
					csi_chan2_port0: port@0 {
						status = "disabled";
						csi_in2: endpoint@4 {
							status = "disabled";
						};
					};
					csi_chan2_port1: port@1 {
						status = "disabled";
						csi_out2: endpoint@5 {
							status = "disabled";
						};
					};
				};
			};
			csi_chan3: channel@3 {
				status = "disabled";
				ports {
					csi_chan3_port0: port@0 {
						status = "disabled";
						csi_in3: endpoint@6 {
							status = "disabled";
						};
					};
					csi_chan3_port1: port@1 {
						status = "disabled";
						csi_out3: endpoint@7 {
							status = "disabled";
						};
					};
				};
			};
			csi_chan4: channel@4 {
				status = "disabled";
				ports {
					csi_chan4_port0: port@0 {
						status = "disabled";
						csi_in4: endpoint@8 {
							status = "disabled";
						};
					};
					csi_chan4_port1: port@1 {
						status = "disabled";
						csi_out4: endpoint@9 {
							status = "disabled";
						};
					};
				};
			};
			csi_chan5: channel@5 {
				status = "disabled";
				ports {
					csi_chan5_port0: port@0 {
						status = "disabled";
						csi_in5: endpoint@10 {
							status = "disabled";
						};
					};
					csi_chan5_port1: port@1 {
						status = "disabled";
						csi_out5: endpoint@11 {
							status = "disabled";
						};
					};
				};
			};
		};
	};

	i2c@3180000 {
		e3326_cam0: ar0135_c@10 {
			status = "okay";
		};
		e3323_cam0: ov23850_a@10 {
			status = "disabled";
		};
		e3323_vcm0: lc898212@72 {
			status = "disabled";
		};
		tca6408@21 {
			status = "disabled";
		};
		tca9548@77 {
			status = "disabled";
			i2c@0 {
				e3333_cam0: ov5693_a@36 {
					status = "disabled";
				};
				e3322_cam0: imx219_a@10 {
					status = "disabled";
				};
			};
			i2c@1 {
				e3333_cam1: ov5693_b@36 {
					status = "disabled";
				};
				e3322_cam1: imx219_b@10 {
					status = "disabled";
				};
			};
			i2c@2 {
				e3333_cam2: ar0135_c@10 {
					status = "disabled";
				};
				e3322_cam2: imx219_c@10 {
					status = "disabled";
				};
			};
			i2c@3 {
				e3333_cam3: ov5693_d@36 {
					status = "disabled";
				};
				e3322_cam3: imx219_d@10 {
					status = "disabled";
				};
			};
			i2c@4 {
				e3333_cam4: ov5693_e@36 {
					status = "disabled";
				};
				e3322_cam4: imx219_e@10 {
					status = "disabled";
				};
			};
			i2c@5 {
				e3333_cam5: ov5693_f@36 {
					status = "disabled";
				};
				e3322_cam5: imx219_f@10 {
					status = "disabled";
				};
			};
		};
		tca9546_70: tca9546@70 {
			status = "disabled";
			i2c@0 {
				imx185_cam0: imx185_a@1a {
					status = "disabled";
				};
			};
		};
		tca9546_70: tca9546@70 {
			status = "disabled";
			i2c@0 {
				imx274_cam0: imx274_a@1a {
					status = "disabled";
				};
			};
		};
	};

	i2c@c240000 {
		e3323_cam1: ov23850_c@36 {
			status = "disabled";
		};
		e3323_vcm1: lc898212@72 {
			status = "disabled";
		};
	};

	tcp: tegra-camera-platform {
		compatible = "nvidia, tegra-camera-platform";
		modules {
			cam_module0: module0 {
				status = "okay";
				cam_module0_drivernode0: drivernode0 {
					status = "okay";
				};
				cam_module0_drivernode1: drivernode1 {
					status = "okay";
					pcl_id = "v4l2_lens";
				};
			};
			cam_module1: module1 {
				status = "disabled";
				cam_module1_drivernode0: drivernode0 {
					status = "disabled";
				};
				cam_module1_drivernode1: drivernode1 {
					status = "disabled";
					pcl_id = "v4l2_lens";
				};
			};
			cam_module2: module2 {
				status = "disabled";
				cam_module2_drivernode0: drivernode0 {
					status = "disabled";
				};
				cam_module2_drivernode1: drivernode1 {
					status = "disabled";
					pcl_id = "v4l2_lens";
				};
			};
			cam_module3: module3 {
				status = "disabled";
				cam_module3_drivernode0: drivernode0 {
					status = "disabled";
				};
				cam_module3_drivernode1: drivernode1 {
					status = "disabled";
					pcl_id = "v4l2_lens";
				};
			};
			cam_module4: module4 {
				status = "disabled";
				cam_module4_drivernode0: drivernode0 {
					status = "disabled";
				};
				cam_module4_drivernode1: drivernode1 {
					status = "disabled";
					pcl_id = "v4l2_lens";
				};
			};
			cam_module5: module5 {
				status = "disabled";
				cam_module5_drivernode0: drivernode0 {
					status = "disabled";
				};
				cam_module5_drivernode1: drivernode1 {
					status = "disabled";
					pcl_id = "v4l2_lens";
				};
			};
		};
	};
};

my hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-e3326-a00.dtsi.

/*
 * Copyright (c) 2015-2016, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <t18x-common-modules/tegra186-camera-e3326-a00.dtsi>
#include "dt-bindings/clock/tegra186-clock.h"

// #define CAM0_RST_L	TEGRA_MAIN_GPIO(R, 5)
// #define CAM0_PWDN	TEGRA_MAIN_GPIO(R, 0)

/* camera control gpio definitions */

/ {
	i2c@3180000 {
		ar0135_c@10 {
			/* Define any required hw resources needed by driver */
			/* ie. clocks, io pins, power sources */
			/* mclk-index indicates the index of the */
			/* mclk-name with in the clock-names array */

			clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
					 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
			clock-names = "extperiph1", "pllp_grtba";
			mclk = "extperiph1";
			//clock-frequency = <24000000>;
			clock-frequency = <25000000>;
			// reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
			// pwdn-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
			vana-supply = <&en_vdd_cam_hv_2v8>;
			vif-supply = <&en_vdd_cam>;
		};
	};

	// gpio@2200000 {
	// 	camera-control-output-low {
	// 		gpio-hog;
	// 		output-low;
	// 		gpios = <CAM0_RST_L 0 CAM0_PWDN 0>;
	// 		label = "cam0-rst", "cam0-pwdn";
	// 	};
	// };
};

Probe function looks run good,but faults happened! Dmesg is:

[    5.676613] tegra-vi4 15700000.vi: initialized
[    5.676739] tegra-vi4 15700000.vi: vi_parse_dt:ar0135 success to find num of channels is 1
[    5.677697] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 Init channel success
[    5.677810] tegra_channel_init_subdevices:ar0135 first add video name vi-output, 150c0000.nvcsi-0
[    5.677823]  (null): i2c_client drvdata is NULL
[    5.677889] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 tegra_vi_graph_init success
[    5.677891] tegra-vi4 15700000.vi: tegra_vi_channels_register: is csi failed
[    5.677893] tegra-vi4 15700000.vi: all channel register failed
[    5.677894] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 tegra_vi_channels_register success

So it seems to be CSI/VI port bind faults?? Please help me! Thanks a lot!

hello 15210962653,

seems you’re not probing the driver correctly,
please check [NVIDIA Tegra Linux Driver Package]-> [Development Guide]-> [Camera Development]-> [Sensor Driver Programming Guide] for reference.
thanks

Hi JerryChang,
Thank you very much for reply!
I looked this file [NVIDIA Tegra Linux Driver Package]-> [Development Guide]-> [Camera Development]-> [Sensor Driver Programming Guide] before I writed my driver.
Has any problems with my dtsi files?
Here is my driver ar0135.c.

/*
 * ar0135_v4l2.c - ar0135 sensor driver
 *
 * Copyright (c) 2013-2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define DEBUG 1   //enable dev_dbg

#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/module.h>


#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>

#include <media/camera_common.h>
#include <media/ar0135.h>

#include "../platform/tegra/camera/camera_gpio.h"

#include "ar0135_mode_tbls.h"

#define AR0135_MAX_COARSE_DIFF		6

#define AR0135_GAIN_SHIFT		8
#define AR0135_REAL_GAIN_SHIFT		4
#define AR0135_MIN_GAIN		(1 << AR0135_GAIN_SHIFT)
#define AR0135_MAX_GAIN		(16 << AR0135_GAIN_SHIFT)
#define AR0135_MAX_UNREAL_GAIN	(0x0F80)
#define AR0135_MIN_FRAME_LENGTH	(0x0)
#define AR0135_MAX_FRAME_LENGTH	(0x7fff)
#define AR0135_MIN_EXPOSURE_COARSE	(0x0002)
#define AR0135_MAX_EXPOSURE_COARSE	\
	(AR0135_MAX_FRAME_LENGTH-AR0135_MAX_COARSE_DIFF)
// #define AR0135_DEFAULT_LINE_LENGTH	(0xA80)
// #define AR0135_DEFAULT_PIXEL_CLOCK	(160)
#define AR0135_DEFAULT_LINE_LENGTH	(0x672)
#define AR0135_DEFAULT_PIXEL_CLOCK	(74)

#define AR0135_DEFAULT_GAIN		AR0135_MIN_GAIN
//#define AR0135_DEFAULT_FRAME_LENGTH	(0x07C0)
#define AR0135_DEFAULT_FRAME_LENGTH	(0x03DE)
#define AR0135_DEFAULT_FRAME_LENGTH_CB	(0x005A)
#define AR0135_DEFAULT_EXPOSURE_COARSE	\
	(AR0135_DEFAULT_FRAME_LENGTH-AR0135_MAX_COARSE_DIFF)

#define AR0135_DEFAULT_MODE	AR0135_MODE_1280X728//AR0135_MODE_2592X1944
//#define AR0135_DEFAULT_HDR_MODE	AR0135_MODE_1280X728_HDR//AR0135_MODE_2592X1944_HDR
#define AR0135_DEFAULT_WIDTH	1280 //2592
#define AR0135_DEFAULT_HEIGHT	728  //1944
#define AR0135_DEFAULT_DATAFMT	MEDIA_BUS_FMT_Y12_1X12//MEDIA_BUS_FMT_SRGGB10_1X10
//#define AR0135_DEFAULT_CLK_FREQ	24000000
#define AR0135_DEFAULT_CLK_FREQ	25000000
 

struct ar0135 {
	struct camera_common_power_rail	power;
	int				numctrls;
	struct v4l2_ctrl_handler	ctrl_handler;
	struct camera_common_eeprom_data eeprom[AR0135_EEPROM_NUM_BLOCKS];
	struct camera_common_deserializer_data   de_data;
	struct camera_common_serializer_data     se_data;
	u8				eeprom_buf[AR0135_EEPROM_SIZE];
	struct i2c_client		*i2c_client;
	struct v4l2_subdev		*subdev;
	struct media_pad		pad;

	int				reg_offset;

	s32				group_hold_prev;
	u32				frame_length;
	bool				group_hold_en;
	struct regmap			*regmap;
	struct camera_common_data	*s_data;
	struct camera_common_pdata	*pdata;
	struct v4l2_ctrl		*ctrls[];
};

static struct regmap_config ar0135_regmap_config = {
	.reg_bits = 16,
	.val_bits = 16,
	//.val_bits = 8,
};

// static int ar0135_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
static int ar0135_s_ctrl(struct v4l2_ctrl *ctrl);
static void ar0135_update_ctrl_range(struct ar0135 *priv, s32 frame_length);

static const struct v4l2_ctrl_ops ar0135_ctrl_ops = {
	//.g_volatile_ctrl = ar0135_g_volatile_ctrl,
	.s_ctrl		= ar0135_s_ctrl,
};

static struct v4l2_ctrl_config ctrl_config_list[] = {
/* Do not change the name field for the controls! */
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_GAIN,
		.name = "Gain",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.flags = V4L2_CTRL_FLAG_SLIDER,
		.min = AR0135_MIN_GAIN,
		.max = AR0135_MAX_GAIN,
		.def = AR0135_DEFAULT_GAIN,
		.step = 1,
	},
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_FRAME_LENGTH,
		.name = "Frame Length",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.flags = V4L2_CTRL_FLAG_SLIDER,
		.min = AR0135_MIN_FRAME_LENGTH,
		.max = AR0135_MAX_FRAME_LENGTH,
		.def = AR0135_DEFAULT_FRAME_LENGTH,
		.step = 1,
	},
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_COARSE_TIME,
		.name = "Coarse Time",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.flags = V4L2_CTRL_FLAG_SLIDER,
		.min = AR0135_MIN_EXPOSURE_COARSE,
		.max = AR0135_MAX_EXPOSURE_COARSE,
		.def = AR0135_DEFAULT_EXPOSURE_COARSE,
		.step = 1,
	},
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_COARSE_TIME_SHORT,
		.name = "Coarse Time Short",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.flags = V4L2_CTRL_FLAG_SLIDER,
		.min = AR0135_MIN_EXPOSURE_COARSE,
		.max = AR0135_MAX_EXPOSURE_COARSE,
		.def = AR0135_DEFAULT_EXPOSURE_COARSE,
		.step = 1,
	},
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_HDR_EN,
		.name = "HDR enable",
		.type = V4L2_CTRL_TYPE_INTEGER_MENU,
		.min = 0,
		.max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
		.menu_skip_mask = 0,
		.def = 0,
		.qmenu_int = switch_ctrl_qmenu,
	},
	{
		.ops = &ar0135_ctrl_ops,
		.id = V4L2_CID_FRAME_LENGTH_CB,
		.name = "Frame Length Cb",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.flags = V4L2_CTRL_FLAG_SLIDER,
		.min = AR0135_MIN_FRAME_LENGTH,
		.max = AR0135_MAX_FRAME_LENGTH,
		.def = AR0135_DEFAULT_FRAME_LENGTH_CB,
		.step = 1,
	},
};

static inline void ar0135_get_frame_length_regs(ar0135_reg *regs,
				u32 frame_length)
{
	regs->addr = AR0135_FRAME_LENGTH_ADDR_LSB;
	regs->val = frame_length & 0xffff;
}

static inline void ar0135_get_frame_length_cb_regs(ar0135_reg *regs,
				u32 frame_length)
{
	regs->addr = AR0135_FRAME_LENGTH_ADDR_MSB;
	regs->val = frame_length & 0xffff;
}


static inline void ar0135_get_coarse_time_regs(ar0135_reg *regs,
				u32 coarse_time)
{
	regs->addr = AR0135_COARSE_TIME_ADDR_1;
	regs->val = coarse_time & 0xffff;
}

static inline void ar0135_get_coarse_time_short_regs(ar0135_reg *regs,
				u32 coarse_time)
{
	regs->addr = AR0135_COARSE_TIME_SHORT_ADDR_1;
	regs->val = coarse_time & 0xffff;
}

static inline void ar0135_get_gain_regs(ar0135_reg *regs,
				u16 gain)
{
	regs->addr = AR0135_GAIN_ADDR_LSB;
	regs->val = gain & 0xffff;
}

static int test_mode;
module_param(test_mode, int, 0644);

static inline int ar0135_read_reg(struct camera_common_data *s_data,
				u16 addr, u16 *val)
{
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;
	int err = 0;
	u32 reg_val = 0;

	err = regmap_read(priv->regmap, addr, &reg_val);
	if (err)
		pr_err("%s:i2c read failed, %x\n",
			__func__, addr);

	*val = reg_val & 0xFFFF;

	return err;
}

static int ar0135_write_reg(struct camera_common_data *s_data, u16 addr, u16 val)
{
	int err;
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;

	err = regmap_write(priv->regmap, addr, val);
	if (err)
		pr_err("%s:i2c write failed, %x = %x\n",
			__func__, addr, val);

	return err;
}

static int ar0135_write_table(struct ar0135 *priv,
			      const ar0135_reg table[])
{
	const struct reg_16 *next;
    int err;

	for (next = table;; next++) {
		/* Handle special address values */
		if (next->addr == AR0135_TABLE_END)
			break;

		if (next->addr == AR0135_TABLE_WAIT_MS) {
			msleep_range(next->val);
			continue;
		}

		err = regmap_write(priv->regmap,next->addr,next->val);
		if (err)
		{
			dev_err(&priv->i2c_client->dev,"%s: addr %04x val %04x faild\n", __func__,next->addr,next->val);
			return err;
		}	
	}
    return 0;
}


static int ar0135_power_on(struct camera_common_data *s_data)
{
	int err = 0;
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;
	struct camera_common_power_rail *pw = &priv->power;

	dev_dbg(&priv->i2c_client->dev, "%s: power on\n", __func__);

	if (priv->pdata && priv->pdata->power_on) {
		err = priv->pdata->power_on(pw);
		if (err)
			pr_err("%s failed.\n", __func__);
		else
			pw->state = SWITCH_ON;

		dev_dbg(&priv->i2c_client->dev, "%s: power on test,err\n", __func__);
		return err;
	}

	/* sleeps calls in the sequence below are for internal device
	 * signal propagation as specified by sensor vendor */

	// if (pw->avdd)
	// 	err = regulator_enable(pw->avdd);
	// if (err)
	// 	goto ar0135_avdd_fail;

	// if (pw->iovdd)
	// 	err = regulator_enable(pw->iovdd);
	// if (err)
	// 	goto ar0135_iovdd_fail;

	// usleep_range(1, 2);
	// if (pw->pwdn_gpio)
	// 	ar0135_gpio_set(priv, pw->pwdn_gpio, 1);

	// /*
	//  * datasheet 2.9: reset requires ~2ms settling time
	//  * a power on reset is generated after core power becomes stable
	//  */
	// usleep_range(2000, 2010);

	// if (pw->reset_gpio)
	// 	ar0135_gpio_set(priv, pw->reset_gpio, 1);

	pw->state = SWITCH_ON;
	// ar0135_write_reg(s_data, 0x0100, 0x1);
	// ar0135_write_reg(s_data, 0x0100, 0x0);
	return 0;

// ar0135_iovdd_fail:
// 	regulator_disable(pw->avdd);

// ar0135_avdd_fail:
// 	pr_err("%s failed.\n", __func__);
// 	return -ENODEV;
}

static int ar0135_power_off(struct camera_common_data *s_data)
{
	int err = 0;
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;
	struct camera_common_power_rail *pw = &priv->power;

	dev_dbg(&priv->i2c_client->dev, "%s: power off\n", __func__);

	if (priv->pdata && priv->pdata->power_off) {
		err = priv->pdata->power_off(pw);
		if (!err) {
			goto power_off_done;
		} else {
			pr_err("%s failed.\n", __func__);
			return err;
		}
	}

	/* sleeps calls in the sequence below are for internal device
	 * signal propagation as specified by sensor vendor */

// 	usleep_range(21, 25);
// 	if (pw->pwdn_gpio)
// 		ar0135_gpio_set(priv, pw->pwdn_gpio, 0);
// 	usleep_range(1, 2);
// 	if (pw->reset_gpio)
// 		ar0135_gpio_set(priv, pw->reset_gpio, 0);

// 	/* datasheet 2.9: reset requires ~2ms settling time*/
// 	usleep_range(2000, 2010);

// 	if (pw->iovdd)
// 		regulator_disable(pw->iovdd);
// 	if (pw->avdd)
// 		regulator_disable(pw->avdd);

power_off_done:
	pw->state = SWITCH_OFF;
	return 0;
}

static int ar0135_power_put(struct ar0135 *priv)
{
	struct camera_common_power_rail *pw = &priv->power;

	if (unlikely(!pw))
		return -EFAULT;

	if (likely(pw->avdd))
		regulator_put(pw->avdd);

	if (likely(pw->iovdd))
		regulator_put(pw->iovdd);

	pw->avdd = NULL;
	pw->iovdd = NULL;

	// if (priv->pdata && priv->pdata->use_cam_gpio)
	// 	cam_gpio_deregister(priv->i2c_client, pw->pwdn_gpio);
	// else {
	// 	gpio_free(pw->pwdn_gpio);
	// 	gpio_free(pw->reset_gpio);
	// }

	return 0;
}

static int ar0135_power_get(struct ar0135 *priv)
{
	struct camera_common_power_rail *pw = &priv->power;
	struct camera_common_pdata *pdata = priv->pdata;
	const char *mclk_name;
	const char *parentclk_name;
	struct clk *parent;
	//int err = 0, ret = 0;
	int err = 0;

	if (!pdata) {
		dev_err(&priv->i2c_client->dev, "pdata missing\n");
		return -EFAULT;
	}

	mclk_name = pdata->mclk_name ?
		    pdata->mclk_name : "cam_mclk1";
	pw->mclk = devm_clk_get(&priv->i2c_client->dev, mclk_name);
	if (IS_ERR(pw->mclk)) {
		dev_err(&priv->i2c_client->dev,
			"unable to get clock %s\n", mclk_name);
		return PTR_ERR(pw->mclk);
	}
	else{
		dev_dbg(&priv->i2c_client->dev,
			"%s:success to get clock %s\n",__func__,mclk_name);  //zhou
	}

	parentclk_name = pdata->parentclk_name;
	if (parentclk_name) {
		parent = devm_clk_get(&priv->i2c_client->dev, parentclk_name);
		if (IS_ERR(parent)) {
			dev_err(&priv->i2c_client->dev,
				"unable to get parent clcok %s",
				parentclk_name);
		} else
			clk_set_parent(pw->mclk, parent);
	}
	else{
		dev_dbg(&priv->i2c_client->dev,
			"%s:parentclk_name is NULL\n",__func__);  //zhou
	}


	/* analog 2.8v */
	err |= camera_common_regulator_get(priv->i2c_client,
			&pw->avdd, pdata->regulators.avdd);
	/* IO 1.8v */
	err |= camera_common_regulator_get(priv->i2c_client,
			&pw->iovdd, pdata->regulators.iovdd);

	if (!err) {
		// pw->reset_gpio = pdata->reset_gpio;
		// pw->pwdn_gpio = pdata->pwdn_gpio;
		dev_err(&priv->i2c_client->dev,
				"%s:success to get avdd and iovdd",
				__func__);
	}

	pw->state = SWITCH_OFF;
	return err;
}

static int ar0135_set_gain(struct ar0135 *priv, s32 val);
static int ar0135_set_frame_length(struct ar0135 *priv, s32 val);
static int ar0135_set_frame_length_cb(struct ar0135 *priv, s32 val);
static int ar0135_set_coarse_time(struct ar0135 *priv, s32 val);
static int ar0135_set_coarse_time_short(struct ar0135 *priv, s32 val);

static int ar0135_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct camera_common_data *s_data = to_camera_common_data(client);
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;
	struct v4l2_control control;
	int err;
	u32 frame_time;
	//u8 val;

	dev_dbg(&client->dev, "%s++\n", __func__);

	if (!enable) {
		ar0135_update_ctrl_range(priv, AR0135_MAX_FRAME_LENGTH);

		// err = ar0135_write_table(priv,
		// 	mode_table[AR0135_MODE_STOP_STREAM]);
		// if (err)
		// 	return err;

		/*
		 * Wait for one frame to make sure sensor is set to
		 * software standby in V-blank
		 *
		 * frame_time = frame length rows * Tline
		 * Tline = line length / pixel clock (in MHz)
		 */
		frame_time = priv->frame_length *
			AR0135_DEFAULT_LINE_LENGTH / AR0135_DEFAULT_PIXEL_CLOCK;

		usleep_range(frame_time, frame_time + 1000);
		dev_dbg(&client->dev, "%s: parameter's enable is zero\n", __func__);
		return 0;
	}

	err = ar0135_write_table(priv, mode_table[s_data->mode]);
	if (err)
		goto exit;


	if (s_data->override_enable) {
		/*
		 * write list of override regs for the asking frame length,
		 * coarse integration time, and gain. Failures to write
		 * overrides are non-fatal
		 */
        dev_dbg(&client->dev, "%s: s_data's override_enable\n", __func__);

		control.id = V4L2_CID_GAIN;
		err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
		err |= ar0135_set_gain(priv, control.value);
		if (err)
			dev_dbg(&client->dev, "%s: warning gain override failed\n",
				__func__);

		control.id = V4L2_CID_FRAME_LENGTH;
		err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
		err |= ar0135_set_frame_length(priv, control.value);
		if (err)
			dev_dbg(&client->dev,
				"%s: warning frame length override failed\n",
				__func__);

		control.id = V4L2_CID_FRAME_LENGTH_CB;   //zhou
		err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
		err |= ar0135_set_frame_length_cb(priv, control.value);
		if (err)
			dev_dbg(&client->dev,
				"%s: warning frame length cb override failed\n",
				__func__);

		control.id = V4L2_CID_COARSE_TIME;
		err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
		err |= ar0135_set_coarse_time(priv, control.value);
		if (err)
			dev_dbg(&client->dev,
				"%s: warning coarse time override failed\n",
				__func__);

		control.id = V4L2_CID_COARSE_TIME_SHORT;
		err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
		err |= ar0135_set_coarse_time_short(priv, control.value);
		if (err)
			dev_dbg(&client->dev,
				"%s: warning coarse time short override failed\n",
				__func__);
	}

	err = ar0135_write_table(priv, mode_table[AR0135_MODE_START_STREAM]);
	if (err)
		goto exit;
    // if (priv->pdata->v_flip) {
	// 	ar0135_read_reg(priv->s_data, AR0135_TIMING_REG20, &val);
	// 	ar0135_write_reg(priv->s_data, AR0135_TIMING_REG20,
	// 			 val | VERTICAL_FLIP);
	// }
	// if (priv->pdata->h_mirror) {
	// 	ar0135_read_reg(priv->s_data, AR0135_TIMING_REG21, &val);
	// 	ar0135_write_reg(priv->s_data, AR0135_TIMING_REG21,
	// 			 val | HORIZONTAL_MIRROR_MASK);
	// } else {
	// 	ar0135_read_reg(priv->s_data, AR0135_TIMING_REG21, &val);
	// 	ar0135_write_reg(priv->s_data, AR0135_TIMING_REG21,
	// 			 val & (~HORIZONTAL_MIRROR_MASK));
	// }
	if (test_mode)
		err = ar0135_write_table(priv,
			mode_table[AR0135_MODE_TEST_PATTERN]);

	dev_dbg(&client->dev, "%s--\n", __func__);
	return 0;
exit:
	dev_dbg(&client->dev, "%s: error setting stream\n", __func__);
	return err;
}

static int ar0135_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct camera_common_data *s_data = to_camera_common_data(client);
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;
	struct camera_common_power_rail *pw = &priv->power;

	*status = pw->state == SWITCH_ON;
	return 0;
}

static struct v4l2_subdev_video_ops ar0135_subdev_video_ops = {
	.s_stream	= ar0135_s_stream,
	.g_mbus_config	= camera_common_g_mbus_config,
	.g_input_status = ar0135_g_input_status,
};

static struct v4l2_subdev_core_ops ar0135_subdev_core_ops = {
	.s_power	= camera_common_s_power,
};

static int ar0135_get_fmt(struct v4l2_subdev *sd,
		struct v4l2_subdev_pad_config *cfg,
		struct v4l2_subdev_format *format)
{
	return camera_common_g_fmt(sd, &format->format);
}

static int ar0135_set_fmt(struct v4l2_subdev *sd,
		struct v4l2_subdev_pad_config *cfg,
		struct v4l2_subdev_format *format)
{
	int ret;

	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
	{
		ret = camera_common_try_fmt(sd, &format->format);
		pr_err("%s: camera common try fmt ret is %d\n",__func__,ret);
	}
	else
	{
		ret = camera_common_s_fmt(sd, &format->format);
		pr_err("%s: camera common s fmt ret is %d\n",__func__,ret);
	}

	return ret;
}

static struct v4l2_subdev_pad_ops ar0135_subdev_pad_ops = {
	.set_fmt = ar0135_set_fmt,
	.get_fmt = ar0135_get_fmt,
	.enum_mbus_code = camera_common_enum_mbus_code,
	.enum_frame_size	= camera_common_enum_framesizes,
	.enum_frame_interval	= camera_common_enum_frameintervals,
};

static struct v4l2_subdev_ops ar0135_subdev_ops = {
	.core	= &ar0135_subdev_core_ops,
	.video	= &ar0135_subdev_video_ops,
	.pad	= &ar0135_subdev_pad_ops,
};

static struct of_device_id ar0135_of_match[] = {
	{ .compatible = "nvidia,ar0135", },
	{ },
};


static struct camera_common_sensor_ops_new ar0135_common_ops = {
	.power_on = ar0135_power_on,
	.power_off = ar0135_power_off,
	.write_reg = ar0135_write_reg,
	.read_reg = ar0135_read_reg,
};


static u16 ar0135_to_real_gain(u32 rep, int shift)
{
	u16 gain;
	int gain_int;
	int gain_dec;
	int min_int = (1 << shift);

	if (rep < AR0135_MIN_GAIN)
		rep = AR0135_MIN_GAIN;
	else if (rep > AR0135_MAX_GAIN)
		rep = AR0135_MAX_GAIN;

	gain_int = (int)(rep >> shift);
	gain_dec = (int)(rep & ~(0xffff << shift));

	/* derived from formulat gain = (x * 16 + 0.5) */
	gain = ((gain_int * min_int + gain_dec) * 32 + min_int) / (2 * min_int);

	return gain;
}

static int ar0135_set_gain(struct ar0135 *priv, s32 val)
{
	ar0135_reg reg_list[1];
	int err;
	u16 gain;
	int i;

	// if (!priv->group_hold_prev)
	// 	ar0135_set_group_hold(priv);

	/* translate value */
	gain = ar0135_to_real_gain((u32)val, AR0135_GAIN_SHIFT);

	ar0135_get_gain_regs(reg_list, gain);
	dev_dbg(&priv->i2c_client->dev,
		 "%s: gain %04x val: %04x\n", __func__, val, gain);

	for (i = 0; i < 1; i++) {
		err = ar0135_write_reg(priv->s_data, reg_list[i].addr,
			 reg_list[i].val);
		if (err)
			goto fail;
	}

	return 0;

fail:
	dev_dbg(&priv->i2c_client->dev,
		 "%s: GAIN control error\n", __func__);
	return err;
}

static void ar0135_update_ctrl_range(struct ar0135 *priv, s32 frame_length)
{
	struct v4l2_ctrl *ctrl = NULL;
	int ctrl_ids[2] = {V4L2_CID_COARSE_TIME,
			V4L2_CID_COARSE_TIME_SHORT};
	s32 max, min, def;
	int i, j;

	for (i = 0; i < ARRAY_SIZE(ctrl_ids); i++) {
		for (j = 0; j < priv->numctrls; j++) {
			if (priv->ctrls[j]->id == ctrl_ids[i]) {
				ctrl = priv->ctrls[j];
				break;
			}
		}

		if (j == priv->numctrls) {
			dev_err(&priv->i2c_client->dev,
				"could not find ctrl %x\n",
				ctrl_ids[i]);
			continue;
		}

		max = frame_length - AR0135_MAX_COARSE_DIFF;
		/* clamp the value in case above is negative */
		max = clamp_val(max, AR0135_MIN_EXPOSURE_COARSE,
			AR0135_MAX_EXPOSURE_COARSE);
		min = AR0135_MIN_EXPOSURE_COARSE;
		def = clamp_val(AR0135_DEFAULT_EXPOSURE_COARSE, min, max);
		if (__v4l2_ctrl_modify_range(ctrl, min, max, 1, def))
			dev_err(&priv->i2c_client->dev,
				"ctrl %x: range update failed\n",
				ctrl_ids[i]);
	}

}

static int ar0135_set_frame_length(struct ar0135 *priv, s32 val)
{
	ar0135_reg reg_list[1];
	int err;
	u32 frame_length;
	int i;

	// if (!priv->group_hold_prev)
	// 	ar0135_set_group_hold(priv);

	frame_length = (u32)val;

	ar0135_get_frame_length_regs(reg_list, frame_length);
	dev_dbg(&priv->i2c_client->dev,
		 "%s: val: %d\n", __func__, frame_length);

	for (i = 0; i < 1; i++) {
		err = ar0135_write_reg(priv->s_data, reg_list[i].addr,
			 reg_list[i].val);
		if (err)
			goto fail;
	}

	priv->frame_length = frame_length;

	ar0135_update_ctrl_range(priv, val);
	return 0;

fail:
	dev_dbg(&priv->i2c_client->dev,
		 "%s: FRAME_LENGTH control error\n", __func__);
	return err;
}

static int ar0135_set_frame_length_cb(struct ar0135 *priv, s32 val)
{
	ar0135_reg reg_list[1];
	int err;
	u32 frame_length;
	int i;

	// if (!priv->group_hold_prev)
	// 	ar0135_set_group_hold(priv);

	frame_length = (u32)val;

	ar0135_get_frame_length_cb_regs(reg_list, frame_length);
	dev_dbg(&priv->i2c_client->dev,
		 "%s: val: %d\n", __func__, frame_length);

	for (i = 0; i < 1; i++) {
		err = ar0135_write_reg(priv->s_data, reg_list[i].addr,
			 reg_list[i].val);
		if (err)
			goto fail;
	}

	priv->frame_length = frame_length;

	ar0135_update_ctrl_range(priv, val);
	return 0;

fail:
	dev_dbg(&priv->i2c_client->dev,
		 "%s: FRAME_LENGTH control error\n", __func__);
	return err;
}

static int ar0135_set_coarse_time(struct ar0135 *priv, s32 val)
{
	ar0135_reg reg_list[1];
	int err;
	u32 coarse_time;
	int i;

	// if (!priv->group_hold_prev)
	// 	ar0135_set_group_hold(priv);

	coarse_time = (u32)val;

	ar0135_get_coarse_time_regs(reg_list, coarse_time);
	dev_dbg(&priv->i2c_client->dev,
		 "%s: val: %d\n", __func__, coarse_time);

	for (i = 0; i < 1; i++) {
		err = ar0135_write_reg(priv->s_data, reg_list[i].addr,
			 reg_list[i].val);
		if (err)
			goto fail;
	}

	return 0;

fail:
	dev_dbg(&priv->i2c_client->dev,
		 "%s: COARSE_TIME control error\n", __func__);
	return err;
}

static int ar0135_set_coarse_time_short(struct ar0135 *priv, s32 val)
{
	ar0135_reg reg_list[1];
	int err;
	struct v4l2_control hdr_control;
	int hdr_en;
	u32 coarse_time_short;
	int i;

	// if (!priv->group_hold_prev)
	// 	ar0135_set_group_hold(priv);

	/* check hdr enable ctrl */
	hdr_control.id = V4L2_CID_HDR_EN;

	err = camera_common_g_ctrl(priv->s_data, &hdr_control);
	if (err < 0) {
		dev_err(&priv->i2c_client->dev,
			"could not find device ctrl.\n");
		return err;
	}

	hdr_en = switch_ctrl_qmenu[hdr_control.value];
	if (hdr_en == SWITCH_OFF)
	{
		dev_err(&priv->i2c_client->dev,
			"%s: hdr_en is switch off\n",__func__);
		//return 0;
	}
		

	coarse_time_short = (u32)val;

	ar0135_get_coarse_time_short_regs(reg_list, coarse_time_short);
	dev_dbg(&priv->i2c_client->dev,
		 "%s: val: %d\n", __func__, coarse_time_short);

	for (i = 0; i < 1; i++) {
		err = ar0135_write_reg(priv->s_data, reg_list[i].addr,
			 reg_list[i].val);
		if (err)
			goto fail;
	}

	return 0;

fail:
	dev_dbg(&priv->i2c_client->dev,
		 "%s: COARSE_TIME_SHORT control error\n", __func__);
	return err;
}


static int ar0135_deserializer_device_release(struct ar0135 *priv)
{
	
	if (priv->de_data.i2c_client != NULL) {
		i2c_unregister_device(priv->de_data.i2c_client);
		priv->de_data.i2c_client = NULL;
	}

	return 0;
}

static int ar0135_deserializer_device_init(struct ar0135 *priv)
{
	char *dev_name = "deserializer_ar0135";
	static struct regmap_config deserializer_regmap_config = {
		.reg_bits = 8,
		.val_bits = 8,
	};
	int err;
		
    priv->de_data.adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
	memset(&priv->de_data.brd, 0, sizeof(priv->de_data.brd));
	strncpy(priv->de_data.brd.type, dev_name,sizeof(priv->de_data.brd.type));
	priv->de_data.brd.addr = 0x3d;
	priv->de_data.i2c_client = i2c_new_device(priv->de_data.adap, &priv->de_data.brd);
	priv->de_data.regmap = devm_regmap_init_i2c(
			priv->de_data.i2c_client, &deserializer_regmap_config);
	if (IS_ERR(priv->de_data.regmap)) {
			err = PTR_ERR(priv->de_data.regmap);
			dev_err(&priv->de_data.i2c_client->dev,"%s regmap error is %d\n",__func__,err);
			ar0135_deserializer_device_release(priv);
			return err;
	}
    usleep_range(10000,11000);
	err=regmap_write(priv->de_data.regmap, 0x32, 0x12);
    if (err)
		pr_err("%s:i2c write failed, 32 = 12\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x1f, 0x02);
    if (err)
		pr_err("%s:i2c write failed, 1f = 02\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x33, 0x23);
    if (err)
		pr_err("%s:i2c write failed, 33 = 21\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xf0);
    if (err)
		pr_err("%s:i2c write failed, 20 = f0\n",
			__func__);
    usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xf2);
    if (err)
		pr_err("%s:i2c write failed, 20 = f2\n",
			__func__);
    usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xd2);
    if (err)
		pr_err("%s:i2c write failed, 20 = d2\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x4c, 0x12);
    if (err)
		pr_err("%s:i2c write failed, 4c = 12\n",
			__func__);
    err=regmap_write(priv->de_data.regmap, 0x58, 0x58);
    if (err)
		pr_err("%s:i2c write failed, 58 = 58\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x5c, 0x18);
    if (err)
		pr_err("%s:i2c write failed, 5c = 18\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x5d, 0x20);
    if (err)
		pr_err("%s:i2c write failed, 5d = 20\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x65, 0x20);
    if (err)
		pr_err("%s:i2c write failed, 65 = 20\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x71, 0x2c);
    if (err)
		pr_err("%s:i2c write failed, 71 = 2c\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x6d, 0x7e);
    if (err)
		pr_err("%s:i2c write failed, 6d = 7e\n",
			__func__);
	
	return err;
}

static int ar0135_serializer_device_release(struct ar0135 *priv)
{
	
	if (priv->se_data.i2c_client != NULL) {
		i2c_unregister_device(priv->se_data.i2c_client);
		priv->se_data.i2c_client = NULL;
	}

	return 0;
}

static int ar0135_serializer_device_init(struct ar0135 *priv)
{
	char *dev_name = "serializer_ar0135";
	static struct regmap_config serializer_regmap_config = {
		.reg_bits = 8,
		.val_bits = 8,
	};
	int err;
		
    priv->se_data.adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
	memset(&priv->se_data.brd, 0, sizeof(priv->se_data.brd));
	strncpy(priv->se_data.brd.type, dev_name,sizeof(priv->se_data.brd.type));
	priv->se_data.brd.addr = 0x0c;
	priv->se_data.i2c_client = i2c_new_device(priv->se_data.adap, &priv->se_data.brd);
	priv->se_data.regmap = devm_regmap_init_i2c(
			priv->se_data.i2c_client, &serializer_regmap_config);
	if (IS_ERR(priv->se_data.regmap)) {
			err = PTR_ERR(priv->se_data.regmap);
			dev_err(&priv->se_data.i2c_client->dev,"%s regmap error is %d\n",__func__,err);
			ar0135_serializer_device_release(priv);
			return err;
	}
    usleep_range(10000,11000);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x91);
    if (err)
		pr_err("%s:i2c write failed, 0d = 91\n",
			__func__);
	usleep_range(1000000,1000100);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x11);
    if (err)
		pr_err("%s:i2c write failed, 0d = 11\n",
			__func__);
    usleep_range(500000,500010);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x91);
    if (err)
		pr_err("%s:i2c write failed, 0d = 91\n",
			__func__);
	usleep_range(100000,100100);
	
	return err;
}

static int ar0135_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct ar0135 *priv =
		container_of(ctrl->handler, struct ar0135, ctrl_handler);
	int err = 0;

	if (priv->power.state == SWITCH_OFF)
	{
		pr_err("%s: priv's power state is switch off\n", __func__);
		return 0;
	}
		

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		err = ar0135_set_gain(priv, ctrl->val);
		break;
	case V4L2_CID_FRAME_LENGTH:
		err = ar0135_set_frame_length(priv, ctrl->val);
		break;
	case V4L2_CID_COARSE_TIME:
		err = ar0135_set_coarse_time(priv, ctrl->val);
		break;
	case V4L2_CID_COARSE_TIME_SHORT:
		err = ar0135_set_coarse_time_short(priv, ctrl->val);
		break;
	case V4L2_CID_FRAME_LENGTH_CB:
		err = ar0135_set_frame_length_cb(priv, ctrl->val);
		break;
	case V4L2_CID_HDR_EN:
		break;
	default:
		pr_err("%s: unknown ctrl id.\n", __func__);
		return -EINVAL;
	}

	return err;
}

static int ar0135_ctrls_init(struct ar0135 *priv, bool eeprom_ctrl)
{
	struct i2c_client *client = priv->i2c_client;
	//struct camera_common_data *common_data = priv->s_data;
	struct v4l2_ctrl *ctrl;
	int numctrls;
	int err;
	int i;

	dev_dbg(&client->dev, "%s++\n", __func__);

	numctrls = ARRAY_SIZE(ctrl_config_list);
	v4l2_ctrl_handler_init(&priv->ctrl_handler, numctrls);

	dev_dbg(&client->dev, "%s: numctrls is %d\n", __func__,numctrls);

	for (i = 0; i < numctrls; i++) {
		/* Skip control 'V4L2_CID_EEPROM_DATA' if eeprom inint err */
		// if (ctrl_config_list[i].id == V4L2_CID_EEPROM_DATA) {
		// 	// if (!eeprom_ctrl) {
		// 	// 	common_data->numctrls -= 1;
		// 	// 	continue;
		// 	// }
		// 	if (eeprom_ctrl) {
		// 		common_data->numctrls -= 1;
		// 		continue;
		// 	}
		// }

		ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler,
			&ctrl_config_list[i], NULL);
		if (ctrl == NULL) {
			dev_err(&client->dev, "Failed to init %s ctrl\n",
				ctrl_config_list[i].name);
			continue;
		}

		if (ctrl_config_list[i].type == V4L2_CTRL_TYPE_STRING &&
			ctrl_config_list[i].flags & V4L2_CTRL_FLAG_READ_ONLY) {
			ctrl->p_new.p_char = devm_kzalloc(&client->dev,
				ctrl_config_list[i].max + 1, GFP_KERNEL);
			if (!ctrl->p_new.p_char)
			{
				dev_dbg(&client->dev, "%s: ctrl p_new.p_char is 0\n", __func__);
				return -ENOMEM;
			}
				
		}
		priv->ctrls[i] = ctrl;
	}

	priv->numctrls = numctrls;
	priv->subdev->ctrl_handler = &priv->ctrl_handler;
	if (priv->ctrl_handler.error) {
		dev_err(&client->dev, "Error %d adding controls\n",
			priv->ctrl_handler.error);
		err = priv->ctrl_handler.error;
		goto error;
	}

	dev_dbg(&client->dev, "%s: v4l2 ctrl setup start\n", __func__);

	err = v4l2_ctrl_handler_setup(&priv->ctrl_handler);
	if (err) {
		dev_err(&client->dev,
			"Error %d setting default controls\n", err);
		goto error;
	}

	dev_dbg(&client->dev, "%s: v4l2 ctrl setup finish\n", __func__);
    
	err = camera_common_s_power(priv->subdev, true);
	if (err)
	{
		dev_err(&client->dev,
			"%s: Error %d camera s power\n", __func__,err);
		return -ENODEV;
	}

	return 0;

error:
	v4l2_ctrl_handler_free(&priv->ctrl_handler);
	return err;
}

MODULE_DEVICE_TABLE(of, ar0135_of_match);

static struct camera_common_pdata *ar0135_parse_dt(struct i2c_client *client)
{
	struct device_node *node = client->dev.of_node;
	struct camera_common_pdata *board_priv_pdata;
	const struct of_device_id *match;
	//int gpio;
	int err;
	struct camera_common_pdata *ret = NULL;

	if (!node)
	{
		dev_err(&client->dev, "%s there has no node\n",__func__);
		return NULL;
	}	

	match = of_match_device(ar0135_of_match, &client->dev);
	if (!match) {
		dev_err(&client->dev, "%s:Failed to find matching dt id\n",__func__);
		return NULL;
	}

	board_priv_pdata = devm_kzalloc(&client->dev,
			   sizeof(*board_priv_pdata), GFP_KERNEL);
	if (!board_priv_pdata)
	{
		dev_err(&client->dev, "%s: Failed to kzalloc borad_priv_data\n",__func__);
		return NULL;
	}	

	err = camera_common_parse_clocks(client, board_priv_pdata);
	if (err) {
		dev_err(&client->dev, "%s:Failed to find clocks\n",__func__);
		goto error;
	}

	err = of_property_read_string(node, "avdd-reg",
			&board_priv_pdata->regulators.avdd);
	if (err) {
		dev_err(&client->dev, "%s:avdd-reg not in DT\n",__func__);
		goto error;
	}
	err = of_property_read_string(node, "iovdd-reg",
			&board_priv_pdata->regulators.iovdd);
	if (err) {
		dev_err(&client->dev, "%s:iovdd-reg not in DT\n",__func__);
		goto error;
	}

	// board_priv_pdata->has_eeprom =
	// 	of_property_read_bool(node, "has-eeprom");
	// board_priv_pdata->v_flip= of_property_read_bool(node, "vertical-flip");
	// board_priv_pdata->h_mirror = of_property_read_bool(node,
	// 						 "horizontal-mirror");
	return board_priv_pdata;

error:
	devm_kfree(&client->dev, board_priv_pdata);
	return ret;
}

static int ar0135_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);

	dev_dbg(&client->dev, "%s:\n", __func__);
	return 0;
}

static const struct v4l2_subdev_internal_ops ar0135_subdev_internal_ops = {
	.open = ar0135_open,
};

static const struct media_entity_operations ar0135_media_ops = {
	.link_validate = v4l2_subdev_link_validate,
};

static int ar0135_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct camera_common_data *common_data;
	struct device_node *node = client->dev.of_node;
	struct ar0135 *priv;
	char debugfs_name[10];
	int err;

	pr_info("[AR0135]: probing v4l2 sensor.\n");

	if (!IS_ENABLED(CONFIG_OF) || !node)
		return -EINVAL;

	common_data = devm_kzalloc(&client->dev,
			    sizeof(struct camera_common_data), GFP_KERNEL);
	if (!common_data)
		return -ENOMEM;

	priv = devm_kzalloc(&client->dev,
			    sizeof(struct ar0135) + sizeof(struct v4l2_ctrl *) *
			    ARRAY_SIZE(ctrl_config_list),
			    GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	dev_dbg(&client->dev, "client addr is %d\n", client->addr);

	priv->regmap = devm_regmap_init_i2c(client, &ar0135_regmap_config);
	if (IS_ERR(priv->regmap)) {
		dev_err(&client->dev,
			"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
		return -ENODEV;
	}

	priv->pdata = ar0135_parse_dt(client);
	if (PTR_ERR(priv->pdata) == -EPROBE_DEFER)
		return -EPROBE_DEFER;
	if (!priv->pdata) {
		dev_err(&client->dev, "unable to get platform data\n");
		return -EFAULT;
	}

	//common_data->ops		= &ar0135_common_ops;
	common_data->ops_new		= &ar0135_common_ops;
	common_data->ctrl_handler	= &priv->ctrl_handler;
	common_data->i2c_client		= client;
	common_data->frmfmt		= ar0135_frmfmt;
	common_data->colorfmt		= camera_common_find_datafmt(
					  AR0135_DEFAULT_DATAFMT);
	common_data->power		= &priv->power;
	common_data->ctrls		= priv->ctrls;
	common_data->priv		= (void *)priv;
	common_data->numctrls		= ARRAY_SIZE(ctrl_config_list);
	common_data->numfmts		= ARRAY_SIZE(ar0135_frmfmt);
	common_data->def_mode		= AR0135_DEFAULT_MODE;
	common_data->def_width		= AR0135_DEFAULT_WIDTH;
	common_data->def_height		= AR0135_DEFAULT_HEIGHT;
	common_data->fmt_width		= common_data->def_width;
	common_data->fmt_height		= common_data->def_height;
	common_data->def_clk_freq	= AR0135_DEFAULT_CLK_FREQ;

	priv->i2c_client = client;
	priv->s_data			= common_data;
	priv->subdev			= &common_data->subdev;
	priv->subdev->dev		= &client->dev;
	priv->s_data->dev		= &client->dev;

	err = ar0135_power_get(priv);
	// if (err)
	// 	return err;
	dev_dbg(&client->dev, "ar0135_power_get err is %d\n", err);

	err = camera_common_parse_ports(client, common_data);
	if (err) {
		dev_err(&client->dev, "Failed to find port info\n");
		//return err;
	}
	sprintf(debugfs_name, "ar0135_%c", common_data->csi_port + 'a');
	dev_dbg(&client->dev, "%s: name %s\n", __func__, debugfs_name);
	camera_common_create_debugfs(common_data, debugfs_name);

	err = ar0135_deserializer_device_init(priv);

	dev_dbg(&client->dev, "ar0135_deserializer_device_init err is %d\n", err);

	usleep_range(100000,100100);

	err = ar0135_serializer_device_init(priv);

	dev_dbg(&client->dev, "ar0135_serializer_device_init err is %d\n", err);

	usleep_range(100000,100100);

	v4l2_i2c_subdev_init(priv->subdev, client, &ar0135_subdev_ops);

	err = ar0135_ctrls_init(priv, !err);
	// if (err)
	// 	return err;
	dev_dbg(&client->dev, "ar0135_ctrls_init err is %d\n", err);

	usleep_range(100000,100100);
	regmap_write(priv->regmap, 0x3028, 0x0010);
	regmap_write(priv->regmap, 0x302A, 0x0008);
	regmap_write(priv->regmap, 0x302C, 0x0001);
	regmap_write(priv->regmap, 0x302E, 0x0008);
	regmap_write(priv->regmap, 0x3030, 0x00C6);
	regmap_write(priv->regmap, 0x3032, 0x0000);
	regmap_write(priv->regmap, 0x30B0, 0x0080);

	regmap_write(priv->regmap, 0x301A, 0x00D8);
	regmap_write(priv->regmap, 0x301A, 0x10DC);
	// regmap_write(priv->regmap, 0x3002, 0x0074);
	// regmap_write(priv->regmap, 0x3004, 0x0000);
	// regmap_write(priv->regmap, 0x3006, 0x034B);
	// regmap_write(priv->regmap, 0x3008, 0x04FF);
	// regmap_write(priv->regmap, 0x300A, 0x02F2);
	// regmap_write(priv->regmap, 0x300C, 0x0672);
	// regmap_write(priv->regmap, 0x3012, 0x02EB);
	// regmap_write(priv->regmap, 0x3014, 0x0009);
	// regmap_write(priv->regmap, 0x30A6, 0x0001);
    // regmap_write(priv->regmap, 0x308C, 0x0000);
	// regmap_write(priv->regmap, 0x308A, 0x0000);
	// regmap_write(priv->regmap, 0x3090, 0x03BF);
	// regmap_write(priv->regmap, 0x308E, 0x04FF);
	// regmap_write(priv->regmap, 0x30AA, 0x03E5);
	// regmap_write(priv->regmap, 0x3016, 0x01C2);
	// regmap_write(priv->regmap, 0x3018, 0x0009);
	// regmap_write(priv->regmap, 0x30A8, 0x0001);
	// regmap_write(priv->regmap, 0x3040, 0x0000);
	// regmap_write(priv->regmap, 0x3064, 0x1982);
	// err = regmap_write(priv->regmap, 0x31C6, 0x8008);
	// dev_err(&client->dev, "ar0135_regmap_write err is %d\n",err);
	 usleep_range(10000,10100);

	priv->subdev->internal_ops = &ar0135_subdev_internal_ops;
	priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
			       V4L2_SUBDEV_FL_HAS_EVENTS;

#if defined(CONFIG_MEDIA_CONTROLLER)
	priv->pad.flags = MEDIA_PAD_FL_SOURCE;
	priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
	priv->subdev->entity.ops = &ar0135_media_ops;
	err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
	if (err < 0) {
		dev_err(&client->dev, "unable to init media entity\n");
		//return err;
	}
	else
	{
		dev_dbg(&client->dev, "%s:media_entity_init success %d\n",__func__,err); //zhou
	}
#endif

	err = v4l2_async_register_subdev(priv->subdev);
	//if (err)
		//return err;
	dev_dbg(&client->dev, "v4l2_async_register_subdev err is %d\n", err);

	if(client->dev.driver_data == NULL)
		dev_err(&client->dev,"ar0135 client dev's drive data is null\n");

	dev_dbg(&client->dev, "Detected AR0135 sensor\n");


	return 0;
}

static int
ar0135_remove(struct i2c_client *client)
{
	struct camera_common_data *s_data = to_camera_common_data(client);
	struct ar0135 *priv = (struct ar0135 *)s_data->priv;

	v4l2_async_unregister_subdev(priv->subdev);
#if defined(CONFIG_MEDIA_CONTROLLER)
	media_entity_cleanup(&priv->subdev->entity);
#endif

	v4l2_ctrl_handler_free(&priv->ctrl_handler);
	ar0135_power_put(priv);
	camera_common_remove_debugfs(s_data);

	return 0;
}

static const struct i2c_device_id ar0135_id[] = {
	{ "ar0135", 0 },
	{ }
};

MODULE_DEVICE_TABLE(i2c, ar0135_id);

static struct i2c_driver ar0135_i2c_driver = {
	.driver = {
		.name = "ar0135",
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(ar0135_of_match),
	},
	.probe = ar0135_probe,
	.remove = ar0135_remove,
	.id_table = ar0135_id,
};

module_i2c_driver(ar0135_i2c_driver);

MODULE_DESCRIPTION("SoC Camera driver for Sony AR0135");
MODULE_AUTHOR("David Wang <davidw@nvidia.com>");
MODULE_LICENSE("GPL v2");

And dmesg is:

nvidia@tegra-ubuntu:~$ ls /dev/v*
/dev/v4l-subdev0  /dev/vcs1  /dev/vcs3  /dev/vcs5  /dev/vcs7  /dev/vcsa1  /dev/vcsa3  /dev/vcsa5  /dev/vcsa7
/dev/vcs          /dev/vcs2  /dev/vcs4  /dev/vcs6  /dev/vcsa  /dev/vcsa2  /dev/vcsa4  /dev/vcsa6
nvidia@tegra-ubuntu:~$ dmesg | grep ar0135
[    2.818624] ar0135 2-0010: client addr is 16
[    2.818648] ar0135 2-0010: mclk in DT extperiph1
[    2.818652] ar0135 2-0010: parent-clk (null)
[    2.819003] ar0135 2-0010: camera_common_regulator_get: vana
[    2.819068] ar0135 2-0010: camera_common_regulator_get: vif
[    2.819071] ar0135 2-0010: ar0135_power_get:success to get avdd and iovdd
[    2.819074] ar0135 2-0010: ar0135_power_get err is 0
[    2.819081] ar0135 2-0010: camera_common_parse_ports: csi port 2 num of lanes 2
[    2.819084] ar0135 2-0010: ar0135_probe: name ar0135_c
[    2.819086] ar0135 2-0010: camera_common_create_debugfs ar0135_c
[    3.433418] ar0135 2-0010: ar0135_deserializer_device_init err is 0
[    5.154182] ar0135 2-0010: ar0135_serializer_device_init err is 0
[    5.254300] ar0135 2-0010: v4l2_i2c_subdev_init: ar0135 config i2c test ar0135 2-0010
[    5.254303] ar0135 2-0010: ar0135_ctrls_init++
[    5.254306] ar0135 2-0010: ar0135_ctrls_init: numctrls is 6
[    5.254322] ar0135 2-0010: ar0135_ctrls_init: v4l2 ctrl setup start
[    5.254325] ar0135_s_ctrl: priv's power state is switch off
[    5.254326] ar0135_s_ctrl: priv's power state is switch off
[    5.254327] ar0135_s_ctrl: priv's power state is switch off
[    5.254328] ar0135_s_ctrl: priv's power state is switch off
[    5.254329] ar0135_s_ctrl: priv's power state is switch off
[    5.254330] ar0135_s_ctrl: priv's power state is switch off
[    5.254333] ar0135 2-0010: ar0135_ctrls_init: v4l2 ctrl setup finish
[    5.254337] ar0135 2-0010: camera_common_mclk_enable: enable MCLK with 25000000 Hz
[    5.254611] ar0135 2-0010: camera_common_mclk_enable: clk_set_rate success
[    5.254701] ar0135 2-0010: camera_common_mclk_enable: clk_prepare_enable err is 0
[    5.254710] ar0135 2-0010: camera_common_dpd_disable: csi 2
[    5.254712] ar0135 2-0010: ar0135_power_on: power on
[    5.254715] ar0135 2-0010: ar0135_ctrls_init err is 0
[    5.373180] ar0135 2-0010: ar0135_probe:media_entity_init success 0
[    5.373183] v4l2_async_register_subdev: ar0135 register subdev test
[    5.373186] ar0135 2-0010: v4l2_async_register_subdev err is 0
[    5.373188] ar0135 2-0010: Detected AR0135 sensor
[    5.570238] nvcsi 150c0000.nvcsi: csi_parse_dt:ar0135 node name is nvcsi
[    5.570266] nvcsi 150c0000.nvcsi: csi_parse_dt:ar0135 csi test
[    5.570276] v4l2_async_register_subdev: ar0135 register subdev test
[    5.570282] nvcsi 150c0000.nvcsi: tegra_csi_media_controller_init:ar0135 success to init csi property,clks
[    5.676739] tegra-vi4 15700000.vi: vi_parse_dt:ar0135 success to find num of channels is 1
[    5.677697] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 Init channel success
[    5.677810] tegra_channel_init_subdevices:ar0135 first add video name vi-output, 150c0000.nvcsi-0
[    5.677889] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 tegra_vi_graph_init success
[    5.677894] tegra-vi4 15700000.vi: tegra_vi_media_controller_init:ar0135 tegra_vi_channels_register success

Please Help me! I have no idea what problem is!!
Thanks a lot!

Hi JerryChang,

There are any problems with my driver probe by the dmesg?
I’m sort of a loss now!

Please Help me! Thanks a lot!

Best regards!

Is your system seeing your deserializer, serializer, and sensor?

sudo i2cdetect -y -r $I2C_BUS_ADDRESS

Here’s example output. In this case I have an i2c mux on 0x70, a deserializer on 0x32, a serializer on 0x30, and a sensor on 0x40. They are displayed as UU because they are claimed by drivers.

root@jetson-0422818069360:~# i2cdetect -y -r 30
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: UU -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: UU -- -- -- -- -- -- --

I’ve worked with the ub960 and ub953 which should be extremely similar to the ub964

Hi D3_growe,
Thank you very much for your reply!
Yes,I can see the deserializer, serializer, and sensor by i2cdetect! But only sensor is displayed as UU,the deserializer and serializer are displayed as real address number,like above 50 51! Because they are not claimed by driver,I don’t write deserializer and serializer driver and device tree alone,they are initialized in the sensor driver probe functiom as i2c device like eeprom on board! And I can control sensor by regmap function.You can see my sensor driver ar0135.c above.
Are the deserializer and serializer must writed driver and device tree alone??
Thanks a lot!
Best regards!

You could use i2cget and i2cset programs in user space but I wouldn’t recommend that as a long term solution. I would use those to prove to yourself that you can read and write to your i2c devices.

You almost certainly will need to change some register settings in your deserializer and serializer to get it working properly (but if the power-on defaults are what you need for your system then you might be OK but that’s very unlikely).

To read/write the deserializer and serializer you could create an i2c dummy client in your driver. Take a look at i2c_new_dummy. This function takes an i2c adapter and an address. You will then have an i2c client that you can use to get a regmap instance so you can read and write the registers in your deserializer and serializer.

Hi D3_growe,
Thank you very much for your reply!
Why do you doubt about my settings with deserializer and serializer? FYI,can you figure out the specific resister I need to change? about MIPI-CSI2 register? Because I can control my sensor and serializer through the deserializer,and the sensor initialization is correct! Here is my deserializer and serializer initialization function:

static int ar0135_deserializer_device_init(struct ar0135 *priv)
{
	char *dev_name = "deserializer_ar0135";
	static struct regmap_config deserializer_regmap_config = {
		.reg_bits = 8,
		.val_bits = 8,
	};
	int err;
		
    priv->de_data.adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
	memset(&priv->de_data.brd, 0, sizeof(priv->de_data.brd));
	strncpy(priv->de_data.brd.type, dev_name,sizeof(priv->de_data.brd.type));
	priv->de_data.brd.addr = 0x3d;
	priv->de_data.i2c_client = i2c_new_device(priv->de_data.adap, &priv->de_data.brd);
	priv->de_data.regmap = devm_regmap_init_i2c(
			priv->de_data.i2c_client, &deserializer_regmap_config);
	if (IS_ERR(priv->de_data.regmap)) {
			err = PTR_ERR(priv->de_data.regmap);
			dev_err(&priv->de_data.i2c_client->dev,"%s regmap error is %d\n",__func__,err);
			ar0135_deserializer_device_release(priv);
			return err;
	}
    usleep_range(10000,11000);
	err=regmap_write(priv->de_data.regmap, 0x32, 0x12);
    if (err)
		pr_err("%s:i2c write failed, 32 = 12\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x1f, 0x02);
    if (err)
		pr_err("%s:i2c write failed, 1f = 02\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x33, 0x23);
    if (err)
		pr_err("%s:i2c write failed, 33 = 21\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xf0);
    if (err)
		pr_err("%s:i2c write failed, 20 = f0\n",
			__func__);
    usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xf2);
    if (err)
		pr_err("%s:i2c write failed, 20 = f2\n",
			__func__);
    usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x20, 0xd2);
    if (err)
		pr_err("%s:i2c write failed, 20 = d2\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x4c, 0x12);
    if (err)
		pr_err("%s:i2c write failed, 4c = 12\n",
			__func__);
    err=regmap_write(priv->de_data.regmap, 0x58, 0x58);
    if (err)
		pr_err("%s:i2c write failed, 58 = 58\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x5c, 0x18);
    if (err)
		pr_err("%s:i2c write failed, 5c = 18\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x5d, 0x20);
    if (err)
		pr_err("%s:i2c write failed, 5d = 20\n",
			__func__);
	err=regmap_write(priv->de_data.regmap, 0x65, 0x20);
    if (err)
		pr_err("%s:i2c write failed, 65 = 20\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x71, 0x2c);
    if (err)
		pr_err("%s:i2c write failed, 71 = 2c\n",
			__func__);
	usleep_range(100000,100100);
	err=regmap_write(priv->de_data.regmap, 0x6d, 0x7e);
    if (err)
		pr_err("%s:i2c write failed, 6d = 7e\n",
			__func__);
	
	return err;
}


static int ar0135_serializer_device_init(struct ar0135 *priv)
{
	char *dev_name = "serializer_ar0135";
	static struct regmap_config serializer_regmap_config = {
		.reg_bits = 8,
		.val_bits = 8,
	};
	int err;
		
    priv->se_data.adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
	memset(&priv->se_data.brd, 0, sizeof(priv->se_data.brd));
	strncpy(priv->se_data.brd.type, dev_name,sizeof(priv->se_data.brd.type));
	priv->se_data.brd.addr = 0x0c;
	priv->se_data.i2c_client = i2c_new_device(priv->se_data.adap, &priv->se_data.brd);
	priv->se_data.regmap = devm_regmap_init_i2c(
			priv->se_data.i2c_client, &serializer_regmap_config);
	if (IS_ERR(priv->se_data.regmap)) {
			err = PTR_ERR(priv->se_data.regmap);
			dev_err(&priv->se_data.i2c_client->dev,"%s regmap error is %d\n",__func__,err);
			ar0135_serializer_device_release(priv);
			return err;
	}
    usleep_range(10000,11000);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x91);
    if (err)
		pr_err("%s:i2c write failed, 0d = 91\n",
			__func__);
	usleep_range(1000000,1000100);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x11);
    if (err)
		pr_err("%s:i2c write failed, 0d = 11\n",
			__func__);
    usleep_range(500000,500010);
	err=regmap_write(priv->se_data.regmap, 0x0d, 0x91);
    if (err)
		pr_err("%s:i2c write failed, 0d = 91\n",
			__func__);
	usleep_range(100000,100100);
	
	return err;
}

And they are called in AR0135 probe function:

static int ar0135_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct camera_common_data *common_data;
	struct device_node *node = client->dev.of_node;
	struct ar0135 *priv;
	char debugfs_name[10];
	int err;

	pr_info("[AR0135]: probing v4l2 sensor.\n");

	if (!IS_ENABLED(CONFIG_OF) || !node)
		return -EINVAL;

	common_data = devm_kzalloc(&client->dev,
			    sizeof(struct camera_common_data), GFP_KERNEL);
	if (!common_data)
		return -ENOMEM;

	priv = devm_kzalloc(&client->dev,
			    sizeof(struct ar0135) + sizeof(struct v4l2_ctrl *) *
			    ARRAY_SIZE(ctrl_config_list),
			    GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	dev_dbg(&client->dev, "client addr is %d\n", client->addr);

	priv->regmap = devm_regmap_init_i2c(client, &ar0135_regmap_config);
	if (IS_ERR(priv->regmap)) {
		dev_err(&client->dev,
			"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
		return -ENODEV;
	}

	priv->pdata = ar0135_parse_dt(client);
	if (PTR_ERR(priv->pdata) == -EPROBE_DEFER)
		return -EPROBE_DEFER;
	if (!priv->pdata) {
		dev_err(&client->dev, "unable to get platform data\n");
		return -EFAULT;
	}

	//common_data->ops		= &ar0135_common_ops;
	common_data->ops_new		= &ar0135_common_ops;
	common_data->ctrl_handler	= &priv->ctrl_handler;
	common_data->i2c_client		= client;
	common_data->frmfmt		= ar0135_frmfmt;
	common_data->colorfmt		= camera_common_find_datafmt(
					  AR0135_DEFAULT_DATAFMT);
	common_data->power		= &priv->power;
	common_data->ctrls		= priv->ctrls;
	common_data->priv		= (void *)priv;
	common_data->numctrls		= ARRAY_SIZE(ctrl_config_list);
	common_data->numfmts		= ARRAY_SIZE(ar0135_frmfmt);
	common_data->def_mode		= AR0135_DEFAULT_MODE;
	common_data->def_width		= AR0135_DEFAULT_WIDTH;
	common_data->def_height		= AR0135_DEFAULT_HEIGHT;
	common_data->fmt_width		= common_data->def_width;
	common_data->fmt_height		= common_data->def_height;
	common_data->def_clk_freq	= AR0135_DEFAULT_CLK_FREQ;

	priv->i2c_client = client;
	priv->s_data			= common_data;
	priv->subdev			= &common_data->subdev;
	priv->subdev->dev		= &client->dev;
	priv->s_data->dev		= &client->dev;

	err = ar0135_power_get(priv);
	// if (err)
	// 	return err;
	dev_dbg(&client->dev, "ar0135_power_get err is %d\n", err);

	err = camera_common_parse_ports(client, common_data);
	if (err) {
		dev_err(&client->dev, "Failed to find port info\n");
		//return err;
	}
	sprintf(debugfs_name, "ar0135_%c", common_data->csi_port + 'a');
	dev_dbg(&client->dev, "%s: name %s\n", __func__, debugfs_name);
	camera_common_create_debugfs(common_data, debugfs_name);

	err = ar0135_deserializer_device_init(priv);

	dev_dbg(&client->dev, "ar0135_deserializer_device_init err is %d\n", err);

	usleep_range(100000,100100);

	err = ar0135_serializer_device_init(priv);

	dev_dbg(&client->dev, "ar0135_serializer_device_init err is %d\n", err);

	usleep_range(100000,100100);

	v4l2_i2c_subdev_init(priv->subdev, client, &ar0135_subdev_ops);

	err = ar0135_ctrls_init(priv, !err);
	// if (err)
	// 	return err;
	dev_dbg(&client->dev, "ar0135_ctrls_init err is %d\n", err);

	usleep_range(100000,100100);
	regmap_write(priv->regmap, 0x3028, 0x0010);
	regmap_write(priv->regmap, 0x302A, 0x0008);
	regmap_write(priv->regmap, 0x302C, 0x0001);
	regmap_write(priv->regmap, 0x302E, 0x0008);
	regmap_write(priv->regmap, 0x3030, 0x00C6);
	regmap_write(priv->regmap, 0x3032, 0x0000);
	regmap_write(priv->regmap, 0x30B0, 0x0080);

	regmap_write(priv->regmap, 0x301A, 0x00D8);
	regmap_write(priv->regmap, 0x301A, 0x10DC);
	// regmap_write(priv->regmap, 0x3002, 0x0074);
	// regmap_write(priv->regmap, 0x3004, 0x0000);
	// regmap_write(priv->regmap, 0x3006, 0x034B);
	// regmap_write(priv->regmap, 0x3008, 0x04FF);
	// regmap_write(priv->regmap, 0x300A, 0x02F2);
	// regmap_write(priv->regmap, 0x300C, 0x0672);
	// regmap_write(priv->regmap, 0x3012, 0x02EB);
	// regmap_write(priv->regmap, 0x3014, 0x0009);
	// regmap_write(priv->regmap, 0x30A6, 0x0001);
    // regmap_write(priv->regmap, 0x308C, 0x0000);
	// regmap_write(priv->regmap, 0x308A, 0x0000);
	// regmap_write(priv->regmap, 0x3090, 0x03BF);
	// regmap_write(priv->regmap, 0x308E, 0x04FF);
	// regmap_write(priv->regmap, 0x30AA, 0x03E5);
	// regmap_write(priv->regmap, 0x3016, 0x01C2);
	// regmap_write(priv->regmap, 0x3018, 0x0009);
	// regmap_write(priv->regmap, 0x30A8, 0x0001);
	// regmap_write(priv->regmap, 0x3040, 0x0000);
	// regmap_write(priv->regmap, 0x3064, 0x1982);
	// err = regmap_write(priv->regmap, 0x31C6, 0x8008);
	// dev_err(&client->dev, "ar0135_regmap_write err is %d\n",err);
	 usleep_range(10000,10100);

	priv->subdev->internal_ops = &ar0135_subdev_internal_ops;
	priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
			       V4L2_SUBDEV_FL_HAS_EVENTS;

#if defined(CONFIG_MEDIA_CONTROLLER)
	priv->pad.flags = MEDIA_PAD_FL_SOURCE;
	priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
	priv->subdev->entity.ops = &ar0135_media_ops;
	err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
	if (err < 0) {
		dev_err(&client->dev, "unable to init media entity\n");
		//return err;
	}
	else
	{
		dev_dbg(&client->dev, "%s:media_entity_init success %d\n",__func__,err); //zhou
	}
#endif

	err = v4l2_async_register_subdev(priv->subdev);
	//if (err)
		//return err;
	dev_dbg(&client->dev, "v4l2_async_register_subdev err is %d\n", err);

	if(client->dev.driver_data == NULL)
		dev_err(&client->dev,"ar0135 client dev's drive data is null\n");

	dev_dbg(&client->dev, "Detected AR0135 sensor\n");


	return 0;
}

are they any problems with this?
Thanks a lot!
Best regards!

hello 15210962653,

to narrow down the issue, please configure your serializer/deserializer driver to outputting test-pattern.
if you’re able to get the same pattern from serializer/deserializer driver, you’ll need to dig into AR0135 sensor drivers for the signaling.
if you’re not able to get the pattern, you should check the connections, or regulator settings of serializer/deserializer driver.
thanks

you can check you kernel log,
is the next log info exit
[ 0.145153] node /plugin-manager/fragment-e3326@0 match with board 3326-*
if not, you can try to change the dtsi:tegra186-quill-camera-plugin-manager.dtsi
modify
ids = “>=3310-1000-800”, “>=3489-0000-200”;
//ids = “3326-*”;

I misunderstood you originally. I see now that you can configure the three devices (deserializer, serializer, and sensor).

The next step would be to verify that you have configured the CSI settings on your deserializer. Also, as Jerry suggested, do utilize the test pattern generator from your deserializer.

I did not look at the specific registers you are programming.

Is your problem solved?I’m porting ov10635 ds90ub964 to jetson agx xavier.