├── patches_nano └── patches │ ├── series │ └── 4.6.4_nano_imx708_v0.1.0.patch ├── patches_orin_nano └── patches │ ├── series │ ├── 6.0_orin_nano_imx708_v0.1.0.patch │ └── 5.1.1_nano_imx708_v0.1.0.patch └── README.md /patches_nano/patches/series: -------------------------------------------------------------------------------- 1 | 4.6.4_nano_imx708_v0.1.0.patch 2 | -------------------------------------------------------------------------------- /patches_orin_nano/patches/series: -------------------------------------------------------------------------------- 1 | 5.1.1_nano_imx708_v0.1.0.patch 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NVIDIA Jetson IMX708 RPI V3 camera driver 2 | This driver has been developed by RidgeRun Engineering as an initiative in order to release the first version of the Sony IMX708 sensor driver for the Raspberry Pi Camera Module 3. 3 | 4 | Supports the following Jetson platforms: 5 | * Jetson Orin Nano 6 | * Jetson Nano 7 | 8 | ## Repository structure 9 | 10 | In this repository you will find the following structure: 11 | ``` 12 | . 13 | ├── patches_nano 14 | │   └── patches 15 | │   ├── 4.6.4_nano_imx708_v0.1.0.patch 16 | │   └── series 17 | ├── patches_orin_nano 18 | │   └── patches 19 | │   ├── 5.1.1_nano_imx708_v0.1.0.patch 20 | │   ├── 6.0_orin_nano_imx708_v0.1.0.patch 21 | │   └── series 22 | └── README.md 23 | ``` 24 | where: 25 | 26 | * `5.1.1_nano_imx708-v0.1.0.patch` is the patch to be applied on the JetPack 5.1.1 sources in order to add support for the IMX708 camera sensor in the Jetson Orin Nano. 27 | * `6.0_orin_nano_imx708-v0.1.0.patch` is the patch to be applied on the JetPack 6.0 sources in order to add support for the IMX708 camera sensor in the Jetson Orin Nano. 28 | * `4.6.4_nano_imx708-v0.1.0.patch` is the patch to be applied on the JetPack 4.6.4 sources in order to add support for the IMX708 camera sensor in the Jetson Nano. 29 | * `series` is a file containing the patch name in order to apply it by using the quilt tool. JetPack 6.0 patch uses git to apply the patch. 30 | 31 | ## JetPack installation instructions 32 | 33 | You can download and install the JetPack by following the instructions below: 34 | 35 | * [JetPack download and installation instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Download_JetPack) 36 | 37 | ## Driver Installation instructions 38 | 39 | There are two options to install the driver: 40 | 41 | ### OPTION A: Installing the kernel and dtb debians (Recommended) 42 | 43 | **Note:** JetPack 6.0 is not supported using this method. 44 | 45 | This is the easiest and fastest way to install the driver. In order to install the debian packages you just need to perform the following instructions: 46 | 47 | * [Installing debians](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Installing_the_Driver_-_Option_A:_Debian_Packages_.28Recommended.29) 48 | 49 | ### OPTION B: Applying the patches on the sources 50 | 51 | In order to apply the patch on the JetPack sources with Orin Nano and Nano support, you must perform the following instructions: 52 | #### For Jetson Orin Nano #### 53 | * [Install required software](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Install_dependencies) 54 | * [JetPack sources download instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Get_the_source_code_from_NVIDIA_oficial_repository) 55 | * [Patch instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Get_the_driver_patches) 56 | * [Setup toolchain](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Set_up_the_toolchain) 57 | * [Kernel build instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Build) 58 | * [Flash the Jetson](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Installation_options) 59 | #### For Jetson Nano #### 60 | * [Install required software](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Install_dependencies) 61 | * [JetPack sources download instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Get_the_source_code_from_NVIDIA_oficial_repository) 62 | * [Patch instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Get_the_driver_patches_2) 63 | * [Setup toolchain](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Set_up_the_toolchain_2) 64 | * [Kernel build instructions](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Build_2) 65 | * [Flash the Jetson](https://developer.ridgerun.com/wiki/index.php/Raspberry_Pi_Camera_Module_3_IMX708_Linux_driver_for_Jetson#Installation_options_2) 66 | 67 | ## Supported features 68 | 69 | ### Resolutions and framerates 70 | 71 | * 4608x2592 @ 14fps 72 | 73 | ### Controls 74 | 75 | * Gain 76 | * Exposure 77 | * Framerate 78 | * Group Hold 79 | 80 | ## Example pipelines 81 | 82 | ### Display 83 | 84 | * 4608x2592 85 | 86 | ``` 87 | SENSOR_ID=0 # 0 for CAM0 port 88 | FRAMERATE=14 # Framerate can go from 2 to 14 for 4608x2592 mode 89 | gst-launch-1.0 nvarguscamerasrc sensor-id=$SENSOR_ID ! "video/x-raw(memory:NVMM),width=4608,height=2592,framerate=$FRAMERATE/1" ! queue ! nvegltransform ! nveglglessink 90 | ``` 91 | 92 | 93 | ### MP4 Recording 94 | 95 | * 4608x2592 96 | 97 | ``` 98 | SENSOR_ID=0 # 0 for CAM0 port 99 | FRAMERATE=14 # Framerate can go from 2 to 14 for 4608x2592 mode 100 | gst-launch-1.0 -e nvarguscamerasrc sensor-id=$SENSOR_ID ! "video/x-raw(memory:NVMM),width=4608,height=2592,framerate=$FRAMERATE/1" ! nvv4l2h264enc ! h264parse ! mp4mux ! filesink location=rpi_v3_imx708_cam$SENSOR_ID.mp4 101 | ``` 102 | 103 | ### JPEG snapshots 104 | 105 | * 4608x2592 106 | 107 | ``` 108 | SENSOR_ID=0 # 0 for CAM0 port 109 | FRAMERATE=60 # Framerate can go from 2 to 14 for 4608x2592 mode 110 | NUMBER_OF_SNAPSHOTS=20 111 | gst-launch-1.0 -e nvarguscamerasrc num-buffers=$NUMBER_OF_SNAPSHOTS sensor-id=$SENSOR_ID ! "video/x-raw(memory:NVMM),width=4608,height=2592,framerate=$FRAMERATE/1" ! nvjpegenc ! multifilesink location=%03d_rpi_v3_imx708_cam$SENSOR_ID.jpeg 112 | ``` 113 | 114 | 115 | ## RidgeRun 116 | 117 | Check our other products in [ridgerun.com](https://www.ridgerun.com) and don't hesitate to contact us if you have any kind of problem with the instructions given by reaching us at https://www.ridgerun.com/contact 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /patches_orin_nano/patches/6.0_orin_nano_imx708_v0.1.0.patch: -------------------------------------------------------------------------------- 1 | From 249edacf088c14cc613cdd9653afbfe0d53202d3 Mon Sep 17 00:00:00 2001 2 | From: David_M 3 | Date: Wed, 2 Oct 2024 18:05:05 -0600 4 | Subject: [PATCH] Squashed commit of the following: 5 | 6 | commit cc7210a7c0ef808409681b79358b4b0eee892d8b 7 | Author: David_M 8 | Date: Wed Oct 2 18:04:41 2024 -0600 9 | 10 | Delete unused data from the device tree 11 | 12 | commit 9374d3ac41796ef8965d8f65cc0efefd3ed267b2 13 | Author: David_M 14 | Date: Tue Oct 1 11:22:28 2024 -0600 15 | 16 | Remove imx219 dtsi from the overlay 17 | 18 | commit e9e426d3eb2c7f9bc9abb871e17bcb2ab4eceb7d 19 | Author: David_M 20 | Date: Mon Sep 30 17:33:42 2024 -0600 21 | 22 | Add include statement to overlay 23 | 24 | commit 5b726760d3338fde97d085d7cca52895c72127fe 25 | Author: David_M 26 | Date: Mon Sep 30 17:32:58 2024 -0600 27 | 28 | Add driver to defconfig 29 | 30 | commit aad5021104e163fb7b15dec51bed11f33bedb3c3 31 | Author: David_M 32 | Date: Mon Sep 30 17:32:39 2024 -0600 33 | 34 | Add Kconfig description 35 | 36 | commit a57de79fff5e04a748c3cac6f09d2b03fd4e9332 37 | Author: David_M 38 | Date: Mon Sep 30 17:31:51 2024 -0600 39 | 40 | Change i2c drivers Makefile 41 | 42 | commit 6ace3fd21f58ff111b94198f380ee5907ab07216 43 | Author: David_M 44 | Date: Mon Sep 30 17:29:19 2024 -0600 45 | 46 | Add modes table 47 | 48 | commit ae347f0dbb7c05fadfb1f7761cdc3a86457c8176 49 | Author: David_M 50 | Date: Mon Sep 30 17:28:55 2024 -0600 51 | 52 | Add driver and header file 53 | 54 | commit 2697d531a6cf4171a6a2da2d4fb78e004ee0c0ea 55 | Author: David_M 56 | Date: Mon Sep 30 17:28:24 2024 -0600 57 | 58 | Add dtsi files 59 | --- 60 | .../tegra234-camera-rpicam3-imx708.dtsi | 278 +++++++ 61 | ...tegra234-p3768-0000+p3767-0000-dynamic.dts | 2 +- 62 | .../tegra234-p3768-camera-rpicam3-imx708.dtsi | 69 ++ 63 | .../arch/arm64/configs/defconfig | 1 + 64 | .../drivers/media/i2c/Kconfig | 9 + 65 | nvidia-oot/drivers/media/i2c/Makefile | 1 + 66 | .../drivers/media/i2c/imx708_mode_tbls.h | 222 +++++ 67 | nvidia-oot/drivers/media/i2c/nv_imx708.c | 773 ++++++++++++++++++ 68 | nvidia-oot/include/media/imx708.h | 53 ++ 69 | 9 files changed, 1407 insertions(+), 1 deletion(-) 70 | create mode 100644 hardware/nvidia/t23x/nv-public/overlay/tegra234-camera-rpicam3-imx708.dtsi 71 | create mode 100644 hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-camera-rpicam3-imx708.dtsi 72 | create mode 100644 nvidia-oot/drivers/media/i2c/imx708_mode_tbls.h 73 | create mode 100644 nvidia-oot/drivers/media/i2c/nv_imx708.c 74 | create mode 100644 nvidia-oot/include/media/imx708.h 75 | 76 | diff --git a/hardware/nvidia/t23x/nv-public/overlay/tegra234-camera-rpicam3-imx708.dtsi b/hardware/nvidia/t23x/nv-public/overlay/tegra234-camera-rpicam3-imx708.dtsi 77 | new file mode 100644 78 | index 000000000..1438d2515 79 | --- /dev/null 80 | +++ b/hardware/nvidia/t23x/nv-public/overlay/tegra234-camera-rpicam3-imx708.dtsi 81 | @@ -0,0 +1,278 @@ 82 | +/* 83 | + * Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. 84 | + * Copyright (c) 2023, RidgeRun . All rights reserved 85 | + * 86 | + * This program is free software; you can redistribute it and/or modify 87 | + * it under the terms of the GNU General Public License as published by 88 | + * the Free Software Foundation; either version 2 of the License, or 89 | + * (at your option) any later version. 90 | + * 91 | + * This program is distributed in the hope that it will be useful, but WITHOUT 92 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 93 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 94 | + * more details. 95 | + * 96 | + * You should have received a copy of the GNU General Public License 97 | + * along with this program. If not, see . 98 | + */ 99 | + 100 | +/ { 101 | + fragment-camera@0 { 102 | + target-path = "/"; 103 | + __overlay__ { 104 | + tegra-capture-vi { 105 | + num-channels = <2>; 106 | + ports { 107 | + #address-cells = <1>; 108 | + #size-cells = <0>; 109 | + vi_port0: port@0 { 110 | + reg = <0>; 111 | + rpicam3_imx708_vi_in0: endpoint { 112 | + status="okay"; 113 | + port-index = <0>; 114 | + bus-width = <2>; 115 | + remote-endpoint = <&rpicam3_imx708_csi_out0>; 116 | + }; 117 | + }; 118 | + vi_port1: port@1 { 119 | + reg = <1>; 120 | + rpicam3_imx708_vi_in1: endpoint { 121 | + status="okay"; 122 | + port-index = <2>; 123 | + bus-width = <2>; 124 | + remote-endpoint = <&rpicam3_imx708_csi_out1>; 125 | + }; 126 | + }; 127 | + }; 128 | + }; 129 | + 130 | + bus@0 { 131 | + host1x@13e00000 { 132 | + nvcsi@15a00000 { 133 | + num-channels = <2>; 134 | + #address-cells = <1>; 135 | + #size-cells = <0>; 136 | + csi_chan0: channel@0 { 137 | + reg = <0>; 138 | + ports { 139 | + #address-cells = <1>; 140 | + #size-cells = <0>; 141 | + csi_chan0_port0: port@0 { 142 | + reg = <0>; 143 | + rpicam3_imx708_csi_in0: endpoint@0 { 144 | + status = "okay"; 145 | + port-index = <1>; 146 | + bus-width = <2>; 147 | + remote-endpoint = <&rpicam3_imx708_out0>; 148 | + }; 149 | + }; 150 | + csi_chan0_port1: port@1 { 151 | + reg = <1>; 152 | + rpicam3_imx708_csi_out0: endpoint@1 { 153 | + status = "okay"; 154 | + remote-endpoint = <&rpicam3_imx708_vi_in0>; 155 | + }; 156 | + }; 157 | + }; 158 | + }; 159 | + csi_chan1: channel@1 { 160 | + reg = <1>; 161 | + ports { 162 | + #address-cells = <1>; 163 | + #size-cells = <0>; 164 | + csi_chan1_port0: port@0 { 165 | + reg = <0>; 166 | + rpicam3_imx708_csi_in1: endpoint@2 { 167 | + status = "okay"; 168 | + port-index = <2>; 169 | + bus-width = <2>; 170 | + remote-endpoint = <&rpicam3_imx708_out1>; 171 | + }; 172 | + }; 173 | + csi_chan1_port1: port@1 { 174 | + reg = <1>; 175 | + rpicam3_imx708_csi_out1: endpoint@3 { 176 | + status = "okay"; 177 | + remote-endpoint = <&rpicam3_imx708_vi_in1>; 178 | + }; 179 | + }; 180 | + }; 181 | + }; 182 | + }; 183 | + }; 184 | + 185 | + cam_i2cmux { 186 | + i2c_0:i2c@0 { 187 | + imx708_cam0: rpicam3_imx708_a@1a { 188 | + status = "okay"; 189 | + compatible = "sony,imx708"; 190 | + reg = <0x1a>; 191 | + devnode = "video0"; 192 | + physical_w = "3.680"; 193 | + physical_h = "2.760"; 194 | + sensor_model = "imx708"; 195 | + use_sensor_mode_id = "true"; 196 | + 197 | + /* IMX708_MODE_4608x2592_14fps */ 198 | + mode0 { 199 | + mclk_khz = "24000"; 200 | + num_lanes = "2"; 201 | + tegra_sinterface = "serial_a"; 202 | + phy_mode = "DPHY"; 203 | + discontinuous_clk = "yes"; 204 | + dpcm_enable = "false"; 205 | + cil_settletime = "0"; 206 | + lane_polarity = "6"; 207 | + 208 | + active_w = "4608"; 209 | + active_h = "2592"; 210 | + mode_type = "bayer"; 211 | + pixel_phase = "rggb"; 212 | + csi_pixel_bit_depth = "10"; 213 | + readout_orientation = "90"; 214 | + line_length = "4808"; 215 | + inherent_gain = "1"; 216 | + pix_clk_hz = "297600000"; 217 | + 218 | + gain_factor = "16"; 219 | + framerate_factor = "1000000"; 220 | + exposure_factor = "1000000"; 221 | + min_gain_val = "16"; 222 | + max_gain_val = "256"; 223 | + step_gain_val = "1"; 224 | + default_gain = "16"; 225 | + min_hdr_ratio = "1"; 226 | + max_hdr_ratio = "1"; 227 | + min_framerate = "2000000"; 228 | + max_framerate = "14000000"; 229 | + step_framerate = "1"; 230 | + default_framerate = "14000000"; 231 | + min_exp_time = "500"; 232 | + max_exp_time = "65487"; 233 | + step_exp_time = "1"; 234 | + default_exp_time = "1600"; 235 | + embedded_metadata_height = "4"; 236 | + }; 237 | + 238 | + ports { 239 | + #address-cells = <1>; 240 | + #size-cells = <0>; 241 | + 242 | + port@0 { 243 | + reg = <0>; 244 | + rpicam3_imx708_out0: endpoint { 245 | + port-index = <0>; 246 | + bus-width = <2>; 247 | + remote-endpoint = <&rpicam3_imx708_csi_in0>; 248 | + }; 249 | + }; 250 | + }; 251 | + }; 252 | + }; 253 | + i2c_1: i2c@1 { 254 | + imx708_cam1: rpicam3_imx708_c@1a { 255 | + status = "okay"; 256 | + compatible = "sony,imx708"; 257 | + reg = <0x1a>; 258 | + devnode = "video1"; 259 | + physical_w = "3.680"; 260 | + physical_h = "2.760"; 261 | + sensor_model = "imx708"; 262 | + use_sensor_mode_id = "true"; 263 | + 264 | + /* IMX708_MODE_4608x2592_14fps */ 265 | + mode0 { 266 | + mclk_khz = "24000"; 267 | + num_lanes = "2"; 268 | + tegra_sinterface = "serial_c"; 269 | + phy_mode = "DPHY"; 270 | + discontinuous_clk = "yes"; 271 | + dpcm_enable = "false"; 272 | + cil_settletime = "0"; 273 | + lane_polarity = "0"; 274 | + 275 | + active_w = "4608"; 276 | + active_h = "2592"; 277 | + mode_type = "bayer"; 278 | + pixel_phase = "rggb"; 279 | + csi_pixel_bit_depth = "10"; 280 | + readout_orientation = "90"; 281 | + line_length = "4808"; 282 | + inherent_gain = "1"; 283 | + pix_clk_hz = "297600000"; 284 | + 285 | + gain_factor = "16"; 286 | + framerate_factor = "1000000"; 287 | + exposure_factor = "1000000"; 288 | + min_gain_val = "16"; 289 | + max_gain_val = "256"; 290 | + step_gain_val = "1"; 291 | + default_gain = "16"; 292 | + min_hdr_ratio = "1"; 293 | + max_hdr_ratio = "1"; 294 | + min_framerate = "2000000"; 295 | + max_framerate = "14000000"; 296 | + step_framerate = "1"; 297 | + default_framerate = "14000000"; 298 | + min_exp_time = "500"; 299 | + max_exp_time = "65487"; 300 | + step_exp_time = "1"; 301 | + default_exp_time = "1600"; 302 | + embedded_metadata_height = "4"; 303 | + }; 304 | + 305 | + ports { 306 | + #address-cells = <1>; 307 | + #size-cells = <0>; 308 | + 309 | + port@0 { 310 | + reg = <0>; 311 | + rpicam3_imx708_out1: endpoint { 312 | + status = "okay"; 313 | + port-index = <2>; 314 | + bus-width = <2>; 315 | + remote-endpoint = <&rpicam3_imx708_csi_in1>; 316 | + }; 317 | + }; 318 | + }; 319 | + }; 320 | + }; 321 | + }; 322 | + }; 323 | + 324 | + tcp: tegra-camera-platform { 325 | + compatible = "nvidia, tegra-camera-platform"; 326 | + num_csi_lanes = <4>; 327 | + max_lane_speed = <2500000>; 328 | + min_bits_per_pixel = <10>; 329 | + vi_peak_byte_per_pixel = <2>; 330 | + vi_bw_margin_pct = <25>; 331 | + max_pixel_rate = <7500000>; 332 | + isp_peak_byte_per_pixel = <5>; 333 | + isp_bw_margin_pct = <25>; 334 | + 335 | + modules { 336 | + cam_module0: module0 { 337 | + status = "okay"; 338 | + badge = "jakku_front_RBPCV3"; 339 | + position = "front"; 340 | + orientation = "1"; 341 | + cam_module0_drivernode0: drivernode0 { 342 | + pcl_id = "v4l2_sensor"; 343 | + sysfs-device-tree = "/sys/firmware/devicetree/base/bus@0/cam_i2cmux/i2c@0/rpicam3_imx708_a@1a"; 344 | + }; 345 | + }; 346 | + cam_module1: module1 { 347 | + badge = "jakku_rear_RBPCV3"; 348 | + position = "rear"; 349 | + orientation = "1"; 350 | + cam_module1_drivernode0: drivernode0 { 351 | + pcl_id = "v4l2_sensor"; 352 | + sysfs-device-tree = "/sys/firmware/devicetree/base/bus@0/cam_i2cmux/i2c@1/rpicam3_imx708_c@1a"; 353 | + }; 354 | + }; 355 | + }; 356 | + }; 357 | + }; 358 | + }; 359 | +}; 360 | diff --git a/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-0000+p3767-0000-dynamic.dts b/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-0000+p3767-0000-dynamic.dts 361 | index b9fed3958..3350ae3df 100644 362 | --- a/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-0000+p3767-0000-dynamic.dts 363 | +++ b/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-0000+p3767-0000-dynamic.dts 364 | @@ -4,7 +4,7 @@ 365 | /dts-v1/; 366 | /plugin/; 367 | 368 | -#include "tegra234-p3768-camera-rbpcv2-imx219.dtsi" 369 | +#include "tegra234-p3768-camera-rpicam3-imx708.dtsi" 370 | 371 | / { 372 | overlay-name = "Tegra234 p3768-0000+p3767-xxxx Dynamic Overlay"; 373 | diff --git a/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-camera-rpicam3-imx708.dtsi b/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-camera-rpicam3-imx708.dtsi 374 | new file mode 100644 375 | index 000000000..2cf415df9 376 | --- /dev/null 377 | +++ b/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3768-camera-rpicam3-imx708.dtsi 378 | @@ -0,0 +1,69 @@ 379 | +/* 380 | + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. 381 | + * Copyright (c) 2023, RidgeRun. All rights reserved. 382 | + * 383 | + * This program is free software; you can redistribute it and/or modify 384 | + * it under the terms of the GNU General Public License as published by 385 | + * the Free Software Foundation; either version 2 of the License, or 386 | + * (at your option) any later version. 387 | + * 388 | + * This program is distributed in the hope that it will be useful, but WITHOUT 389 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 390 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 391 | + * more details. 392 | + * 393 | + * You should have received a copy of the GNU General Public License 394 | + * along with this program. If not, see . 395 | + */ 396 | + 397 | +#include 398 | +#include "tegra234-camera-rpicam3-imx708.dtsi" 399 | + 400 | +#define CAM0_RST TEGRA234_MAIN_GPIO(H, 3) 401 | +#define CAM0_PWDN TEGRA234_MAIN_GPIO(H, 6) 402 | +#define CAM1_PWDN TEGRA234_MAIN_GPIO(AC, 0) 403 | +#define CAM_I2C_MUX TEGRA234_AON_GPIO(CC, 3) 404 | + 405 | +/ { 406 | + fragment-camera-imx708@0 { 407 | + target-path = "/"; 408 | + __overlay__ { 409 | + bus@0 { 410 | + cam_i2cmux { 411 | + status = "okay"; 412 | + compatible = "i2c-mux-gpio"; 413 | + #address-cells = <1>; 414 | + #size-cells = <0>; 415 | + mux-gpios = <&gpio_aon CAM_I2C_MUX GPIO_ACTIVE_HIGH>; 416 | + i2c-parent = <&cam_i2c>; 417 | + i2c@0 { 418 | + reg = <0>; 419 | + #address-cells = <1>; 420 | + #size-cells = <0>; 421 | + rpicam3_imx708_a@1a { 422 | + reset-gpios = <&gpio CAM0_PWDN GPIO_ACTIVE_HIGH>; 423 | + }; 424 | + }; 425 | + i2c@1 { 426 | + status = "okay"; 427 | + reg = <1>; 428 | + #address-cells = <1>; 429 | + #size-cells = <0>; 430 | + rpicam3_imx708_c@1a { 431 | + reset-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>; 432 | + }; 433 | + }; 434 | + }; 435 | + 436 | + gpio@2200000 { 437 | + camera-control-output-low { 438 | + gpio-hog; 439 | + output-low; 440 | + gpios = ; 441 | + label = "cam0-rst"; 442 | + }; 443 | + }; 444 | + }; 445 | + }; 446 | + }; 447 | +}; 448 | diff --git a/kernel/kernel-jammy-src/arch/arm64/configs/defconfig b/kernel/kernel-jammy-src/arch/arm64/configs/defconfig 449 | index 57e2a364e..bebf12dc8 100644 450 | --- a/kernel/kernel-jammy-src/arch/arm64/configs/defconfig 451 | +++ b/kernel/kernel-jammy-src/arch/arm64/configs/defconfig 452 | @@ -1329,3 +1329,4 @@ CONFIG_FUNCTION_TRACER=y 453 | # CONFIG_FUNCTION_GRAPH_TRACER is not set 454 | # CONFIG_DYNAMIC_FTRACE is not set 455 | CONFIG_MEMTEST=y 456 | +CONFIG_NV_VIDEO_IMX708=m 457 | diff --git a/kernel/kernel-jammy-src/drivers/media/i2c/Kconfig b/kernel/kernel-jammy-src/drivers/media/i2c/Kconfig 458 | index 67b15c24e..04cb16c38 100644 459 | --- a/kernel/kernel-jammy-src/drivers/media/i2c/Kconfig 460 | +++ b/kernel/kernel-jammy-src/drivers/media/i2c/Kconfig 461 | @@ -883,6 +883,15 @@ config VIDEO_IMX412 462 | To compile this driver as a module, choose M here: the 463 | module will be called imx412. 464 | 465 | +config NV_VIDEO_IMX708 466 | + tristate "Sony IMX708 sensor support" 467 | + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 468 | + help 469 | + This driver supports IMX708 camera sensor from Sony 470 | + 471 | + To compile this driver as a module, choose M here: the module 472 | + will be called IMX708. 473 | + 474 | config VIDEO_OV02A10 475 | tristate "OmniVision OV02A10 sensor support" 476 | depends on VIDEO_V4L2 && I2C 477 | diff --git a/nvidia-oot/drivers/media/i2c/Makefile b/nvidia-oot/drivers/media/i2c/Makefile 478 | index 7c5913c64..0ba7d6e5e 100644 479 | --- a/nvidia-oot/drivers/media/i2c/Makefile 480 | +++ b/nvidia-oot/drivers/media/i2c/Makefile 481 | @@ -17,6 +17,7 @@ obj-m += nv_imx274.o 482 | obj-m += nv_imx318.o 483 | obj-m += nv_imx390.o 484 | obj-m += nv_imx477.o 485 | +obj-$(CONFIG_NV_VIDEO_IMX708) += nv_imx708.o 486 | obj-m += nv_ov5693.o 487 | obj-m += nv_ar0234.o 488 | obj-m += nv_hawk_owl.o 489 | diff --git a/nvidia-oot/drivers/media/i2c/imx708_mode_tbls.h b/nvidia-oot/drivers/media/i2c/imx708_mode_tbls.h 490 | new file mode 100644 491 | index 000000000..7d975066e 492 | --- /dev/null 493 | +++ b/nvidia-oot/drivers/media/i2c/imx708_mode_tbls.h 494 | @@ -0,0 +1,222 @@ 495 | +/* 496 | + * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved. 497 | + * Copyright (C) 2022, Raspberry Pi Ltd 498 | + * Copyright (c) 2023, RidgeRun . All rights reserved 499 | + * 500 | + * This program is free software; you can redistribute it and/or modify 501 | + * it under the terms of the GNU General Public License as published by 502 | + * the Free Software Foundation; either version 2 of the License, or 503 | + * (at your option) any later version. 504 | + * 505 | + * This program is distributed in the hope that it will be useful, but WITHOUT 506 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 507 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 508 | + * more details. 509 | + * 510 | + * You should have received a copy of the GNU General Public License 511 | + * along with this program. If not, see . 512 | + */ 513 | + 514 | +#ifndef __IMX708_I2C_TABLES__ 515 | +#define __IMX708_I2C_TABLES__ 516 | + 517 | +#include 518 | + 519 | +#define IMX708_TABLE_WAIT_MS 0 520 | +#define IMX708_TABLE_END 1 521 | +#define IMX708_WAIT_MS 1 522 | +#define IMX708_STANDBY_REG 0x0100 523 | + 524 | +#define imx708_reg struct reg_8 525 | + 526 | +static const imx708_reg imx708_start[] = { 527 | + {IMX708_STANDBY_REG, 0x1}, 528 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*3}, 529 | + {IMX708_TABLE_END, 0x00} 530 | +}; 531 | + 532 | +static const imx708_reg imx708_stop[] = { 533 | + {IMX708_STANDBY_REG, 0x0}, 534 | + {IMX708_TABLE_END, 0x00} 535 | +}; 536 | + 537 | +static const imx708_reg imx708_mode_common[] = { 538 | + /* software reset */ 539 | + {0x0103, 0x01}, 540 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*10}, 541 | + {0x0100, 0x00}, 542 | + {0x0136, 0x18}, 543 | + {0x0137, 0x00}, 544 | + {0x33F0, 0x02}, 545 | + {0x33F1, 0x05}, 546 | + {0x3062, 0x00}, 547 | + {0x3063, 0x12}, 548 | + {0x3068, 0x00}, 549 | + {0x3069, 0x12}, 550 | + {0x306A, 0x00}, 551 | + {0x306B, 0x30}, 552 | + {0x3076, 0x00}, 553 | + {0x3077, 0x30}, 554 | + {0x3078, 0x00}, 555 | + {0x3079, 0x30}, 556 | + {0x5E54, 0x0C}, 557 | + {0x6E44, 0x00}, 558 | + {0xB0B6, 0x01}, 559 | + {0xE829, 0x00}, 560 | + {0xF001, 0x08}, 561 | + {0xF003, 0x08}, 562 | + {0xF00D, 0x10}, 563 | + {0xF00F, 0x10}, 564 | + {0xF031, 0x08}, 565 | + {0x0830, 0x01}, 566 | + {0x0831, 0x01}, 567 | + {0x0832, 0x01}, 568 | + {0xF033, 0x08}, 569 | + {0xF03D, 0x10}, 570 | + {0xF03F, 0x10}, 571 | + {0x0112, 0x0a}, 572 | + {0x0113, 0x0a}, 573 | + {0x0114, 0x01}, 574 | + {0x0B8E, 0x01}, 575 | + {0x0B8F, 0x00}, 576 | + {0x0B94, 0x01}, 577 | + {0x0B95, 0x00}, 578 | + {0x3400, 0x01}, 579 | + {0x3478, 0x01}, 580 | + {0x3479, 0x1c}, 581 | + {0x3091, 0x01}, 582 | + {0x3092, 0x00}, 583 | + {0x3419, 0x00}, 584 | + {0xBCF1, 0x02}, 585 | + {0x3094, 0x01}, 586 | + {0x3095, 0x01}, 587 | + {0x3362, 0x00}, 588 | + {0x3363, 0x00}, 589 | + {0x3364, 0x00}, 590 | + {0x3365, 0x00}, 591 | + {0x0138, 0x01}, 592 | + {IMX708_TABLE_END, 0x0000} 593 | +}; 594 | + 595 | +static const imx708_reg imx708_mode_4608x2592_14fps[] = { 596 | + {0x0342, 0x3D}, 597 | + {0x0343, 0x20}, 598 | + {0x0340, 0x0A}, 599 | + {0x0341, 0x5a}, 600 | + {0x0344, 0x00}, 601 | + {0x0345, 0x00}, 602 | + {0x0346, 0x00}, 603 | + {0x0347, 0x00}, 604 | + {0x0348, 0x11}, 605 | + {0x0349, 0xFF}, 606 | + {0x034A, 0X0A}, 607 | + {0x034B, 0x1F}, 608 | + {0x0220, 0x62}, 609 | + {0x0222, 0x01}, 610 | + {0x0900, 0x00}, 611 | + {0x0901, 0x11}, 612 | + {0x0902, 0x0A}, 613 | + {0x3200, 0x01}, 614 | + {0x3201, 0x01}, 615 | + {0x32D5, 0x01}, 616 | + {0x32D6, 0x00}, 617 | + {0x32DB, 0x01}, 618 | + {0x32DF, 0x00}, 619 | + {0x350C, 0x00}, 620 | + {0x350D, 0x00}, 621 | + {0x0408, 0x00}, 622 | + {0x0409, 0x00}, 623 | + {0x040A, 0x00}, 624 | + {0x040B, 0x00}, 625 | + {0x040C, 0x12}, 626 | + {0x040D, 0x00}, 627 | + {0x040E, 0x0A}, 628 | + {0x040F, 0x20}, 629 | + {0x034C, 0x12}, 630 | + {0x034D, 0x00}, 631 | + {0x034E, 0x0A}, 632 | + {0x034F, 0x20}, 633 | + {0x0301, 0x05}, 634 | + {0x0303, 0x02}, 635 | + {0x0305, 0x02}, 636 | + {0x0306, 0x00}, 637 | + {0x0307, 0x7C}, 638 | + {0x030B, 0x02}, 639 | + {0x030D, 0x04}, 640 | + {0x030E, 0x01}, 641 | + {0x030F, 0x2C}, 642 | + {0x0310, 0x01}, 643 | + {0x3CA0, 0x00}, 644 | + {0x3CA1, 0x64}, 645 | + {0x3CA4, 0x00}, 646 | + {0x3CA5, 0x00}, 647 | + {0x3CA6, 0x00}, 648 | + {0x3CA7, 0x00}, 649 | + {0x3CAA, 0x00}, 650 | + {0x3CAB, 0x00}, 651 | + {0x3CB8, 0x00}, 652 | + {0x3CB9, 0x08}, 653 | + {0x3CBA, 0x00}, 654 | + {0x3CBB, 0x00}, 655 | + {0x3CBC, 0x00}, 656 | + {0x3CBD, 0x3C}, 657 | + {0x3CBE, 0x00}, 658 | + {0x3CBF, 0x00}, 659 | + {0x0202, 0x0A}, 660 | + {0x0203, 0x2a}, 661 | + {0x0224, 0x01}, 662 | + {0x0225, 0xF4}, 663 | + {0x3116, 0x01}, 664 | + {0x3117, 0xF4}, 665 | + {0x0204, 0x03}, 666 | + {0x0205, 0x55}, 667 | + {0x0216, 0x00}, 668 | + {0x0217, 0x00}, 669 | + {0x0218, 0x01}, 670 | + {0x0219, 0x00}, 671 | + {0x020E, 0x01}, 672 | + {0x020F, 0x00}, 673 | + {0x3118, 0x00}, 674 | + {0x3119, 0x00}, 675 | + {0x311A, 0x01}, 676 | + {0x311B, 0x00}, 677 | + {0x341a, 0x00}, 678 | + {0x341b, 0x00}, 679 | + {0x341c, 0x00}, 680 | + {0x341d, 0x00}, 681 | + {0x341e, 0x01}, 682 | + {0x341f, 0x20}, 683 | + {0x3420, 0x00}, 684 | + {0x3421, 0xd8}, 685 | + {0xC428, 0x00}, 686 | + {0xC429, 0x04}, 687 | + {0x3366, 0x00}, 688 | + {0x3367, 0x00}, 689 | + {0x3368, 0x00}, 690 | + {0x3369, 0x00}, 691 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS}, 692 | + {IMX708_TABLE_END, 0x0000} 693 | +}; 694 | + 695 | +enum { 696 | + IMX708_MODE_4608x2592_14FPS, 697 | + IMX708_MODE_COMMON, 698 | + IMX708_START_STREAM, 699 | + IMX708_STOP_STREAM, 700 | +}; 701 | + 702 | +static const imx708_reg *mode_table[] = { 703 | + [IMX708_MODE_4608x2592_14FPS] = imx708_mode_4608x2592_14fps, 704 | + [IMX708_MODE_COMMON] = imx708_mode_common, 705 | + [IMX708_START_STREAM] = imx708_start, 706 | + [IMX708_STOP_STREAM] = imx708_stop, 707 | +}; 708 | + 709 | +static const int imx708_14_fr[] = { 710 | + 14, 711 | +}; 712 | + 713 | +static const struct camera_common_frmfmt imx708_frmfmt[] = { 714 | + {{4608, 2592}, imx708_14_fr, 1, 0, IMX708_MODE_4608x2592_14FPS}, 715 | +}; 716 | +#endif 717 | diff --git a/nvidia-oot/drivers/media/i2c/nv_imx708.c b/nvidia-oot/drivers/media/i2c/nv_imx708.c 718 | new file mode 100644 719 | index 000000000..4db5a7b54 720 | --- /dev/null 721 | +++ b/nvidia-oot/drivers/media/i2c/nv_imx708.c 722 | @@ -0,0 +1,773 @@ 723 | +/* 724 | + * imx708.c - imx708 sensor driver 725 | + * 726 | + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. 727 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 728 | + * 729 | + * Contact us: support@ridgerun.com 730 | + * 731 | + * This program is free software; you can redistribute it and/or modify it 732 | + * under the terms and conditions of the GNU General Public License, 733 | + * version 2, as published by the Free Software Foundation. 734 | + * 735 | + * This program is distributed in the hope it will be useful, but WITHOUT 736 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 737 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 738 | + * more details. 739 | + * 740 | + * You should have received a copy of the GNU General Public License 741 | + * along with this program. If not, see . 742 | + */ 743 | + 744 | +#include 745 | +#include 746 | +#include 747 | +#include 748 | +#include 749 | + 750 | +#include "../platform/tegra/camera/camera_gpio.h" 751 | +#include "imx708_mode_tbls.h" 752 | + 753 | +static const struct of_device_id imx708_of_match[] = { 754 | + {.compatible = "sony,imx708",}, 755 | + {}, 756 | +}; 757 | + 758 | +MODULE_DEVICE_TABLE(of, imx708_of_match); 759 | + 760 | +static const u32 ctrl_cid_list[] = { 761 | + TEGRA_CAMERA_CID_GAIN, 762 | + TEGRA_CAMERA_CID_EXPOSURE, 763 | + TEGRA_CAMERA_CID_FRAME_RATE, 764 | + TEGRA_CAMERA_CID_SENSOR_MODE_ID, 765 | +}; 766 | + 767 | +struct imx708 { 768 | + struct i2c_client *i2c_client; 769 | + struct v4l2_subdev *subdev; 770 | + u16 fine_integ_time; 771 | + u32 frame_length; 772 | + struct camera_common_data *s_data; 773 | + struct tegracam_device *tc_dev; 774 | +}; 775 | + 776 | +static const struct regmap_config sensor_regmap_config = { 777 | + .reg_bits = 16, 778 | + .val_bits = 8, 779 | + .cache_type = REGCACHE_RBTREE, 780 | +#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE 781 | + .use_single_rw = true, 782 | +#else 783 | + .use_single_read = true, 784 | + .use_single_write = true, 785 | +#endif 786 | +}; 787 | + 788 | +static inline void imx708_get_frame_length_regs(imx708_reg * regs, 789 | + u32 frame_length) 790 | +{ 791 | + regs->addr = IMX708_FRAME_LENGTH_ADDR_MSB; 792 | + regs->val = (frame_length >> 8) & 0xff; 793 | + (regs + 1)->addr = IMX708_FRAME_LENGTH_ADDR_LSB; 794 | + (regs + 1)->val = (frame_length) & 0xff; 795 | +} 796 | + 797 | +static inline void imx708_get_coarse_integ_time_regs(imx708_reg * regs, 798 | + u32 coarse_time) 799 | +{ 800 | + regs->addr = IMX708_COARSE_INTEG_TIME_ADDR_MSB; 801 | + regs->val = (coarse_time >> 8) & 0xff; 802 | + (regs + 1)->addr = IMX708_COARSE_INTEG_TIME_ADDR_LSB; 803 | + (regs + 1)->val = (coarse_time) & 0xff; 804 | +} 805 | + 806 | +static inline void imx708_get_gain_reg(imx708_reg * reg, u16 gain) 807 | +{ 808 | + reg->addr = IMX708_ANALOG_GAIN_ADDR_MSB; 809 | + reg->val = (gain >> IMX708_SHIFT_8_BITS) & IMX708_MASK_LSB_2_BITS; 810 | + 811 | + (reg + 1)->addr = IMX708_ANALOG_GAIN_ADDR_LSB; 812 | + (reg + 1)->val = (gain) & IMX708_MASK_LSB_8_BITS; 813 | +} 814 | + 815 | +static inline int imx708_read_reg(struct camera_common_data *s_data, 816 | + u16 addr, u8 * val) 817 | +{ 818 | + int err = 0; 819 | + u32 reg_val = 0; 820 | + 821 | + err = regmap_read(s_data->regmap, addr, ®_val); 822 | + *val = reg_val & 0xff; 823 | + 824 | + return err; 825 | +} 826 | + 827 | +static inline int imx708_write_reg(struct camera_common_data *s_data, 828 | + u16 addr, u8 val) 829 | +{ 830 | + int err = 0; 831 | + 832 | + err = regmap_write(s_data->regmap, addr, val); 833 | + if (err) 834 | + dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x", 835 | + __func__, addr, val); 836 | + 837 | + return err; 838 | +} 839 | + 840 | +static int imx708_write_table(struct imx708 *priv, const imx708_reg table[]) 841 | +{ 842 | + return regmap_util_write_table_8(priv->s_data->regmap, table, NULL, 0, 843 | + IMX708_TABLE_WAIT_MS, 844 | + IMX708_TABLE_END); 845 | +} 846 | + 847 | +static int imx708_set_group_hold(struct tegracam_device *tc_dev, bool val) 848 | +{ 849 | + struct camera_common_data *s_data = tc_dev->s_data; 850 | + struct device *dev = tc_dev->dev; 851 | + int err = 0; 852 | + 853 | + dev_dbg(dev, "%s: Setting group hold control to: %u\n", __func__, val); 854 | + 855 | + err = imx708_write_reg(s_data, IMX708_GROUP_HOLD_ADDR, val); 856 | + if (err) { 857 | + dev_err(dev, "%s: Group hold control error\n", __func__); 858 | + return err; 859 | + } 860 | + 861 | + return 0; 862 | +} 863 | + 864 | +static int imx708_get_fine_integ_time(struct imx708 *priv, u16 * fine_time) 865 | +{ 866 | + struct camera_common_data *s_data = priv->s_data; 867 | + int err = 0; 868 | + u8 reg_val[2] = {0}; 869 | + 870 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_MSB, 871 | + ®_val[0]); 872 | + if (err) 873 | + goto done; 874 | + 875 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_LSB, 876 | + ®_val[1]); 877 | + if (err) 878 | + goto done; 879 | + 880 | + *fine_time = (reg_val[0] << 8) | reg_val[1]; 881 | + 882 | +done: 883 | + return err; 884 | +} 885 | + 886 | +static int imx708_set_gain(struct tegracam_device *tc_dev, s64 val) 887 | +{ 888 | + struct camera_common_data *s_data = tc_dev->s_data; 889 | + struct device *dev = s_data->dev; 890 | + const struct sensor_mode_properties *mode = 891 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 892 | + int err = 0; 893 | + int i = 0; 894 | + imx708_reg gain_reg[2] = {0}; 895 | + s16 gain = 0; 896 | + 897 | + dev_dbg(dev, "%s: Setting gain control to: %lld\n", __func__, val); 898 | + 899 | + /* Gain Formula: 900 | + Gain = (IMX708_GAIN_C0 - (IMX708_GAIN_C0 * gain_factor / val)) 901 | + */ 902 | + gain = 903 | + (s16) (IMX708_ANALOG_GAIN_C0 - 904 | + (mode->control_properties.gain_factor * 905 | + IMX708_ANALOG_GAIN_C0 / val)); 906 | + 907 | + dev_dbg(dev, "%s: val: %lld (/%d) [times], gain: %u\n", 908 | + __func__, val, mode->control_properties.gain_factor, gain); 909 | + 910 | + imx708_get_gain_reg(gain_reg, (u16) gain); 911 | + 912 | + for (i = 0; i < ARRAY_SIZE(gain_reg); i++) { 913 | + err = imx708_write_reg(s_data, gain_reg[i].addr, 914 | + gain_reg[i].val); 915 | + if (err) { 916 | + dev_err(dev, "%s: gain control error\n", __func__); 917 | + break; 918 | + } 919 | + } 920 | + 921 | + return err; 922 | +} 923 | + 924 | +static int imx708_set_frame_rate(struct tegracam_device *tc_dev, s64 val) 925 | +{ 926 | + struct camera_common_data *s_data = tc_dev->s_data; 927 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 928 | + struct device *dev = tc_dev->dev; 929 | + const struct sensor_mode_properties *mode = 930 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 931 | + 932 | + int err = 0; 933 | + imx708_reg fl_regs[2] = {0}; 934 | + u32 frame_length = 0; 935 | + int i = 0; 936 | + 937 | + dev_dbg(dev, "%s: Setting framerate control to: %lld\n", __func__, val); 938 | + 939 | + frame_length = (u32)(mode->signal_properties.pixel_clock.val * 940 | + (u64)mode->control_properties.framerate_factor / 941 | + mode->image_properties.line_length / val); 942 | + 943 | + dev_dbg(dev, 944 | + "%s: val: %llde-6 [fps], frame_length: %u [lines]\n", 945 | + __func__, val, frame_length); 946 | + 947 | + imx708_get_frame_length_regs(fl_regs, frame_length); 948 | + for (i = 0; i < 2; i++) { 949 | + err = imx708_write_reg(s_data, fl_regs[i].addr, fl_regs[i].val); 950 | + if (err) { 951 | + dev_err(dev, 952 | + "%s: frame_length control error\n", __func__); 953 | + return err; 954 | + } 955 | + } 956 | + 957 | + priv->frame_length = frame_length; 958 | + 959 | + return err; 960 | +} 961 | + 962 | +static int imx708_set_exposure(struct tegracam_device *tc_dev, s64 val) 963 | +{ 964 | + struct camera_common_data *s_data = tc_dev->s_data; 965 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 966 | + struct device *dev = tc_dev->dev; 967 | + const struct sensor_mode_properties *mode = 968 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 969 | + 970 | + int err = 0; 971 | + imx708_reg ct_regs[2] = {0}; 972 | + const s32 fine_integ_time_factor = priv->fine_integ_time * 973 | + mode->control_properties.exposure_factor / 974 | + mode->signal_properties.pixel_clock.val; 975 | + u32 coarse_time = 0; 976 | + int i = 0; 977 | + 978 | + dev_dbg(dev, "%s: Setting exposure control to: %lld\n", __func__, val); 979 | + 980 | + coarse_time = (val - fine_integ_time_factor) 981 | + * mode->signal_properties.pixel_clock.val 982 | + / mode->control_properties.exposure_factor 983 | + / mode->image_properties.line_length; 984 | + 985 | + dev_dbg(dev, "%s: val: %lld [us], coarse_time: %d [lines]\n", 986 | + __func__, val, coarse_time); 987 | + 988 | + imx708_get_coarse_integ_time_regs(ct_regs, coarse_time); 989 | + 990 | + for (i = 0; i < 2; i++) { 991 | + err = imx708_write_reg(s_data, ct_regs[i].addr, ct_regs[i].val); 992 | + if (err) { 993 | + dev_err(dev, 994 | + "%s: coarse_time control error\n", __func__); 995 | + return err; 996 | + } 997 | + } 998 | + 999 | + return err; 1000 | +} 1001 | + 1002 | +static struct tegracam_ctrl_ops imx708_ctrl_ops = { 1003 | + .numctrls = ARRAY_SIZE(ctrl_cid_list), 1004 | + .ctrl_cid_list = ctrl_cid_list, 1005 | + .set_gain = imx708_set_gain, 1006 | + .set_exposure = imx708_set_exposure, 1007 | + .set_frame_rate = imx708_set_frame_rate, 1008 | + .set_group_hold = imx708_set_group_hold, 1009 | +}; 1010 | + 1011 | +static int imx708_power_on(struct camera_common_data *s_data) 1012 | +{ 1013 | + int err = 0; 1014 | + struct camera_common_power_rail *pw = s_data->power; 1015 | + struct camera_common_pdata *pdata = s_data->pdata; 1016 | + struct device *dev = s_data->dev; 1017 | + 1018 | + dev_dbg(dev, "%s: power on\n", __func__); 1019 | + if (pdata && pdata->power_on) { 1020 | + err = pdata->power_on(pw); 1021 | + if (err) 1022 | + dev_err(dev, "%s failed.\n", __func__); 1023 | + else 1024 | + pw->state = SWITCH_ON; 1025 | + return err; 1026 | + } 1027 | + 1028 | + if (pw->reset_gpio) { 1029 | + if (gpio_cansleep(pw->reset_gpio)) 1030 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 1031 | + else 1032 | + gpio_set_value(pw->reset_gpio, 0); 1033 | + } 1034 | + 1035 | + if (unlikely(!(pw->avdd || pw->iovdd || pw->dvdd))) 1036 | + goto skip_power_seqn; 1037 | + 1038 | + usleep_range(10, 20); 1039 | + 1040 | + if (pw->avdd) { 1041 | + err = regulator_enable(pw->avdd); 1042 | + if (err) 1043 | + goto imx708_avdd_fail; 1044 | + } 1045 | + 1046 | + if (pw->iovdd) { 1047 | + err = regulator_enable(pw->iovdd); 1048 | + if (err) 1049 | + goto imx708_iovdd_fail; 1050 | + } 1051 | + 1052 | + if (pw->dvdd) { 1053 | + err = regulator_enable(pw->dvdd); 1054 | + if (err) 1055 | + goto imx708_dvdd_fail; 1056 | + } 1057 | + 1058 | + usleep_range(10, 20); 1059 | + 1060 | +skip_power_seqn: 1061 | + if (pw->reset_gpio) { 1062 | + if (gpio_cansleep(pw->reset_gpio)) 1063 | + gpio_set_value_cansleep(pw->reset_gpio, 1); 1064 | + else 1065 | + gpio_set_value(pw->reset_gpio, 1); 1066 | + } 1067 | + 1068 | + /* Need to wait for t4 + t5 + t9 + t10 time as per the data sheet */ 1069 | + /* t4 - 200us, t5 - 21.2ms, t9 - 1.2ms t10 - 270 ms */ 1070 | + usleep_range(300000, 300100); 1071 | + 1072 | + pw->state = SWITCH_ON; 1073 | + 1074 | + return 0; 1075 | + 1076 | +imx708_dvdd_fail: 1077 | + regulator_disable(pw->iovdd); 1078 | + 1079 | +imx708_iovdd_fail: 1080 | + regulator_disable(pw->avdd); 1081 | + 1082 | +imx708_avdd_fail: 1083 | + dev_err(dev, "%s failed.\n", __func__); 1084 | + 1085 | + return -ENODEV; 1086 | +} 1087 | + 1088 | +static int imx708_power_off(struct camera_common_data *s_data) 1089 | +{ 1090 | + int err = 0; 1091 | + struct camera_common_power_rail *pw = s_data->power; 1092 | + struct camera_common_pdata *pdata = s_data->pdata; 1093 | + struct device *dev = s_data->dev; 1094 | + 1095 | + dev_dbg(dev, "%s: power off\n", __func__); 1096 | + 1097 | + if (pdata && pdata->power_off) { 1098 | + err = pdata->power_off(pw); 1099 | + if (err) { 1100 | + dev_err(dev, "%s failed.\n", __func__); 1101 | + return err; 1102 | + } 1103 | + } else { 1104 | + if (pw->reset_gpio) { 1105 | + if (gpio_cansleep(pw->reset_gpio)) 1106 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 1107 | + else 1108 | + gpio_set_value(pw->reset_gpio, 0); 1109 | + } 1110 | + 1111 | + usleep_range(10, 10); 1112 | + 1113 | + if (pw->dvdd) 1114 | + regulator_disable(pw->dvdd); 1115 | + if (pw->iovdd) 1116 | + regulator_disable(pw->iovdd); 1117 | + if (pw->avdd) 1118 | + regulator_disable(pw->avdd); 1119 | + } 1120 | + 1121 | + pw->state = SWITCH_OFF; 1122 | + 1123 | + return 0; 1124 | +} 1125 | + 1126 | +static int imx708_power_put(struct tegracam_device *tc_dev) 1127 | +{ 1128 | + struct camera_common_data *s_data = tc_dev->s_data; 1129 | + struct camera_common_power_rail *pw = s_data->power; 1130 | + 1131 | + if (unlikely(!pw)) 1132 | + return -EFAULT; 1133 | + 1134 | + if (likely(pw->dvdd)) 1135 | + devm_regulator_put(pw->dvdd); 1136 | + 1137 | + if (likely(pw->avdd)) 1138 | + devm_regulator_put(pw->avdd); 1139 | + 1140 | + if (likely(pw->iovdd)) 1141 | + devm_regulator_put(pw->iovdd); 1142 | + 1143 | + pw->dvdd = NULL; 1144 | + pw->avdd = NULL; 1145 | + pw->iovdd = NULL; 1146 | + 1147 | + if (likely(pw->reset_gpio)) 1148 | + gpio_free(pw->reset_gpio); 1149 | + 1150 | + return 0; 1151 | +} 1152 | + 1153 | +static int imx708_power_get(struct tegracam_device *tc_dev) 1154 | +{ 1155 | + struct device *dev = tc_dev->dev; 1156 | + struct camera_common_data *s_data = tc_dev->s_data; 1157 | + struct camera_common_power_rail *pw = s_data->power; 1158 | + struct camera_common_pdata *pdata = s_data->pdata; 1159 | + struct clk *parent; 1160 | + int err = 0; 1161 | + 1162 | + if (!pdata) { 1163 | + dev_err(dev, "pdata missing\n"); 1164 | + return -EFAULT; 1165 | + } 1166 | + 1167 | + /* Sensor MCLK (aka. INCK) */ 1168 | + if (pdata->mclk_name) { 1169 | + pw->mclk = devm_clk_get(dev, pdata->mclk_name); 1170 | + if (IS_ERR(pw->mclk)) { 1171 | + dev_err(dev, "unable to get clock %s\n", 1172 | + pdata->mclk_name); 1173 | + return PTR_ERR(pw->mclk); 1174 | + } 1175 | + 1176 | + if (pdata->parentclk_name) { 1177 | + parent = devm_clk_get(dev, pdata->parentclk_name); 1178 | + if (IS_ERR(parent)) { 1179 | + dev_err(dev, "unable to get parent clock %s", 1180 | + pdata->parentclk_name); 1181 | + } else 1182 | + clk_set_parent(pw->mclk, parent); 1183 | + } 1184 | + } 1185 | + 1186 | + /* analog 2.8v */ 1187 | + if (pdata->regulators.avdd) 1188 | + err |= camera_common_regulator_get(dev, 1189 | + &pw->avdd, 1190 | + pdata->regulators.avdd); 1191 | + /* IO 1.8v */ 1192 | + if (pdata->regulators.iovdd) 1193 | + err |= camera_common_regulator_get(dev, 1194 | + &pw->iovdd, 1195 | + pdata->regulators.iovdd); 1196 | + /* dig 1.2v */ 1197 | + if (pdata->regulators.dvdd) 1198 | + err |= camera_common_regulator_get(dev, 1199 | + &pw->dvdd, 1200 | + pdata->regulators.dvdd); 1201 | + if (err) { 1202 | + dev_err(dev, "%s: unable to get regulator(s)\n", __func__); 1203 | + goto done; 1204 | + } 1205 | + 1206 | + /* Reset or ENABLE GPIO */ 1207 | + 1208 | + pw->reset_gpio = pdata->reset_gpio; 1209 | + err = gpio_request(pw->reset_gpio, "cam_reset_gpio"); 1210 | + if (err < 0) { 1211 | + dev_err(dev, "%s: unable to request reset_gpio (%d)\n", 1212 | + __func__, err); 1213 | + goto done; 1214 | + } 1215 | + 1216 | +done: 1217 | + pw->state = SWITCH_OFF; 1218 | + 1219 | + return err; 1220 | +} 1221 | + 1222 | +static struct camera_common_pdata *imx708_parse_dt(struct tegracam_device 1223 | + *tc_dev) 1224 | +{ 1225 | + struct device *dev = tc_dev->dev; 1226 | + struct device_node *np = dev->of_node; 1227 | + struct camera_common_pdata *board_priv_pdata; 1228 | + const struct of_device_id *match; 1229 | + struct camera_common_pdata *ret = NULL; 1230 | + int err = 0; 1231 | + int gpio = 0; 1232 | + 1233 | + if (!np) 1234 | + return NULL; 1235 | + 1236 | + match = of_match_device(imx708_of_match, dev); 1237 | + if (!match) { 1238 | + dev_err(dev, "Failed to find matching dt id\n"); 1239 | + return NULL; 1240 | + } 1241 | + 1242 | + board_priv_pdata = devm_kzalloc(dev, 1243 | + sizeof(*board_priv_pdata), GFP_KERNEL); 1244 | + if (!board_priv_pdata) 1245 | + return NULL; 1246 | + 1247 | + gpio = of_get_named_gpio(np, "reset-gpios", 0); 1248 | + if (gpio < 0) { 1249 | + if (gpio == -EPROBE_DEFER) 1250 | + ret = ERR_PTR(-EPROBE_DEFER); 1251 | + dev_err(dev, "reset-gpios not found\n"); 1252 | + goto error; 1253 | + } 1254 | + board_priv_pdata->reset_gpio = (unsigned int)gpio; 1255 | + 1256 | + err = of_property_read_string(np, "avdd-reg", 1257 | + &board_priv_pdata->regulators.avdd); 1258 | + err |= of_property_read_string(np, "iovdd-reg", 1259 | + &board_priv_pdata->regulators.iovdd); 1260 | + err |= of_property_read_string(np, "dvdd-reg", 1261 | + &board_priv_pdata->regulators.dvdd); 1262 | + if (err) 1263 | + dev_dbg(dev, "avdd, iovdd and/or dvdd reglrs. not present, " 1264 | + "assume sensor powered independently\n"); 1265 | + 1266 | + board_priv_pdata->has_eeprom = of_property_read_bool(np, "has-eeprom"); 1267 | + 1268 | + return board_priv_pdata; 1269 | + 1270 | +error: 1271 | + devm_kfree(dev, board_priv_pdata); 1272 | + 1273 | + return ret; 1274 | +} 1275 | + 1276 | +static int imx708_set_mode(struct tegracam_device *tc_dev) 1277 | +{ 1278 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1279 | + struct camera_common_data *s_data = tc_dev->s_data; 1280 | + 1281 | + int err = 0; 1282 | + 1283 | + err = imx708_write_table(priv, mode_table[IMX708_MODE_COMMON]); 1284 | + if (err) 1285 | + { 1286 | + dev_err(tc_dev->dev, "failed writing common mode err:%d\n", err); 1287 | + return err; 1288 | + } 1289 | + 1290 | + if (s_data->mode < 0) 1291 | + return -EINVAL; 1292 | + err = imx708_write_table(priv, mode_table[s_data->mode]); 1293 | + if (err) 1294 | + { 1295 | + dev_err(tc_dev->dev, "failed to write mode %d err:%d\n", s_data->mode, err); 1296 | + return err; 1297 | + } 1298 | + 1299 | + return 0; 1300 | +} 1301 | + 1302 | + 1303 | +static int imx708_start_streaming(struct tegracam_device *tc_dev) 1304 | +{ 1305 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1306 | + 1307 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1308 | + 1309 | + return imx708_write_table(priv, mode_table[IMX708_START_STREAM]); 1310 | +} 1311 | + 1312 | +static int imx708_stop_streaming(struct tegracam_device *tc_dev) 1313 | +{ 1314 | + int err = 0; 1315 | + 1316 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1317 | + 1318 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1319 | + 1320 | + err = imx708_write_table(priv, mode_table[IMX708_STOP_STREAM]); 1321 | + 1322 | + return err; 1323 | +} 1324 | + 1325 | +static struct camera_common_sensor_ops imx708_common_ops = { 1326 | + .numfrmfmts = ARRAY_SIZE(imx708_frmfmt), 1327 | + .frmfmt_table = imx708_frmfmt, 1328 | + .power_on = imx708_power_on, 1329 | + .power_off = imx708_power_off, 1330 | + .write_reg = imx708_write_reg, 1331 | + .read_reg = imx708_read_reg, 1332 | + .parse_dt = imx708_parse_dt, 1333 | + .power_get = imx708_power_get, 1334 | + .power_put = imx708_power_put, 1335 | + .set_mode = imx708_set_mode, 1336 | + .start_streaming = imx708_start_streaming, 1337 | + .stop_streaming = imx708_stop_streaming, 1338 | +}; 1339 | + 1340 | +static int imx708_board_setup(struct imx708 *priv) 1341 | +{ 1342 | + struct camera_common_data *s_data = priv->s_data; 1343 | + struct device *dev = s_data->dev; 1344 | + u8 reg_val[2] = {0}; 1345 | + int err = 0; 1346 | + 1347 | + /* Skip mclk enable as this camera has an internal oscillator */ 1348 | + err = imx708_power_on(s_data); 1349 | + if (err) { 1350 | + dev_err(dev, "error during power on sensor (%d)\n", err); 1351 | + goto done; 1352 | + } 1353 | + 1354 | + /* Probe sensor model id registers */ 1355 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_MSB, ®_val[0]); 1356 | + if (err) { 1357 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1358 | + __func__, err); 1359 | + goto err_reg_probe; 1360 | + } 1361 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_LSB, ®_val[1]); 1362 | + if (err) { 1363 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1364 | + __func__, err); 1365 | + goto err_reg_probe; 1366 | + } 1367 | + 1368 | + if (!((reg_val[0] == IMX708_MODEL_ID_VALUE_MSB) && 1369 | + reg_val[1] == IMX708_MODEL_ID_VALUE_LSB)) 1370 | + dev_err(dev, "%s: invalid sensor model id: %x%x\n", 1371 | + __func__, reg_val[0], reg_val[1]); 1372 | + 1373 | + /* Sensor fine integration time */ 1374 | + err = imx708_get_fine_integ_time(priv, &priv->fine_integ_time); 1375 | + if (err) 1376 | + dev_err(dev, "%s: error querying sensor fine integ. time\n", 1377 | + __func__); 1378 | + 1379 | +err_reg_probe: 1380 | + imx708_power_off(s_data); 1381 | + 1382 | +done: 1383 | + return err; 1384 | +} 1385 | + 1386 | +static int imx708_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1387 | +{ 1388 | + struct i2c_client *client = v4l2_get_subdevdata(sd); 1389 | + dev_dbg(&client->dev, "%s:\n", __func__); 1390 | + 1391 | + return 0; 1392 | +} 1393 | + 1394 | +static const struct v4l2_subdev_internal_ops imx708_subdev_internal_ops = { 1395 | + .open = imx708_open, 1396 | +}; 1397 | + 1398 | +static int imx708_probe(struct i2c_client *client, 1399 | + const struct i2c_device_id *id) 1400 | +{ 1401 | + struct device *dev = &client->dev; 1402 | + struct tegracam_device *tc_dev = NULL; 1403 | + struct imx708 *priv = NULL; 1404 | + int err = 0; 1405 | + 1406 | + dev_err(dev, "probing v4l2 sensor at addr 0x%0x\n", client->addr); 1407 | + 1408 | + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) 1409 | + return -EINVAL; 1410 | + 1411 | + priv = devm_kzalloc(dev, sizeof(struct imx708), GFP_KERNEL); 1412 | + if (!priv) 1413 | + return -ENOMEM; 1414 | + 1415 | + tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL); 1416 | + if (!tc_dev) 1417 | + return -ENOMEM; 1418 | + 1419 | + priv->i2c_client = tc_dev->client = client; 1420 | + tc_dev->dev = dev; 1421 | + strncpy(tc_dev->name, "imx708", sizeof(tc_dev->name)); 1422 | + tc_dev->dev_regmap_config = &sensor_regmap_config; 1423 | + tc_dev->sensor_ops = &imx708_common_ops; 1424 | + tc_dev->v4l2sd_internal_ops = &imx708_subdev_internal_ops; 1425 | + tc_dev->tcctrl_ops = &imx708_ctrl_ops; 1426 | + 1427 | + err = tegracam_device_register(tc_dev); 1428 | + if (err) { 1429 | + dev_err(dev, "tegra camera driver registration failed\n"); 1430 | + goto register_error; 1431 | + } 1432 | + priv->tc_dev = tc_dev; 1433 | + priv->s_data = tc_dev->s_data; 1434 | + priv->subdev = &tc_dev->s_data->subdev; 1435 | + tegracam_set_privdata(tc_dev, (void *)priv); 1436 | + 1437 | + err = imx708_board_setup(priv); 1438 | + if (err) { 1439 | + dev_err(dev, "board setup failed\n"); 1440 | + goto tegracam_error; 1441 | + } 1442 | + 1443 | + err = tegracam_v4l2subdev_register(tc_dev, true); 1444 | + if (err) { 1445 | + dev_err(dev, "tegra camera subdev registration failed\n"); 1446 | + goto v4l2_error; 1447 | + } 1448 | + 1449 | + dev_dbg(dev, "detected imx708 sensor\n"); 1450 | + 1451 | + return 0; 1452 | + 1453 | +v4l2_error: 1454 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1455 | +tegracam_error: 1456 | + tegracam_device_unregister(priv->tc_dev); 1457 | +register_error: 1458 | + return err; 1459 | + 1460 | +} 1461 | + 1462 | + 1463 | +static int imx708_remove(struct i2c_client *client) 1464 | +{ 1465 | + struct camera_common_data *s_data = to_camera_common_data(&client->dev); 1466 | + struct imx708 *priv = (struct imx708 *)s_data->priv; 1467 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1468 | + tegracam_device_unregister(priv->tc_dev); 1469 | + 1470 | + return 0; 1471 | +} 1472 | + 1473 | +static const struct i2c_device_id imx708_id[] = { 1474 | + {"imx708", 0}, 1475 | + {} 1476 | +}; 1477 | + 1478 | +MODULE_DEVICE_TABLE(i2c, imx708_id); 1479 | + 1480 | +static struct i2c_driver imx708_i2c_driver = { 1481 | + .driver = { 1482 | + .name = "imx708", 1483 | + .owner = THIS_MODULE, 1484 | + .of_match_table = of_match_ptr(imx708_of_match), 1485 | + }, 1486 | + .probe = imx708_probe, 1487 | + .remove = imx708_remove, 1488 | + .id_table = imx708_id, 1489 | +}; 1490 | + 1491 | +module_i2c_driver(imx708_i2c_driver); 1492 | + 1493 | +MODULE_DESCRIPTION("Media Controller driver for Sony IMX708"); 1494 | +MODULE_AUTHOR("RidgeRun"); 1495 | +MODULE_LICENSE("GPL v2"); 1496 | diff --git a/nvidia-oot/include/media/imx708.h b/nvidia-oot/include/media/imx708.h 1497 | new file mode 100644 1498 | index 000000000..1e98f4c1e 1499 | --- /dev/null 1500 | +++ b/nvidia-oot/include/media/imx708.h 1501 | @@ -0,0 +1,53 @@ 1502 | +/* 1503 | + * imx708.h - imx708 sensor header 1504 | + * 1505 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 1506 | + * 1507 | + * Contact us: support@ridgerun.com 1508 | + * 1509 | + * This program is free software; you can redistribute it and/or modify it 1510 | + * under the terms and conditions of the GNU General Public License, 1511 | + * version 2, as published by the Free Software Foundation. 1512 | + * 1513 | + * This program is distributed in the hope it will be useful, but WITHOUT 1514 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1515 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1516 | + * more details. 1517 | + * 1518 | + * You should have received a copy of the GNU General Public License 1519 | + * along with this program. If not, see . 1520 | + */ 1521 | + 1522 | +#ifndef __IMX708_H__ 1523 | +#define __IMX708_H__ 1524 | + 1525 | +/* imx708 - sensor parameters */ 1526 | +#define IMX708_MIN_GAIN (0) 1527 | +#define IMX708_MAX_GAIN (978) 1528 | +#define IMX708_ANALOG_GAIN_C0 (516) 1529 | +#define IMX708_SHIFT_8_BITS (8) 1530 | +#define IMX708_MIN_FRAME_LENGTH (256) 1531 | +#define IMX708_MAX_FRAME_LENGTH (65535) 1532 | +#define IMX708_MIN_COARSE_EXPOSURE (1) 1533 | +#define IMX708_MAX_COARSE_DIFF (10) 1534 | +#define IMX708_MASK_LSB_2_BITS 0x0003 1535 | +#define IMX708_MASK_LSB_8_BITS 0x00ff 1536 | + 1537 | +/* imx708 sensor register address */ 1538 | +#define IMX708_MODEL_ID_ADDR_MSB 0x0000 1539 | +#define IMX708_MODEL_ID_ADDR_LSB 0x0001 1540 | +#define IMX708_MODEL_ID_VALUE_MSB 0x0003 1541 | +#define IMX708_MODEL_ID_VALUE_LSB 0x0001 1542 | +#define IMX708_ANALOG_GAIN_ADDR_MSB 0x0204 1543 | +#define IMX708_ANALOG_GAIN_ADDR_LSB 0x0205 1544 | +#define IMX708_DIGITAL_GAIN_ADDR_MSB 0x020e 1545 | +#define IMX708_DIGITAL_GAIN_ADDR_LSB 0x020f 1546 | +#define IMX708_FRAME_LENGTH_ADDR_MSB 0x0340 1547 | +#define IMX708_FRAME_LENGTH_ADDR_LSB 0x0341 1548 | +#define IMX708_COARSE_INTEG_TIME_ADDR_MSB 0x0202 1549 | +#define IMX708_COARSE_INTEG_TIME_ADDR_LSB 0x0203 1550 | +#define IMX708_FINE_INTEG_TIME_ADDR_MSB 0x0200 1551 | +#define IMX708_FINE_INTEG_TIME_ADDR_LSB 0x0201 1552 | +#define IMX708_GROUP_HOLD_ADDR 0x0104 1553 | + 1554 | +#endif /* __IMX708_H__ */ 1555 | -- 1556 | 2.34.1 1557 | 1558 | -------------------------------------------------------------------------------- /patches_nano/patches/4.6.4_nano_imx708_v0.1.0.patch: -------------------------------------------------------------------------------- 1 | From f9091eed7c28fe3c072ab72e4bdb892966d79a94 Mon Sep 17 00:00:00 2001 2 | From: alfredpchacon 3 | Date: Tue, 25 Jul 2023 20:34:03 +0000 4 | Subject: [PATCH] Squashed commit of the following: 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | commit 233ef2094eea38fe750e12ac1ec2561145c0471c 10 | Merge: ccfdcc7fc f481e9579 11 | Author: Mac Alfred Pinnock Chacón 12 | Date: Tue Jul 25 20:30:39 2023 +0000 13 | 14 | Merge branch '4.6.4/nano/imx708-dev' into '4.6.4/nano/imx708' 15 | 16 | IMX708 for Jetson Nano 2 GB single camera platform 17 | 18 | See merge request ridgerun/drivers/jetson/nano-drivers!70 19 | 20 | commit f481e9579025a4ff4d204d945d03fd534d9b8d84 21 | Author: alfredpchacon 22 | Date: Tue Jul 25 20:05:07 2023 +0000 23 | 24 | Change compatible 25 | 26 | commit 18b5f0d4bee716e8ee7a481c5ae188df93fd8b7b 27 | Author: alfredpchacon 28 | Date: Tue Jul 25 19:30:54 2023 +0000 29 | 30 | Add SISO logic 31 | 32 | commit 9f5a2f85be89c277ab26c84f4377cdb616405197 33 | Author: alfredpchacon 34 | Date: Tue Jul 25 18:29:24 2023 +0000 35 | 36 | Fix driver error 37 | 38 | commit 4358bcfbe4b3f5ea9fb1bf00c1e7191db18d7044 39 | Author: alfredpchacon 40 | Date: Tue Jul 25 18:28:55 2023 +0000 41 | 42 | Remove extra code 43 | 44 | commit c76da6346c0e457038bf36350c8ab5aabd824b0c 45 | Author: alfredpchacon 46 | Date: Tue Jul 25 16:17:22 2023 +0000 47 | 48 | Remove unnecesary logic 49 | 50 | commit 2075817a689bbca31c9516f649d7e752d61c722f 51 | Author: alfredpchacon 52 | Date: Tue Jul 25 15:31:50 2023 +0000 53 | 54 | Add compatible 55 | 56 | commit 77fce7f58f3771e155be187a193e3e3cee582aaa 57 | Author: Mac Alfred Pinnock Chacón 58 | Date: Mon Jul 24 03:58:47 2023 +0000 59 | 60 | Fix format 61 | 62 | commit f1eeb2c2788000311125a103f0643f3d7147d450 63 | Author: alfredpchacon 64 | Date: Mon Jul 24 03:03:55 2023 +0000 65 | 66 | Set IMX708 as default in menuconfig 67 | 68 | commit 58796e2a18f26fa511e02aa41d9dc990850c77d7 69 | Author: alfredpchacon 70 | Date: Sat Jul 22 21:27:30 2023 +0000 71 | 72 | Add unregister driver 73 | 74 | commit b4107fa9c2791da4ac604864f803492a4935ac3f 75 | Author: alfredpchacon 76 | Date: Sat Jul 22 21:02:42 2023 +0000 77 | 78 | Add define 79 | 80 | commit e52182573ebfe46fa91b07a84e8dea489c461fc3 81 | Author: alfredpchacon 82 | Date: Sat Jul 22 20:57:06 2023 +0000 83 | 84 | Check max/min value from user 85 | 86 | commit b873271f1f06a9399e8ae3e801014d70e08b1671 87 | Author: Mac Alfred Pinnock Chacón 88 | Date: Thu Jul 20 02:50:01 2023 +0000 89 | 90 | Remove duplicated empty line 91 | 92 | commit eb06bf2adf242eddeed8862d9d565682a83c9578 93 | Author: Mac Alfred Pinnock Chacón 94 | Date: Thu Jul 20 02:48:45 2023 +0000 95 | 96 | Set duplicated empty line 97 | 98 | commit a7a16a55456e1766ac9413c6aa1fe346cc3699ea 99 | Author: Mac Alfred Pinnock Chacón 100 | Date: Thu Jul 20 02:44:20 2023 +0000 101 | 102 | Remove trashy code 103 | 104 | commit 6bbe1bdd118fb73d2b521ee2f4b49e3b2c5f07dc 105 | Author: Mac Alfred Pinnock Chacón 106 | Date: Thu Jul 20 02:08:48 2023 +0000 107 | 108 | Fix name error 109 | 110 | commit dfd0915c9427728f6a6e2be7c2792b37c9d2c6f9 111 | Author: Mac Alfred Pinnock Chacón 112 | Date: Thu Jul 20 02:06:47 2023 +0000 113 | 114 | Remove extra dependency 115 | 116 | commit e19a7a9b83e085de52d3436439fabf57918b9ae2 117 | Author: alfredpchacon 118 | Date: Wed Jul 19 19:08:24 2023 +0000 119 | 120 | Remove extra dependencies 121 | 122 | commit 124eaec279b94c143b47e73c9d6a4668be78b90c 123 | Author: alfredpchacon 124 | Date: Wed Jul 19 19:05:49 2023 +0000 125 | 126 | Initialize variables 127 | 128 | commit 154a7721510b3603d2ffc0ed27e199974d7ff3d3 129 | Author: alfredpchacon 130 | Date: Wed Jul 19 19:05:30 2023 +0000 131 | 132 | Remove extra file 133 | 134 | commit 81570e32c649f7774dba6dc8aa4d82033aed109f 135 | Author: alfredpchacon 136 | Date: Wed Jul 19 19:01:31 2023 +0000 137 | 138 | Remove debug errors 139 | 140 | commit ca04f48008779672235163ab02e3a827ebfdb249 141 | Author: alfredpchacon 142 | Date: Mon Jul 17 20:45:26 2023 +0000 143 | 144 | Remove extra copyright 145 | 146 | commit 263376c288b84526b828fce18846f7c63ece213d 147 | Author: alfredpchacon 148 | Date: Mon Jul 17 20:43:25 2023 +0000 149 | 150 | Remove extra file 151 | 152 | commit 87c61156be6340ef8c17e9a1df411ac7a5f8903b 153 | Author: alfredpchacon 154 | Date: Mon Jul 17 17:01:16 2023 +0000 155 | 156 | Remove commented code 157 | 158 | commit 56aac8f017cb11fd9ee261efb232542108c2d76c 159 | Author: alfredpchacon 160 | Date: Mon Jul 17 16:59:02 2023 +0000 161 | 162 | Renove extra dependencies 163 | 164 | commit 0f71188d82dbbd82ec1ac86a2cc0be4fab816666 165 | Author: alfredpchacon 166 | Date: Mon Jul 17 16:58:34 2023 +0000 167 | 168 | Change dtb ordering 169 | 170 | commit 481520e5e2cc5f0e1de27b69c9e14fa9eaaac293 171 | Author: alfredpchacon 172 | Date: Mon Jul 17 16:25:35 2023 +0000 173 | 174 | Remove extra files 175 | 176 | commit 141561c8a3234097c46e5d2aeeca2f047154ee51 177 | Author: alfredpchacon 178 | Date: Mon Jul 17 16:11:16 2023 +0000 179 | 180 | remove commented code 181 | 182 | commit c40b8fa4dfeadb4da35249635364c440efd56037 183 | Author: alfredpchacon 184 | Date: Mon Jul 17 15:44:08 2023 +0000 185 | 186 | Fix the capture image error 187 | 188 | commit 3899f631cdde9431058058aeb2d6cf4193aa3d95 189 | Author: alfredpchacon 190 | Date: Sun Jul 9 19:13:19 2023 +0000 191 | 192 | Add dependencies to overrides makefile 193 | 194 | commit 73fff9ecaa9fd6c959f3930079ba674e6635e43f 195 | Author: alfredpchacon 196 | Date: Sun Jul 9 19:12:28 2023 +0000 197 | 198 | Fix indentation error 199 | 200 | commit c715e20c6789ba969bf982c07b90188e7d2da203 201 | Author: alfredpchacon 202 | Date: Sun Jul 9 19:12:14 2023 +0000 203 | 204 | Increase verbosity 205 | 206 | commit 6284e827fc67e2bf13bedd413c8b284ef5913df4 207 | Author: alfredpchacon 208 | Date: Sun Jul 9 19:12:01 2023 +0000 209 | 210 | Disable unnecsary logic 211 | 212 | commit 71ff1d47224ce62434f38060e3c7674943cf5e1f 213 | Author: alfredpchacon 214 | Date: Sun Jul 9 19:11:46 2023 +0000 215 | 216 | Fix name error 217 | 218 | commit a4dde960e4ed58def5b0820358a50d8ca567e099 219 | Author: alfredpchacon 220 | Date: Sun Jul 9 19:11:19 2023 +0000 221 | 222 | Add overrides 223 | 224 | commit 67d23be862945c7acc5556535a8b413537523545 225 | Author: alfredpchacon 226 | Date: Thu Jul 6 04:03:55 2023 +0000 227 | 228 | Add missing dependencie 229 | 230 | commit 32a95c92de45d2481b64b59acc2b975a4043acd8 231 | Author: alfredpchacon 232 | Date: Thu Jul 6 04:03:29 2023 +0000 233 | 234 | Add dependencie for nano 2gb 235 | 236 | commit d669df6d16b8ec7359b74d79f02c24dd0562daea 237 | Author: alfredpchacon 238 | Date: Wed Jul 5 19:10:20 2023 +0000 239 | 240 | Add sensor header 241 | 242 | commit 517d3e14b825d0dfa2fd6a6cd1741f8495b9de3f 243 | Author: alfredpchacon 244 | Date: Wed Jul 5 19:09:55 2023 +0000 245 | 246 | Add driver to compililation dependencies 247 | 248 | commit 8cd996967665856e51512071f24c484d36c26c01 249 | Author: alfredpchacon 250 | Date: Wed Jul 5 18:58:25 2023 +0000 251 | 252 | Add .c file 253 | 254 | commit b5059198c5bdb7e9e15844dc53cbd0677ef35c25 255 | Author: alfredpchacon 256 | Date: Wed Jul 5 18:57:52 2023 +0000 257 | 258 | Add header file 259 | 260 | commit ca8a355633184c2bf77bd71158e09022f6ef76d6 261 | Author: alfredpchacon 262 | Date: Wed Jul 5 18:56:40 2023 +0000 263 | 264 | Revert "Add .c and .h driver files" 265 | 266 | This reverts commit 632597d8eabdb849fca876713c80034c62b74ece. 267 | 268 | commit 632597d8eabdb849fca876713c80034c62b74ece 269 | Author: alfredpchacon 270 | Date: Wed Jul 5 18:55:00 2023 +0000 271 | 272 | Add .c and .h driver files 273 | 274 | commit f10841dba3034737f7f4ed1c3bdfe6075438b784 275 | Author: alfredpchacon 276 | Date: Wed Jul 5 18:53:18 2023 +0000 277 | 278 | Include files in the hierarchy 279 | 280 | commit d1e2b9a4af0b2a5120ee4cfb98c2125c0197c859 281 | Author: alfredpchacon 282 | Date: Wed Jul 5 18:49:48 2023 +0000 283 | 284 | Add dtsi for single camera platforms 285 | 286 | commit 8811c6e12be2a4c0754b58930eb49dba999feb4e 287 | Author: alfredpchacon 288 | Date: Wed Jul 5 18:23:18 2023 +0000 289 | 290 | Add kconfig description 291 | 292 | commit 71ab919ab5a72aaa49beba47a238ac0d2cec949e 293 | Author: alfredpchacon 294 | Date: Wed Jul 5 18:23:04 2023 +0000 295 | 296 | Add dtsi files 297 | --- 298 | .../tegra210-p3448-0003-p3542-0000.dts | 1 + 299 | .../tegra210-camera-rbpcv3-imx708.dtsi | 166 ++++ 300 | .../tegra210-porg-camera-rbpcv3-imx708.dtsi | 41 + 301 | .../arch/arm64/configs/tegra_defconfig | 13 +- 302 | kernel/nvidia/drivers/media/i2c/Kconfig | 9 + 303 | kernel/nvidia/drivers/media/i2c/Makefile | 1 + 304 | kernel/nvidia/drivers/media/i2c/imx708.c | 774 ++++++++++++++++++ 305 | .../drivers/media/i2c/imx708_mode_tbls.h | 221 +++++ 306 | kernel/nvidia/include/media/imx708.h | 51 ++ 307 | 9 files changed, 1271 insertions(+), 6 deletions(-) 308 | create mode 100644 hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-camera-rbpcv3-imx708.dtsi 309 | create mode 100644 hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx708.dtsi 310 | create mode 100644 kernel/nvidia/drivers/media/i2c/imx708.c 311 | create mode 100644 kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 312 | create mode 100644 kernel/nvidia/include/media/imx708.h 313 | 314 | diff --git a/hardware/nvidia/platform/t210/batuu/kernel-dts/tegra210-p3448-0003-p3542-0000.dts b/hardware/nvidia/platform/t210/batuu/kernel-dts/tegra210-p3448-0003-p3542-0000.dts 315 | index 7d19df5a8..0a2c678d5 100644 316 | --- a/hardware/nvidia/platform/t210/batuu/kernel-dts/tegra210-p3448-0003-p3542-0000.dts 317 | +++ b/hardware/nvidia/platform/t210/batuu/kernel-dts/tegra210-p3448-0003-p3542-0000.dts 318 | @@ -21,6 +21,7 @@ 319 | #include "../../porg/kernel-dts/tegra210-porg-p3448-common.dtsi" 320 | #include "../../porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx477.dtsi" 321 | #include "../../porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv2-imx219.dtsi" 322 | +#include "../../porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx708.dtsi" 323 | #include "batuu-platforms/tegra210-batuu-pinmux-p3448-0003.dtsi" 324 | #include "batuu-platforms/tegra210-batuu-gpio-p3448-0003.dtsi" 325 | #include "batuu-platforms/tegra210-batuu-p3448-emc-a00.dtsi" 326 | diff --git a/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-camera-rbpcv3-imx708.dtsi b/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-camera-rbpcv3-imx708.dtsi 327 | new file mode 100644 328 | index 000000000..00b5473c5 329 | --- /dev/null 330 | +++ b/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-camera-rbpcv3-imx708.dtsi 331 | @@ -0,0 +1,166 @@ 332 | +/* 333 | + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. 334 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 335 | + * 336 | + * This program is free software; you can redistribute it and/or modify 337 | + * it under the terms of the GNU General Public License as published by 338 | + * the Free Software Foundation; either version 2 of the License, or 339 | + * (at your option) any later version. 340 | + * 341 | + * This program is distributed in the hope that it will be useful, but WITHOUT 342 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 343 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 344 | + * more details. 345 | + * 346 | + * You should have received a copy of the GNU General Public License 347 | + * along with this program. If not, see . 348 | + */ 349 | + 350 | +#include 351 | +#include 352 | + 353 | +/ { 354 | + host1x { 355 | + vi_base: vi { 356 | + num-channels = <1>; 357 | + ports { 358 | + #address-cells = <1>; 359 | + #size-cells = <0>; 360 | + vi_port0: port@0 { 361 | + reg = <0>; 362 | + rbpcv3_imx708_vi_in0: endpoint { 363 | + status="okay"; 364 | + port-index = <0>; 365 | + bus-width = <2>; 366 | + remote-endpoint = <&rbpcv3_imx708_csi_out0>; 367 | + }; 368 | + }; 369 | + }; 370 | + }; 371 | + 372 | + csi_base: nvcsi { 373 | + num-channels = <1>; 374 | + #address-cells = <1>; 375 | + #size-cells = <0>; 376 | + csi_chan0: channel@0 { 377 | + reg = <0>; 378 | + ports { 379 | + #address-cells = <1>; 380 | + #size-cells = <0>; 381 | + csi_chan0_port0: port@0 { 382 | + reg = <0>; 383 | + rbpcv3_imx708_csi_in0: endpoint@0 { 384 | + status="okay"; 385 | + port-index = <0>; 386 | + bus-width = <2>; 387 | + remote-endpoint = <&rbpcv3_imx708_out0>; 388 | + }; 389 | + }; 390 | + csi_chan0_port1: port@1 { 391 | + reg = <1>; 392 | + rbpcv3_imx708_csi_out0: endpoint@1 { 393 | + status = "okay"; 394 | + remote-endpoint = <&rbpcv3_imx708_vi_in0>; 395 | + }; 396 | + }; 397 | + }; 398 | + }; 399 | + }; 400 | + 401 | + i2c@546c0000 { 402 | + imx708_single_cam0: rbpcv3_imx708_a@1a { 403 | + status = "okay"; 404 | + compatible = "sony,imx708"; 405 | + reg = <0x1a>; 406 | + devnode = "video0"; 407 | + physical_w = "3.680"; 408 | + physical_h = "2.760"; 409 | + sensor_model = "imx708"; 410 | + use_sensor_mode_id = "true"; 411 | + 412 | + /* IMX708_MODE_4608x2592_14fps */ 413 | + mode0 { 414 | + mclk_khz = "24000"; 415 | + num_lanes = "2"; 416 | + tegra_sinterface = "serial_a"; 417 | + phy_mode = "DPHY"; 418 | + discontinuous_clk = "yes"; 419 | + dpcm_enable = "false"; 420 | + cil_settletime = "0"; 421 | + 422 | + active_w = "4608"; 423 | + active_h = "2592"; 424 | + mode_type = "bayer"; 425 | + pixel_phase = "rggb"; 426 | + csi_pixel_bit_depth = "10"; 427 | + readout_orientation = "90"; 428 | + line_length = "15648"; 429 | + inherent_gain = "1"; 430 | + pix_clk_hz = "595200000"; 431 | + 432 | + gain_factor = "16"; 433 | + framerate_factor = "1000000"; 434 | + exposure_factor = "1000000"; 435 | + min_gain_val = "16"; 436 | + max_gain_val = "512"; 437 | + step_gain_val = "1"; 438 | + default_gain = "16"; 439 | + min_hdr_ratio = "1"; 440 | + max_hdr_ratio = "1"; 441 | + min_framerate = "2000000"; 442 | + max_framerate = "14000000"; 443 | + step_framerate = "1"; 444 | + default_framerate = "14000000"; 445 | + min_exp_time = "500"; 446 | + max_exp_time = "65487"; 447 | + step_exp_time = "1"; 448 | + default_exp_time = "1600"; 449 | + embedded_metadata_height = "2"; 450 | + }; 451 | + 452 | + ports { 453 | + #address-cells = <1>; 454 | + #size-cells = <0>; 455 | + 456 | + port@0 { 457 | + reg = <0>; 458 | + rbpcv3_imx708_out0: endpoint { 459 | + port-index = <0>; 460 | + bus-width = <2>; 461 | + remote-endpoint = <&rbpcv3_imx708_csi_in0>; 462 | + }; 463 | + }; 464 | + }; 465 | + }; 466 | + }; 467 | + }; 468 | +}; 469 | + 470 | +/ { 471 | + tcp: tegra-camera-platform { 472 | + compatible = "nvidia, tegra-camera-platform"; 473 | + num_csi_lanes = <2>; 474 | + max_lane_speed = <2500000>; 475 | + min_bits_per_pixel = <10>; 476 | + vi_peak_byte_per_pixel = <2>; 477 | + vi_bw_margin_pct = <25>; 478 | + max_pixel_rate = <7500000>; 479 | + isp_peak_byte_per_pixel = <5>; 480 | + isp_bw_margin_pct = <25>; 481 | + 482 | + modules { 483 | + cam_module0: module0 { 484 | + status = "okay"; 485 | + badge = "porg_front_RBPCV3"; 486 | + position = "front"; 487 | + orientation = "1"; 488 | + cam_module0_drivernode0: drivernode0 { 489 | + status = "okay"; 490 | + pcl_id = "v4l2_sensor"; 491 | + devname = "imx708 6-001a"; 492 | + proc-device-tree = "/proc/device-tree/host1x/i2c@546c0000/rbpcv3_imx708_a@1a"; 493 | + }; 494 | + }; 495 | + }; 496 | + }; 497 | +}; 498 | diff --git a/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx708.dtsi b/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx708.dtsi 499 | new file mode 100644 500 | index 000000000..581ebe406 501 | --- /dev/null 502 | +++ b/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-camera-rbpcv3-imx708.dtsi 503 | @@ -0,0 +1,41 @@ 504 | +/* 505 | + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. 506 | + * Copyright (c) 2023, RidgeRun. All rights reserved. 507 | + * 508 | + * This program is free software; you can redistribute it and/or modify 509 | + * it under the terms of the GNU General Public License as published by 510 | + * the Free Software Foundation; either version 2 of the License, or 511 | + * (at your option) any later version. 512 | + * 513 | + * This program is distributed in the hope that it will be useful, but WITHOUT 514 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 515 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 516 | + * more details. 517 | + * 518 | + * You should have received a copy of the GNU General Public License 519 | + * along with this program. If not, see . 520 | + */ 521 | + 522 | +#include "tegra210-camera-rbpcv3-imx708.dtsi" 523 | + 524 | +#define CAM1_PWDN TEGRA_GPIO(S, 7) 525 | + 526 | +/ { 527 | + host1x { 528 | + i2c@546c0000 { 529 | + rbpcv3_imx708_a@1a { 530 | + status = "okay"; 531 | + reset-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>; 532 | + }; 533 | + }; 534 | + }; 535 | + 536 | + gpio@6000d000 { 537 | + camera-control-output-low { 538 | + gpio-hog; 539 | + output-low; 540 | + gpios = < CAM1_PWDN 0 >; 541 | + label = "cam1-pwdn"; 542 | + }; 543 | + }; 544 | +}; 545 | diff --git a/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig b/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig 546 | index 8ab7fb986..41d3e5fa5 100644 547 | --- a/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig 548 | +++ b/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig 549 | @@ -758,12 +758,13 @@ CONFIG_VIDEO_VIVID=m 550 | CONFIG_VIDEO_CAMERA=y 551 | CONFIG_VIDEO_TEGRA_VIVID=m 552 | # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set 553 | -CONFIG_VIDEO_IMX185=m 554 | -CONFIG_VIDEO_IMX477=y 555 | -CONFIG_VIDEO_IMX219=y 556 | -CONFIG_VIDEO_IMX268=y 557 | -CONFIG_VIDEO_IMX274=m 558 | -CONFIG_VIDEO_IMX318=y 559 | +CONFIG_VIDEO_IMX185=n 560 | +CONFIG_VIDEO_IMX477=n 561 | +CONFIG_VIDEO_IMX219=n 562 | +CONFIG_VIDEO_IMX268=n 563 | +CONFIG_VIDEO_IMX274=n 564 | +CONFIG_VIDEO_IMX318=n 565 | +CONFIG_VIDEO_IMX708=y 566 | CONFIG_VIDEO_LC898212=y 567 | CONFIG_VIDEO_OV5693=m 568 | CONFIG_VIDEO_OV9281=y 569 | diff --git a/kernel/nvidia/drivers/media/i2c/Kconfig b/kernel/nvidia/drivers/media/i2c/Kconfig 570 | index 326dbb096..99398a22c 100644 571 | --- a/kernel/nvidia/drivers/media/i2c/Kconfig 572 | +++ b/kernel/nvidia/drivers/media/i2c/Kconfig 573 | @@ -13,6 +13,15 @@ config VIDEO_IMX185 574 | To compile this driver as a module, choose M here: the module 575 | will be called imx185. 576 | 577 | +config VIDEO_IMX708 578 | + tristate "IMX708 camera sensor support" 579 | + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 580 | + ---help--- 581 | + This driver supports IMX708 camera sensor from Sony 582 | + 583 | + To compile this driver as a module, choose M here: the module 584 | + will be called imx708. 585 | + 586 | config VIDEO_IMX477 587 | tristate "IMX477 camera sensor support" 588 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 589 | diff --git a/kernel/nvidia/drivers/media/i2c/Makefile b/kernel/nvidia/drivers/media/i2c/Makefile 590 | index c6d34e807..3d0947d4f 100644 591 | --- a/kernel/nvidia/drivers/media/i2c/Makefile 592 | +++ b/kernel/nvidia/drivers/media/i2c/Makefile 593 | @@ -5,6 +5,7 @@ ccflags-y += -I$(srctree)/drivers/video/tegra/camera 594 | 595 | obj-$(CONFIG_VIDEO_IMX185) += imx185.o 596 | obj-$(CONFIG_VIDEO_IMX185) += imx185_v1.o 597 | +obj-$(CONFIG_VIDEO_IMX708) += imx708.o 598 | obj-$(CONFIG_VIDEO_IMX477) += imx477.o 599 | obj-$(CONFIG_VIDEO_IMX219) += imx219.o 600 | obj-$(CONFIG_VIDEO_IMX268) += imx268.o 601 | diff --git a/kernel/nvidia/drivers/media/i2c/imx708.c b/kernel/nvidia/drivers/media/i2c/imx708.c 602 | new file mode 100644 603 | index 000000000..c33fc24b5 604 | --- /dev/null 605 | +++ b/kernel/nvidia/drivers/media/i2c/imx708.c 606 | @@ -0,0 +1,774 @@ 607 | +/* 608 | + * imx708.c - imx708 sensor driver 609 | + * 610 | + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. 611 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 612 | + * 613 | + * Contact us: support@ridgerun.com 614 | + * 615 | + * This program is free software; you can redistribute it and/or modify it 616 | + * under the terms and conditions of the GNU General Public License, 617 | + * version 2, as published by the Free Software Foundation. 618 | + * 619 | + * This program is distributed in the hope it will be useful, but WITHOUT 620 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 621 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 622 | + * more details. 623 | + * 624 | + * You should have received a copy of the GNU General Public License 625 | + * along with this program. If not, see . 626 | + */ 627 | + 628 | +#include 629 | +#include 630 | +#include 631 | +#include 632 | +#include 633 | + 634 | +#include "../platform/tegra/camera/camera_gpio.h" 635 | +#include "imx708_mode_tbls.h" 636 | + 637 | +static const struct of_device_id imx708_of_match[] = { 638 | + {.compatible = "sony,imx708",}, 639 | + {}, 640 | +}; 641 | + 642 | +MODULE_DEVICE_TABLE(of, imx708_of_match); 643 | + 644 | +static const u32 ctrl_cid_list[] = { 645 | + TEGRA_CAMERA_CID_GAIN, 646 | + TEGRA_CAMERA_CID_EXPOSURE, 647 | + TEGRA_CAMERA_CID_FRAME_RATE, 648 | + TEGRA_CAMERA_CID_SENSOR_MODE_ID, 649 | +}; 650 | + 651 | +struct imx708 { 652 | + struct i2c_client *i2c_client; 653 | + struct v4l2_subdev *subdev; 654 | + u16 fine_integ_time; 655 | + u32 frame_length; 656 | + struct camera_common_data *s_data; 657 | + struct tegracam_device *tc_dev; 658 | +}; 659 | + 660 | +static const struct regmap_config sensor_regmap_config = { 661 | + .reg_bits = 16, 662 | + .val_bits = 8, 663 | + .cache_type = REGCACHE_RBTREE, 664 | +#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE 665 | + .use_single_rw = true, 666 | +#else 667 | + .use_single_read = true, 668 | + .use_single_write = true, 669 | +#endif 670 | +}; 671 | + 672 | +static inline void imx708_get_frame_length_regs(imx708_reg * regs, 673 | + u32 frame_length) 674 | +{ 675 | + regs->addr = IMX708_FRAME_LENGTH_ADDR_MSB; 676 | + regs->val = (frame_length >> 8) & 0xff; 677 | + (regs + 1)->addr = IMX708_FRAME_LENGTH_ADDR_LSB; 678 | + (regs + 1)->val = (frame_length) & 0xff; 679 | +} 680 | + 681 | +static inline void imx708_get_coarse_integ_time_regs(imx708_reg * regs, 682 | + u32 coarse_time) 683 | +{ 684 | + regs->addr = IMX708_COARSE_INTEG_TIME_ADDR_MSB; 685 | + regs->val = (coarse_time >> 8) & 0xff; 686 | + (regs + 1)->addr = IMX708_COARSE_INTEG_TIME_ADDR_LSB; 687 | + (regs + 1)->val = (coarse_time) & 0xff; 688 | +} 689 | + 690 | +static inline void imx708_get_gain_reg(imx708_reg * reg, u16 gain) 691 | +{ 692 | + reg->addr = IMX708_ANALOG_GAIN_ADDR_MSB; 693 | + reg->val = (gain >> IMX708_SHIFT_8_BITS) & IMX708_MASK_LSB_2_BITS; 694 | + 695 | + (reg + 1)->addr = IMX708_ANALOG_GAIN_ADDR_LSB; 696 | + (reg + 1)->val = (gain) & IMX708_MASK_LSB_8_BITS; 697 | +} 698 | + 699 | +static inline int imx708_read_reg(struct camera_common_data *s_data, 700 | + u16 addr, u8 * val) 701 | +{ 702 | + int err = 0; 703 | + u32 reg_val = 0; 704 | + 705 | + err = regmap_read(s_data->regmap, addr, ®_val); 706 | + *val = reg_val & 0xff; 707 | + 708 | + return err; 709 | +} 710 | + 711 | +static inline int imx708_write_reg(struct camera_common_data *s_data, 712 | + u16 addr, u8 val) 713 | +{ 714 | + int err = 0; 715 | + 716 | + err = regmap_write(s_data->regmap, addr, val); 717 | + if (err) 718 | + dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x", 719 | + __func__, addr, val); 720 | + 721 | + return err; 722 | +} 723 | + 724 | +static int imx708_write_table(struct imx708 *priv, const imx708_reg table[]) 725 | +{ 726 | + return regmap_util_write_table_8(priv->s_data->regmap, table, NULL, 0, 727 | + IMX708_TABLE_WAIT_MS, 728 | + IMX708_TABLE_END); 729 | +} 730 | + 731 | +static int imx708_set_group_hold(struct tegracam_device *tc_dev, bool val) 732 | +{ 733 | + struct camera_common_data *s_data = tc_dev->s_data; 734 | + struct device *dev = tc_dev->dev; 735 | + int err = 0; 736 | + 737 | + dev_dbg(dev, "%s: Setting group hold control to: %u\n", __func__, val); 738 | + 739 | + err = imx708_write_reg(s_data, IMX708_GROUP_HOLD_ADDR, val); 740 | + if (err) { 741 | + dev_err(dev, "%s: Group hold control error\n", __func__); 742 | + return err; 743 | + } 744 | + 745 | + return 0; 746 | +} 747 | + 748 | +static int imx708_get_fine_integ_time(struct imx708 *priv, u16 * fine_time) 749 | +{ 750 | + struct camera_common_data *s_data = priv->s_data; 751 | + int err = 0; 752 | + u8 reg_val[2] = {0}; 753 | + 754 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_MSB, 755 | + ®_val[0]); 756 | + if (err) 757 | + goto done; 758 | + 759 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_LSB, 760 | + ®_val[1]); 761 | + if (err) 762 | + goto done; 763 | + 764 | + *fine_time = (reg_val[0] << 8) | reg_val[1]; 765 | + 766 | +done: 767 | + return err; 768 | +} 769 | + 770 | +static int imx708_set_gain(struct tegracam_device *tc_dev, s64 val) 771 | +{ 772 | + struct camera_common_data *s_data = tc_dev->s_data; 773 | + struct device *dev = s_data->dev; 774 | + const struct sensor_mode_properties *mode = 775 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 776 | + int err = 0; 777 | + int i = 0; 778 | + imx708_reg gain_reg[2] = {0}; 779 | + s16 gain = 0; 780 | + 781 | + dev_dbg(dev, "%s: Setting gain control to: %lld\n", __func__, val); 782 | + 783 | + /* Gain Formula: 784 | + Gain = (IMX708_GAIN_C0 - (IMX708_GAIN_C0 * gain_factor / val)) 785 | + */ 786 | + gain = 787 | + (s16) (IMX708_ANALOG_GAIN_C0 - 788 | + (mode->control_properties.gain_factor * 789 | + IMX708_ANALOG_GAIN_C0 / val)); 790 | + 791 | + dev_dbg(dev, "%s: val: %lld (/%d) [times], gain: %u\n", 792 | + __func__, val, mode->control_properties.gain_factor, gain); 793 | + 794 | + imx708_get_gain_reg(gain_reg, (u16) gain); 795 | + 796 | + for (i = 0; i < ARRAY_SIZE(gain_reg); i++) { 797 | + err = imx708_write_reg(s_data, gain_reg[i].addr, 798 | + gain_reg[i].val); 799 | + if (err) { 800 | + dev_err(dev, "%s: gain control error\n", __func__); 801 | + break; 802 | + } 803 | + } 804 | + 805 | + return err; 806 | +} 807 | + 808 | +static int imx708_set_frame_rate(struct tegracam_device *tc_dev, s64 val) 809 | +{ 810 | + struct camera_common_data *s_data = tc_dev->s_data; 811 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 812 | + struct device *dev = tc_dev->dev; 813 | + const struct sensor_mode_properties *mode = 814 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 815 | + 816 | + int err = 0; 817 | + imx708_reg fl_regs[2] = {0}; 818 | + u32 frame_length = 0; 819 | + int i = 0; 820 | + 821 | + dev_dbg(dev, "%s: Setting framerate control to: %lld\n", __func__, val); 822 | + 823 | + frame_length = (u32)(mode->signal_properties.pixel_clock.val * 824 | + (u64)mode->control_properties.framerate_factor / 825 | + mode->image_properties.line_length / val); 826 | + 827 | + dev_dbg(dev, 828 | + "%s: val: %llde-6 [fps], frame_length: %u [lines]\n", 829 | + __func__, val, frame_length); 830 | + 831 | + imx708_get_frame_length_regs(fl_regs, frame_length); 832 | + for (i = 0; i < 2; i++) { 833 | + err = imx708_write_reg(s_data, fl_regs[i].addr, fl_regs[i].val); 834 | + if (err) { 835 | + dev_err(dev, 836 | + "%s: frame_length control error\n", __func__); 837 | + return err; 838 | + } 839 | + } 840 | + 841 | + priv->frame_length = frame_length; 842 | + 843 | + return err; 844 | +} 845 | + 846 | +static int imx708_set_exposure(struct tegracam_device *tc_dev, s64 val) 847 | +{ 848 | + struct camera_common_data *s_data = tc_dev->s_data; 849 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 850 | + struct device *dev = tc_dev->dev; 851 | + const struct sensor_mode_properties *mode = 852 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 853 | + 854 | + int err = 0; 855 | + imx708_reg ct_regs[2] = {0}; 856 | + const s32 fine_integ_time_factor = priv->fine_integ_time * 857 | + mode->control_properties.exposure_factor / 858 | + mode->signal_properties.pixel_clock.val; 859 | + u32 coarse_time = 0; 860 | + int i = 0; 861 | + 862 | + dev_dbg(dev, "%s: Setting exposure control to: %lld\n", __func__, val); 863 | + 864 | + coarse_time = (val - fine_integ_time_factor) 865 | + * mode->signal_properties.pixel_clock.val 866 | + / mode->control_properties.exposure_factor 867 | + / mode->image_properties.line_length; 868 | + 869 | + dev_dbg(dev, "%s: val: %lld [us], coarse_time: %d [lines]\n", 870 | + __func__, val, coarse_time); 871 | + 872 | + imx708_get_coarse_integ_time_regs(ct_regs, coarse_time); 873 | + 874 | + for (i = 0; i < 2; i++) { 875 | + err = imx708_write_reg(s_data, ct_regs[i].addr, ct_regs[i].val); 876 | + if (err) { 877 | + dev_err(dev, 878 | + "%s: coarse_time control error\n", __func__); 879 | + return err; 880 | + } 881 | + } 882 | + 883 | + return err; 884 | +} 885 | + 886 | +static struct tegracam_ctrl_ops imx708_ctrl_ops = { 887 | + .numctrls = ARRAY_SIZE(ctrl_cid_list), 888 | + .ctrl_cid_list = ctrl_cid_list, 889 | + .set_gain = imx708_set_gain, 890 | + .set_exposure = imx708_set_exposure, 891 | + .set_frame_rate = imx708_set_frame_rate, 892 | + .set_group_hold = imx708_set_group_hold, 893 | +}; 894 | + 895 | +static int imx708_power_on(struct camera_common_data *s_data) 896 | +{ 897 | + int err = 0; 898 | + struct camera_common_power_rail *pw = s_data->power; 899 | + struct camera_common_pdata *pdata = s_data->pdata; 900 | + struct device *dev = s_data->dev; 901 | + 902 | + dev_dbg(dev, "%s: power on\n", __func__); 903 | + if (pdata && pdata->power_on) { 904 | + err = pdata->power_on(pw); 905 | + if (err) 906 | + dev_err(dev, "%s failed.\n", __func__); 907 | + else 908 | + pw->state = SWITCH_ON; 909 | + return err; 910 | + } 911 | + 912 | + if (pw->reset_gpio) { 913 | + if (gpio_cansleep(pw->reset_gpio)) 914 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 915 | + else 916 | + gpio_set_value(pw->reset_gpio, 0); 917 | + } 918 | + 919 | + if (unlikely(!(pw->avdd || pw->iovdd || pw->dvdd))) 920 | + goto skip_power_seqn; 921 | + 922 | + usleep_range(10, 20); 923 | + 924 | + if (pw->avdd) { 925 | + err = regulator_enable(pw->avdd); 926 | + if (err) 927 | + goto imx708_avdd_fail; 928 | + } 929 | + 930 | + if (pw->iovdd) { 931 | + err = regulator_enable(pw->iovdd); 932 | + if (err) 933 | + goto imx708_iovdd_fail; 934 | + } 935 | + 936 | + if (pw->dvdd) { 937 | + err = regulator_enable(pw->dvdd); 938 | + if (err) 939 | + goto imx708_dvdd_fail; 940 | + } 941 | + 942 | + usleep_range(10, 20); 943 | + 944 | +skip_power_seqn: 945 | + if (pw->reset_gpio) { 946 | + if (gpio_cansleep(pw->reset_gpio)) 947 | + gpio_set_value_cansleep(pw->reset_gpio, 1); 948 | + else 949 | + gpio_set_value(pw->reset_gpio, 1); 950 | + } 951 | + 952 | + /* Need to wait for t4 + t5 + t9 + t10 time as per the data sheet */ 953 | + /* t4 - 200us, t5 - 21.2ms, t9 - 1.2ms t10 - 270 ms */ 954 | + usleep_range(300000, 300100); 955 | + 956 | + pw->state = SWITCH_ON; 957 | + 958 | + return 0; 959 | + 960 | +imx708_dvdd_fail: 961 | + regulator_disable(pw->iovdd); 962 | + 963 | +imx708_iovdd_fail: 964 | + regulator_disable(pw->avdd); 965 | + 966 | +imx708_avdd_fail: 967 | + dev_err(dev, "%s failed.\n", __func__); 968 | + 969 | + return -ENODEV; 970 | +} 971 | + 972 | +static int imx708_power_off(struct camera_common_data *s_data) 973 | +{ 974 | + int err = 0; 975 | + struct camera_common_power_rail *pw = s_data->power; 976 | + struct camera_common_pdata *pdata = s_data->pdata; 977 | + struct device *dev = s_data->dev; 978 | + 979 | + dev_dbg(dev, "%s: power off\n", __func__); 980 | + 981 | + if (pdata && pdata->power_off) { 982 | + err = pdata->power_off(pw); 983 | + if (err) { 984 | + dev_err(dev, "%s failed.\n", __func__); 985 | + return err; 986 | + } 987 | + } else { 988 | + if (pw->reset_gpio) { 989 | + if (gpio_cansleep(pw->reset_gpio)) 990 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 991 | + else 992 | + gpio_set_value(pw->reset_gpio, 0); 993 | + } 994 | + 995 | + usleep_range(10, 10); 996 | + 997 | + if (pw->dvdd) 998 | + regulator_disable(pw->dvdd); 999 | + if (pw->iovdd) 1000 | + regulator_disable(pw->iovdd); 1001 | + if (pw->avdd) 1002 | + regulator_disable(pw->avdd); 1003 | + } 1004 | + 1005 | + pw->state = SWITCH_OFF; 1006 | + 1007 | + return 0; 1008 | +} 1009 | + 1010 | +static int imx708_power_put(struct tegracam_device *tc_dev) 1011 | +{ 1012 | + struct camera_common_data *s_data = tc_dev->s_data; 1013 | + struct camera_common_power_rail *pw = s_data->power; 1014 | + 1015 | + if (unlikely(!pw)) 1016 | + return -EFAULT; 1017 | + 1018 | + if (likely(pw->dvdd)) 1019 | + devm_regulator_put(pw->dvdd); 1020 | + 1021 | + if (likely(pw->avdd)) 1022 | + devm_regulator_put(pw->avdd); 1023 | + 1024 | + if (likely(pw->iovdd)) 1025 | + devm_regulator_put(pw->iovdd); 1026 | + 1027 | + pw->dvdd = NULL; 1028 | + pw->avdd = NULL; 1029 | + pw->iovdd = NULL; 1030 | + 1031 | + if (likely(pw->reset_gpio)) 1032 | + gpio_free(pw->reset_gpio); 1033 | + 1034 | + return 0; 1035 | +} 1036 | + 1037 | +static int imx708_power_get(struct tegracam_device *tc_dev) 1038 | +{ 1039 | + struct device *dev = tc_dev->dev; 1040 | + struct camera_common_data *s_data = tc_dev->s_data; 1041 | + struct camera_common_power_rail *pw = s_data->power; 1042 | + struct camera_common_pdata *pdata = s_data->pdata; 1043 | + struct clk *parent; 1044 | + int err = 0; 1045 | + 1046 | + if (!pdata) { 1047 | + dev_err(dev, "pdata missing\n"); 1048 | + return -EFAULT; 1049 | + } 1050 | + 1051 | + /* Sensor MCLK (aka. INCK) */ 1052 | + if (pdata->mclk_name) { 1053 | + pw->mclk = devm_clk_get(dev, pdata->mclk_name); 1054 | + if (IS_ERR(pw->mclk)) { 1055 | + dev_err(dev, "unable to get clock %s\n", 1056 | + pdata->mclk_name); 1057 | + return PTR_ERR(pw->mclk); 1058 | + } 1059 | + 1060 | + if (pdata->parentclk_name) { 1061 | + parent = devm_clk_get(dev, pdata->parentclk_name); 1062 | + if (IS_ERR(parent)) { 1063 | + dev_err(dev, "unable to get parent clock %s", 1064 | + pdata->parentclk_name); 1065 | + } else 1066 | + clk_set_parent(pw->mclk, parent); 1067 | + } 1068 | + } 1069 | + 1070 | + /* analog 2.8v */ 1071 | + if (pdata->regulators.avdd) 1072 | + err |= camera_common_regulator_get(dev, 1073 | + &pw->avdd, 1074 | + pdata->regulators.avdd); 1075 | + /* IO 1.8v */ 1076 | + if (pdata->regulators.iovdd) 1077 | + err |= camera_common_regulator_get(dev, 1078 | + &pw->iovdd, 1079 | + pdata->regulators.iovdd); 1080 | + /* dig 1.2v */ 1081 | + if (pdata->regulators.dvdd) 1082 | + err |= camera_common_regulator_get(dev, 1083 | + &pw->dvdd, 1084 | + pdata->regulators.dvdd); 1085 | + if (err) { 1086 | + dev_err(dev, "%s: unable to get regulator(s)\n", __func__); 1087 | + goto done; 1088 | + } 1089 | + 1090 | + /* Reset or ENABLE GPIO */ 1091 | + pw->reset_gpio = pdata->reset_gpio; 1092 | + err = gpio_request(pw->reset_gpio, "cam_reset_gpio"); 1093 | + if (err < 0) { 1094 | + dev_err(dev, "%s: unable to request reset_gpio (%d)\n", 1095 | + __func__, err); 1096 | + goto done; 1097 | + } 1098 | + 1099 | +done: 1100 | + pw->state = SWITCH_OFF; 1101 | + 1102 | + return err; 1103 | +} 1104 | + 1105 | +static struct camera_common_pdata *imx708_parse_dt(struct tegracam_device 1106 | + *tc_dev) 1107 | +{ 1108 | + struct device *dev = tc_dev->dev; 1109 | + struct device_node *np = dev->of_node; 1110 | + struct camera_common_pdata *board_priv_pdata; 1111 | + const struct of_device_id *match; 1112 | + struct camera_common_pdata *ret = NULL; 1113 | + int err = 0; 1114 | + int gpio = 0; 1115 | + 1116 | + if (!np) 1117 | + return NULL; 1118 | + 1119 | + match = of_match_device(imx708_of_match, dev); 1120 | + if (!match) { 1121 | + dev_err(dev, "Failed to find matching dt id\n"); 1122 | + return NULL; 1123 | + } 1124 | + 1125 | + board_priv_pdata = devm_kzalloc(dev, 1126 | + sizeof(*board_priv_pdata), GFP_KERNEL); 1127 | + if (!board_priv_pdata) 1128 | + return NULL; 1129 | + 1130 | + gpio = of_get_named_gpio(np, "reset-gpios", 0); 1131 | + if (gpio < 0) { 1132 | + if (gpio == -EPROBE_DEFER) 1133 | + ret = ERR_PTR(-EPROBE_DEFER); 1134 | + dev_err(dev, "reset-gpios not found\n"); 1135 | + goto error; 1136 | + } 1137 | + board_priv_pdata->reset_gpio = (unsigned int)gpio; 1138 | + 1139 | + err = of_property_read_string(np, "avdd-reg", 1140 | + &board_priv_pdata->regulators.avdd); 1141 | + err |= of_property_read_string(np, "iovdd-reg", 1142 | + &board_priv_pdata->regulators.iovdd); 1143 | + err |= of_property_read_string(np, "dvdd-reg", 1144 | + &board_priv_pdata->regulators.dvdd); 1145 | + if (err) 1146 | + dev_dbg(dev, "avdd, iovdd and/or dvdd reglrs. not present, " 1147 | + "assume sensor powered independently\n"); 1148 | + 1149 | + board_priv_pdata->has_eeprom = of_property_read_bool(np, "has-eeprom"); 1150 | + 1151 | + return board_priv_pdata; 1152 | + 1153 | +error: 1154 | + devm_kfree(dev, board_priv_pdata); 1155 | + 1156 | + return ret; 1157 | +} 1158 | + 1159 | +static int imx708_set_mode(struct tegracam_device *tc_dev) 1160 | +{ 1161 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1162 | + struct camera_common_data *s_data = tc_dev->s_data; 1163 | + 1164 | + int err = 0; 1165 | + 1166 | + err = imx708_write_table(priv, mode_table[IMX708_MODE_COMMON]); 1167 | + if (err) 1168 | + { 1169 | + dev_err(tc_dev->dev, "failed writing common mode err:%d\n", err); 1170 | + return err; 1171 | + } 1172 | + 1173 | + if (s_data->mode < 0) 1174 | + return -EINVAL; 1175 | + err = imx708_write_table(priv, mode_table[s_data->mode]); 1176 | + if (err) 1177 | + { 1178 | + dev_err(tc_dev->dev, "failed to write mode %d err:%d\n", s_data->mode, err); 1179 | + return err; 1180 | + } 1181 | + 1182 | + return 0; 1183 | +} 1184 | + 1185 | + 1186 | +static int imx708_start_streaming(struct tegracam_device *tc_dev) 1187 | +{ 1188 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1189 | + 1190 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1191 | + 1192 | + return imx708_write_table(priv, mode_table[IMX708_START_STREAM]); 1193 | +} 1194 | + 1195 | +static int imx708_stop_streaming(struct tegracam_device *tc_dev) 1196 | +{ 1197 | + int err = 0; 1198 | + 1199 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1200 | + 1201 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1202 | + 1203 | + err = imx708_write_table(priv, mode_table[IMX708_STOP_STREAM]); 1204 | + 1205 | + return err; 1206 | +} 1207 | + 1208 | +static struct camera_common_sensor_ops imx708_common_ops = { 1209 | + .numfrmfmts = ARRAY_SIZE(imx708_frmfmt), 1210 | + .frmfmt_table = imx708_frmfmt, 1211 | + .power_on = imx708_power_on, 1212 | + .power_off = imx708_power_off, 1213 | + .write_reg = imx708_write_reg, 1214 | + .read_reg = imx708_read_reg, 1215 | + .parse_dt = imx708_parse_dt, 1216 | + .power_get = imx708_power_get, 1217 | + .power_put = imx708_power_put, 1218 | + .set_mode = imx708_set_mode, 1219 | + .start_streaming = imx708_start_streaming, 1220 | + .stop_streaming = imx708_stop_streaming, 1221 | +}; 1222 | + 1223 | +static int imx708_board_setup(struct imx708 *priv) 1224 | +{ 1225 | + struct camera_common_data *s_data = priv->s_data; 1226 | + struct device *dev = s_data->dev; 1227 | + u8 reg_val[2] = {0}; 1228 | + int err = 0; 1229 | + 1230 | + /* Skip mclk enable as this camera has an internal oscillator */ 1231 | + err = imx708_power_on(s_data); 1232 | + if (err) { 1233 | + dev_err(dev, "error during power on sensor (%d)\n", err); 1234 | + goto done; 1235 | + } 1236 | + 1237 | + /* Probe sensor model id registers */ 1238 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_MSB, ®_val[0]); 1239 | + if (err) { 1240 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1241 | + __func__, err); 1242 | + goto err_reg_probe; 1243 | + } 1244 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_LSB, ®_val[1]); 1245 | + if (err) { 1246 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1247 | + __func__, err); 1248 | + goto err_reg_probe; 1249 | + } 1250 | + 1251 | + if (!((reg_val[0] == IMX708_MODEL_ID_VALUE_MSB) && 1252 | + reg_val[1] == IMX708_MODEL_ID_VALUE_LSB)) 1253 | + dev_err(dev, "%s: invalid sensor model id: %x%x\n", 1254 | + __func__, reg_val[0], reg_val[1]); 1255 | + 1256 | + /* Sensor fine integration time */ 1257 | + err = imx708_get_fine_integ_time(priv, &priv->fine_integ_time); 1258 | + if (err) 1259 | + dev_err(dev, "%s: error querying sensor fine integ. time\n", 1260 | + __func__); 1261 | + 1262 | +err_reg_probe: 1263 | + imx708_power_off(s_data); 1264 | + 1265 | +done: 1266 | + return err; 1267 | +} 1268 | + 1269 | +static int imx708_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1270 | +{ 1271 | + struct i2c_client *client = v4l2_get_subdevdata(sd); 1272 | + 1273 | + dev_dbg(&client->dev, "%s:\n", __func__); 1274 | + 1275 | + return 0; 1276 | +} 1277 | + 1278 | +static const struct v4l2_subdev_internal_ops imx708_subdev_internal_ops = { 1279 | + .open = imx708_open, 1280 | +}; 1281 | + 1282 | +static int imx708_probe(struct i2c_client *client, 1283 | + const struct i2c_device_id *id) 1284 | +{ 1285 | + struct device *dev = &client->dev; 1286 | + struct tegracam_device *tc_dev = NULL; 1287 | + struct imx708 *priv = NULL; 1288 | + int err = 0; 1289 | + 1290 | + dev_dbg(dev, "probing v4l2 sensor at addr 0x%0x\n", client->addr); 1291 | + 1292 | + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) 1293 | + return -EINVAL; 1294 | + 1295 | + priv = devm_kzalloc(dev, sizeof(struct imx708), GFP_KERNEL); 1296 | + if (!priv) 1297 | + return -ENOMEM; 1298 | + 1299 | + tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL); 1300 | + if (!tc_dev) 1301 | + return -ENOMEM; 1302 | + 1303 | + priv->i2c_client = tc_dev->client = client; 1304 | + tc_dev->dev = dev; 1305 | + strncpy(tc_dev->name, "imx708", sizeof(tc_dev->name)); 1306 | + tc_dev->dev_regmap_config = &sensor_regmap_config; 1307 | + tc_dev->sensor_ops = &imx708_common_ops; 1308 | + tc_dev->v4l2sd_internal_ops = &imx708_subdev_internal_ops; 1309 | + tc_dev->tcctrl_ops = &imx708_ctrl_ops; 1310 | + 1311 | + err = tegracam_device_register(tc_dev); 1312 | + if (err) { 1313 | + dev_err(dev, "tegra camera driver registration failed\n"); 1314 | + goto register_error; 1315 | + } 1316 | + priv->tc_dev = tc_dev; 1317 | + priv->s_data = tc_dev->s_data; 1318 | + priv->subdev = &tc_dev->s_data->subdev; 1319 | + tegracam_set_privdata(tc_dev, (void *)priv); 1320 | + 1321 | + err = imx708_board_setup(priv); 1322 | + if (err) { 1323 | + dev_err(dev, "board setup failed\n"); 1324 | + goto tegracam_error; 1325 | + } 1326 | + 1327 | + err = tegracam_v4l2subdev_register(tc_dev, true); 1328 | + if (err) { 1329 | + dev_err(dev, "tegra camera subdev registration failed\n"); 1330 | + goto v4l2_error; 1331 | + } 1332 | + 1333 | + dev_dbg(dev, "detected imx708 sensor\n"); 1334 | + 1335 | + return 0; 1336 | + 1337 | +v4l2_error: 1338 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1339 | +tegracam_error: 1340 | + tegracam_device_unregister(priv->tc_dev); 1341 | +register_error: 1342 | + return err; 1343 | + 1344 | +} 1345 | + 1346 | + 1347 | +static int imx708_remove(struct i2c_client *client) 1348 | +{ 1349 | + struct camera_common_data *s_data = to_camera_common_data(&client->dev); 1350 | + struct imx708 *priv = (struct imx708 *)s_data->priv; 1351 | + 1352 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1353 | + tegracam_device_unregister(priv->tc_dev); 1354 | + 1355 | + return 0; 1356 | +} 1357 | + 1358 | +static const struct i2c_device_id imx708_id[] = { 1359 | + {"imx708", 0}, 1360 | + {} 1361 | +}; 1362 | + 1363 | +MODULE_DEVICE_TABLE(i2c, imx708_id); 1364 | + 1365 | +static struct i2c_driver imx708_i2c_driver = { 1366 | + .driver = { 1367 | + .name = "imx708", 1368 | + .owner = THIS_MODULE, 1369 | + .of_match_table = of_match_ptr(imx708_of_match), 1370 | + }, 1371 | + .probe = imx708_probe, 1372 | + .remove = imx708_remove, 1373 | + .id_table = imx708_id, 1374 | +}; 1375 | + 1376 | +module_i2c_driver(imx708_i2c_driver); 1377 | + 1378 | +MODULE_DESCRIPTION("Media Controller driver for Sony IMX708"); 1379 | +MODULE_AUTHOR("RidgeRun"); 1380 | +MODULE_LICENSE("GPL v2"); 1381 | diff --git a/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h b/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 1382 | new file mode 100644 1383 | index 000000000..ac7862b2d 1384 | --- /dev/null 1385 | +++ b/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 1386 | @@ -0,0 +1,221 @@ 1387 | +/* 1388 | + * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved. 1389 | + * Copyright (c) 2023, RidgeRun . All rights reserved 1390 | + * 1391 | + * This program is free software; you can redistribute it and/or modify 1392 | + * it under the terms of the GNU General Public License as published by 1393 | + * the Free Software Foundation; either version 2 of the License, or 1394 | + * (at your option) any later version. 1395 | + * 1396 | + * This program is distributed in the hope that it will be useful, but WITHOUT 1397 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1398 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1399 | + * more details. 1400 | + * 1401 | + * You should have received a copy of the GNU General Public License 1402 | + * along with this program. If not, see . 1403 | + */ 1404 | + 1405 | +#ifndef __IMX708_I2C_TABLES__ 1406 | +#define __IMX708_I2C_TABLES__ 1407 | + 1408 | +#include 1409 | + 1410 | +#define IMX708_TABLE_WAIT_MS 0 1411 | +#define IMX708_TABLE_END 1 1412 | +#define IMX708_WAIT_MS 1 1413 | +#define IMX708_STANDBY_REG 0x0100 1414 | + 1415 | +#define imx708_reg struct reg_8 1416 | + 1417 | +static const imx708_reg imx708_start[] = { 1418 | + {IMX708_STANDBY_REG, 0x1}, 1419 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*3}, 1420 | + {IMX708_TABLE_END, 0x00} 1421 | +}; 1422 | + 1423 | +static const imx708_reg imx708_stop[] = { 1424 | + {IMX708_STANDBY_REG, 0x0}, 1425 | + {IMX708_TABLE_END, 0x00} 1426 | +}; 1427 | + 1428 | +static const imx708_reg imx708_mode_common[] = { 1429 | + /* software reset */ 1430 | + {0x0103, 0x01}, 1431 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*10}, 1432 | + {0x0100, 0x00}, 1433 | + {0x0136, 0x18}, 1434 | + {0x0137, 0x00}, 1435 | + {0x33F0, 0x02}, 1436 | + {0x33F1, 0x05}, 1437 | + {0x3062, 0x00}, 1438 | + {0x3063, 0x12}, 1439 | + {0x3068, 0x00}, 1440 | + {0x3069, 0x12}, 1441 | + {0x306A, 0x00}, 1442 | + {0x306B, 0x30}, 1443 | + {0x3076, 0x00}, 1444 | + {0x3077, 0x30}, 1445 | + {0x3078, 0x00}, 1446 | + {0x3079, 0x30}, 1447 | + {0x5E54, 0x0C}, 1448 | + {0x6E44, 0x00}, 1449 | + {0xB0B6, 0x01}, 1450 | + {0xE829, 0x00}, 1451 | + {0xF001, 0x08}, 1452 | + {0xF003, 0x08}, 1453 | + {0xF00D, 0x10}, 1454 | + {0xF00F, 0x10}, 1455 | + {0xF031, 0x08}, 1456 | + {0x0830, 0x01}, 1457 | + {0x0831, 0x01}, 1458 | + {0x0832, 0x01}, 1459 | + {0xF033, 0x08}, 1460 | + {0xF03D, 0x10}, 1461 | + {0xF03F, 0x10}, 1462 | + {0x0112, 0x0a}, 1463 | + {0x0113, 0x0a}, 1464 | + {0x0114, 0x01}, 1465 | + {0x0B8E, 0x01}, 1466 | + {0x0B8F, 0x00}, 1467 | + {0x0B94, 0x01}, 1468 | + {0x0B95, 0x00}, 1469 | + {0x3400, 0x01}, 1470 | + {0x3478, 0x01}, 1471 | + {0x3479, 0x1c}, 1472 | + {0x3091, 0x01}, 1473 | + {0x3092, 0x00}, 1474 | + {0x3419, 0x00}, 1475 | + {0xBCF1, 0x02}, 1476 | + {0x3094, 0x01}, 1477 | + {0x3095, 0x01}, 1478 | + {0x3362, 0x00}, 1479 | + {0x3363, 0x00}, 1480 | + {0x3364, 0x00}, 1481 | + {0x3365, 0x00}, 1482 | + {0x0138, 0x01}, 1483 | + {IMX708_TABLE_END, 0x0000} 1484 | +}; 1485 | + 1486 | +static const imx708_reg imx708_mode_4608x2592_14fps[] = { 1487 | + {0x0342, 0x3D}, 1488 | + {0x0343, 0x20}, 1489 | + {0x0340, 0x0A}, 1490 | + {0x0341, 0x5a}, 1491 | + {0x0344, 0x00}, 1492 | + {0x0345, 0x00}, 1493 | + {0x0346, 0x00}, 1494 | + {0x0347, 0x00}, 1495 | + {0x0348, 0x11}, 1496 | + {0x0349, 0xFF}, 1497 | + {0x034A, 0X0A}, 1498 | + {0x034B, 0x1F}, 1499 | + {0x0220, 0x62}, 1500 | + {0x0222, 0x01}, 1501 | + {0x0900, 0x00}, 1502 | + {0x0901, 0x11}, 1503 | + {0x0902, 0x0A}, 1504 | + {0x3200, 0x01}, 1505 | + {0x3201, 0x01}, 1506 | + {0x32D5, 0x01}, 1507 | + {0x32D6, 0x00}, 1508 | + {0x32DB, 0x01}, 1509 | + {0x32DF, 0x00}, 1510 | + {0x350C, 0x00}, 1511 | + {0x350D, 0x00}, 1512 | + {0x0408, 0x00}, 1513 | + {0x0409, 0x00}, 1514 | + {0x040A, 0x00}, 1515 | + {0x040B, 0x00}, 1516 | + {0x040C, 0x12}, 1517 | + {0x040D, 0x00}, 1518 | + {0x040E, 0x0A}, 1519 | + {0x040F, 0x20}, 1520 | + {0x034C, 0x12}, 1521 | + {0x034D, 0x00}, 1522 | + {0x034E, 0x0A}, 1523 | + {0x034F, 0x20}, 1524 | + {0x0301, 0x05}, 1525 | + {0x0303, 0x02}, 1526 | + {0x0305, 0x02}, 1527 | + {0x0306, 0x00}, 1528 | + {0x0307, 0x7C}, 1529 | + {0x030B, 0x02}, 1530 | + {0x030D, 0x04}, 1531 | + {0x030E, 0x01}, 1532 | + {0x030F, 0x2C}, 1533 | + {0x0310, 0x01}, 1534 | + {0x3CA0, 0x00}, 1535 | + {0x3CA1, 0x64}, 1536 | + {0x3CA4, 0x00}, 1537 | + {0x3CA5, 0x00}, 1538 | + {0x3CA6, 0x00}, 1539 | + {0x3CA7, 0x00}, 1540 | + {0x3CAA, 0x00}, 1541 | + {0x3CAB, 0x00}, 1542 | + {0x3CB8, 0x00}, 1543 | + {0x3CB9, 0x08}, 1544 | + {0x3CBA, 0x00}, 1545 | + {0x3CBB, 0x00}, 1546 | + {0x3CBC, 0x00}, 1547 | + {0x3CBD, 0x3C}, 1548 | + {0x3CBE, 0x00}, 1549 | + {0x3CBF, 0x00}, 1550 | + {0x0202, 0x0A}, 1551 | + {0x0203, 0x2a}, 1552 | + {0x0224, 0x01}, 1553 | + {0x0225, 0xF4}, 1554 | + {0x3116, 0x01}, 1555 | + {0x3117, 0xF4}, 1556 | + {0x0204, 0x03}, 1557 | + {0x0205, 0x55}, 1558 | + {0x0216, 0x00}, 1559 | + {0x0217, 0x00}, 1560 | + {0x0218, 0x01}, 1561 | + {0x0219, 0x00}, 1562 | + {0x020E, 0x01}, 1563 | + {0x020F, 0x00}, 1564 | + {0x3118, 0x00}, 1565 | + {0x3119, 0x00}, 1566 | + {0x311A, 0x01}, 1567 | + {0x311B, 0x00}, 1568 | + {0x341a, 0x00}, 1569 | + {0x341b, 0x00}, 1570 | + {0x341c, 0x00}, 1571 | + {0x341d, 0x00}, 1572 | + {0x341e, 0x01}, 1573 | + {0x341f, 0x20}, 1574 | + {0x3420, 0x00}, 1575 | + {0x3421, 0xd8}, 1576 | + {0xC428, 0x00}, 1577 | + {0xC429, 0x04}, 1578 | + {0x3366, 0x00}, 1579 | + {0x3367, 0x00}, 1580 | + {0x3368, 0x00}, 1581 | + {0x3369, 0x00}, 1582 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS}, 1583 | + {IMX708_TABLE_END, 0x0000} 1584 | +}; 1585 | + 1586 | +enum { 1587 | + IMX708_MODE_4608x2592_14FPS, 1588 | + IMX708_MODE_COMMON, 1589 | + IMX708_START_STREAM, 1590 | + IMX708_STOP_STREAM, 1591 | +}; 1592 | + 1593 | +static const imx708_reg *mode_table[] = { 1594 | + [IMX708_MODE_4608x2592_14FPS] = imx708_mode_4608x2592_14fps, 1595 | + [IMX708_MODE_COMMON] = imx708_mode_common, 1596 | + [IMX708_START_STREAM] = imx708_start, 1597 | + [IMX708_STOP_STREAM] = imx708_stop, 1598 | +}; 1599 | + 1600 | +static const int imx708_14_fr[] = { 1601 | + 14, 1602 | +}; 1603 | + 1604 | +static const struct camera_common_frmfmt imx708_frmfmt[] = { 1605 | + {{4608, 2592}, imx708_14_fr, 1, 0, IMX708_MODE_4608x2592_14FPS}, 1606 | +}; 1607 | +#endif 1608 | diff --git a/kernel/nvidia/include/media/imx708.h b/kernel/nvidia/include/media/imx708.h 1609 | new file mode 100644 1610 | index 000000000..972aa1a62 1611 | --- /dev/null 1612 | +++ b/kernel/nvidia/include/media/imx708.h 1613 | @@ -0,0 +1,51 @@ 1614 | +/* 1615 | + * imx708.h - imx708 sensor header 1616 | + * 1617 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 1618 | + * 1619 | + * Contact us: support@ridgerun.com 1620 | + * 1621 | + * This program is free software; you can redistribute it and/or modify it 1622 | + * under the terms and conditions of the GNU General Public License, 1623 | + * version 2, as published by the Free Software Foundation. 1624 | + * 1625 | + * This program is distributed in the hope it will be useful, but WITHOUT 1626 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1627 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1628 | + * more details. 1629 | + * 1630 | + * You should have received a copy of the GNU General Public License 1631 | + * along with this program. If not, see . 1632 | + */ 1633 | + 1634 | +#ifndef __IMX708_H__ 1635 | +#define __IMX708_H__ 1636 | + 1637 | +/* imx708 - sensor parameters */ 1638 | +#define IMX708_MIN_GAIN (0) 1639 | +#define IMX708_MAX_GAIN (978) 1640 | +#define IMX708_ANALOG_GAIN_C0 (516) 1641 | +#define IMX708_SHIFT_8_BITS (8) 1642 | +#define IMX708_MIN_FRAME_LENGTH (256) 1643 | +#define IMX708_MAX_FRAME_LENGTH (65535) 1644 | +#define IMX708_MASK_LSB_2_BITS 0x0003 1645 | +#define IMX708_MASK_LSB_8_BITS 0x00ff 1646 | + 1647 | +/* imx708 sensor register address */ 1648 | +#define IMX708_MODEL_ID_ADDR_MSB 0x0000 1649 | +#define IMX708_MODEL_ID_ADDR_LSB 0x0001 1650 | +#define IMX708_MODEL_ID_VALUE_MSB 0x0003 1651 | +#define IMX708_MODEL_ID_VALUE_LSB 0x0001 1652 | +#define IMX708_ANALOG_GAIN_ADDR_MSB 0x0204 1653 | +#define IMX708_ANALOG_GAIN_ADDR_LSB 0x0205 1654 | +#define IMX708_DIGITAL_GAIN_ADDR_MSB 0x020e 1655 | +#define IMX708_DIGITAL_GAIN_ADDR_LSB 0x020f 1656 | +#define IMX708_FRAME_LENGTH_ADDR_MSB 0x0340 1657 | +#define IMX708_FRAME_LENGTH_ADDR_LSB 0x0341 1658 | +#define IMX708_COARSE_INTEG_TIME_ADDR_MSB 0x0202 1659 | +#define IMX708_COARSE_INTEG_TIME_ADDR_LSB 0x0203 1660 | +#define IMX708_FINE_INTEG_TIME_ADDR_MSB 0x0200 1661 | +#define IMX708_FINE_INTEG_TIME_ADDR_LSB 0x0201 1662 | +#define IMX708_GROUP_HOLD_ADDR 0x0104 1663 | + 1664 | +#endif /* __IMX708_H__ */ 1665 | -- 1666 | 2.17.1 1667 | 1668 | -------------------------------------------------------------------------------- /patches_orin_nano/patches/5.1.1_nano_imx708_v0.1.0.patch: -------------------------------------------------------------------------------- 1 | From 1b8a980db1ae1877fbe0c1e4806d7154ae505d35 Mon Sep 17 00:00:00 2001 2 | From: alfredpchacon 3 | Date: Tue, 5 Sep 2023 20:34:51 -0600 4 | Subject: [PATCH] Squashed commit of the following: 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | commit 002257de66c7cf876faf5f0c3bb45e05c7a1c0fb 10 | Author: alfredpchacon 11 | Date: Tue Jul 25 14:27:47 2023 -0600 12 | 13 | Changes from Nano implementation 14 | 15 | commit 08f0edee86f8d6855c8248de23eef42d9ad636bd 16 | Author: alfredpchacon 17 | Date: Wed Jul 19 20:45:08 2023 -0600 18 | 19 | Remove trashy code 20 | 21 | commit fc25f3508cac71da0ce7bb7f4215c890a955aa33 22 | Author: Mac Alfred Pinnock Chacón 23 | Date: Mon Jul 17 23:39:08 2023 +0000 24 | 25 | Fix duplicated copyright 26 | 27 | commit 4cfae7c5b2c2284a4a26ecbcc2ca4889f04635de 28 | Author: alfredpchacon 29 | Date: Mon Sep 4 20:51:16 2023 -0600 30 | 31 | Change compatibles 32 | 33 | commit bdce0b2d6d8fe5275a072915bb7479e40e4cbe97 34 | Author: alfredpchacon 35 | Date: Mon Sep 4 14:43:47 2023 -0600 36 | 37 | Fix dual capture 38 | 39 | commit fb8039235a1ec03af1e10479ca714452a8a69b21 40 | Author: Mac Alfred Pinnock Chacón 41 | Date: Sat Jul 1 19:10:44 2023 +0000 42 | 43 | Fix imx708.h typo 44 | 45 | commit 56ce8b4fcdeda0f14e2fada142e87a8fc62fbf66 46 | Author: alfredpchacon 47 | Date: Fri Jun 30 09:09:41 2023 -0600 48 | 49 | Remove extra code and initialize variable 50 | 51 | commit d1104464a08a74d62d929a60d3af7bd3de1deae6 52 | Author: alfredpchacon 53 | Date: Thu Jun 29 21:46:23 2023 -0600 54 | 55 | Remove extra files and initialize variables 56 | 57 | commit 4085c92d23ecdeb51db3637c1b483b3cde4f880a 58 | Author: alfredpchacon 59 | Date: Fri Jun 23 08:25:33 2023 -0600 60 | 61 | Remove 4 lane config 62 | 63 | commit 0094f8bdc7e7b977b357eb879d7c84a358a4f5b8 64 | Author: alfredpchacon 65 | Date: Fri Jun 23 08:23:20 2023 -0600 66 | 67 | Remove extra file 68 | 69 | commit 5c06593b273ccfb2bdcc39f5a98170e562b49543 70 | Author: alfredpchacon 71 | Date: Fri Jun 23 08:22:48 2023 -0600 72 | 73 | Remove extra empty line 74 | 75 | commit 8f71d88cba1f0ddce3e5f38bac9b385eb8be98df 76 | Author: alfredpchacon 77 | Date: Fri Jun 23 08:22:05 2023 -0600 78 | 79 | Change debug messages category 80 | 81 | commit ff6ac37faaaa7c721390f2fb4643d2778737caf5 82 | Author: alfredpchacon 83 | Date: Fri Jun 23 08:21:13 2023 -0600 84 | 85 | Add RPI copyright 86 | 87 | commit 0d99199def849ab1d02710fe6add4b566eb41d88 88 | Author: alfredpchacon 89 | Date: Thu Jun 22 18:48:34 2023 -0600 90 | 91 | Fix missing points in comments 92 | 93 | commit 9b44918944cff84af0ac554cc324684784a71664 94 | Author: alfredpchacon 95 | Date: Thu Jun 22 17:46:25 2023 -0600 96 | 97 | Add copyright 98 | 99 | commit 38cbb444412608b656cc1ef14145299b7a1b8b82 100 | Author: alfredpchacon 101 | Date: Thu Jun 22 17:36:46 2023 -0600 102 | 103 | Remove debug code and comments 104 | 105 | commit c897c0ea30114260b03197bd5326b4e3d70f2616 106 | Author: alfredpchacon 107 | Date: Tue Jun 20 14:51:43 2023 -0600 108 | 109 | Fix half black image issue 110 | 111 | commit 4c175f0f6756b782b518ec4f16de780b9dd24b52 112 | Author: alfredpchacon 113 | Date: Thu Jun 15 17:22:02 2023 -0600 114 | 115 | Fix timeout error 116 | 117 | commit d47fb01a32b6971a0e73ed960a678dfc765c2a44 118 | Author: alfredpchacon 119 | Date: Wed Jun 14 10:05:53 2023 -0600 120 | 121 | Change bit depth 122 | 123 | commit be53d62a317d92089aa2b99c940fa900f940fbb9 124 | Author: alfredpchacon 125 | Date: Tue Jun 13 21:04:31 2023 -0600 126 | 127 | Add more functions for reg dump 128 | 129 | commit fcdd523b3dd8feb881f9e2d020b488f22c43c553 130 | Author: alfredpchacon 131 | Date: Tue Jun 13 11:16:40 2023 -0600 132 | 133 | Add cache bypass to regdump 134 | 135 | commit aa42f1ca04511e4331f66bb4b74a1a65afd58bdc 136 | Author: alfredpchacon 137 | Date: Tue Jun 13 10:01:04 2023 -0600 138 | 139 | Add register dump compatibility 140 | 141 | commit 3568037beabb966255c718889cc3947d8c8791d7 142 | Author: alfredpchacon 143 | Date: Fri Jun 9 14:49:59 2023 -0600 144 | 145 | Change values to default 14 fps 146 | 147 | commit 1f8acb248b832691e442c320ea593f58eebbe501 148 | Author: alfredpchacon 149 | Date: Wed Jun 7 23:50:56 2023 -0600 150 | 151 | Change clock to discontinuous 152 | 153 | commit 35c8bb97e1fc59f9a48602e0604dd9aa36d9b44d 154 | Author: alfredpchacon 155 | Date: Wed Jun 7 11:26:34 2023 -0600 156 | 157 | Set framerate to 10 fps 158 | 159 | commit ec1061c534de4d4f9569c7b2e67165f5a56aac96 160 | Author: alfredpchacon 161 | Date: Tue Jun 6 11:32:26 2023 -0600 162 | 163 | Change config for 24 fps from RPI 164 | 165 | commit 377844b100ece9f6157943beec409ff3e691c8b4 166 | Author: alfredpchacon 167 | Date: Mon Jun 5 15:24:32 2023 -0600 168 | 169 | Change fps and add port 170 | 171 | commit b6aca7c3272bf241df16e2b0745a9bc9202c7da8 172 | Author: alfredpchacon 173 | Date: Mon Jun 5 14:12:54 2023 -0600 174 | 175 | Add port index in p3768-0000-a0.dtsi 176 | 177 | commit ab741d1fb1a414cdce69de1a887d92865039aedf 178 | Author: alfredpchacon 179 | Date: Sat Jun 3 18:04:46 2023 -0600 180 | 181 | Fix dependencies name mismatch 182 | 183 | commit d4af37452a9958404a668e1410a0612e9f5f4b84 184 | Author: alfredpchacon 185 | Date: Sat Jun 3 18:03:55 2023 -0600 186 | 187 | Add mode table 188 | 189 | commit 4f598a5d2453f5e79efa33e0bbcf7abc75eb118c 190 | Author: alfredpchacon 191 | Date: Sat Jun 3 18:03:12 2023 -0600 192 | 193 | Fix files names 194 | 195 | commit 4b95d50345f197ec9ee5ba125979e842fdf90d40 196 | Author: alfredpchacon 197 | Date: Sat Jun 3 16:26:21 2023 -0600 198 | 199 | Add c file and header file 200 | 201 | commit 97f3dda46156e216d1ad08f15c2b95f13def0ce3 202 | Author: alfredpchacon 203 | Date: Sat Jun 3 16:23:30 2023 -0600 204 | 205 | Add dtsi in de main dtsi file 206 | 207 | commit 0c3db025fc6e9f9042d5afe19e3ce421eaa5eba1 208 | Author: alfredpchacon 209 | Date: Sat Jun 3 16:21:56 2023 -0600 210 | 211 | Add camera in defconfig 212 | 213 | commit ae28ad6004c40252a4ce79ca942dc97a1aee0b42 214 | Author: alfredpchacon 215 | Date: Sat Jun 3 16:19:26 2023 -0600 216 | 217 | Add Kconfig description 218 | 219 | commit e1fa357912503cafa600f430740af3af69300dc8 220 | Author: alfredpchacon 221 | Date: Sat Jun 3 16:17:44 2023 -0600 222 | 223 | Add .c file and change makefile 224 | 225 | commit f0bfe8df660bb05e1521157e7ae340ca477dde9d 226 | Author: alfredpchacon 227 | Date: Sat Jun 3 16:14:22 2023 -0600 228 | 229 | Add dtb kernel config 230 | 231 | commit f12f71686e8ac76cf3700d91ece04c61ad3e5e10 232 | Author: alfredpchacon 233 | Date: Sat Jun 3 15:17:15 2023 -0600 234 | 235 | Add port description 236 | 237 | commit 26bc5c795bbe046f5989983de02e7b018dff64fd 238 | Author: alfredpchacon 239 | Date: Sat Jun 3 15:16:16 2023 -0600 240 | 241 | Add dtb files for cvb directory using imx219 fix 242 | 243 | commit 0b2f6711cf61472883d964139b50ac57bcd1df3f 244 | Author: alfredpchacon 245 | Date: Sat Jun 3 14:52:28 2023 -0600 246 | 247 | Add common device tree port description files 248 | 249 | commit f5e14f6bd834b326ac9a7b42ca143866dc62e18f 250 | Author: Mac Alfred Pinnock Chacón 251 | Date: Fri Jun 2 02:17:29 2023 +0000 252 | 253 | Revert "Fix IMX219 dtb error in missing okay status and port index" 254 | 255 | This reverts commit 9fe9c0f556c57b6f2feab6f41d31f72b484c042b 256 | 257 | commit 9fe9c0f556c57b6f2feab6f41d31f72b484c042b 258 | Author: alfredpchacon 259 | Date: Thu Jun 1 20:07:24 2023 -0600 260 | 261 | Fix IMX219 dtb error in missing okay status and port index 262 | --- 263 | .../cvb/tegra234-camera-rpicam3-imx708.dtsi | 277 +++++++ 264 | .../kernel-dts/cvb/tegra234-p3509-a02.dtsi | 1 + 265 | .../cvb/tegra234-p3768-0000-a0.dtsi | 15 + 266 | .../tegra234-p3768-camera-rpicam3-imx708.dtsi | 61 ++ 267 | .../kernel-5.10/arch/arm64/configs/defconfig | 1 + 268 | kernel/nvidia/drivers/media/i2c/Kconfig | 9 + 269 | kernel/nvidia/drivers/media/i2c/Makefile | 1 + 270 | .../drivers/media/i2c/imx708_mode_tbls.h | 222 +++++ 271 | kernel/nvidia/drivers/media/i2c/nv_imx708.c | 774 ++++++++++++++++++ 272 | kernel/nvidia/include/media/imx708.h | 53 ++ 273 | 10 files changed, 1414 insertions(+) 274 | create mode 100644 hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-camera-rpicam3-imx708.dtsi 275 | create mode 100644 hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-camera-rpicam3-imx708.dtsi 276 | create mode 100644 kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 277 | create mode 100644 kernel/nvidia/drivers/media/i2c/nv_imx708.c 278 | create mode 100644 kernel/nvidia/include/media/imx708.h 279 | 280 | diff --git a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-camera-rpicam3-imx708.dtsi b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-camera-rpicam3-imx708.dtsi 281 | new file mode 100644 282 | index 000000000..c05c1022e 283 | --- /dev/null 284 | +++ b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-camera-rpicam3-imx708.dtsi 285 | @@ -0,0 +1,277 @@ 286 | +/* 287 | + * Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. 288 | + * Copyright (c) 2023, RidgeRun . All rights reserved 289 | + * 290 | + * This program is free software; you can redistribute it and/or modify 291 | + * it under the terms of the GNU General Public License as published by 292 | + * the Free Software Foundation; either version 2 of the License, or 293 | + * (at your option) any later version. 294 | + * 295 | + * This program is distributed in the hope that it will be useful, but WITHOUT 296 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 297 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 298 | + * more details. 299 | + * 300 | + * You should have received a copy of the GNU General Public License 301 | + * along with this program. If not, see . 302 | + */ 303 | + 304 | +/ { 305 | + tegra-capture-vi { 306 | + num-channels = <2>; 307 | + ports { 308 | + #address-cells = <1>; 309 | + #size-cells = <0>; 310 | + vi_port0: port@0 { 311 | + reg = <0>; 312 | + rpicam3_imx708_vi_in0: endpoint { 313 | + status="okay"; 314 | + port-index = <0>; 315 | + bus-width = <2>; 316 | + remote-endpoint = <&rpicam3_imx708_csi_out0>; 317 | + }; 318 | + }; 319 | + vi_port1: port@1 { 320 | + reg = <1>; 321 | + rpicam3_imx708_vi_in1: endpoint { 322 | + status="okay"; 323 | + port-index = <2>; 324 | + bus-width = <2>; 325 | + remote-endpoint = <&rpicam3_imx708_csi_out1>; 326 | + }; 327 | + }; 328 | + }; 329 | + }; 330 | + 331 | + host1x@13e00000 { 332 | + nvcsi@15a00000 { 333 | + num-channels = <2>; 334 | + #address-cells = <1>; 335 | + #size-cells = <0>; 336 | + csi_chan0: channel@0 { 337 | + reg = <0>; 338 | + ports { 339 | + #address-cells = <1>; 340 | + #size-cells = <0>; 341 | + csi_chan0_port0: port@0 { 342 | + reg = <0>; 343 | + rpicam3_imx708_csi_in0: endpoint@0 { 344 | + status = "okay"; 345 | + port-index = <1>; 346 | + bus-width = <2>; 347 | + remote-endpoint = <&rpicam3_imx708_out0>; 348 | + }; 349 | + }; 350 | + csi_chan0_port1: port@1 { 351 | + reg = <1>; 352 | + rpicam3_imx708_csi_out0: endpoint@1 { 353 | + status = "okay"; 354 | + remote-endpoint = <&rpicam3_imx708_vi_in0>; 355 | + }; 356 | + }; 357 | + }; 358 | + }; 359 | + csi_chan1: channel@1 { 360 | + reg = <1>; 361 | + ports { 362 | + #address-cells = <1>; 363 | + #size-cells = <0>; 364 | + csi_chan1_port0: port@0 { 365 | + reg = <0>; 366 | + rpicam3_imx708_csi_in1: endpoint@2 { 367 | + status = "okay"; 368 | + port-index = <2>; 369 | + bus-width = <2>; 370 | + remote-endpoint = <&rpicam3_imx708_out1>; 371 | + }; 372 | + }; 373 | + csi_chan1_port1: port@1 { 374 | + reg = <1>; 375 | + rpicam3_imx708_csi_out1: endpoint@3 { 376 | + status = "okay"; 377 | + remote-endpoint = <&rpicam3_imx708_vi_in1>; 378 | + }; 379 | + }; 380 | + }; 381 | + }; 382 | + }; 383 | + }; 384 | + 385 | + cam_i2cmux { 386 | + i2c_0:i2c@0 { 387 | + imx708_cam0: rpicam3_imx708_a@1a { 388 | + status = "okay"; 389 | + compatible = "sony,imx708"; 390 | + reg = <0x1a>; 391 | + devnode = "video0"; 392 | + physical_w = "3.680"; 393 | + physical_h = "2.760"; 394 | + sensor_model = "imx708"; 395 | + use_sensor_mode_id = "true"; 396 | + 397 | + /* IMX708_MODE_4608x2592_14fps */ 398 | + mode0 { 399 | + mclk_khz = "24000"; 400 | + num_lanes = "2"; 401 | + tegra_sinterface = "serial_a"; 402 | + phy_mode = "DPHY"; 403 | + discontinuous_clk = "yes"; 404 | + dpcm_enable = "false"; 405 | + cil_settletime = "0"; 406 | + lane_polarity = "6"; 407 | + 408 | + active_w = "4608"; 409 | + active_h = "2592"; 410 | + mode_type = "bayer"; 411 | + pixel_phase = "rggb"; 412 | + csi_pixel_bit_depth = "10"; 413 | + readout_orientation = "90"; 414 | + line_length = "4808"; 415 | + inherent_gain = "1"; 416 | + pix_clk_hz = "297600000"; 417 | + 418 | + gain_factor = "16"; 419 | + framerate_factor = "1000000"; 420 | + exposure_factor = "1000000"; 421 | + min_gain_val = "16"; 422 | + max_gain_val = "256"; 423 | + step_gain_val = "1"; 424 | + default_gain = "16"; 425 | + min_hdr_ratio = "1"; 426 | + max_hdr_ratio = "1"; 427 | + min_framerate = "2000000"; 428 | + max_framerate = "14000000"; 429 | + step_framerate = "1"; 430 | + default_framerate = "14000000"; 431 | + min_exp_time = "500"; 432 | + max_exp_time = "65487"; 433 | + step_exp_time = "1"; 434 | + default_exp_time = "1600"; 435 | + embedded_metadata_height = "4"; 436 | + }; 437 | + 438 | + ports { 439 | + #address-cells = <1>; 440 | + #size-cells = <0>; 441 | + 442 | + port@0 { 443 | + reg = <0>; 444 | + rpicam3_imx708_out0: endpoint { 445 | + port-index = <0>; 446 | + bus-width = <2>; 447 | + remote-endpoint = <&rpicam3_imx708_csi_in0>; 448 | + }; 449 | + }; 450 | + }; 451 | + }; 452 | + }; 453 | + i2c_1: i2c@1 { 454 | + imx708_cam1: rpicam3_imx708_c@1a { 455 | + status = "okay"; 456 | + compatible = "sony,imx708"; 457 | + reg = <0x1a>; 458 | + devnode = "video1"; 459 | + physical_w = "3.680"; 460 | + physical_h = "2.760"; 461 | + sensor_model = "imx708"; 462 | + use_sensor_mode_id = "true"; 463 | + 464 | + /* IMX708_MODE_4608x2592_14fps */ 465 | + mode0 { 466 | + mclk_khz = "24000"; 467 | + num_lanes = "2"; 468 | + tegra_sinterface = "serial_c"; 469 | + phy_mode = "DPHY"; 470 | + discontinuous_clk = "yes"; 471 | + dpcm_enable = "false"; 472 | + cil_settletime = "0"; 473 | + lane_polarity = "0"; 474 | + 475 | + active_w = "4608"; 476 | + active_h = "2592"; 477 | + mode_type = "bayer"; 478 | + pixel_phase = "rggb"; 479 | + csi_pixel_bit_depth = "10"; 480 | + readout_orientation = "90"; 481 | + line_length = "4808"; 482 | + inherent_gain = "1"; 483 | + pix_clk_hz = "297600000"; 484 | + 485 | + gain_factor = "16"; 486 | + framerate_factor = "1000000"; 487 | + exposure_factor = "1000000"; 488 | + min_gain_val = "16"; 489 | + max_gain_val = "256"; 490 | + step_gain_val = "1"; 491 | + default_gain = "16"; 492 | + min_hdr_ratio = "1"; 493 | + max_hdr_ratio = "1"; 494 | + min_framerate = "2000000"; 495 | + max_framerate = "14000000"; 496 | + step_framerate = "1"; 497 | + default_framerate = "14000000"; 498 | + min_exp_time = "500"; 499 | + max_exp_time = "65487"; 500 | + step_exp_time = "1"; 501 | + default_exp_time = "1600"; 502 | + embedded_metadata_height = "4"; 503 | + }; 504 | + 505 | + ports { 506 | + #address-cells = <1>; 507 | + #size-cells = <0>; 508 | + 509 | + port@0 { 510 | + reg = <0>; 511 | + rpicam3_imx708_out1: endpoint { 512 | + status = "okay"; 513 | + port-index = <2>; 514 | + bus-width = <2>; 515 | + remote-endpoint = <&rpicam3_imx708_csi_in1>; 516 | + }; 517 | + }; 518 | + }; 519 | + }; 520 | + }; 521 | + }; 522 | +}; 523 | + 524 | +/ { 525 | + tegra-camera-platform { 526 | + compatible = "nvidia, tegra-camera-platform"; 527 | + num_csi_lanes = <4>; 528 | + max_lane_speed = <2500000>; 529 | + min_bits_per_pixel = <10>; 530 | + vi_peak_byte_per_pixel = <2>; 531 | + vi_bw_margin_pct = <25>; 532 | + max_pixel_rate = <7500000>; 533 | + isp_peak_byte_per_pixel = <5>; 534 | + isp_bw_margin_pct = <25>; 535 | + 536 | + modules { 537 | + cam_module0: module0 { 538 | + status = "okay"; 539 | + badge = "jakku_front_RBPCV3"; 540 | + position = "front"; 541 | + orientation = "1"; 542 | + cam_module0_drivernode0: drivernode0 { 543 | + status = "okay"; 544 | + pcl_id = "v4l2_sensor"; 545 | + devname = "imx708 9-001a"; 546 | + proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@0/rpicam3_imx708_a@1a"; 547 | + }; 548 | + }; 549 | + cam_module1: module1 { 550 | + badge = "jakku_rear_RBPCV3"; 551 | + position = "rear"; 552 | + orientation = "1"; 553 | + cam_module1_drivernode0: drivernode0 { 554 | + status = "okay"; 555 | + pcl_id = "v4l2_sensor"; 556 | + devname = "imx708 10-001a"; 557 | + proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@1/rpicam3_imx708_c@1a"; 558 | + }; 559 | + }; 560 | + }; 561 | + }; 562 | +}; 563 | diff --git a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3509-a02.dtsi b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3509-a02.dtsi 564 | index b6f1047d2..daf32c0c9 100644 565 | --- a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3509-a02.dtsi 566 | +++ b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3509-a02.dtsi 567 | @@ -16,6 +16,7 @@ 568 | #include "tegra234-p3509-a02-pcie.dtsi" 569 | #include "tegra234-p3509-a02-fixed-regulator.dtsi" 570 | #include "tegra234-p3509-audio.dtsi" 571 | +#include "tegra234-p3768-camera-rpicam3-imx708.dtsi" 572 | #include "tegra234-p3768-camera-rbpcv3-imx477.dtsi" 573 | #include "tegra234-p3768-camera-rbpcv2-imx219.dtsi" 574 | 575 | diff --git a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi 576 | index 01f41c8d0..f81570d42 100644 577 | --- a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi 578 | +++ b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi 579 | @@ -18,6 +18,7 @@ 580 | #include "tegra234-p3768-audio.dtsi" 581 | #include "tegra234-p3768-camera-rbpcv3-imx477.dtsi" 582 | #include "tegra234-p3768-camera-rbpcv2-imx219.dtsi" 583 | +#include "tegra234-p3768-camera-rpicam3-imx708.dtsi" 584 | 585 | / { 586 | gpio-keys { 587 | @@ -334,6 +335,20 @@ 588 | }; 589 | }; 590 | }; 591 | + 592 | + rpicam3_imx708_a@1a { 593 | + mode0 { 594 | + tegra_sinterface = "serial_b"; 595 | + lane_polarity = "6"; 596 | + }; 597 | + ports { 598 | + port@0 { 599 | + endpoint { 600 | + port-index = <1>; 601 | + }; 602 | + }; 603 | + }; 604 | + }; 605 | }; 606 | }; 607 | }; 608 | diff --git a/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-camera-rpicam3-imx708.dtsi b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-camera-rpicam3-imx708.dtsi 609 | new file mode 100644 610 | index 000000000..cd7e43584 611 | --- /dev/null 612 | +++ b/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-camera-rpicam3-imx708.dtsi 613 | @@ -0,0 +1,61 @@ 614 | +/* 615 | + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. 616 | + * Copyright (c) 2023, RidgeRun. All rights reserved. 617 | + * 618 | + * This program is free software; you can redistribute it and/or modify 619 | + * it under the terms of the GNU General Public License as published by 620 | + * the Free Software Foundation; either version 2 of the License, or 621 | + * (at your option) any later version. 622 | + * 623 | + * This program is distributed in the hope that it will be useful, but WITHOUT 624 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 625 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 626 | + * more details. 627 | + * 628 | + * You should have received a copy of the GNU General Public License 629 | + * along with this program. If not, see . 630 | + */ 631 | + 632 | +#include "tegra234-camera-rpicam3-imx708.dtsi" 633 | + 634 | +#define CAM0_PWDN TEGRA234_MAIN_GPIO(H, 6) 635 | +#define CAM1_PWDN TEGRA234_MAIN_GPIO(AC, 0) 636 | +#define CAM_I2C_MUX TEGRA234_AON_GPIO(CC, 3) 637 | + 638 | +/ { 639 | + cam_i2cmux { 640 | + status = "okay"; 641 | + compatible = "i2c-mux-gpio"; 642 | + #address-cells = <1>; 643 | + #size-cells = <0>; 644 | + mux-gpios = <&tegra_aon_gpio CAM_I2C_MUX GPIO_ACTIVE_HIGH>; 645 | + i2c-parent = <&cam_i2c>; 646 | + i2c@0 { 647 | + status = "okay"; 648 | + reg = <0>; 649 | + #address-cells = <1>; 650 | + #size-cells = <0>; 651 | + rpicam3_imx708_a@1a { 652 | + reset-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>; 653 | + }; 654 | + }; 655 | + i2c@1 { 656 | + status = "okay"; 657 | + reg = <1>; 658 | + #address-cells = <1>; 659 | + #size-cells = <0>; 660 | + rpicam3_imx708_c@1a { 661 | + reset-gpios = <&tegra_main_gpio CAM1_PWDN GPIO_ACTIVE_HIGH>; 662 | + }; 663 | + }; 664 | + }; 665 | + 666 | + gpio@2200000 { 667 | + camera-control-output-low { 668 | + gpio-hog; 669 | + output-low; 670 | + gpios = ; 671 | + label = "cam0-pwdn","cam1-pwdn"; 672 | + }; 673 | + }; 674 | +}; 675 | diff --git a/kernel/kernel-5.10/arch/arm64/configs/defconfig b/kernel/kernel-5.10/arch/arm64/configs/defconfig 676 | index bda2dff57..53b23f47a 100644 677 | --- a/kernel/kernel-5.10/arch/arm64/configs/defconfig 678 | +++ b/kernel/kernel-5.10/arch/arm64/configs/defconfig 679 | @@ -886,6 +886,7 @@ CONFIG_VIDEO_ECAM=m 680 | CONFIG_NV_VIDEO_IMX185=m 681 | CONFIG_NV_VIDEO_IMX219=m 682 | CONFIG_NV_VIDEO_IMX477=m 683 | +CONFIG_NV_VIDEO_IMX708=m 684 | CONFIG_NV_VIDEO_IMX268=m 685 | CONFIG_NV_VIDEO_IMX274=m 686 | CONFIG_NV_VIDEO_IMX318=m 687 | diff --git a/kernel/nvidia/drivers/media/i2c/Kconfig b/kernel/nvidia/drivers/media/i2c/Kconfig 688 | index 0592973a8..7d8c07269 100644 689 | --- a/kernel/nvidia/drivers/media/i2c/Kconfig 690 | +++ b/kernel/nvidia/drivers/media/i2c/Kconfig 691 | @@ -13,6 +13,15 @@ config NV_VIDEO_IMX185 692 | To compile this driver as a module, choose M here: the module 693 | will be called imx185. 694 | 695 | +config NV_VIDEO_IMX708 696 | + tristate "IMX708 camera sensor support" 697 | + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 698 | + help 699 | + This driver supports IMX708 camera sensor from Sony 700 | + 701 | + To compile this driver as a module, choose M here: the module 702 | + will be called IMX708. 703 | + 704 | config NV_VIDEO_IMX477 705 | tristate "IMX477 camera sensor support" 706 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 707 | diff --git a/kernel/nvidia/drivers/media/i2c/Makefile b/kernel/nvidia/drivers/media/i2c/Makefile 708 | index f8f6c3ba0..b9c2a7950 100644 709 | --- a/kernel/nvidia/drivers/media/i2c/Makefile 710 | +++ b/kernel/nvidia/drivers/media/i2c/Makefile 711 | @@ -5,6 +5,7 @@ ccflags-y += -I$(srctree)/drivers/video/tegra/camera 712 | 713 | obj-$(CONFIG_NV_VIDEO_IMX185) += nv_imx185.o 714 | obj-$(CONFIG_NV_VIDEO_IMX185) += nv_imx185_v1.o 715 | +obj-$(CONFIG_NV_VIDEO_IMX708) += nv_imx708.o 716 | obj-$(CONFIG_NV_VIDEO_IMX477) += nv_imx477.o 717 | obj-$(CONFIG_NV_VIDEO_IMX219) += nv_imx219.o 718 | obj-$(CONFIG_NV_VIDEO_IMX268) += nv_imx268.o 719 | diff --git a/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h b/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 720 | new file mode 100644 721 | index 000000000..0d273d1a8 722 | --- /dev/null 723 | +++ b/kernel/nvidia/drivers/media/i2c/imx708_mode_tbls.h 724 | @@ -0,0 +1,222 @@ 725 | +/* 726 | + * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved. 727 | + * Copyright (C) 2022, Raspberry Pi Ltd 728 | + * Copyright (c) 2023, RidgeRun . All rights reserved 729 | + * 730 | + * This program is free software; you can redistribute it and/or modify 731 | + * it under the terms of the GNU General Public License as published by 732 | + * the Free Software Foundation; either version 2 of the License, or 733 | + * (at your option) any later version. 734 | + * 735 | + * This program is distributed in the hope that it will be useful, but WITHOUT 736 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 737 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 738 | + * more details. 739 | + * 740 | + * You should have received a copy of the GNU General Public License 741 | + * along with this program. If not, see . 742 | + */ 743 | + 744 | +#ifndef __IMX708_I2C_TABLES__ 745 | +#define __IMX708_I2C_TABLES__ 746 | + 747 | +#include 748 | + 749 | +#define IMX708_TABLE_WAIT_MS 0 750 | +#define IMX708_TABLE_END 1 751 | +#define IMX708_WAIT_MS 1 752 | +#define IMX708_STANDBY_REG 0x0100 753 | + 754 | +#define imx708_reg struct reg_8 755 | + 756 | +static const imx708_reg imx708_start[] = { 757 | + {IMX708_STANDBY_REG, 0x1}, 758 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*3}, 759 | + {IMX708_TABLE_END, 0x00} 760 | +}; 761 | + 762 | +static const imx708_reg imx708_stop[] = { 763 | + {IMX708_STANDBY_REG, 0x0}, 764 | + {IMX708_TABLE_END, 0x00} 765 | +}; 766 | + 767 | +static const imx708_reg imx708_mode_common[] = { 768 | + /* software reset */ 769 | + {0x0103, 0x01}, 770 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS*10}, 771 | + {0x0100, 0x00}, 772 | + {0x0136, 0x18}, 773 | + {0x0137, 0x00}, 774 | + {0x33F0, 0x02}, 775 | + {0x33F1, 0x05}, 776 | + {0x3062, 0x00}, 777 | + {0x3063, 0x12}, 778 | + {0x3068, 0x00}, 779 | + {0x3069, 0x12}, 780 | + {0x306A, 0x00}, 781 | + {0x306B, 0x30}, 782 | + {0x3076, 0x00}, 783 | + {0x3077, 0x30}, 784 | + {0x3078, 0x00}, 785 | + {0x3079, 0x30}, 786 | + {0x5E54, 0x0C}, 787 | + {0x6E44, 0x00}, 788 | + {0xB0B6, 0x01}, 789 | + {0xE829, 0x00}, 790 | + {0xF001, 0x08}, 791 | + {0xF003, 0x08}, 792 | + {0xF00D, 0x10}, 793 | + {0xF00F, 0x10}, 794 | + {0xF031, 0x08}, 795 | + {0x0830, 0x01}, 796 | + {0x0831, 0x01}, 797 | + {0x0832, 0x01}, 798 | + {0xF033, 0x08}, 799 | + {0xF03D, 0x10}, 800 | + {0xF03F, 0x10}, 801 | + {0x0112, 0x0a}, 802 | + {0x0113, 0x0a}, 803 | + {0x0114, 0x01}, 804 | + {0x0B8E, 0x01}, 805 | + {0x0B8F, 0x00}, 806 | + {0x0B94, 0x01}, 807 | + {0x0B95, 0x00}, 808 | + {0x3400, 0x01}, 809 | + {0x3478, 0x01}, 810 | + {0x3479, 0x1c}, 811 | + {0x3091, 0x01}, 812 | + {0x3092, 0x00}, 813 | + {0x3419, 0x00}, 814 | + {0xBCF1, 0x02}, 815 | + {0x3094, 0x01}, 816 | + {0x3095, 0x01}, 817 | + {0x3362, 0x00}, 818 | + {0x3363, 0x00}, 819 | + {0x3364, 0x00}, 820 | + {0x3365, 0x00}, 821 | + {0x0138, 0x01}, 822 | + {IMX708_TABLE_END, 0x0000} 823 | +}; 824 | + 825 | +static const imx708_reg imx708_mode_4608x2592_14fps[] = { 826 | + {0x0342, 0x3D}, 827 | + {0x0343, 0x20}, 828 | + {0x0340, 0x0A}, 829 | + {0x0341, 0x5a}, 830 | + {0x0344, 0x00}, 831 | + {0x0345, 0x00}, 832 | + {0x0346, 0x00}, 833 | + {0x0347, 0x00}, 834 | + {0x0348, 0x11}, 835 | + {0x0349, 0xFF}, 836 | + {0x034A, 0X0A}, 837 | + {0x034B, 0x1F}, 838 | + {0x0220, 0x62}, 839 | + {0x0222, 0x01}, 840 | + {0x0900, 0x00}, 841 | + {0x0901, 0x11}, 842 | + {0x0902, 0x0A}, 843 | + {0x3200, 0x01}, 844 | + {0x3201, 0x01}, 845 | + {0x32D5, 0x01}, 846 | + {0x32D6, 0x00}, 847 | + {0x32DB, 0x01}, 848 | + {0x32DF, 0x00}, 849 | + {0x350C, 0x00}, 850 | + {0x350D, 0x00}, 851 | + {0x0408, 0x00}, 852 | + {0x0409, 0x00}, 853 | + {0x040A, 0x00}, 854 | + {0x040B, 0x00}, 855 | + {0x040C, 0x12}, 856 | + {0x040D, 0x00}, 857 | + {0x040E, 0x0A}, 858 | + {0x040F, 0x20}, 859 | + {0x034C, 0x12}, 860 | + {0x034D, 0x00}, 861 | + {0x034E, 0x0A}, 862 | + {0x034F, 0x20}, 863 | + {0x0301, 0x05}, 864 | + {0x0303, 0x02}, 865 | + {0x0305, 0x02}, 866 | + {0x0306, 0x00}, 867 | + {0x0307, 0x7C}, 868 | + {0x030B, 0x02}, 869 | + {0x030D, 0x04}, 870 | + {0x030E, 0x01}, 871 | + {0x030F, 0x2C}, 872 | + {0x0310, 0x01}, 873 | + {0x3CA0, 0x00}, 874 | + {0x3CA1, 0x64}, 875 | + {0x3CA4, 0x00}, 876 | + {0x3CA5, 0x00}, 877 | + {0x3CA6, 0x00}, 878 | + {0x3CA7, 0x00}, 879 | + {0x3CAA, 0x00}, 880 | + {0x3CAB, 0x00}, 881 | + {0x3CB8, 0x00}, 882 | + {0x3CB9, 0x08}, 883 | + {0x3CBA, 0x00}, 884 | + {0x3CBB, 0x00}, 885 | + {0x3CBC, 0x00}, 886 | + {0x3CBD, 0x3C}, 887 | + {0x3CBE, 0x00}, 888 | + {0x3CBF, 0x00}, 889 | + {0x0202, 0x0A}, 890 | + {0x0203, 0x2a}, 891 | + {0x0224, 0x01}, 892 | + {0x0225, 0xF4}, 893 | + {0x3116, 0x01}, 894 | + {0x3117, 0xF4}, 895 | + {0x0204, 0x03}, 896 | + {0x0205, 0x55}, 897 | + {0x0216, 0x00}, 898 | + {0x0217, 0x00}, 899 | + {0x0218, 0x01}, 900 | + {0x0219, 0x00}, 901 | + {0x020E, 0x01}, 902 | + {0x020F, 0x00}, 903 | + {0x3118, 0x00}, 904 | + {0x3119, 0x00}, 905 | + {0x311A, 0x01}, 906 | + {0x311B, 0x00}, 907 | + {0x341a, 0x00}, 908 | + {0x341b, 0x00}, 909 | + {0x341c, 0x00}, 910 | + {0x341d, 0x00}, 911 | + {0x341e, 0x01}, 912 | + {0x341f, 0x20}, 913 | + {0x3420, 0x00}, 914 | + {0x3421, 0xd8}, 915 | + {0xC428, 0x00}, 916 | + {0xC429, 0x04}, 917 | + {0x3366, 0x00}, 918 | + {0x3367, 0x00}, 919 | + {0x3368, 0x00}, 920 | + {0x3369, 0x00}, 921 | + {IMX708_TABLE_WAIT_MS, IMX708_WAIT_MS}, 922 | + {IMX708_TABLE_END, 0x0000} 923 | +}; 924 | + 925 | +enum { 926 | + IMX708_MODE_4608x2592_14FPS, 927 | + IMX708_MODE_COMMON, 928 | + IMX708_START_STREAM, 929 | + IMX708_STOP_STREAM, 930 | +}; 931 | + 932 | +static const imx708_reg *mode_table[] = { 933 | + [IMX708_MODE_4608x2592_14FPS] = imx708_mode_4608x2592_14fps, 934 | + [IMX708_MODE_COMMON] = imx708_mode_common, 935 | + [IMX708_START_STREAM] = imx708_start, 936 | + [IMX708_STOP_STREAM] = imx708_stop, 937 | +}; 938 | + 939 | +static const int imx708_14_fr[] = { 940 | + 14, 941 | +}; 942 | + 943 | +static const struct camera_common_frmfmt imx708_frmfmt[] = { 944 | + {{4608, 2592}, imx708_14_fr, 1, 0, IMX708_MODE_4608x2592_14FPS}, 945 | +}; 946 | +#endif 947 | diff --git a/kernel/nvidia/drivers/media/i2c/nv_imx708.c b/kernel/nvidia/drivers/media/i2c/nv_imx708.c 948 | new file mode 100644 949 | index 000000000..c33fc24b5 950 | --- /dev/null 951 | +++ b/kernel/nvidia/drivers/media/i2c/nv_imx708.c 952 | @@ -0,0 +1,774 @@ 953 | +/* 954 | + * imx708.c - imx708 sensor driver 955 | + * 956 | + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. 957 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 958 | + * 959 | + * Contact us: support@ridgerun.com 960 | + * 961 | + * This program is free software; you can redistribute it and/or modify it 962 | + * under the terms and conditions of the GNU General Public License, 963 | + * version 2, as published by the Free Software Foundation. 964 | + * 965 | + * This program is distributed in the hope it will be useful, but WITHOUT 966 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 967 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 968 | + * more details. 969 | + * 970 | + * You should have received a copy of the GNU General Public License 971 | + * along with this program. If not, see . 972 | + */ 973 | + 974 | +#include 975 | +#include 976 | +#include 977 | +#include 978 | +#include 979 | + 980 | +#include "../platform/tegra/camera/camera_gpio.h" 981 | +#include "imx708_mode_tbls.h" 982 | + 983 | +static const struct of_device_id imx708_of_match[] = { 984 | + {.compatible = "sony,imx708",}, 985 | + {}, 986 | +}; 987 | + 988 | +MODULE_DEVICE_TABLE(of, imx708_of_match); 989 | + 990 | +static const u32 ctrl_cid_list[] = { 991 | + TEGRA_CAMERA_CID_GAIN, 992 | + TEGRA_CAMERA_CID_EXPOSURE, 993 | + TEGRA_CAMERA_CID_FRAME_RATE, 994 | + TEGRA_CAMERA_CID_SENSOR_MODE_ID, 995 | +}; 996 | + 997 | +struct imx708 { 998 | + struct i2c_client *i2c_client; 999 | + struct v4l2_subdev *subdev; 1000 | + u16 fine_integ_time; 1001 | + u32 frame_length; 1002 | + struct camera_common_data *s_data; 1003 | + struct tegracam_device *tc_dev; 1004 | +}; 1005 | + 1006 | +static const struct regmap_config sensor_regmap_config = { 1007 | + .reg_bits = 16, 1008 | + .val_bits = 8, 1009 | + .cache_type = REGCACHE_RBTREE, 1010 | +#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE 1011 | + .use_single_rw = true, 1012 | +#else 1013 | + .use_single_read = true, 1014 | + .use_single_write = true, 1015 | +#endif 1016 | +}; 1017 | + 1018 | +static inline void imx708_get_frame_length_regs(imx708_reg * regs, 1019 | + u32 frame_length) 1020 | +{ 1021 | + regs->addr = IMX708_FRAME_LENGTH_ADDR_MSB; 1022 | + regs->val = (frame_length >> 8) & 0xff; 1023 | + (regs + 1)->addr = IMX708_FRAME_LENGTH_ADDR_LSB; 1024 | + (regs + 1)->val = (frame_length) & 0xff; 1025 | +} 1026 | + 1027 | +static inline void imx708_get_coarse_integ_time_regs(imx708_reg * regs, 1028 | + u32 coarse_time) 1029 | +{ 1030 | + regs->addr = IMX708_COARSE_INTEG_TIME_ADDR_MSB; 1031 | + regs->val = (coarse_time >> 8) & 0xff; 1032 | + (regs + 1)->addr = IMX708_COARSE_INTEG_TIME_ADDR_LSB; 1033 | + (regs + 1)->val = (coarse_time) & 0xff; 1034 | +} 1035 | + 1036 | +static inline void imx708_get_gain_reg(imx708_reg * reg, u16 gain) 1037 | +{ 1038 | + reg->addr = IMX708_ANALOG_GAIN_ADDR_MSB; 1039 | + reg->val = (gain >> IMX708_SHIFT_8_BITS) & IMX708_MASK_LSB_2_BITS; 1040 | + 1041 | + (reg + 1)->addr = IMX708_ANALOG_GAIN_ADDR_LSB; 1042 | + (reg + 1)->val = (gain) & IMX708_MASK_LSB_8_BITS; 1043 | +} 1044 | + 1045 | +static inline int imx708_read_reg(struct camera_common_data *s_data, 1046 | + u16 addr, u8 * val) 1047 | +{ 1048 | + int err = 0; 1049 | + u32 reg_val = 0; 1050 | + 1051 | + err = regmap_read(s_data->regmap, addr, ®_val); 1052 | + *val = reg_val & 0xff; 1053 | + 1054 | + return err; 1055 | +} 1056 | + 1057 | +static inline int imx708_write_reg(struct camera_common_data *s_data, 1058 | + u16 addr, u8 val) 1059 | +{ 1060 | + int err = 0; 1061 | + 1062 | + err = regmap_write(s_data->regmap, addr, val); 1063 | + if (err) 1064 | + dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x", 1065 | + __func__, addr, val); 1066 | + 1067 | + return err; 1068 | +} 1069 | + 1070 | +static int imx708_write_table(struct imx708 *priv, const imx708_reg table[]) 1071 | +{ 1072 | + return regmap_util_write_table_8(priv->s_data->regmap, table, NULL, 0, 1073 | + IMX708_TABLE_WAIT_MS, 1074 | + IMX708_TABLE_END); 1075 | +} 1076 | + 1077 | +static int imx708_set_group_hold(struct tegracam_device *tc_dev, bool val) 1078 | +{ 1079 | + struct camera_common_data *s_data = tc_dev->s_data; 1080 | + struct device *dev = tc_dev->dev; 1081 | + int err = 0; 1082 | + 1083 | + dev_dbg(dev, "%s: Setting group hold control to: %u\n", __func__, val); 1084 | + 1085 | + err = imx708_write_reg(s_data, IMX708_GROUP_HOLD_ADDR, val); 1086 | + if (err) { 1087 | + dev_err(dev, "%s: Group hold control error\n", __func__); 1088 | + return err; 1089 | + } 1090 | + 1091 | + return 0; 1092 | +} 1093 | + 1094 | +static int imx708_get_fine_integ_time(struct imx708 *priv, u16 * fine_time) 1095 | +{ 1096 | + struct camera_common_data *s_data = priv->s_data; 1097 | + int err = 0; 1098 | + u8 reg_val[2] = {0}; 1099 | + 1100 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_MSB, 1101 | + ®_val[0]); 1102 | + if (err) 1103 | + goto done; 1104 | + 1105 | + err = imx708_read_reg(s_data, IMX708_FINE_INTEG_TIME_ADDR_LSB, 1106 | + ®_val[1]); 1107 | + if (err) 1108 | + goto done; 1109 | + 1110 | + *fine_time = (reg_val[0] << 8) | reg_val[1]; 1111 | + 1112 | +done: 1113 | + return err; 1114 | +} 1115 | + 1116 | +static int imx708_set_gain(struct tegracam_device *tc_dev, s64 val) 1117 | +{ 1118 | + struct camera_common_data *s_data = tc_dev->s_data; 1119 | + struct device *dev = s_data->dev; 1120 | + const struct sensor_mode_properties *mode = 1121 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 1122 | + int err = 0; 1123 | + int i = 0; 1124 | + imx708_reg gain_reg[2] = {0}; 1125 | + s16 gain = 0; 1126 | + 1127 | + dev_dbg(dev, "%s: Setting gain control to: %lld\n", __func__, val); 1128 | + 1129 | + /* Gain Formula: 1130 | + Gain = (IMX708_GAIN_C0 - (IMX708_GAIN_C0 * gain_factor / val)) 1131 | + */ 1132 | + gain = 1133 | + (s16) (IMX708_ANALOG_GAIN_C0 - 1134 | + (mode->control_properties.gain_factor * 1135 | + IMX708_ANALOG_GAIN_C0 / val)); 1136 | + 1137 | + dev_dbg(dev, "%s: val: %lld (/%d) [times], gain: %u\n", 1138 | + __func__, val, mode->control_properties.gain_factor, gain); 1139 | + 1140 | + imx708_get_gain_reg(gain_reg, (u16) gain); 1141 | + 1142 | + for (i = 0; i < ARRAY_SIZE(gain_reg); i++) { 1143 | + err = imx708_write_reg(s_data, gain_reg[i].addr, 1144 | + gain_reg[i].val); 1145 | + if (err) { 1146 | + dev_err(dev, "%s: gain control error\n", __func__); 1147 | + break; 1148 | + } 1149 | + } 1150 | + 1151 | + return err; 1152 | +} 1153 | + 1154 | +static int imx708_set_frame_rate(struct tegracam_device *tc_dev, s64 val) 1155 | +{ 1156 | + struct camera_common_data *s_data = tc_dev->s_data; 1157 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 1158 | + struct device *dev = tc_dev->dev; 1159 | + const struct sensor_mode_properties *mode = 1160 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 1161 | + 1162 | + int err = 0; 1163 | + imx708_reg fl_regs[2] = {0}; 1164 | + u32 frame_length = 0; 1165 | + int i = 0; 1166 | + 1167 | + dev_dbg(dev, "%s: Setting framerate control to: %lld\n", __func__, val); 1168 | + 1169 | + frame_length = (u32)(mode->signal_properties.pixel_clock.val * 1170 | + (u64)mode->control_properties.framerate_factor / 1171 | + mode->image_properties.line_length / val); 1172 | + 1173 | + dev_dbg(dev, 1174 | + "%s: val: %llde-6 [fps], frame_length: %u [lines]\n", 1175 | + __func__, val, frame_length); 1176 | + 1177 | + imx708_get_frame_length_regs(fl_regs, frame_length); 1178 | + for (i = 0; i < 2; i++) { 1179 | + err = imx708_write_reg(s_data, fl_regs[i].addr, fl_regs[i].val); 1180 | + if (err) { 1181 | + dev_err(dev, 1182 | + "%s: frame_length control error\n", __func__); 1183 | + return err; 1184 | + } 1185 | + } 1186 | + 1187 | + priv->frame_length = frame_length; 1188 | + 1189 | + return err; 1190 | +} 1191 | + 1192 | +static int imx708_set_exposure(struct tegracam_device *tc_dev, s64 val) 1193 | +{ 1194 | + struct camera_common_data *s_data = tc_dev->s_data; 1195 | + struct imx708 *priv = (struct imx708 *)tc_dev->priv; 1196 | + struct device *dev = tc_dev->dev; 1197 | + const struct sensor_mode_properties *mode = 1198 | + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; 1199 | + 1200 | + int err = 0; 1201 | + imx708_reg ct_regs[2] = {0}; 1202 | + const s32 fine_integ_time_factor = priv->fine_integ_time * 1203 | + mode->control_properties.exposure_factor / 1204 | + mode->signal_properties.pixel_clock.val; 1205 | + u32 coarse_time = 0; 1206 | + int i = 0; 1207 | + 1208 | + dev_dbg(dev, "%s: Setting exposure control to: %lld\n", __func__, val); 1209 | + 1210 | + coarse_time = (val - fine_integ_time_factor) 1211 | + * mode->signal_properties.pixel_clock.val 1212 | + / mode->control_properties.exposure_factor 1213 | + / mode->image_properties.line_length; 1214 | + 1215 | + dev_dbg(dev, "%s: val: %lld [us], coarse_time: %d [lines]\n", 1216 | + __func__, val, coarse_time); 1217 | + 1218 | + imx708_get_coarse_integ_time_regs(ct_regs, coarse_time); 1219 | + 1220 | + for (i = 0; i < 2; i++) { 1221 | + err = imx708_write_reg(s_data, ct_regs[i].addr, ct_regs[i].val); 1222 | + if (err) { 1223 | + dev_err(dev, 1224 | + "%s: coarse_time control error\n", __func__); 1225 | + return err; 1226 | + } 1227 | + } 1228 | + 1229 | + return err; 1230 | +} 1231 | + 1232 | +static struct tegracam_ctrl_ops imx708_ctrl_ops = { 1233 | + .numctrls = ARRAY_SIZE(ctrl_cid_list), 1234 | + .ctrl_cid_list = ctrl_cid_list, 1235 | + .set_gain = imx708_set_gain, 1236 | + .set_exposure = imx708_set_exposure, 1237 | + .set_frame_rate = imx708_set_frame_rate, 1238 | + .set_group_hold = imx708_set_group_hold, 1239 | +}; 1240 | + 1241 | +static int imx708_power_on(struct camera_common_data *s_data) 1242 | +{ 1243 | + int err = 0; 1244 | + struct camera_common_power_rail *pw = s_data->power; 1245 | + struct camera_common_pdata *pdata = s_data->pdata; 1246 | + struct device *dev = s_data->dev; 1247 | + 1248 | + dev_dbg(dev, "%s: power on\n", __func__); 1249 | + if (pdata && pdata->power_on) { 1250 | + err = pdata->power_on(pw); 1251 | + if (err) 1252 | + dev_err(dev, "%s failed.\n", __func__); 1253 | + else 1254 | + pw->state = SWITCH_ON; 1255 | + return err; 1256 | + } 1257 | + 1258 | + if (pw->reset_gpio) { 1259 | + if (gpio_cansleep(pw->reset_gpio)) 1260 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 1261 | + else 1262 | + gpio_set_value(pw->reset_gpio, 0); 1263 | + } 1264 | + 1265 | + if (unlikely(!(pw->avdd || pw->iovdd || pw->dvdd))) 1266 | + goto skip_power_seqn; 1267 | + 1268 | + usleep_range(10, 20); 1269 | + 1270 | + if (pw->avdd) { 1271 | + err = regulator_enable(pw->avdd); 1272 | + if (err) 1273 | + goto imx708_avdd_fail; 1274 | + } 1275 | + 1276 | + if (pw->iovdd) { 1277 | + err = regulator_enable(pw->iovdd); 1278 | + if (err) 1279 | + goto imx708_iovdd_fail; 1280 | + } 1281 | + 1282 | + if (pw->dvdd) { 1283 | + err = regulator_enable(pw->dvdd); 1284 | + if (err) 1285 | + goto imx708_dvdd_fail; 1286 | + } 1287 | + 1288 | + usleep_range(10, 20); 1289 | + 1290 | +skip_power_seqn: 1291 | + if (pw->reset_gpio) { 1292 | + if (gpio_cansleep(pw->reset_gpio)) 1293 | + gpio_set_value_cansleep(pw->reset_gpio, 1); 1294 | + else 1295 | + gpio_set_value(pw->reset_gpio, 1); 1296 | + } 1297 | + 1298 | + /* Need to wait for t4 + t5 + t9 + t10 time as per the data sheet */ 1299 | + /* t4 - 200us, t5 - 21.2ms, t9 - 1.2ms t10 - 270 ms */ 1300 | + usleep_range(300000, 300100); 1301 | + 1302 | + pw->state = SWITCH_ON; 1303 | + 1304 | + return 0; 1305 | + 1306 | +imx708_dvdd_fail: 1307 | + regulator_disable(pw->iovdd); 1308 | + 1309 | +imx708_iovdd_fail: 1310 | + regulator_disable(pw->avdd); 1311 | + 1312 | +imx708_avdd_fail: 1313 | + dev_err(dev, "%s failed.\n", __func__); 1314 | + 1315 | + return -ENODEV; 1316 | +} 1317 | + 1318 | +static int imx708_power_off(struct camera_common_data *s_data) 1319 | +{ 1320 | + int err = 0; 1321 | + struct camera_common_power_rail *pw = s_data->power; 1322 | + struct camera_common_pdata *pdata = s_data->pdata; 1323 | + struct device *dev = s_data->dev; 1324 | + 1325 | + dev_dbg(dev, "%s: power off\n", __func__); 1326 | + 1327 | + if (pdata && pdata->power_off) { 1328 | + err = pdata->power_off(pw); 1329 | + if (err) { 1330 | + dev_err(dev, "%s failed.\n", __func__); 1331 | + return err; 1332 | + } 1333 | + } else { 1334 | + if (pw->reset_gpio) { 1335 | + if (gpio_cansleep(pw->reset_gpio)) 1336 | + gpio_set_value_cansleep(pw->reset_gpio, 0); 1337 | + else 1338 | + gpio_set_value(pw->reset_gpio, 0); 1339 | + } 1340 | + 1341 | + usleep_range(10, 10); 1342 | + 1343 | + if (pw->dvdd) 1344 | + regulator_disable(pw->dvdd); 1345 | + if (pw->iovdd) 1346 | + regulator_disable(pw->iovdd); 1347 | + if (pw->avdd) 1348 | + regulator_disable(pw->avdd); 1349 | + } 1350 | + 1351 | + pw->state = SWITCH_OFF; 1352 | + 1353 | + return 0; 1354 | +} 1355 | + 1356 | +static int imx708_power_put(struct tegracam_device *tc_dev) 1357 | +{ 1358 | + struct camera_common_data *s_data = tc_dev->s_data; 1359 | + struct camera_common_power_rail *pw = s_data->power; 1360 | + 1361 | + if (unlikely(!pw)) 1362 | + return -EFAULT; 1363 | + 1364 | + if (likely(pw->dvdd)) 1365 | + devm_regulator_put(pw->dvdd); 1366 | + 1367 | + if (likely(pw->avdd)) 1368 | + devm_regulator_put(pw->avdd); 1369 | + 1370 | + if (likely(pw->iovdd)) 1371 | + devm_regulator_put(pw->iovdd); 1372 | + 1373 | + pw->dvdd = NULL; 1374 | + pw->avdd = NULL; 1375 | + pw->iovdd = NULL; 1376 | + 1377 | + if (likely(pw->reset_gpio)) 1378 | + gpio_free(pw->reset_gpio); 1379 | + 1380 | + return 0; 1381 | +} 1382 | + 1383 | +static int imx708_power_get(struct tegracam_device *tc_dev) 1384 | +{ 1385 | + struct device *dev = tc_dev->dev; 1386 | + struct camera_common_data *s_data = tc_dev->s_data; 1387 | + struct camera_common_power_rail *pw = s_data->power; 1388 | + struct camera_common_pdata *pdata = s_data->pdata; 1389 | + struct clk *parent; 1390 | + int err = 0; 1391 | + 1392 | + if (!pdata) { 1393 | + dev_err(dev, "pdata missing\n"); 1394 | + return -EFAULT; 1395 | + } 1396 | + 1397 | + /* Sensor MCLK (aka. INCK) */ 1398 | + if (pdata->mclk_name) { 1399 | + pw->mclk = devm_clk_get(dev, pdata->mclk_name); 1400 | + if (IS_ERR(pw->mclk)) { 1401 | + dev_err(dev, "unable to get clock %s\n", 1402 | + pdata->mclk_name); 1403 | + return PTR_ERR(pw->mclk); 1404 | + } 1405 | + 1406 | + if (pdata->parentclk_name) { 1407 | + parent = devm_clk_get(dev, pdata->parentclk_name); 1408 | + if (IS_ERR(parent)) { 1409 | + dev_err(dev, "unable to get parent clock %s", 1410 | + pdata->parentclk_name); 1411 | + } else 1412 | + clk_set_parent(pw->mclk, parent); 1413 | + } 1414 | + } 1415 | + 1416 | + /* analog 2.8v */ 1417 | + if (pdata->regulators.avdd) 1418 | + err |= camera_common_regulator_get(dev, 1419 | + &pw->avdd, 1420 | + pdata->regulators.avdd); 1421 | + /* IO 1.8v */ 1422 | + if (pdata->regulators.iovdd) 1423 | + err |= camera_common_regulator_get(dev, 1424 | + &pw->iovdd, 1425 | + pdata->regulators.iovdd); 1426 | + /* dig 1.2v */ 1427 | + if (pdata->regulators.dvdd) 1428 | + err |= camera_common_regulator_get(dev, 1429 | + &pw->dvdd, 1430 | + pdata->regulators.dvdd); 1431 | + if (err) { 1432 | + dev_err(dev, "%s: unable to get regulator(s)\n", __func__); 1433 | + goto done; 1434 | + } 1435 | + 1436 | + /* Reset or ENABLE GPIO */ 1437 | + pw->reset_gpio = pdata->reset_gpio; 1438 | + err = gpio_request(pw->reset_gpio, "cam_reset_gpio"); 1439 | + if (err < 0) { 1440 | + dev_err(dev, "%s: unable to request reset_gpio (%d)\n", 1441 | + __func__, err); 1442 | + goto done; 1443 | + } 1444 | + 1445 | +done: 1446 | + pw->state = SWITCH_OFF; 1447 | + 1448 | + return err; 1449 | +} 1450 | + 1451 | +static struct camera_common_pdata *imx708_parse_dt(struct tegracam_device 1452 | + *tc_dev) 1453 | +{ 1454 | + struct device *dev = tc_dev->dev; 1455 | + struct device_node *np = dev->of_node; 1456 | + struct camera_common_pdata *board_priv_pdata; 1457 | + const struct of_device_id *match; 1458 | + struct camera_common_pdata *ret = NULL; 1459 | + int err = 0; 1460 | + int gpio = 0; 1461 | + 1462 | + if (!np) 1463 | + return NULL; 1464 | + 1465 | + match = of_match_device(imx708_of_match, dev); 1466 | + if (!match) { 1467 | + dev_err(dev, "Failed to find matching dt id\n"); 1468 | + return NULL; 1469 | + } 1470 | + 1471 | + board_priv_pdata = devm_kzalloc(dev, 1472 | + sizeof(*board_priv_pdata), GFP_KERNEL); 1473 | + if (!board_priv_pdata) 1474 | + return NULL; 1475 | + 1476 | + gpio = of_get_named_gpio(np, "reset-gpios", 0); 1477 | + if (gpio < 0) { 1478 | + if (gpio == -EPROBE_DEFER) 1479 | + ret = ERR_PTR(-EPROBE_DEFER); 1480 | + dev_err(dev, "reset-gpios not found\n"); 1481 | + goto error; 1482 | + } 1483 | + board_priv_pdata->reset_gpio = (unsigned int)gpio; 1484 | + 1485 | + err = of_property_read_string(np, "avdd-reg", 1486 | + &board_priv_pdata->regulators.avdd); 1487 | + err |= of_property_read_string(np, "iovdd-reg", 1488 | + &board_priv_pdata->regulators.iovdd); 1489 | + err |= of_property_read_string(np, "dvdd-reg", 1490 | + &board_priv_pdata->regulators.dvdd); 1491 | + if (err) 1492 | + dev_dbg(dev, "avdd, iovdd and/or dvdd reglrs. not present, " 1493 | + "assume sensor powered independently\n"); 1494 | + 1495 | + board_priv_pdata->has_eeprom = of_property_read_bool(np, "has-eeprom"); 1496 | + 1497 | + return board_priv_pdata; 1498 | + 1499 | +error: 1500 | + devm_kfree(dev, board_priv_pdata); 1501 | + 1502 | + return ret; 1503 | +} 1504 | + 1505 | +static int imx708_set_mode(struct tegracam_device *tc_dev) 1506 | +{ 1507 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1508 | + struct camera_common_data *s_data = tc_dev->s_data; 1509 | + 1510 | + int err = 0; 1511 | + 1512 | + err = imx708_write_table(priv, mode_table[IMX708_MODE_COMMON]); 1513 | + if (err) 1514 | + { 1515 | + dev_err(tc_dev->dev, "failed writing common mode err:%d\n", err); 1516 | + return err; 1517 | + } 1518 | + 1519 | + if (s_data->mode < 0) 1520 | + return -EINVAL; 1521 | + err = imx708_write_table(priv, mode_table[s_data->mode]); 1522 | + if (err) 1523 | + { 1524 | + dev_err(tc_dev->dev, "failed to write mode %d err:%d\n", s_data->mode, err); 1525 | + return err; 1526 | + } 1527 | + 1528 | + return 0; 1529 | +} 1530 | + 1531 | + 1532 | +static int imx708_start_streaming(struct tegracam_device *tc_dev) 1533 | +{ 1534 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1535 | + 1536 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1537 | + 1538 | + return imx708_write_table(priv, mode_table[IMX708_START_STREAM]); 1539 | +} 1540 | + 1541 | +static int imx708_stop_streaming(struct tegracam_device *tc_dev) 1542 | +{ 1543 | + int err = 0; 1544 | + 1545 | + struct imx708 *priv = (struct imx708 *)tegracam_get_privdata(tc_dev); 1546 | + 1547 | + dev_dbg(tc_dev->dev, "%s:\n", __func__); 1548 | + 1549 | + err = imx708_write_table(priv, mode_table[IMX708_STOP_STREAM]); 1550 | + 1551 | + return err; 1552 | +} 1553 | + 1554 | +static struct camera_common_sensor_ops imx708_common_ops = { 1555 | + .numfrmfmts = ARRAY_SIZE(imx708_frmfmt), 1556 | + .frmfmt_table = imx708_frmfmt, 1557 | + .power_on = imx708_power_on, 1558 | + .power_off = imx708_power_off, 1559 | + .write_reg = imx708_write_reg, 1560 | + .read_reg = imx708_read_reg, 1561 | + .parse_dt = imx708_parse_dt, 1562 | + .power_get = imx708_power_get, 1563 | + .power_put = imx708_power_put, 1564 | + .set_mode = imx708_set_mode, 1565 | + .start_streaming = imx708_start_streaming, 1566 | + .stop_streaming = imx708_stop_streaming, 1567 | +}; 1568 | + 1569 | +static int imx708_board_setup(struct imx708 *priv) 1570 | +{ 1571 | + struct camera_common_data *s_data = priv->s_data; 1572 | + struct device *dev = s_data->dev; 1573 | + u8 reg_val[2] = {0}; 1574 | + int err = 0; 1575 | + 1576 | + /* Skip mclk enable as this camera has an internal oscillator */ 1577 | + err = imx708_power_on(s_data); 1578 | + if (err) { 1579 | + dev_err(dev, "error during power on sensor (%d)\n", err); 1580 | + goto done; 1581 | + } 1582 | + 1583 | + /* Probe sensor model id registers */ 1584 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_MSB, ®_val[0]); 1585 | + if (err) { 1586 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1587 | + __func__, err); 1588 | + goto err_reg_probe; 1589 | + } 1590 | + err = imx708_read_reg(s_data, IMX708_MODEL_ID_ADDR_LSB, ®_val[1]); 1591 | + if (err) { 1592 | + dev_err(dev, "%s: error during i2c read probe (%d)\n", 1593 | + __func__, err); 1594 | + goto err_reg_probe; 1595 | + } 1596 | + 1597 | + if (!((reg_val[0] == IMX708_MODEL_ID_VALUE_MSB) && 1598 | + reg_val[1] == IMX708_MODEL_ID_VALUE_LSB)) 1599 | + dev_err(dev, "%s: invalid sensor model id: %x%x\n", 1600 | + __func__, reg_val[0], reg_val[1]); 1601 | + 1602 | + /* Sensor fine integration time */ 1603 | + err = imx708_get_fine_integ_time(priv, &priv->fine_integ_time); 1604 | + if (err) 1605 | + dev_err(dev, "%s: error querying sensor fine integ. time\n", 1606 | + __func__); 1607 | + 1608 | +err_reg_probe: 1609 | + imx708_power_off(s_data); 1610 | + 1611 | +done: 1612 | + return err; 1613 | +} 1614 | + 1615 | +static int imx708_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1616 | +{ 1617 | + struct i2c_client *client = v4l2_get_subdevdata(sd); 1618 | + 1619 | + dev_dbg(&client->dev, "%s:\n", __func__); 1620 | + 1621 | + return 0; 1622 | +} 1623 | + 1624 | +static const struct v4l2_subdev_internal_ops imx708_subdev_internal_ops = { 1625 | + .open = imx708_open, 1626 | +}; 1627 | + 1628 | +static int imx708_probe(struct i2c_client *client, 1629 | + const struct i2c_device_id *id) 1630 | +{ 1631 | + struct device *dev = &client->dev; 1632 | + struct tegracam_device *tc_dev = NULL; 1633 | + struct imx708 *priv = NULL; 1634 | + int err = 0; 1635 | + 1636 | + dev_dbg(dev, "probing v4l2 sensor at addr 0x%0x\n", client->addr); 1637 | + 1638 | + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) 1639 | + return -EINVAL; 1640 | + 1641 | + priv = devm_kzalloc(dev, sizeof(struct imx708), GFP_KERNEL); 1642 | + if (!priv) 1643 | + return -ENOMEM; 1644 | + 1645 | + tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL); 1646 | + if (!tc_dev) 1647 | + return -ENOMEM; 1648 | + 1649 | + priv->i2c_client = tc_dev->client = client; 1650 | + tc_dev->dev = dev; 1651 | + strncpy(tc_dev->name, "imx708", sizeof(tc_dev->name)); 1652 | + tc_dev->dev_regmap_config = &sensor_regmap_config; 1653 | + tc_dev->sensor_ops = &imx708_common_ops; 1654 | + tc_dev->v4l2sd_internal_ops = &imx708_subdev_internal_ops; 1655 | + tc_dev->tcctrl_ops = &imx708_ctrl_ops; 1656 | + 1657 | + err = tegracam_device_register(tc_dev); 1658 | + if (err) { 1659 | + dev_err(dev, "tegra camera driver registration failed\n"); 1660 | + goto register_error; 1661 | + } 1662 | + priv->tc_dev = tc_dev; 1663 | + priv->s_data = tc_dev->s_data; 1664 | + priv->subdev = &tc_dev->s_data->subdev; 1665 | + tegracam_set_privdata(tc_dev, (void *)priv); 1666 | + 1667 | + err = imx708_board_setup(priv); 1668 | + if (err) { 1669 | + dev_err(dev, "board setup failed\n"); 1670 | + goto tegracam_error; 1671 | + } 1672 | + 1673 | + err = tegracam_v4l2subdev_register(tc_dev, true); 1674 | + if (err) { 1675 | + dev_err(dev, "tegra camera subdev registration failed\n"); 1676 | + goto v4l2_error; 1677 | + } 1678 | + 1679 | + dev_dbg(dev, "detected imx708 sensor\n"); 1680 | + 1681 | + return 0; 1682 | + 1683 | +v4l2_error: 1684 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1685 | +tegracam_error: 1686 | + tegracam_device_unregister(priv->tc_dev); 1687 | +register_error: 1688 | + return err; 1689 | + 1690 | +} 1691 | + 1692 | + 1693 | +static int imx708_remove(struct i2c_client *client) 1694 | +{ 1695 | + struct camera_common_data *s_data = to_camera_common_data(&client->dev); 1696 | + struct imx708 *priv = (struct imx708 *)s_data->priv; 1697 | + 1698 | + tegracam_v4l2subdev_unregister(priv->tc_dev); 1699 | + tegracam_device_unregister(priv->tc_dev); 1700 | + 1701 | + return 0; 1702 | +} 1703 | + 1704 | +static const struct i2c_device_id imx708_id[] = { 1705 | + {"imx708", 0}, 1706 | + {} 1707 | +}; 1708 | + 1709 | +MODULE_DEVICE_TABLE(i2c, imx708_id); 1710 | + 1711 | +static struct i2c_driver imx708_i2c_driver = { 1712 | + .driver = { 1713 | + .name = "imx708", 1714 | + .owner = THIS_MODULE, 1715 | + .of_match_table = of_match_ptr(imx708_of_match), 1716 | + }, 1717 | + .probe = imx708_probe, 1718 | + .remove = imx708_remove, 1719 | + .id_table = imx708_id, 1720 | +}; 1721 | + 1722 | +module_i2c_driver(imx708_i2c_driver); 1723 | + 1724 | +MODULE_DESCRIPTION("Media Controller driver for Sony IMX708"); 1725 | +MODULE_AUTHOR("RidgeRun"); 1726 | +MODULE_LICENSE("GPL v2"); 1727 | diff --git a/kernel/nvidia/include/media/imx708.h b/kernel/nvidia/include/media/imx708.h 1728 | new file mode 100644 1729 | index 000000000..fb888d691 1730 | --- /dev/null 1731 | +++ b/kernel/nvidia/include/media/imx708.h 1732 | @@ -0,0 +1,53 @@ 1733 | +/* 1734 | + * imx708.h - imx708 sensor header 1735 | + * 1736 | + * Copyright (c) 2023, RidgeRun . All rights reserved. 1737 | + * 1738 | + * Contact us: support@ridgerun.com 1739 | + * 1740 | + * This program is free software; you can redistribute it and/or modify it 1741 | + * under the terms and conditions of the GNU General Public License, 1742 | + * version 2, as published by the Free Software Foundation. 1743 | + * 1744 | + * This program is distributed in the hope it will be useful, but WITHOUT 1745 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1746 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1747 | + * more details. 1748 | + * 1749 | + * You should have received a copy of the GNU General Public License 1750 | + * along with this program. If not, see . 1751 | + */ 1752 | + 1753 | +#ifndef __IMX708_H__ 1754 | +#define __IMX708_H__ 1755 | + 1756 | +/* imx708 - sensor parameters */ 1757 | +#define IMX708_MIN_GAIN (0) 1758 | +#define IMX708_MAX_GAIN (978) 1759 | +#define IMX708_ANALOG_GAIN_C0 (516) 1760 | +#define IMX708_SHIFT_8_BITS (8) 1761 | +#define IMX708_MIN_FRAME_LENGTH (256) 1762 | +#define IMX708_MAX_FRAME_LENGTH (65535) 1763 | +#define IMX708_MIN_COARSE_EXPOSURE (1) 1764 | +#define IMX708_MAX_COARSE_DIFF (10) 1765 | +#define IMX708_MASK_LSB_2_BITS 0x0003 1766 | +#define IMX708_MASK_LSB_8_BITS 0x00ff 1767 | + 1768 | +/* imx708 sensor register address */ 1769 | +#define IMX708_MODEL_ID_ADDR_MSB 0x0000 1770 | +#define IMX708_MODEL_ID_ADDR_LSB 0x0001 1771 | +#define IMX708_MODEL_ID_VALUE_MSB 0x0003 1772 | +#define IMX708_MODEL_ID_VALUE_LSB 0x0001 1773 | +#define IMX708_ANALOG_GAIN_ADDR_MSB 0x0204 1774 | +#define IMX708_ANALOG_GAIN_ADDR_LSB 0x0205 1775 | +#define IMX708_DIGITAL_GAIN_ADDR_MSB 0x020e 1776 | +#define IMX708_DIGITAL_GAIN_ADDR_LSB 0x020f 1777 | +#define IMX708_FRAME_LENGTH_ADDR_MSB 0x0340 1778 | +#define IMX708_FRAME_LENGTH_ADDR_LSB 0x0341 1779 | +#define IMX708_COARSE_INTEG_TIME_ADDR_MSB 0x0202 1780 | +#define IMX708_COARSE_INTEG_TIME_ADDR_LSB 0x0203 1781 | +#define IMX708_FINE_INTEG_TIME_ADDR_MSB 0x0200 1782 | +#define IMX708_FINE_INTEG_TIME_ADDR_LSB 0x0201 1783 | +#define IMX708_GROUP_HOLD_ADDR 0x0104 1784 | + 1785 | +#endif /* __IMX708_H__ */ 1786 | -- 1787 | 2.34.1 1788 | 1789 | --------------------------------------------------------------------------------