diff --git a/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-ar0144-a00.dtsi b/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-ar0144-a00.dtsi
new file mode 100644
index 00000000..20b9ef0b
--- /dev/null
+++ b/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-ar0144-a00.dtsi
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+/ {
+ host1x {
+ vi@15700000 {
+ num-channels = <3>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_vi_in0: endpoint {
+ csi-port = <0>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_out0>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ liar0144_vi_in1: endpoint {
+ csi-port = <2>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_out1>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ liar0144_vi_in2: endpoint {
+ csi-port = <4>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_out2>;
+ };
+ };
+ };
+ };
+
+ nvcsi@150c0000 {
+ num-channels = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ channel@0 {
+ reg = <0>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_csi_in0: endpoint@0 {
+ csi-port = <0>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_ar0144_out0>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ liar0144_csi_out0: endpoint@1 {
+ remote-endpoint = <&liar0144_vi_in0>;
+ };
+ };
+ };
+ };
+ channel@1 {
+ reg = <1>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_csi_in1: endpoint@0 {
+ csi-port = <2>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_ar0144_out1>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ liar0144_csi_out1: endpoint@1 {
+ remote-endpoint = <&liar0144_vi_in1>;
+ };
+ };
+ };
+ };
+ channel@2 {
+ reg = <2>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_csi_in2: endpoint@0 {
+ csi-port = <4>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_ar0144_out2>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ liar0144_csi_out2: endpoint@1 {
+ remote-endpoint = <&liar0144_vi_in2>;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ i2c@3180000 {
+ tca9546@70 {
+ i2c@0 {
+ ar0144_a@10 {
+ compatible = "nvidia,ar0144";
+ /* I2C device address */
+ reg = <0x10>;
+
+ /* V4L2 device node location */
+ /*devnode = "video0";*/
+
+ /* Physical dimensions of sensor */
+ physical_w = "1.948";
+ physical_h = "1.109";
+
+
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ avdd-reg = "vana";
+ iovdd-reg = "vif";
+ dvdd-reg = "vdig";
+ sensor_model ="ar0144";
+
+ /* Defines number of frames to be dropped by driver internally after applying */
+ /* sensor crop settings. Some sensors send corrupt frames after applying */
+ /* crop co-ordinates */
+ post_crop_frame_drop = "0";
+
+ /* if true, delay gain setting by one frame to be in sync with exposure */
+ delayed_gain = "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)
+ *
+ * embedded_metadata_height = "";
+ * Sensor embedded metadata height in units of rows.
+ * If sensor does not support embedded metadata value should be 0.
+ */
+ mode0 {/*mode AR0144_MODE_1920X1080_CROP_30FPS*/
+ mclk_khz = "27000";
+ num_lanes = "2";
+ tegra_sinterface = "serial_a";
+ discontinuous_clk = "yes";
+ dpcm_enable = "false";
+ cil_settletime = "0";
+
+ dynamic_pixel_bit_depth = "12";
+ csi_pixel_bit_depth = "12";
+ mode_type = "bayer";
+ pixel_phase = "rggb";
+// pixel_t = "bayer_rggb12";
+
+
+ active_w = "1280";
+ active_h = "720";
+ readout_orientation = "0";
+ line_length = "1488";
+ inherent_gain = "1";
+ mclk_multiplier = "2.75";
+ pix_clk_hz = "74250000";
+
+ min_gain_val = "1";
+ max_gain_val = "31";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "64";
+ min_framerate = "6";
+ max_framerate = "60";
+ min_exp_time = "200";
+ max_exp_time = "166332";
+ embedded_metadata_height = "4";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_ar0144_out0: endpoint {
+ csi-port = <0>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_in0>;
+ };
+ };
+ };
+ };
+ };
+ i2c@1 {
+ ar0144_b@10 {
+ compatible = "nvidia,ar0144";
+ /* I2C device address */
+ reg = <0x10>;
+
+ /* V4L2 device node location */
+ /*devnode = "video1";*/
+
+ /* Physical dimensions of sensor */
+ physical_w = "1.948";
+ physical_h = "1.109";
+
+
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ avdd-reg = "vana";
+ iovdd-reg = "vif";
+ dvdd-reg = "vdig";
+ sensor_model ="ar0144";
+
+ /* Defines number of frames to be dropped by driver internally after applying */
+ /* sensor crop settings. Some sensors send corrupt frames after applying */
+ /* crop co-ordinates */
+ post_crop_frame_drop = "0";
+
+ /* if true, delay gain setting by one frame to be in sync with exposure */
+ delayed_gain = "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)
+ *
+ * embedded_metadata_height = "";
+ * Sensor embedded metadata height in units of rows.
+ * If sensor does not support embedded metadata value should be 0.
+ */
+ mode0 {/*mode AR0144_MODE_1920X1080_CROP_30FPS*/
+ mclk_khz = "27000";
+ num_lanes = "2";
+ tegra_sinterface = "serial_c";
+ discontinuous_clk = "yes";
+ dpcm_enable = "false";
+ cil_settletime = "0";
+
+ dynamic_pixel_bit_depth = "12";
+ csi_pixel_bit_depth = "12";
+ mode_type = "bayer";
+ pixel_phase = "rggb";
+// pixel_t = "bayer_rggb12";
+
+ active_w = "1280";
+ active_h = "720";
+ readout_orientation = "0";
+ line_length = "1488";
+ inherent_gain = "1";
+ mclk_multiplier = "2.75";
+ pix_clk_hz = "74250000";
+
+ min_gain_val = "1"; /* dB */
+ max_gain_val = "31"; /* dB */
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "64";
+ min_framerate = "6";
+ max_framerate = "60";
+ min_exp_time = "200";
+ max_exp_time = "166332";
+ embedded_metadata_height = "4";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_ar0144_out1: endpoint {
+ csi-port = <2>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_in1>;
+ };
+ };
+ };
+ };
+ };
+ i2c@2 {
+ ar0144_c@10 {
+ compatible = "nvidia,ar0144";
+ /* I2C device address */
+ reg = <0x10>;
+
+ /* V4L2 device node location */
+ /*devnode = "video2";*/
+
+ /* Physical dimensions of sensor */
+ physical_w = "1.948";
+ physical_h = "1.109";
+
+
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ avdd-reg = "vana";
+ iovdd-reg = "vif";
+ dvdd-reg = "vdig";
+ sensor_model ="ar0144";
+
+ /* Defines number of frames to be dropped by driver internally after applying */
+ /* sensor crop settings. Some sensors send corrupt frames after applying */
+ /* crop co-ordinates */
+ post_crop_frame_drop = "0";
+
+ /* if true, delay gain setting by one frame to be in sync with exposure */
+ delayed_gain = "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)
+ *
+ * embedded_metadata_height = "";
+ * Sensor embedded metadata height in units of rows.
+ * If sensor does not support embedded metadata value should be 0.
+ */
+ mode0 {/*mode AR0144_MODE_1920X1080_CROP_30FPS*/
+ mclk_khz = "27000";
+ num_lanes = "2";
+ tegra_sinterface = "serial_e";
+ discontinuous_clk = "yes";
+ dpcm_enable = "false";
+ cil_settletime = "0";
+
+ dynamic_pixel_bit_depth = "12";
+ csi_pixel_bit_depth = "12";
+ mode_type = "bayer";
+ pixel_phase = "rggb";
+// pixel_t = "bayer_rggb12";
+
+ active_w = "1280";
+ active_h = "720";
+ readout_orientation = "0";
+ line_length = "1488";
+ inherent_gain = "1";
+ mclk_multiplier = "2.75";
+ pix_clk_hz = "74250000";
+
+ min_gain_val = "1"; /* dB */
+ max_gain_val = "31"; /* dB */
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "64";
+ min_framerate = "6";
+ max_framerate = "60";
+ min_exp_time = "200";
+ max_exp_time = "166332";
+ embedded_metadata_height = "4";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ liar0144_ar0144_out2: endpoint {
+ csi-port = <4>;
+ bus-width = <2>;
+ remote-endpoint = <&liar0144_csi_in2>;
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+};
+
+
+
+/ {
+
+ 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 = <6>;
+ max_lane_speed = <1500000>;
+ min_bits_per_pixel = <10>;
+ vi_peak_byte_per_pixel = <2>;
+ vi_bw_margin_pct = <25>;
+ 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 {
+ module2 {
+ badge = "ar0144_bottomleft_liar0144";
+ position = "bottomleft";
+ orientation = "1";
+ status = "okay";
+ drivernode0 {
+ /* Declare PCL support driver (classically known as guid) */
+ pcl_id = "v4l2_sensor";
+ /* Driver v4l2 device name */
+ devname = "ar0144 30-0010";
+ /* Declare the device-tree hierarchy to driver instance */
+ proc-device-tree = "/proc/device-tree/i2c@3180000/tca9546@70/i2c@0/ar0144_a@10";
+ status = "okay";
+ };
+ };
+ module1 {
+ badge = "ar0144_centerleft_liar0144";
+ position = "centerleft";
+ orientation = "1";
+ status = "okay";
+ drivernode0 {
+ /* Declare PCL support driver (classically known as guid) */
+ pcl_id = "v4l2_sensor";
+ /* Driver v4l2 device name */
+ devname = "ar0144 31-0010";
+ /* Declare the device-tree hierarchy to driver instance */
+ proc-device-tree = "/proc/device-tree/i2c@3180000/tca9546@70/i2c@1/ar0144_b@10";
+ status = "okay";
+ };
+ };
+ module0 {
+ badge = "ar0144_centerright_liar0144";
+ position = "centerright";
+ orientation = "1";
+ status = "okay";
+ drivernode0 {
+ /* Declare PCL support driver (classically known as guid) */
+ pcl_id = "v4l2_sensor";
+ /* Driver v4l2 device name */
+ devname = "ar0144 32-0010";
+ /* Declare the device-tree hierarchy to driver instance */
+ proc-device-tree = "/proc/device-tree/i2c@3180000/tca9546@70/i2c@2/ar0144_c@10";
+ status = "okay";
+ };
+ };
+ };
+ };
+};
diff --git a/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-ar0144-a00.dtsi b/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-ar0144-a00.dtsi
new file mode 100644
index 00000000..9705180a
--- /dev/null
+++ b/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-ar0144-a00.dtsi
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 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 .
+ */
+#include
+#include "dt-bindings/clock/tegra186-clock.h"
+
+#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)
+#define CAMERA_I2C_MUX_BUS(x) (0x1E + x)
+
+/* camera control gpio definitions */
+
+/ {
+ i2c@3180000 {
+ tca9546@70 {
+ compatible = "nxp,pca9546";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ skip_mux_detect = "yes";
+ /*vif-supply = <&en_vdd_cam>;*/
+ vcc-pullup-supply = <&en_vdd_cam>;
+ vcc-supply = <&en_vdd_cam>;
+ vcc_lp = "vcc";
+ force_bus_start = ;
+
+ i2c@0 {
+ reg = <0>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pca9570_a@24 {
+ compatible = "nvidia,pca9570";
+ reg = <0x24>;
+ channel = "a";
+ drive_ic = "DRV8838";
+ };
+ ar0144_a@10 {
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
+ <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
+ clock-names = "extperiph1", "pllp_grtba";
+ clock-frequency = <27000000>;
+ mclk = "extperiph1";
+ reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
+ vana-supply = <&en_vdd_cam_hv_2v8>;
+ vif-supply = <&en_vdd_cam>;
+ vdig-supply = <&en_vdd_cam_1v2>;
+
+ };
+ };
+ i2c@1 {
+ reg = <1>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pca9570_b@24 {
+ compatible = "nvidia,pca9570";
+ reg = <0x24>;
+ channel = "b";
+ drive_ic = "DRV8838";
+ };
+ ar0144_b@10 {
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH2>,
+ <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
+ clock-names = "extperiph1", "pllp_grtba";
+ clock-frequency = <27000000>;
+ mclk = "extperiph1";
+ reset-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
+ vana-supply = <&en_vdd_cam_hv_2v8>;
+ vif-supply = <&en_vdd_cam>;
+ vdig-supply = <&en_vdd_cam_1v2>;
+
+ };
+ };
+ i2c@2 {
+ reg = <2>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pca9570_c@24 {
+ compatible = "nvidia,pca9570";
+ reg = <0x24>;
+ channel = "c";
+ drive_ic = "DRV8838";
+ };
+ ar0144_c@10 {
+ /* Define any required hw resources needed by driver */
+ /* ie. clocks, io pins, power sources */
+ clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH3>,
+ <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
+ clock-names = "extperiph1", "pllp_grtba";
+ clock-frequency = <27000000>;
+ mclk = "extperiph1";
+ /*
+ reset-gpios = <&gpio_i2c_0_77 9 1>;
+ */
+ reset-gpios = <&gpio_i2c_0_77 7 GPIO_ACTIVE_HIGH>;
+ vana-supply = <&en_vdd_cam_hv_2v8>;
+ vif-supply = <&en_vdd_cam>;
+ vdig-supply = <&en_vdd_cam_1v2>;
+ };
+ };
+ };
+ };
+};
diff --git a/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dts b/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dts
index d79f701d..322b50ca 100644
--- a/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dts
+++ b/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dts
@@ -15,7 +15,8 @@
#include
#include
-#include
+//#include
+#include "t18x-common-platforms/tegra186-quill-camera-ar0144-a00.dtsi"
#include
/* comms dtsi file should be included after gpio dtsi file */
@@ -24,7 +25,7 @@
#include
#include
#include
-#include
+//#include
#include
diff --git a/kernel/kernel-4.4/arch/arm64/configs/tegra18_defconfig b/kernel/kernel-4.4/arch/arm64/configs/tegra18_defconfig
index a4974a17..23f946a9 100644
--- a/kernel/kernel-4.4/arch/arm64/configs/tegra18_defconfig
+++ b/kernel/kernel-4.4/arch/arm64/configs/tegra18_defconfig
@@ -1,6 +1,7 @@
CONFIG_ARCH_TEGRA_18x_SOC=y
CONFIG_ARCH_TEGRA_19x_SOC=y
# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_LOCALVERSION='-tegra'
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_FHANDLE=y
@@ -369,7 +370,7 @@ CONFIG_VIDEO_OV10823=y
CONFIG_VIDEO_OV23850=y
CONFIG_VIDEO_LC898212=y
CONFIG_VIDEO_OV5693=y
-CONFIG_VIDEO_IMX274=y
+CONFIG_VIDEO_AR0144=y
CONFIG_VIDEO_IMX185=y
CONFIG_I2C_IOEXPANDER_PCA9570=y
# CONFIG_VGA_ARB is not set
diff --git a/kernel/kernel-4.4/drivers/media/i2c/Kconfig b/kernel/kernel-4.4/drivers/media/i2c/Kconfig
index f94dfed0..97b95eae 100644
--- a/kernel/kernel-4.4/drivers/media/i2c/Kconfig
+++ b/kernel/kernel-4.4/drivers/media/i2c/Kconfig
@@ -574,15 +574,15 @@ config VIDEO_IMX219
To compile this driver as a module, choose M here: the module
will be called imx219.
-config VIDEO_IMX274
- tristate "IMX274 camera sensor support"
+config VIDEO_AR0144
+ tristate "AR0144 camera sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help---
This is a Video4Linux2 sensor-level driver for the Sony
- IMX274 camera sensor
+ AR0144 camera sensor
To compile this driver as a module, choose M here: the module
- will be called imx274.
+ will be called ar0144.
config VIDEO_TC358840
tristate "Toshiba TC358840 decoder"
diff --git a/kernel/kernel-4.4/drivers/media/i2c/Makefile b/kernel/kernel-4.4/drivers/media/i2c/Makefile
index 5f3a2fa0..369945e0 100644
--- a/kernel/kernel-4.4/drivers/media/i2c/Makefile
+++ b/kernel/kernel-4.4/drivers/media/i2c/Makefile
@@ -80,7 +80,7 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
-obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
+obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.oS
obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
obj-$(CONFIG_VIDEO_OV9281) += ov9281.o
@@ -89,6 +89,6 @@ obj-$(CONFIG_VIDEO_OV23850) += ov23850.o
obj-$(CONFIG_VIDEO_LC898212) += lc898212.o
obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
obj-$(CONFIG_VIDEO_IMX219) += imx219.o
-obj-$(CONFIG_VIDEO_IMX274) += imx274.o
+obj-$(CONFIG_VIDEO_AR0144) += ar0144.o
obj-$(CONFIG_VIDEO_TC358840) += tc358840.o
obj-$(CONFIG_I2C_IOEXPANDER_PCA9570) += pca9570.o
diff --git a/kernel/kernel-4.4/drivers/media/i2c/ar0144.c b/kernel/kernel-4.4/drivers/media/i2c/ar0144.c
new file mode 100644
index 00000000..328a7f0c
--- /dev/null
+++ b/kernel/kernel-4.4/drivers/media/i2c/ar0144.c
@@ -0,0 +1,1176 @@
+/*
+ * ar0144.c - ar0144 sensor driver
+ *
+ * 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 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 .
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include "ar0144_mode_tbls.h"
+
+/* differ to max coarse */
+#define AR0144_MAX_COARSE_DIFF (12)
+/* max gain reg value */
+
+/* minimum gain value */
+#define AR0144_MIN_GAIN (1)
+/* maximum gain value */
+#define AR0144_MAX_GAIN (31)
+
+/* minimum frame length */
+#define AR0144_MIN_FRAME_LENGTH (0x33F)
+/* maximum frame length */
+#define AR0144_MAX_FRAME_LENGTH (0x2080)
+/* minimum exposure coarse */
+#define AR0144_MIN_EXPOSURE_COARSE (0xA)
+/* maximum exposure coarse */
+#define AR0144_MAX_EXPOSURE_COARSE (0x206C)
+
+/* default gain value */
+#define AR0144_DEFAULT_GAIN (0x01)
+/* default frame length value */
+#define AR0144_DEFAULT_FRAME_LENGTH (0x33F)
+/* default exposure coarse value */
+#define AR0144_DEFAULT_EXPOSURE_COARSE (0x190)
+
+/* default mode */
+#define AR0144_DEFAULT_MODE AR0144_LINEAR_MODE_1280X720_60FPS
+
+/* default image output width */
+#define AR0144_DEFAULT_WIDTH (1280)
+/* default image output height */
+#define AR0144_DEFAULT_HEIGHT (720)
+/* default image data format */
+#define AR0144_DEFAULT_DATAFMT MEDIA_BUS_FMT_SRGGB12_1X12
+
+/* default output clk frequency for camera */
+#define AR0144_DEFAULT_CLK_FREQ (27000000)
+
+
+struct ar0144 {
+ struct camera_common_power_rail power;
+ int numctrls;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct i2c_client *i2c_client;
+ struct v4l2_subdev *subdev;
+ struct media_pad pad;
+ u32 frame_length;
+ s32 group_hold_prev;
+ bool group_hold_en;
+ s64 last_wdr_et_val;
+ struct regmap *regmap;
+ struct camera_common_data *s_data;
+ struct camera_common_pdata *pdata;
+ struct v4l2_ctrl *ctrls[];
+};
+
+static const struct regmap_config sensor_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .cache_type = REGCACHE_RBTREE,
+ .use_single_rw = true,
+};
+
+static int ar0144_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
+static int ar0144_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops ar0144_ctrl_ops = {
+ .g_volatile_ctrl = ar0144_g_volatile_ctrl,
+ .s_ctrl = ar0144_s_ctrl,
+};
+
+static struct v4l2_ctrl_config ctrl_config_list[] = {
+/* Do not change the name field for the controls! */
+ {
+ .ops = &ar0144_ctrl_ops,
+ .id = TEGRA_CAMERA_CID_GAIN,
+ .name = "Gain",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ .min = AR0144_MIN_GAIN,
+ .max = AR0144_MAX_GAIN,
+ .def = AR0144_DEFAULT_GAIN,
+ .step = 1,
+ },
+ {
+ .ops = &ar0144_ctrl_ops,
+ .id = TEGRA_CAMERA_CID_FRAME_LENGTH,
+ .name = "Frame Length",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ .min = AR0144_MIN_FRAME_LENGTH,
+ .max = AR0144_MAX_FRAME_LENGTH,
+ .def = AR0144_DEFAULT_FRAME_LENGTH,
+ .step = 1,
+ },
+ {
+ .ops = &ar0144_ctrl_ops,
+ .id = TEGRA_CAMERA_CID_COARSE_TIME,
+ .name = "Coarse Time",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ .min = AR0144_MIN_EXPOSURE_COARSE,
+ .max = AR0144_MAX_EXPOSURE_COARSE,
+ .def = AR0144_DEFAULT_EXPOSURE_COARSE,
+ .step = 1,
+ },
+ {
+ .ops = &ar0144_ctrl_ops,
+ .id = TEGRA_CAMERA_CID_GROUP_HOLD,
+ .name = "Group Hold",
+ .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 = &ar0144_ctrl_ops,
+ .id = TEGRA_CAMERA_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,
+ },
+};
+
+static inline void ar0144_calculate_frame_length_regs(ar0144_reg *regs,
+ u32 frame_length)
+{
+ regs->addr = AR0144_FRAME_LENGTH_ADDR;
+ regs->val = (frame_length) & 0xffff;
+}
+
+/*
+ * ar0144_calculate_coarse_time_regs - Function for calculate coarse time
+ * register value
+ * @regs: Pointer to ar0144 reg structure
+ * @coarse_time: Coarse time value
+ *
+ * This is used to get the coarse time value for coarse time register
+ */
+static inline void ar0144_calculate_coarse_time_regs(ar0144_reg *regs,
+ u32 coarse_time)
+{
+ regs->addr = AR0144_COARSE_TIME_ADDR;
+ regs->val = (coarse_time) & 0xffff;
+}
+
+/*
+ * ar0144_calculate_gain_regs - Function for calculate gain
+ * register value
+ * @regs: Pointer to ar0144 reg structure
+ * @gain: Gain value
+ *
+ * This is used to get the gain value for gain register
+ */
+static inline void ar0144_calculate_gain_regs(ar0144_reg *regs, u16 again,
+ u16 dgain)
+{
+ regs->addr = AR0144_ANALOG_GAIN_ADDR;
+ regs->val = (again << 4) & 0xffff;
+ (regs + 1)->addr = AR0144_DIGITAL_GAIN_ADDR;
+ (regs + 1)->val = (dgain) & 0xffff;
+}
+
+static inline int ar0144_read_reg(struct camera_common_data *s_data,
+ u16 addr, u8 *val)
+{
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+ int err = 0;
+ u32 reg_val = 0;
+
+ err = regmap_read(priv->regmap, addr, ®_val);
+ *val = reg_val & 0xFF;
+
+ return err;
+}
+static inline int ar0144_read_reg16(struct camera_common_data *s_data,
+ u16 addr, u16 *val)
+{
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+
+ return regmap_read(priv->regmap, addr, (unsigned int *) val);
+}
+static int ar0144_write_reg(struct camera_common_data *s_data,
+ u16 addr, u8 val)
+{
+ int err;
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+
+ err = regmap_write(priv->regmap, addr, val);
+ if (err)
+ pr_err("%s:i2c write failed, 0x%x = %x\n",
+ __func__, addr, val);
+
+ return err;
+}
+
+static int ar0144_write_reg16(struct camera_common_data *s_data,
+ u16 addr, u16 val)
+{
+ int err;
+ struct ar0144 *priv = (struct ar0144 *)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 ar0144_write_table(struct ar0144 *priv,
+ const ar0144_reg table[])
+{
+ int i = 0;
+
+ while (table[i].addr != AR0144_TABLE_END) {
+ regmap_write(priv->regmap, table[i].addr, table[i].val);
+ i++;
+ }
+
+ return 0;
+}
+
+static int ar0144_power_on(struct camera_common_data *s_data)
+{
+ int err = 0;
+ /* static int i = 0; */
+ struct ar0144 *priv = (struct ar0144 *)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;
+ return err;
+ }
+ usleep_range(1, 2);
+ if (pw->reset_gpio) {
+ gpio_direction_output(pw->reset_gpio, 0);
+ /* printk("meng = %d,pw->reset_gpio = %d\n", i++, pw->reset_gpio); */
+ }
+
+ usleep_range(1, 2);
+
+ if (pw->reset_gpio) {
+ gpio_direction_output(pw->reset_gpio, 1);
+ /* printk("####### =%d,pw->reset_gpio = %d\n", i++, pw->reset_gpio); */
+ }
+
+ /* if (pw->pwdn_gpio)
+ gpio_direction_output(pw->pwdn_gpio, 0); */
+
+
+ usleep_range(10, 20);
+
+
+ if (pw->dvdd)
+ err = regulator_enable(pw->dvdd);
+ if (err)
+ goto ar0144_dvdd_fail;
+
+ if (pw->iovdd)
+ err = regulator_enable(pw->iovdd);
+ if (err)
+ goto ar0144_iovdd_fail;
+
+ if (pw->avdd)
+ err = regulator_enable(pw->avdd);
+ if (err)
+ goto ar0144_avdd_fail;
+
+ usleep_range(1, 2);
+ if (pw->reset_gpio)
+ gpio_direction_output(pw->reset_gpio, 1);
+ if (pw->pwdn_gpio)
+ gpio_direction_output(pw->pwdn_gpio, 1);
+
+ usleep_range(300, 310);
+
+
+ pw->state = SWITCH_ON;
+ return 0;
+
+ar0144_dvdd_fail:
+ if (pw->af_gpio)
+ gpio_direction_output(pw->af_gpio, 0);
+
+ar0144_iovdd_fail:
+ regulator_disable(pw->dvdd);
+
+ar0144_avdd_fail:
+ regulator_disable(pw->iovdd);
+
+ pr_err("%s failed.\n", __func__);
+ return -ENODEV;
+
+}
+
+static int ar0144_power_off(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct ar0144 *priv = (struct ar0144 *)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;
+ }
+ usleep_range(1, 2);
+ /*if (pw->reset_gpio && (pw->reset_gpio != 148))
+ gpio_direction_output(pw->reset_gpio, 0);
+ printk("111111pw->reset_gpio = %d\n", pw->reset_gpio); */
+#if 0
+ if (pw->reset_gpio)
+ gpio_direction_output(pw->reset_gpio, 0);
+ if (pw->af_gpio)
+ gpio_direction_output(pw->af_gpio, 0);
+ if (pw->pwdn_gpio)
+ gpio_direction_output(pw->pwdn_gpio, 0);
+#endif
+
+ usleep_range(1, 2);
+
+ if (pw->avdd)
+ regulator_disable(pw->avdd);
+
+ if (pw->iovdd)
+ regulator_disable(pw->iovdd);
+ if (pw->dvdd)
+ regulator_disable(pw->dvdd);
+
+power_off_done:
+ pw->state = SWITCH_OFF;
+ return 0;
+}
+static int ar0144_power_put(struct ar0144 *priv)
+{
+ struct camera_common_power_rail *pw = &priv->power;
+ if (unlikely(!pw))
+ return -EFAULT;
+
+ if (likely(pw->avdd)) {
+ regulator_put(pw->avdd);
+ dev_dbg(&priv->i2c_client->dev, "%s: regulator_put(avdd)\n", __func__);
+ }
+
+ if (likely(pw->iovdd)) {
+ regulator_put(pw->iovdd);
+ dev_dbg(&priv->i2c_client->dev, "%s: regulator_put(iovdd)\n", __func__);
+ }
+
+ if (likely(pw->dvdd)) {
+ regulator_put(pw->dvdd);
+ dev_dbg(&priv->i2c_client->dev, "%s: regulator_put(dvdd)\n", __func__);
+ }
+
+ pw->avdd = NULL;
+ pw->iovdd = NULL;
+ pw->dvdd = NULL;
+
+ return 0;
+}
+
+static int ar0144_power_get(struct ar0144 *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;
+
+ dev_dbg(&priv->i2c_client->dev, "%s()\n", __func__);
+
+ mclk_name = priv->pdata->mclk_name ?
+ priv->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);
+ }
+
+ parentclk_name = priv->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);
+ }
+
+ /* ananlog 2.7v */
+ err |= camera_common_regulator_get(&priv->i2c_client->dev,
+ &pw->avdd, pdata->regulators.avdd);
+#if 1
+ /* digital 1.2v */
+ err |= camera_common_regulator_get(&priv->i2c_client->dev,
+ &pw->dvdd, pdata->regulators.dvdd);
+ /* IO 1.8v */
+ err |= camera_common_regulator_get(&priv->i2c_client->dev,
+ &pw->iovdd, pdata->regulators.iovdd);
+#endif
+
+ if (!err) {
+ pw->reset_gpio = pdata->reset_gpio;
+ pw->af_gpio = pdata->af_gpio;
+ pw->pwdn_gpio = pdata->pwdn_gpio;
+ }
+
+ pw->state = SWITCH_OFF;
+ return err;
+}
+
+static int ar0144_set_gain(struct ar0144 *priv, s32 val);
+static int ar0144_set_frame_length(struct ar0144 *priv, u32 val);
+static int ar0144_set_coarse_time(struct ar0144 *priv, s32 val);
+
+static int ar0144_start_stream(struct ar0144 *priv, int mode)
+{
+ static int metadata=3;
+ int regval = 0;
+ int err = 0;
+
+ dev_dbg(&priv->i2c_client->dev, "%s()\n", __func__);
+
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_1]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail1=%d\n", __func__, err);
+ return err;
+ }
+ msleep(20);
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_2]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail2=%d\n", __func__, err);
+ return err;
+ }
+ msleep(20);
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_3]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail3=%d\n", __func__, err);
+ return err;
+ }
+ msleep(20);
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_4]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail4=%d\n", __func__, err);
+ return err;
+ }
+ msleep(20);
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_5]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail5=%d\n", __func__, err);
+ return err;
+ }
+
+ msleep(20);
+ err = ar0144_write_table(priv, mode_table[mode]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() failm=%d\n", __func__, err);
+ return err;
+ }
+ msleep(20);
+
+ // cycle through all combinations of embedded_data and embedded_stats_en
+ regval = 0x1802 | (metadata << 7);
+ dev_dbg(&priv->i2c_client->dev, "%s() R0x3064=%04x, data=%d, stats=%d\n",
+ __func__, regval, (regval & 0x0100)?1:0, (regval & 0x0080)?1:0);
+ regmap_write(priv->regmap, 0x3064, regval);
+ // metadata = (metadata + 1) % 4;
+
+ err = ar0144_write_table(priv, mode_table[AR0144_MODE_START_STREAM_6]);
+ if (err) {
+ dev_err(&priv->i2c_client->dev, "%s() fail6=%d\n", __func__, err);
+ return err;
+ }
+
+ dev_dbg(&priv->i2c_client->dev, "%s() - success\n", __func__);
+ return 0;
+}
+
+static int ar0144_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->dev);
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+ struct v4l2_control control;
+ int err = 0;
+
+ dev_dbg(&client->dev, "%s++\n", __func__);
+
+ if (!enable)
+ return ar0144_write_table(priv,
+ mode_table[AR0144_MODE_STOP_STREAM]);
+
+ err = ar0144_start_stream(priv, 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. */
+ control.id = TEGRA_CAMERA_CID_GAIN;
+ err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+ err |= ar0144_set_gain(priv, control.value);
+ if (err)
+ dev_dbg(&client->dev,
+ "%s: error gain override\n", __func__);
+
+ control.id = TEGRA_CAMERA_CID_FRAME_LENGTH;
+ err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+ err |= ar0144_set_frame_length(priv, control.value);
+ if (err)
+ dev_dbg(&client->dev,
+ "%s: error frame length override\n", __func__);
+
+ control.id = TEGRA_CAMERA_CID_COARSE_TIME;
+ err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
+ err |= ar0144_set_coarse_time(priv, control.value);
+ if (err)
+ dev_dbg(&client->dev,
+ "%s: error coarse time override\n", __func__);
+ }
+
+ return 0;
+exit:
+ dev_dbg(&client->dev, "%s: error setting stream\n", __func__);
+ return err;
+}
+
+static int ar0144_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->dev);
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+ struct camera_common_power_rail *pw = &priv->power;
+
+ *status = pw->state == SWITCH_ON;
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops ar0144_subdev_video_ops = {
+ .s_stream = ar0144_s_stream,
+ .g_mbus_config = camera_common_g_mbus_config,
+ .g_input_status = ar0144_g_input_status,
+};
+
+static struct v4l2_subdev_core_ops ar0144_subdev_core_ops = {
+ .s_power = camera_common_s_power,
+};
+
+static int ar0144_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 ar0144_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);
+ else
+ ret = camera_common_s_fmt(sd, &format->format);
+
+ return ret;
+}
+
+static struct v4l2_subdev_pad_ops ar0144_subdev_pad_ops = {
+ .set_fmt = ar0144_set_fmt,
+ .get_fmt = ar0144_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 ar0144_subdev_ops = {
+ .core = &ar0144_subdev_core_ops,
+ .video = &ar0144_subdev_video_ops,
+ .pad = &ar0144_subdev_pad_ops,
+};
+
+const struct of_device_id ar0144_of_match[] = {
+ { .compatible = "nvidia,ar0144",},
+ { },
+};
+
+static struct camera_common_sensor_ops ar0144_common_ops = {
+ .power_on = ar0144_power_on,
+ .power_off = ar0144_power_off,
+ .write_reg = ar0144_write_reg,
+ .read_reg = ar0144_read_reg,
+};
+
+static int ar0144_set_group_hold(struct ar0144 *priv)
+{
+ int gh_prev = switch_ctrl_qmenu[priv->group_hold_prev];
+
+ if (priv->group_hold_en == true && gh_prev == SWITCH_OFF) {
+ priv->group_hold_prev = 1;
+ } else if (priv->group_hold_en == false && gh_prev == SWITCH_ON) {
+ priv->group_hold_prev = 0;
+ }
+ return 0;
+}
+
+
+#define AR0144_GAIN_SHIFT 7
+
+static void ar0144_to_real_gain(u32 val, u16 *again, u16 *dgain)
+{
+ int gint;
+
+ gint = (val >> AR0144_GAIN_SHIFT);
+ if (gint > AR0144_MAX_GAIN)
+ gint = AR0144_MAX_GAIN;
+ else if (val < AR0144_MIN_GAIN)
+ gint = AR0144_MIN_GAIN;
+ if (gint >= 64 && gint <= 127) {
+ *again = 3;
+ *dgain = val / 8;
+ } else if (gint >= 32 && gint < 64) {
+ *again = 2;
+ *dgain = val / 4;
+ } else if (gint >= 16 && gint < 32) {
+ *again = 1;
+ *dgain = val / 2;
+ } else if (gint >= 1 && gint < 16) {
+ *again = 0;
+ *dgain = val;
+ }
+}
+static int ar0144_set_gain(struct ar0144 *priv, s32 val)
+{
+ ar0144_reg reg_list[2];
+ int err;
+ u16 again, dgain;
+ int i;
+
+ dev_dbg(&priv->i2c_client->dev, "%s - val = %d\n", __func__, val);
+
+ if (!priv->group_hold_prev)
+ ar0144_set_group_hold(priv);
+
+ val = val << AR0144_GAIN_SHIFT;
+
+ dev_dbg(&priv->i2c_client->dev, "input gain value: %d\n", val);
+ ar0144_to_real_gain((u32)val, &again, &dgain);
+
+ ar0144_calculate_gain_regs(reg_list, again, dgain);
+ dev_dbg(&priv->i2c_client->dev,
+ "%s: gain %04x val: again %04x, dgain %04x\n", __func__,
+ val, again, dgain);
+ for (i = 0; i < 2; i++) {
+ err = ar0144_write_reg16(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;
+}
+
+/*
+ * ar0144_set_frame_length - Function called when setting frame length
+ * @priv: Pointer to device structure
+ * Set frame length based on input value.
+ * Return: 0 extra tokens at end ofon success, errors otherwise
+ */
+static int ar0144_set_frame_length(struct ar0144 *priv, u32 val)
+{
+ ar0144_reg reg_list[3];
+ int err;
+ u32 frame_length;
+ int i;
+
+ dev_dbg(&priv->i2c_client->dev, "%s length = %d\n", __func__, val);
+
+
+ if (val > AR0144_MAX_FRAME_LENGTH)
+ val = AR0144_MAX_FRAME_LENGTH;
+ else if (val < AR0144_MIN_FRAME_LENGTH)
+ val = AR0144_MIN_FRAME_LENGTH;
+
+ if (!priv->group_hold_prev)
+ ar0144_set_group_hold(priv);
+
+ frame_length = (u32)val;
+
+ priv->frame_length = frame_length;
+ ar0144_calculate_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 = ar0144_write_reg16(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: FRAME_LENGTH control error\n", __func__);
+ return err;
+}
+/*
+ * ar0144_clamp_coarse_time - Function to clamp coarse time
+ * @priv: Pointer to ar0144 structure
+ * @val: Pointer to coarse time value
+ *
+ * This is used to clamp coarse time for ar0144 sensor.
+ *
+ * Return: 0 one success, errors otherwise
+ */
+static int ar0144_clamp_coarse_time(struct ar0144 *priv, s32 *val)
+{
+ if (*val > AR0144_MAX_EXPOSURE_COARSE) {
+ *val = AR0144_MAX_EXPOSURE_COARSE;
+ } else if (*val < AR0144_MIN_EXPOSURE_COARSE) {
+ *val = AR0144_MIN_EXPOSURE_COARSE;
+ }
+ return 0;
+}
+/*
+ * ar0144_set_coarse_time - Function called when setting SHR value
+ * @priv: Pointer to ar0144 structure
+ * @val: Value for exposure time in number of line_length, or [HMAX]
+ *
+ * Set SHR value based on input value.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int ar0144_set_coarse_time(struct ar0144 *priv, s32 val)
+{
+ ar0144_reg reg_list[2];
+ int err;
+ u32 coarse_time;
+ int i;
+
+ dev_dbg(&priv->i2c_client->dev, "%s\n", __func__);
+
+ if (priv->frame_length == 0)
+ priv->frame_length = AR0144_MIN_FRAME_LENGTH;
+
+ if (!priv->group_hold_prev)
+ ar0144_set_group_hold(priv);
+
+ coarse_time = (u32)val;
+ dev_dbg(&priv->i2c_client->dev,
+ "%s: input val: %d\n", __func__, coarse_time);
+
+ ar0144_clamp_coarse_time(priv, &coarse_time);
+
+ ar0144_calculate_coarse_time_regs(reg_list, coarse_time);
+ dev_dbg(&priv->i2c_client->dev,
+ "%s: set val: %d\n", __func__, coarse_time);
+
+ for (i = 0; i < 1; i++) {
+ err = ar0144_write_reg16(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 ar0144_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ar0144 *priv =
+ container_of(ctrl->handler, struct ar0144, ctrl_handler);
+ int err = 0;
+
+ if (priv->power.state == SWITCH_OFF)
+ return 0;
+
+ switch (ctrl->id) {
+ default:
+ pr_err("%s: unknown ctrl id.\n", __func__);
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int ar0144_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ar0144 *priv =
+ container_of(ctrl->handler, struct ar0144, ctrl_handler);
+ /* struct camera_common_data *s_data = priv->s_data; */
+ int err = 0;
+
+ if (priv->power.state == SWITCH_OFF)
+ return 0;
+
+ switch (ctrl->id) {
+ case TEGRA_CAMERA_CID_GAIN:
+ err = ar0144_set_gain(priv, *ctrl->p_new.p_s64);
+ break;
+ case TEGRA_CAMERA_CID_COARSE_TIME:
+ err = ar0144_set_coarse_time(priv, ctrl->val);
+ break;
+ case TEGRA_CAMERA_CID_FRAME_LENGTH:
+ err = ar0144_set_frame_length(priv, ctrl->val);
+ break;
+ case TEGRA_CAMERA_CID_GROUP_HOLD:
+ err = ar0144_set_group_hold(priv);
+ break;
+ case TEGRA_CAMERA_CID_HDR_EN:
+ break;
+ default:
+ pr_err("%s: unknown ctrl id.\n", __func__);
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int ar0144_ctrls_init(struct ar0144 *priv)
+{
+ struct i2c_client *client = priv->i2c_client;
+ struct v4l2_ctrl *ctrl;
+ int num_ctrls;
+ int err;
+ int i;
+
+ dev_dbg(&client->dev, "%s++\n", __func__);
+
+ num_ctrls = ARRAY_SIZE(ctrl_config_list);
+ v4l2_ctrl_handler_init(&priv->ctrl_handler, num_ctrls);
+
+ for (i = 0; i < num_ctrls; i++) {
+ 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);
+ }
+ priv->ctrls[i] = ctrl;
+ }
+
+ priv->numctrls = num_ctrls;
+ 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;
+ }
+
+ err = v4l2_ctrl_handler_setup(&priv->ctrl_handler);
+ if (err) {
+ dev_err(&client->dev,
+ "Error %d setting default controls\n", err);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ v4l2_ctrl_handler_free(&priv->ctrl_handler);
+ return err;
+}
+
+MODULE_DEVICE_TABLE(of, ar0144_of_match);
+
+static struct camera_common_pdata *ar0144_parse_dt(struct i2c_client *client,
+ struct camera_common_data *s_data)
+{
+ struct device_node *node = client->dev.of_node;
+ struct camera_common_pdata *board_priv_pdata;
+ const struct of_device_id *match;
+ int err;
+
+ dev_dbg(&client->dev, "%s()\n", __func__);
+
+ if (!node)
+ return NULL;
+
+ match = of_match_device(ar0144_of_match, &client->dev);
+ if (!match) {
+ dev_err(&client->dev, " Failed to find matching dt id\n");
+ return NULL;
+ }
+
+ board_priv_pdata = devm_kzalloc(&client->dev,
+ sizeof(*board_priv_pdata), GFP_KERNEL);
+ if (!board_priv_pdata) {
+ dev_err(&client->dev, "Failed to allocate pdata\n");
+ return NULL;
+ }
+
+
+ err = camera_common_parse_clocks(&client->dev, board_priv_pdata);
+ if (err) {
+ dev_err(&client->dev, "Failed to find clocks\n");
+ goto error;
+ }
+
+ err = of_property_read_string(node, "mclk",
+ &board_priv_pdata->mclk_name);
+ if (err)
+ dev_err(&client->dev, "mclk not in DT\n");
+
+ board_priv_pdata->reset_gpio = of_get_named_gpio(node,
+ "reset-gpios", 0);
+
+ of_property_read_string(node, "avdd-reg",
+ &board_priv_pdata->regulators.avdd);
+ of_property_read_string(node, "dvdd-reg",
+ &board_priv_pdata->regulators.dvdd);
+ of_property_read_string(node, "iovdd-reg",
+ &board_priv_pdata->regulators.iovdd);
+
+ return board_priv_pdata;
+
+error:
+ devm_kfree(&client->dev, board_priv_pdata);
+ return NULL;
+}
+
+static int ar0144_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 ar0144_subdev_internal_ops = {
+ .open = ar0144_open,
+};
+
+static const struct media_entity_operations ar0144_media_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static int ar0144_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct camera_common_data *common_data;
+ struct ar0144 *priv;
+ /* char debugfs_name[10]; */
+ int err;
+
+ dev_info(&client->dev, "[AR0144]: probing v4l2 sensor at addr 0x%0x.\n",
+ client->addr);
+
+ if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+ return -EINVAL;
+
+ common_data = devm_kzalloc(&client->dev,
+ sizeof(struct camera_common_data), GFP_KERNEL);
+
+ priv = devm_kzalloc(&client->dev,
+ sizeof(struct ar0144) + sizeof(struct v4l2_ctrl *) *
+ ARRAY_SIZE(ctrl_config_list),
+ GFP_KERNEL);
+ if (!priv) {
+ dev_err(&client->dev, "unable to allocate memory!\n");
+ return -ENOMEM;
+ }
+
+ priv->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&client->dev,
+ "regmap init failed: %ld\n", PTR_ERR(priv->regmap));
+ return -ENODEV;
+ }
+
+ if (client->dev.of_node)
+ priv->pdata = ar0144_parse_dt(client, common_data);
+ if (!priv->pdata) {
+ dev_err(&client->dev, "unable to get platform data\n");
+ return -EFAULT;
+ }
+ /* printk("in %s <--> Line:%d", __func__, __LINE__); */
+ common_data->ops = &ar0144_common_ops;
+ common_data->ctrl_handler = &priv->ctrl_handler;
+ common_data->dev = &client->dev;
+ common_data->frmfmt = &ar0144_frmfmt[0];
+ common_data->colorfmt = camera_common_find_datafmt(
+ AR0144_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(ar0144_frmfmt);
+ common_data->def_mode = AR0144_DEFAULT_MODE;
+ common_data->def_width = AR0144_DEFAULT_WIDTH;
+ common_data->def_height = AR0144_DEFAULT_HEIGHT;
+ common_data->fmt_width = common_data->def_width;
+ common_data->fmt_height = common_data->def_height;
+ common_data->def_clk_freq = AR0144_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;
+ priv->last_wdr_et_val = 0;
+
+ err = ar0144_power_get(priv);
+ if (err)
+ return err;
+
+ err = camera_common_initialize(common_data, "ar0144");
+ if (err) {
+ dev_err(&client->dev, "Failed to initialize ar0144.\n");
+ return err;
+ }
+#if 0
+ if (common_data->csi_port == 2)
+ priv->pdata->reset_gpio = 209;
+ if (common_data->csi_port == 3)
+ priv->pdata->reset_gpio = 211;
+
+ if (common_data->csi_port == 4)
+ priv->pdata->reset_gpio = 213;
+
+ if (common_data->csi_port == 5)
+ priv->pdata->reset_gpio = 215;
+#endif
+
+ err = ar0144_power_get(priv);
+ if (err) {
+ dev_err(&client->dev, "Failed to ar0144_power_get().\n");
+ return err;
+ }
+
+ /* camera_common_create_debugfs(common_data, debugfs_name); */
+ v4l2_i2c_subdev_init(priv->subdev, client, &ar0144_subdev_ops);
+
+ err = ar0144_ctrls_init(priv);
+ if (err)
+ return err;
+
+ priv->subdev->internal_ops = &ar0144_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 = &ar0144_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;
+ }
+#endif
+
+ err = v4l2_async_register_subdev(priv->subdev);
+ if (err)
+ return err;
+
+ dev_info(&client->dev, "Detected AR0144 sensor\n");
+
+ return 0;
+}
+
+static int
+ar0144_remove(struct i2c_client *client)
+{
+ struct camera_common_data *s_data = to_camera_common_data(&client->dev);
+ struct ar0144 *priv = (struct ar0144 *)s_data->priv;
+
+ dev_dbg(&client->dev, "%s()\n", __func__);
+
+ 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);
+ ar0144_power_put(priv);
+ camera_common_cleanup(s_data);
+ return 0;
+}
+
+static const struct i2c_device_id ar0144_id[] = {
+ { "ar0144", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, ar0144_id);
+
+static struct i2c_driver ar0144_i2c_driver = {
+ .driver = {
+ .name = "ar0144",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ar0144_of_match),
+ },
+ .probe = ar0144_probe,
+ .remove = ar0144_remove,
+ .id_table = ar0144_id,
+};
+
+module_i2c_driver(ar0144_i2c_driver);
+
+MODULE_DESCRIPTION("Media Controller driver for Sony AR0144");
+MODULE_AUTHOR("NVIDIA Corporation");
+MODULE_LICENSE("GPL v2");
diff --git a/kernel/kernel-4.4/drivers/media/i2c/ar0144_mode_tbls.h b/kernel/kernel-4.4/drivers/media/i2c/ar0144_mode_tbls.h
new file mode 100644
index 00000000..da9eacf7
--- /dev/null
+++ b/kernel/kernel-4.4/drivers/media/i2c/ar0144_mode_tbls.h
@@ -0,0 +1,432 @@
+/*
+ * ar0144_mode_tbls.h - ar0144 sensor mode tables
+ *
+ * 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 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 .
+ */
+#ifndef __AR0144_I2C_TABLES__
+#define __AR0144_I2C_TABLES__
+
+#include
+#include
+
+/*
+ * define register table operation macro
+ */
+#define AR0144_TABLE_WAIT_MS 0
+#define AR0144_TABLE_END 1
+#define AR0144_MAX_RETRIES 3
+#define AR0144_WAIT_MS 3
+
+/*
+ * define the ar0144 reg list structure
+*/
+#define ar0144_reg struct reg_16
+
+/*
+ * ar0144 mode(refer to datasheet) register configuration with
+ * 1280x720 resolution, raw12 data and mipi two lane output
+ */
+static const ar0144_reg ar0144_start_1[] = {
+ {0x301A, 0x00D9},
+ {AR0144_TABLE_END, 0x00}
+};
+static const ar0144_reg ar0144_start_2[] = {
+ {0x3088, 0x8000},
+ {0x3086, 0x327F},
+ {0x3086, 0x5780},
+ {0x3086, 0x2730},
+ {0x3086, 0x7E13},
+ {0x3086, 0x8000},
+ {0x3086, 0x157E},
+ {0x3086, 0x1380},
+ {0x3086, 0x000F},
+ {0x3086, 0x8190},
+ {0x3086, 0x1643},
+ {0x3086, 0x163E},
+ {0x3086, 0x4522},
+ {0x3086, 0x0937},
+ {0x3086, 0x8190},
+ {0x3086, 0x1643},
+ {0x3086, 0x167F},
+ {0x3086, 0x9080},
+ {0x3086, 0x0038},
+ {0x3086, 0x7F13},
+ {0x3086, 0x8023},
+ {0x3086, 0x3B7F},
+ {0x3086, 0x9345},
+ {0x3086, 0x0280},
+ {0x3086, 0x007F},
+ {0x3086, 0xB08D},
+ {0x3086, 0x667F},
+ {0x3086, 0x9081},
+ {0x3086, 0x923C},
+ {0x3086, 0x1635},
+ {0x3086, 0x7F93},
+ {0x3086, 0x4502},
+ {0x3086, 0x8000},
+ {0x3086, 0x7FB0},
+ {0x3086, 0x8D66},
+ {0x3086, 0x7F90},
+ {0x3086, 0x8182},
+ {0x3086, 0x3745},
+ {0x3086, 0x0236},
+ {0x3086, 0x8180},
+ {0x3086, 0x4416},
+ {0x3086, 0x3143},
+ {0x3086, 0x7416},
+ {0x3086, 0x787B},
+ {0x3086, 0x7D45},
+ {0x3086, 0x023D},
+ {0x3086, 0x6445},
+ {0x3086, 0x0A3D},
+ {0x3086, 0x647E},
+ {0x3086, 0x1281},
+ {0x3086, 0x8037},
+ {0x3086, 0x7F10},
+ {0x3086, 0x450A},
+ {0x3086, 0x3F74},
+ {0x3086, 0x7E10},
+ {0x3086, 0x7E12},
+ {0x3086, 0x0F3D},
+ {0x3086, 0xD27F},
+ {0x3086, 0xD480},
+ {0x3086, 0x2482},
+ {0x3086, 0x9C03},
+ {0x3086, 0x430D},
+ {0x3086, 0x2D46},
+ {0x3086, 0x4316},
+ {0x3086, 0x5F16},
+ {0x3086, 0x532D},
+ {0x3086, 0x1660},
+ {0x3086, 0x404C},
+ {0x3086, 0x2904},
+ {0x3086, 0x2984},
+ {0x3086, 0x81E7},
+ {0x3086, 0x816F},
+ {0x3086, 0x170A},
+ {0x3086, 0x81E7},
+ {0x3086, 0x7F81},
+ {0x3086, 0x5C0D},
+ {0x3086, 0x5749},
+ {0x3086, 0x5F53},
+ {0x3086, 0x2553},
+ {0x3086, 0x274D},
+ {0x3086, 0x2BF8},
+ {0x3086, 0x1016},
+ {0x3086, 0x4C09},
+ {0x3086, 0x2BB8},
+ {0x3086, 0x2B98},
+ {0x3086, 0x4E11},
+ {0x3086, 0x5367},
+ {0x3086, 0x4001},
+ {0x3086, 0x605C},
+ {0x3086, 0x095C},
+ {0x3086, 0x1B40},
+ {0x3086, 0x0245},
+ {0x3086, 0x0045},
+ {0x3086, 0x8029},
+ {0x3086, 0xB67F},
+ {0x3086, 0x8040},
+ {0x3086, 0x047F},
+ {0x3086, 0x8841},
+ {0x3086, 0x095C},
+ {0x3086, 0x0B29},
+ {0x3086, 0xB241},
+ {0x3086, 0x0C40},
+ {0x3086, 0x0340},
+ {0x3086, 0x135C},
+ {0x3086, 0x0341},
+ {0x3086, 0x1117},
+ {0x3086, 0x125F},
+ {0x3086, 0x2B90},
+ {0x3086, 0x2B80},
+ {0x3086, 0x816F},
+ {0x3086, 0x4010},
+ {0x3086, 0x4101},
+ {0x3086, 0x5327},
+ {0x3086, 0x4001},
+ {0x3086, 0x6029},
+ {0x3086, 0xA35F},
+ {0x3086, 0x4D1C},
+ {0x3086, 0x1702},
+ {0x3086, 0x81E7},
+ {0x3086, 0x2983},
+ {0x3086, 0x4588},
+ {0x3086, 0x4021},
+ {0x3086, 0x7F8A},
+ {0x3086, 0x4039},
+ {0x3086, 0x4580},
+ {0x3086, 0x2440},
+ {0x3086, 0x087F},
+ {0x3086, 0x885D},
+ {0x3086, 0x5367},
+ {0x3086, 0x2992},
+ {0x3086, 0x8810},
+ {0x3086, 0x2B04},
+ {0x3086, 0x8916},
+ {0x3086, 0x5C43},
+ {0x3086, 0x8617},
+ {0x3086, 0x0B5C},
+ {0x3086, 0x038A},
+ {0x3086, 0x484D},
+ {0x3086, 0x4E2B},
+ {0x3086, 0x804C},
+ {0x3086, 0x0B41},
+ {0x3086, 0x9F81},
+ {0x3086, 0x6F41},
+ {0x3086, 0x1040},
+ {0x3086, 0x0153},
+ {0x3086, 0x2740},
+ {0x3086, 0x0160},
+ {0x3086, 0x2983},
+ {0x3086, 0x2943},
+ {0x3086, 0x5C05},
+ {0x3086, 0x5F4D},
+ {0x3086, 0x1C81},
+ {0x3086, 0xE745},
+ {0x3086, 0x0281},
+ {0x3086, 0x807F},
+ {0x3086, 0x8041},
+ {0x3086, 0x0A91},
+ {0x3086, 0x4416},
+ {0x3086, 0x092F},
+ {0x3086, 0x7E37},
+ {0x3086, 0x8020},
+ {0x3086, 0x307E},
+ {0x3086, 0x3780},
+ {0x3086, 0x2015},
+ {0x3086, 0x7E37},
+ {0x3086, 0x8020},
+ {0x3086, 0x0343},
+ {0x3086, 0x164A},
+ {0x3086, 0x0A43},
+ {0x3086, 0x160B},
+ {0x3086, 0x4316},
+ {0x3086, 0x8F43},
+ {0x3086, 0x1690},
+ {0x3086, 0x4316},
+ {0x3086, 0x7F81},
+ {0x3086, 0x450A},
+ {0x3086, 0x4130},
+ {0x3086, 0x7F83},
+ {0x3086, 0x5D29},
+ {0x3086, 0x4488},
+ {0x3086, 0x102B},
+ {0x3086, 0x0453},
+ {0x3086, 0x2D40},
+ {0x3086, 0x3045},
+ {0x3086, 0x0240},
+ {0x3086, 0x087F},
+ {0x3086, 0x8053},
+ {0x3086, 0x2D89},
+ {0x3086, 0x165C},
+ {0x3086, 0x4586},
+ {0x3086, 0x170B},
+ {0x3086, 0x5C05},
+ {0x3086, 0x8A60},
+ {0x3086, 0x4B91},
+ {0x3086, 0x4416},
+ {0x3086, 0x0915},
+ {0x3086, 0x3DFF},
+ {0x3086, 0x3D87},
+ {0x3086, 0x7E3D},
+ {0x3086, 0x7E19},
+ {0x3086, 0x8000},
+ {0x3086, 0x8B1F},
+ {0x3086, 0x2A1F},
+ {0x3086, 0x83A2},
+ {0x3086, 0x7E11},
+ {0x3086, 0x7516},
+ {0x3086, 0x3345},
+ {0x3086, 0x0A7F},
+ {0x3086, 0x5380},
+ {0x3086, 0x238C},
+ {0x3086, 0x667F},
+ {0x3086, 0x1381},
+ {0x3086, 0x8414},
+ {0x3086, 0x8180},
+ {0x3086, 0x313D},
+ {0x3086, 0x6445},
+ {0x3086, 0x2A3D},
+ {0x3086, 0xD27F},
+ {0x3086, 0x4480},
+ {0x3086, 0x2494},
+ {0x3086, 0x3DFF},
+ {0x3086, 0x3D4D},
+ {0x3086, 0x4502},
+ {0x3086, 0x7FD0},
+ {0x3086, 0x8000},
+ {0x3086, 0x8C66},
+ {0x3086, 0x7F90},
+ {0x3086, 0x8194},
+ {0x3086, 0x3F44},
+ {0x3086, 0x1681},
+ {0x3086, 0x8416},
+ {0x3086, 0x2C2C},
+ {0x3086, 0x2C2C},
+ {AR0144_TABLE_END, 0x00}
+};
+
+static const ar0144_reg ar0144_start_3[] = {
+ {0x3ED6, 0x3CB5},
+ {0x3ED8, 0x8765},
+ {0x3EDA, 0x8888},
+ {0x3EDC, 0x97FF},
+
+ {0x3EF8, 0x6522},
+ {0x3EFA, 0x2222},
+ {0x3EFC, 0x6666},
+ {0x3F00, 0xAA05},
+ {0x3EE2, 0x180E},
+ {0x3EE4, 0x0808},
+ {0X3EEA, 0x2A09},
+ {0x3060, 0x0000},
+
+ {0x3092, 0x00CF},
+ {0X3268, 0x0030},
+ {0X3786, 0x0006},
+ {0x3F4A, 0x0F70},
+ {0x306E, 0x4810},
+ {0x3064, 0x1802},
+ {0x3EF6, 0x8041},
+ {0x3180, 0xC08F},
+ {0x30BA, 0x7623},
+ {0x3176, 0x0480},
+ {0x3178, 0x0480},
+ {0x317A, 0x0480},
+ {0x317C, 0x0480},
+
+ {AR0144_TABLE_END, 0x00}
+};
+
+static const ar0144_reg ar0144_start_4[] = {
+ {0x302A, 0x0006},
+ {0x302C, 0x0001},
+ {0x302E, 0x0004},
+ {0x3030, 0x0042},
+ {0x3036, 0x000C},
+ {0x3038, 0x0001},
+
+ {0x30B0, 0x0038},
+
+ {AR0144_TABLE_END, 0x00}
+};
+
+static const ar0144_reg ar0144_start_5[] = {
+ {0x31AE, 0x0202},
+ {0x31AC, 0x0C0C},
+ {0x31B0, 0x0042},
+ {0x31B2, 0x002E},
+ {0x31B4, 0x1665},
+ {0x31B6, 0x110E},
+ {0x31B8, 0x2047},
+ {0x31BA, 0x0105},
+ {0x31BC, 0x0004},
+ {AR0144_TABLE_END, 0x00}
+};
+
+static const ar0144_reg ar0144_linear_mode_1280x720_60fps[] = {
+ {0x3002, 0x0028}, // y start: 40
+ {0x3004, 0x0003}, // x start: 3, moved by 1 to get RGGB pattern
+ {0x3006, 0x02F7}, // y end: 759
+ {0x3008, 0x0502}, // x end : 1282, moved by 1 to get RGGB pattern
+ {0x300A, 0x033F},
+ {0x300C, 0x05D0},
+ {0x3012, 0x0064},
+ {0x30A2, 0x0001},
+ {0x30A6, 0x0001},
+ {0x3040, 0x0000},
+
+ {0x3040, 0x0400},
+ {0x30A8, 0x0003},
+ {0x3040, 0x0c00},
+ {0x30AE, 0x0003},
+
+ {AR0144_TABLE_END, 0x00}
+};
+
+
+static const ar0144_reg ar0144_linear_mode_1280x720_30fps[] = {
+ {0x3002, 0x0028}, // y start: 40
+ {0x3004, 0x0003}, // x start: 3, moved by 1 to get RGGB pattern
+ {0x3006, 0x02F7}, // y end: 759
+ {0x3008, 0x0502}, // x end : 1282, moved by 1 to get RGGB pattern
+
+ {0x300A, 0x067F},
+ {0x300C, 0x05D0},
+ {0x3012, 0x0190},
+ {0x30A2, 0x0001},
+ {0x30A6, 0x0001},
+ {0x3040, 0x0000},
+
+ {0x3040, 0x0400},
+ {0x30A8, 0x0003},
+ {0x3040, 0x0c00},
+ {0x30AE, 0x0003},
+ {AR0144_TABLE_END, 0x00}
+};
+static const ar0144_reg ar0144_start_6[] = {
+ // {0x3064, 0x1802}, // no statistics
+ /* no embedded statistics (like histogram)
+ {0x3064, 0x1882}, */
+ /* don't put register data into vblank
+ {0x3064, 0x1982},
+ */
+
+ {0x3270, 0x0100}, // enable LED flash
+
+ {0x3028, 0x0010}, // row speed 0b001: DOUT changes on falling edge of pixclk.
+
+ {0x301A, 0x005C},
+
+ {AR0144_TABLE_END, 0x00}
+};
+
+static const ar0144_reg ar0144_stop[] = {
+ {0x301A, 0x0058},
+ {AR0144_TABLE_END, 0x00}
+};
+
+
+enum {
+ AR0144_LINEAR_MODE_1280X720_60FPS,
+ AR0144_MODE_START_STREAM_1,
+ AR0144_MODE_START_STREAM_2,
+ AR0144_MODE_START_STREAM_3,
+ AR0144_MODE_START_STREAM_4,
+ AR0144_MODE_START_STREAM_5,
+ AR0144_MODE_START_STREAM_6,
+ AR0144_MODE_STOP_STREAM
+};
+
+static const ar0144_reg *mode_table[] = {
+ [AR0144_LINEAR_MODE_1280X720_60FPS] = ar0144_linear_mode_1280x720_60fps,
+ [AR0144_MODE_START_STREAM_1] = ar0144_start_1,
+ [AR0144_MODE_START_STREAM_2] = ar0144_start_2,
+ [AR0144_MODE_START_STREAM_3] = ar0144_start_3,
+ [AR0144_MODE_START_STREAM_4] = ar0144_start_4,
+ [AR0144_MODE_START_STREAM_5] = ar0144_start_5,
+ [AR0144_MODE_START_STREAM_6] = ar0144_start_6,
+ [AR0144_MODE_STOP_STREAM] = ar0144_stop
+};
+
+static const int ar0144_60fps[] = {
+ 60,
+};
+
+static const struct camera_common_frmfmt ar0144_frmfmt[] = {
+ {{1280, 720}, ar0144_60fps, 1, 0, AR0144_LINEAR_MODE_1280X720_60FPS},
+};
+#endif /* __AR0144_TABLES__ */
diff --git a/kernel/kernel-4.4/drivers/media/platform/tegra/camera/csi/csi4_fops.c b/kernel/kernel-4.4/drivers/media/platform/tegra/camera/csi/csi4_fops.c
index 0377d7b8..932c4722 100644
--- a/kernel/kernel-4.4/drivers/media/platform/tegra/camera/csi/csi4_fops.c
+++ b/kernel/kernel-4.4/drivers/media/platform/tegra/camera/csi/csi4_fops.c
@@ -76,8 +76,21 @@ static void csi4_stream_init(struct tegra_csi_channel *chan, int port_num)
csi4_stream_write(chan, port_num, INTR_STATUS, 0x3ffff);
csi4_stream_write(chan, port_num, ERR_INTR_STATUS, 0x7ffff);
csi4_stream_write(chan, port_num, ERROR_STATUS2VI_MASK, 0x0);
+#if 1
csi4_stream_write(chan, port_num, INTR_MASK, 0x0);
csi4_stream_write(chan, port_num, ERR_INTR_MASK, 0x0);
+#else // disable ECC check
+ csi4_stream_write(chan, port_num, INTR_MASK, PH_ECC_MULTI_BIT_ERR |
+ PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
+ csi4_stream_write(chan, port_num, ERR_INTR_MASK, PH_ECC_MULTI_BIT_ERR |
+ PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
+ csi4_stream_write(chan, port_num, ERROR_STATUS2VI_MASK,
+ CFG_ERR_STATUS2VI_MASK_VC0 |
+ CFG_ERR_STATUS2VI_MASK_VC1 |
+ CFG_ERR_STATUS2VI_MASK_VC2 |
+ CFG_ERR_STATUS2VI_MASK_VC3);
+#endif
+
}
static void csi4_stream_config(struct tegra_csi_channel *chan, int port_num)
diff --git a/kernel/kernel-4.4/drivers/media/platform/tegra/camera/vi/vi4_fops.c b/kernel/kernel-4.4/drivers/media/platform/tegra/camera/vi/vi4_fops.c
index 67763dd4..b6030764 100644
--- a/kernel/kernel-4.4/drivers/media/platform/tegra/camera/vi/vi4_fops.c
+++ b/kernel/kernel-4.4/drivers/media/platform/tegra/camera/vi/vi4_fops.c
@@ -202,7 +202,7 @@ static bool vi_notify_wait(struct tegra_channel *chan,
for (i = 0; i < chan->valid_ports; i++) {
err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
chan->syncpt[i][SOF_SYNCPT_IDX], thresh[i],
- 250, NULL, NULL);
+ 5*250, NULL, NULL);
if (unlikely(err))
dev_err(chan->vi->dev,
"PXL_SOF syncpt timeout! err = %d\n", err);
diff --git a/kernel/kernel-4.4/include/media/ar0144.h b/kernel/kernel-4.4/include/media/ar0144.h
new file mode 100644
index 00000000..e7565820
--- /dev/null
+++ b/kernel/kernel-4.4/include/media/ar0144.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013-2015, 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 .
+ */
+
+#ifndef __AR0144_H__
+#define __AR0144_H__
+
+#include /* For IOCTL macros */
+#include
+#include
+
+#define AR0144_IOCTL_SET_MODE _IOW('o', 1, struct imx327_mode)
+#define AR0144_IOCTL_SET_FRAME_LENGTH _IOW('o', 2, __u32)
+#define AR0144_IOCTL_SET_COARSE_TIME _IOW('o', 3, __u32)
+#define AR0144_IOCTL_SET_GAIN _IOW('o', 4, __u16)
+#define AR0144_IOCTL_GET_STATUS _IOR('o', 5, __u8)
+#define AR0144_IOCTL_SET_BINNING _IOW('o', 6, __u8)
+#define AR0144_IOCTL_TEST_PATTERN _IOW('o', 7, \
+ enum imx327_test_pattern)
+#define AR0144_IOCTL_SET_GROUP_HOLD _IOW('o', 8, struct imx327_ae)
+/* IOCTL to set the operating mode of camera. */
+/* This can be either stereo , leftOnly or rightOnly */
+#define AR0144_IOCTL_SET_CAMERA_MODE _IOW('o', 10, __u32)
+#define AR0144_IOCTL_SYNC_SENSORS _IOW('o', 11, __u32)
+#define AR0144_IOCTL_GET_FUSEID _IOR('o', 12, struct nvc_fuseid)
+#define AR0144_IOCTL_SET_HDR_COARSE_TIME _IOW('o', 13, struct imx327_hdr)
+#define AR0144_IOCTL_READ_OTP_BANK _IOWR('o', 14, \
+ struct imx327_otp_bank)
+#define AR0144_IOCTL_SET_CAL_DATA _IOW('o', 15, \
+ struct imx327_cal_data)
+#define AR0144_IOCTL_GET_EEPROM_DATA _IOR('o', 20, __u8 *)
+#define AR0144_IOCTL_SET_EEPROM_DATA _IOW('o', 21, __u8 *)
+#define AR0144_IOCTL_GET_CAPS _IOR('o', 22, struct nvc_imager_cap)
+#define AR0144_IOCTL_SET_POWER _IOW('o', 23, __u32)
+
+#define AR0144_INVALID_COARSE_TIME -1
+/* The following register address need to be updated */
+#define AR0144_EEPROM_ADDRESS 0x50
+#define AR0144_EEPROM_SIZE 1024
+#define AR0144_EEPROM_STR_SIZE (AR0144_EEPROM_SIZE * 2)
+#define AR0144_EEPROM_BLOCK_SIZE (1 << 8)
+#define AR0144_EEPROM_NUM_BLOCKS \
+ (AR0144_EEPROM_SIZE / AR0144_EEPROM_BLOCK_SIZE)
+
+/* The following register address need to be updated */
+#define AR0144_OTP_LOAD_CTRL_ADDR 0x3D81
+#define AR0144_OTP_BANK_SELECT_ADDR 0x3D84
+#define AR0144_OTP_BANK_START_ADDR 0x3D00
+#define AR0144_OTP_BANK_END_ADDR 0x3D0F
+#define AR0144_OTP_NUM_BANKS (32)
+#define AR0144_OTP_BANK_SIZE \
+ (AR0144_OTP_BANK_END_ADDR - AR0144_OTP_BANK_START_ADDR + 1)
+#define AR0144_OTP_SIZE \
+ (AR0144_OTP_BANK_SIZE * AR0144_OTP_NUM_BANKS)
+#define AR0144_OTP_STR_SIZE (AR0144_OTP_SIZE * 2)
+
+#define AR0144_FUSE_ID_OTP_START_ADDR 0x3D00
+#define AR0144_FUSE_ID_OTP_BANK 0
+#define AR0144_FUSE_ID_SIZE 8
+#define AR0144_FUSE_ID_STR_SIZE (AR0144_FUSE_ID_SIZE * 2)
+
+#define AR0144_FRAME_LENGTH_ADDR_1 0x301A /* VMAX, MSB */
+#define AR0144_FRAME_LENGTH_ADDR_2 0x3019 /* VMAX, */
+#define AR0144_FRAME_LENGTH_ADDR_3 0x3018 /* VMAX , LSB */
+#define AR0144_SVR_REG_MSB 0x300F /* SVR */
+#define AR0144_SVR_REG_LSB 0x300E /* SVR */
+#define AR0144_COARSE_TIME_ADDR_MSB 0x3021 /* SHS1 */
+#define AR0144_COARSE_TIME_ADDR_LSB 0x3020 /* SHS1 */
+#define AR0144_GROUP_HOLD_ADDR 0x3001 /* REG HOLD */
+/*#define AR0144_ANALOG_GAIN_ADDR 0x3014 GAIN ADDR */
+
+#define AR0144_STANDBY_REG 0x3000
+#define AR0144_FRAME_LENGTH_ADDR 0x300A
+#define AR0144_COARSE_TIME_ADDR 0x3012
+#define AR0144_ANALOG_GAIN_ADDR 0x3060
+#define AR0144_DIGITAL_GAIN_ADDR 0x305E
+
+struct imx327_mode {
+ int res_x;
+ int res_y;
+ int fps;
+ __u32 frame_length;
+ __u32 coarse_time;
+ __u32 coarse_time_short;
+ __u16 gain;
+ __u8 hdr_en;
+};
+
+struct imx327_ae {
+ __u32 frame_length;
+ __u8 frame_length_enable;
+ __u32 coarse_time;
+ __u32 coarse_time_short;
+ __u8 coarse_time_enable;
+ __s32 gain;
+ __u8 gain_enable;
+};
+
+struct imx327_fuseid {
+ __u32 size;
+ __u8 id[16];
+};
+
+struct imx327_hdr {
+ __u32 coarse_time_long;
+ __u32 coarse_time_short;
+};
+
+struct imx327_otp_bank {
+ __u32 id;
+ __u8 buf[16];
+};
+
+struct imx327_cal_data {
+ int loaded;
+ int rg_ratio;
+ int bg_ratio;
+ int rg_ratio_typical;
+ int bg_ratio_typical;
+ __u8 lenc[62];
+};
+
+/* See notes in the nvc.h file on the GPIO usage */
+enum imx327_gpio_type {
+ AR0144_GPIO_TYPE_PWRDN = 0,
+ AR0144_GPIO_TYPE_RESET,
+};
+
+struct imx327_eeprom_data {
+ struct i2c_client *i2c_client;
+ struct i2c_adapter *adap;
+ struct i2c_board_info brd;
+ struct regmap *regmap;
+};
+
+struct imx327_power_rail {
+ struct regulator *dvdd;
+ struct regulator *avdd;
+ struct regulator *dovdd;
+};
+
+struct imx327_regulators {
+ const char *avdd;
+ const char *dvdd;
+ const char *dovdd;
+};
+
+struct imx327_platform_data {
+ unsigned cfg;
+ unsigned num;
+ const char *dev_name;
+ unsigned gpio_count; /* see nvc.h GPIO notes */
+ struct nvc_gpio_pdata *gpio; /* see nvc.h GPIO notes */
+ struct nvc_imager_static_nvc *static_info;
+ bool use_vcm_vdd;
+ int (*probe_clock)(unsigned long);
+ int (*power_on)(struct imx327_power_rail *);
+ int (*power_off)(struct imx327_power_rail *);
+ const char *mclk_name;
+ struct nvc_imager_cap *cap;
+ struct imx327_regulators regulators;
+ bool has_eeprom;
+ bool use_cam_gpio;
+};
+
+#endif /* __AR0144_H__ */