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__ */