├── Makefile ├── README.md ├── dkms.conf ├── dkms.postinst ├── imx283-overlay.dts ├── imx283.c └── setup.sh /Makefile: -------------------------------------------------------------------------------- 1 | obj-m += imx283.o 2 | 3 | #dtbo-y += imx283.dtbo 4 | 5 | KDIR ?= /lib/modules/$(shell uname -r)/build 6 | 7 | #targets += $(dtbo-y) 8 | 9 | #always-y := $(dtbo-y) 10 | 11 | all: 12 | make -C $(KDIR) M=$(shell pwd) modules 13 | 14 | clean: 15 | make -C $(KDIR) M=$(shell pwd) clean 16 | 17 | %.dtbo: %.dts 18 | dtc -@ -I dts -O dtb -o $@ $< 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kernel Driver for IMX283 2 | 3 | This guide provides detailed instructions on how to install the IMX283 kernel driver on a Linux system, specifically Raspbian. 4 | 5 | ## Prerequisites 6 | 7 | Before you begin the installation process, please ensure the following prerequisites are met: 8 | 9 | - **Kernel version**: You should be running on a Linux kernel version 6.1 or newer. You can verify your kernel version by executing `uname -r` in your terminal. 10 | 11 | - **Development tools**: Essential tools such as `gcc`, `dkms`, and `linux-headers` are required for compiling a kernel module. If not already installed, these can be installed using the package manager with the following command: 12 | 13 | ```bash 14 | sudo apt install linux-headers dkms git 15 | ``` 16 | 17 | ## Installation Steps 18 | 19 | ### Setting Up the Tools 20 | 21 | First, install the necessary tools (`linux-headers`, `dkms`, and `git`) if you haven't done so: 22 | 23 | ```bash 24 | sudo apt install linux-headers dkms git 25 | ``` 26 | 27 | ### Fetching the Source Code 28 | 29 | Clone the repository to your local machine and navigate to the cloned directory: 30 | 31 | ```bash 32 | git clone https://github.com/will127534/imx283-v4l2-driver.git 33 | cd imx283-v4l2-driver/ 34 | ``` 35 | 36 | ### Compiling and Installing the Kernel Driver 37 | 38 | To compile and install the kernel driver, execute the provided installation script: 39 | 40 | ```bash 41 | ./setup.sh 42 | ``` 43 | 44 | ### Updating the Boot Configuration 45 | 46 | Edit the boot configuration file using the following command: 47 | 48 | ```bash 49 | sudo nano /boot/config.txt 50 | ``` 51 | 52 | In the opened editor, locate the line containing `camera_auto_detect` and change its value to `0`. Then, add the line `dtoverlay=imx283`. So, it will look like this: 53 | 54 | ``` 55 | camera_auto_detect=0 56 | dtoverlay=imx283 57 | ``` 58 | 59 | After making these changes, save the file and exit the editor. 60 | 61 | Remember to reboot your system for the changes to take effect. 62 | 63 | ## dtoverlay options 64 | 65 | ### cam0 66 | 67 | If the camera is attached to cam0 port, append the dtoverlay with `,cam0` like this: 68 | ``` 69 | camera_auto_detect=0 70 | dtoverlay=imx283,cam0 71 | ``` 72 | 73 | ### always-on 74 | 75 | If you want to keep the camera power always on (Useful for debugging HW issues, specifically this will set CAM_GPIO to high constantly), append the dtoverlay with `,always-on` like this: 76 | ``` 77 | camera_auto_detect=0 78 | dtoverlay=imx283,always-on 79 | ``` 80 | 81 | ### mix usage 82 | 83 | Last note is that all the options can be used at the same time, the dtoverlay will looks like this: 84 | ``` 85 | camera_auto_detect=0 86 | dtoverlay=imx283,always-on,cam0 87 | ``` 88 | 89 | ## Special Thanks 90 | 91 | Special thanks to Sasha Shturma's Raspberry Pi CM4 Сarrier with Hi-Res MIPI Display project, the install script is adapted from the github project page: https://github.com/renetec-io/cm4-panel-jdi-lt070me05000 92 | 93 | 94 | -------------------------------------------------------------------------------- /dkms.conf: -------------------------------------------------------------------------------- 1 | MAKE="make KDIR=/lib/modules/${kernelver}/build" 2 | CLEAN="make clean" 3 | BUILT_MODULE_NAME=imx283 4 | DEST_MODULE_LOCATION="/updates" 5 | PACKAGE_NAME=imx283-dkms 6 | PACKAGE_VERSION=0.0.1 7 | AUTOINSTALL="yes" 8 | POST_INSTALL="dkms.postinst" 9 | -------------------------------------------------------------------------------- /dkms.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | dtc -Wno-interrupts_property -Wno-unit_address_vs_reg -@ -I dts -O dtb -o imx283.dtbo imx283-overlay.dts 4 | 5 | install -m 751 imx283.dtbo /boot/overlays/ 6 | -------------------------------------------------------------------------------- /imx283-overlay.dts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-only 2 | // Definitions for IMX283 camera module on VC I2C bus 3 | /dts-v1/; 4 | /plugin/; 5 | /{ 6 | compatible = "brcm,bcm2835"; 7 | 8 | fragment@0 { 9 | target = <&i2c0if>; 10 | __overlay__ { 11 | status = "okay"; 12 | }; 13 | }; 14 | 15 | clk_frag: fragment@1 { 16 | target = <&cam1_clk>; 17 | cam_clk: __overlay__ { 18 | clock-frequency = <24000000>; 19 | status = "okay"; 20 | }; 21 | }; 22 | 23 | fragment@2 { 24 | target = <&i2c0mux>; 25 | __overlay__ { 26 | status = "okay"; 27 | }; 28 | }; 29 | 30 | reg_frag: fragment@3 { 31 | target = <&cam1_reg>; 32 | cam_reg: __overlay__ { 33 | startup-delay-us = <300000>; 34 | }; 35 | }; 36 | 37 | reg_alwayson_frag: fragment@99 { 38 | target = <&cam1_reg>; 39 | __dormant__ { 40 | regulator-always-on; 41 | }; 42 | }; 43 | 44 | i2c_frag: fragment@100 { 45 | target = <&i2c_csi_dsi>; 46 | __overlay__ { 47 | #address-cells = <1>; 48 | #size-cells = <0>; 49 | status = "okay"; 50 | 51 | cam_node: imx283@1a { 52 | reg = <0x1a>; 53 | status = "okay"; 54 | compatible = "sony,imx283"; 55 | clocks = <&cam1_clk>; 56 | clock-names = "xclk"; 57 | 58 | VANA-supply = <&cam1_reg>; /* 2.8v */ 59 | VDIG-supply = <&cam_dummy_reg>; /* 1.2v */ 60 | VDDL-supply = <&cam_dummy_reg>; /* 1.8v */ 61 | 62 | rotation = <0>; 63 | orientation = <0>; 64 | 65 | port { 66 | cam_endpoint: endpoint { 67 | clock-lanes = <0>; 68 | data-lanes = <1 2 3 4>; 69 | clock-noncontinuous; 70 | remote-endpoint = <&csi_ep>; 71 | link-frequencies = 72 | /bits/ 64 <720000000>; 73 | }; 74 | }; 75 | 76 | }; 77 | 78 | }; 79 | }; 80 | 81 | csi_frag: fragment@101 { 82 | target = <&csi1>; 83 | csi: __overlay__ { 84 | status = "okay"; 85 | brcm,media-controller; 86 | 87 | port { 88 | csi_ep: endpoint { 89 | remote-endpoint = <&cam_endpoint>; 90 | clock-lanes = <0>; 91 | data-lanes = <1 2 3 4>; 92 | clock-noncontinuous; 93 | }; 94 | }; 95 | }; 96 | }; 97 | 98 | __overrides__ { 99 | rotation = <&cam_node>,"rotation:0"; 100 | orientation = <&cam_node>,"orientation:0"; 101 | media-controller = <&csi>,"brcm,media-controller?"; 102 | cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, 103 | <&csi_frag>, "target:0=",<&csi0>, 104 | <&clk_frag>, "target:0=",<&cam0_clk>, 105 | <®_frag>, "target:0=",<&cam0_reg>, 106 | <®_alwayson_frag>, "target:0=",<&cam0_reg>, 107 | <&cam_node>, "clocks:0=",<&cam0_clk>, 108 | <&cam_node>, "VANA-supply:0=",<&cam0_reg>; 109 | always-on = <0>, "+99"; 110 | }; 111 | }; 112 | -------------------------------------------------------------------------------- /imx283.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * V4L2 Support for the IMX283 4 | * 5 | * The IMX283 has BigEndian register addresses 6 | * and uses little-endian value. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | struct cci_reg_sequence { 27 | u32 reg; 28 | u64 val; 29 | }; 30 | 31 | #define CCI_REG_ADDR_MASK GENMASK(15, 0) 32 | #define CCI_REG_WIDTH_SHIFT 16 33 | #define CCI_REG_WIDTH_MASK GENMASK(19, 16) 34 | #define CCI_REG_LE BIT(20) 35 | 36 | 37 | #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) 38 | #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) 39 | #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) 40 | #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) 41 | #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) 42 | #define CCI_REG16_LE(x) (CCI_REG_LE | (2U << CCI_REG_WIDTH_SHIFT) | (x)) 43 | #define CCI_REG24_LE(x) (CCI_REG_LE | (3U << CCI_REG_WIDTH_SHIFT) | (x)) 44 | #define CCI_REG32_LE(x) (CCI_REG_LE | (4U << CCI_REG_WIDTH_SHIFT) | (x)) 45 | #define CCI_REG64_LE(x) (CCI_REG_LE | (8U << CCI_REG_WIDTH_SHIFT) | (x)) 46 | 47 | 48 | 49 | 50 | /* 51 | * TODOs 52 | * - Move to active state api 53 | * - Add 720 MBps speed mode to link_freq 54 | * - HMAX/VMAX must be calculated based on link-freq to support this. 55 | * - Support arbitrary cropping 56 | * 57 | * - account for the VOB 58 | * - Identify where the HOB is coming from. 59 | * 60 | * - Remove 'events' that are not used. 61 | * - Fix/remove HFLIP/VFLIP which aren't well supported at all. 62 | * - Fix exposure and blanking calculations 63 | */ 64 | 65 | /* Chip ID */ 66 | #define IMX283_REG_CHIP_ID CCI_REG8(0x3000) 67 | #define IMX283_CHIP_ID 0x0b // Default power on state 68 | 69 | #define IMX283_REG_STANDBY CCI_REG8(0x3000) 70 | #define IMX283_ACTIVE 0 71 | #define IMX283_STANDBY BIT(0) 72 | #define IMX283_STBLOGIC BIT(1) 73 | #define IMX283_STBMIPI BIT(2) 74 | #define IMX283_STBDV BIT(3) 75 | #define IMX283_SLEEP BIT(4) 76 | 77 | #define IMX283_REG_CLAMP CCI_REG8(0x3001) 78 | #define IMX283_CLPSQRST BIT(4) 79 | 80 | #define IMX283_REG_PLSTMG08 CCI_REG8(0x3003) 81 | #define IMX283_PLSTMG08_VAL 0x77 82 | 83 | #define IMX283_REG_MDSEL1 CCI_REG8(0x3004) 84 | #define IMX283_REG_MDSEL2 CCI_REG8(0x3005) 85 | #define IMX283_REG_MDSEL3 CCI_REG8(0x3006) 86 | #define IMX283_REG_MDSEL4 CCI_REG8(0x3007) 87 | 88 | #define IMX283_REG_SVR CCI_REG16_LE(0x3009) 89 | 90 | #define IMX283_REG_HTRIMMING CCI_REG8(0x300b) 91 | #define IMX283_MDVREV BIT(0) // VFLIP 92 | #define IMX283_HTRIMMING_EN BIT(4) 93 | #define IMX283_HTRIMMING_RESERVED BIT(5) 94 | 95 | #define IMX283_REG_VWINPOS CCI_REG16_LE(0x300f) 96 | #define IMX283_REG_VWIDCUT CCI_REG16_LE(0x3011) 97 | 98 | #define IMX283_REG_MDSEL7 CCI_REG16_LE(0x3013) 99 | 100 | /* CSI Clock Configuration */ 101 | #define IMX283_REG_TCLKPOST CCI_REG8(0x3018) 102 | #define IMX283_REG_THSPREPARE CCI_REG8(0x301a) 103 | #define IMX283_REG_THSZERO CCI_REG8(0x301c) 104 | #define IMX283_REG_THSTRAIL CCI_REG8(0x3020) 105 | #define IMX283_REG_TCLKPREPARE CCI_REG8(0x3022) 106 | #define IMX283_REG_TCLKZERO CCI_REG16_LE(0x3024) 107 | #define IMX283_REG_TLPX CCI_REG8(0x3026) 108 | #define IMX283_REG_THSEXIT CCI_REG8(0x3028) 109 | #define IMX283_REG_TCLKPRE CCI_REG8(0x302a) 110 | 111 | #define IMX283_REG_Y_OUT_SIZE CCI_REG16_LE(0x302f) 112 | #define IMX283_REG_WRITE_VSIZE CCI_REG16_LE(0x3031) 113 | #define IMX283_REG_OB_SIZE_V CCI_REG8(0x3033) 114 | 115 | /* HMAX internal HBLANK*/ 116 | #define IMX283_REG_HMAX CCI_REG16_LE(0x3036) 117 | #define IMX283_HMAX_MAX 0xffff 118 | 119 | /* VMAX internal VBLANK */ 120 | #define IMX283_REG_VMAX CCI_REG24_LE(0x3038) 121 | #define IMX283_VMAX_MAX 0xfffff 122 | 123 | /* SHR internal */ 124 | #define IMX283_REG_SHR CCI_REG16_LE(0x303b) 125 | #define IMX283_SHR_MIN 11 126 | 127 | /* 128 | * Analog gain control 129 | * Gain [dB] = –20log{(2048 – value [10:0]) /2048} 130 | * Range: 0dB to approximately +27dB 131 | */ 132 | #define IMX283_REG_ANALOG_GAIN CCI_REG16_LE(0x3042) 133 | #define IMX283_ANA_GAIN_MIN 0 134 | #define IMX283_ANA_GAIN_MAX 1957 135 | #define IMX283_ANA_GAIN_STEP 1 136 | #define IMX283_ANA_GAIN_DEFAULT 0x0 137 | 138 | /* 139 | * Digital gain control 140 | * Gain [dB] = value * 6 141 | * Range: 0dB to +18db 142 | */ 143 | #define IMX283_REG_DIGITAL_GAIN CCI_REG8(0x3044) 144 | #define IMX283_DGTL_GAIN_MIN 0 145 | #define IMX283_DGTL_GAIN_MAX 3 146 | #define IMX283_DGTL_GAIN_DEFAULT 0 147 | #define IMX283_DGTL_GAIN_STEP 1 148 | 149 | #define IMX283_REG_HTRIMMING_START CCI_REG16_LE(0x3058) 150 | #define IMX283_REG_HTRIMMING_END CCI_REG16_LE(0x305a) 151 | 152 | #define IMX283_REG_MDSEL18 CCI_REG16_LE(0x30f6) 153 | 154 | /* Master Mode Operation Control */ 155 | #define IMX283_REG_XMSTA CCI_REG8(0x3105) 156 | #define IMX283_XMSTA BIT(0) 157 | 158 | #define IMX283_REG_SYNCDRV CCI_REG8(0x3107) 159 | #define IMX283_SYNCDRV_XHS_XVS (0xa0 | 0x02) 160 | #define IMX283_SYNCDRV_HIZ (0xa0 | 0x03) 161 | 162 | /* PLL Standby */ 163 | #define IMX283_REG_STBPL CCI_REG8(0x320b) 164 | #define IMX283_STBPL_NORMAL 0x00 165 | #define IMX283_STBPL_STANDBY 0x03 166 | 167 | /* Input Frequency Setting */ 168 | #define IMX283_REG_PLRD1 CCI_REG8(0x36c1) 169 | #define IMX283_REG_PLRD2 CCI_REG16_LE(0x36c2) 170 | #define IMX283_REG_PLRD3 CCI_REG8(0x36f7) 171 | #define IMX283_REG_PLRD4 CCI_REG8(0x36f8) 172 | 173 | #define IMX283_REG_PLSTMG02 CCI_REG8(0x36aa) 174 | #define IMX283_PLSTMG02_VAL 0x00 175 | 176 | #define IMX283_REG_EBD_X_OUT_SIZE CCI_REG16_LE(0x3a54) 177 | 178 | /* Test pattern generator */ 179 | #define IMX283_REG_TPG_CTRL CCI_REG8(0x3156) 180 | #define IMX283_TPG_CTRL_CLKEN BIT(0) 181 | #define IMX283_TPG_CTRL_PATEN BIT(4) 182 | 183 | #define IMX283_REG_TPG_PAT CCI_REG8(0x3157) 184 | #define IMX283_TPG_PAT_ALL_000 0x00 185 | #define IMX283_TPG_PAT_ALL_FFF 0x01 186 | #define IMX283_TPG_PAT_ALL_555 0x02 187 | #define IMX283_TPG_PAT_ALL_AAA 0x03 188 | #define IMX283_TPG_PAT_H_COLOR_BARS 0x0a 189 | #define IMX283_TPG_PAT_V_COLOR_BARS 0x0b 190 | 191 | #define MHZ(x) ((x) * 1000 * 1000) 192 | 193 | /* MIPI link speed is fixed at 1.44Gbps for all the modes */ 194 | #define IMX283_DEFAULT_LINK_FREQ MHZ(720) 195 | 196 | /* Exposure control */ 197 | #define IMX283_EXPOSURE_MIN 52 198 | #define IMX283_EXPOSURE_STEP 1 199 | #define IMX283_EXPOSURE_DEFAULT 1000 200 | #define IMX283_EXPOSURE_MAX 49865 201 | 202 | /* Embedded metadata stream structure */ 203 | #define IMX283_EMBEDDED_LINE_WIDTH 16384 204 | #define IMX283_NUM_EMBEDDED_LINES 1 205 | 206 | #define IMAGE_PAD 0 207 | 208 | /* imx283 native and active pixel array size. */ 209 | static const struct v4l2_rect imx283_native_area = { 210 | .top = 0, 211 | .left = 0, 212 | .width = 5592, 213 | .height = 3710, 214 | }; 215 | 216 | static const struct v4l2_rect imx283_active_area = { 217 | .top = 108, 218 | .left = 40, 219 | .width = 5472, 220 | .height = 3648, 221 | }; 222 | 223 | struct IMX283_reg_list { 224 | unsigned int num_of_regs; 225 | const struct cci_reg_sequence *regs; 226 | }; 227 | 228 | /* Mode : resolution and related config&values */ 229 | struct imx283_mode { 230 | unsigned int mode; 231 | 232 | /* Bits per pixel */ 233 | unsigned int bpp; 234 | 235 | /* Frame width */ 236 | unsigned int width; 237 | 238 | /* Frame height */ 239 | unsigned int height; 240 | 241 | /* minimum H-timing */ 242 | u64 min_HMAX; 243 | 244 | /* minimum V-timing */ 245 | u64 min_VMAX; 246 | 247 | /* default H-timing */ 248 | u64 default_HMAX; 249 | 250 | /* default V-timing */ 251 | u64 default_VMAX; 252 | 253 | /* minimum SHR */ 254 | u64 min_SHR; 255 | 256 | /* Optical Blanking */ 257 | u32 horizontal_ob; 258 | u32 vertical_ob; 259 | 260 | /* Analog crop rectangle. */ 261 | struct v4l2_rect crop; 262 | }; 263 | 264 | struct imx283_input_frequency { 265 | unsigned int mhz; 266 | unsigned int reg_count; 267 | struct cci_reg_sequence regs[4]; 268 | }; 269 | 270 | static const struct imx283_input_frequency imx283_frequencies[] = { 271 | { 272 | .mhz = MHZ(6), 273 | .reg_count = 4, 274 | .regs = { 275 | { IMX283_REG_PLRD1, 0x00 }, 276 | { IMX283_REG_PLRD2, 0x00f0 }, 277 | { IMX283_REG_PLRD3, 0x00 }, 278 | { IMX283_REG_PLRD4, 0xc0 }, 279 | }, 280 | }, 281 | { 282 | .mhz = MHZ(12), 283 | .reg_count = 4, 284 | .regs = { 285 | { IMX283_REG_PLRD1, 0x01 }, 286 | { IMX283_REG_PLRD2, 0x00f0 }, 287 | { IMX283_REG_PLRD3, 0x01 }, 288 | { IMX283_REG_PLRD4, 0xc0 }, 289 | }, 290 | }, 291 | { 292 | .mhz = MHZ(18), 293 | .reg_count = 4, 294 | .regs = { 295 | { IMX283_REG_PLRD1, 0x01 }, 296 | { IMX283_REG_PLRD2, 0x00a0 }, 297 | { IMX283_REG_PLRD3, 0x01 }, 298 | { IMX283_REG_PLRD4, 0x80 }, 299 | }, 300 | }, 301 | { 302 | .mhz = MHZ(24), 303 | .reg_count = 4, 304 | .regs = { 305 | { IMX283_REG_PLRD1, 0x02 }, 306 | { IMX283_REG_PLRD2, 0x00f0 }, 307 | { IMX283_REG_PLRD3, 0x02 }, 308 | { IMX283_REG_PLRD4, 0xc0 }, 309 | }, 310 | }, 311 | }; 312 | 313 | enum imx283_modes { 314 | IMX283_MODE_0, 315 | IMX283_MODE_1, 316 | IMX283_MODE_1A, 317 | IMX283_MODE_1S, 318 | IMX283_MODE_2, 319 | IMX283_MODE_2A, 320 | IMX283_MODE_3, 321 | IMX283_MODE_4, 322 | IMX283_MODE_5, 323 | IMX283_MODE_6, 324 | }; 325 | 326 | struct imx283_readout_mode { 327 | u64 mdsel1; 328 | u64 mdsel2; 329 | u64 mdsel3; 330 | u64 mdsel4; 331 | }; 332 | 333 | static const struct imx283_readout_mode imx283_readout_modes[] = { 334 | /* All pixel scan modes */ 335 | [IMX283_MODE_0] = { 0x04, 0x03, 0x10, 0x00 }, /* 12 bit */ 336 | [IMX283_MODE_1] = { 0x04, 0x01, 0x00, 0x00 }, /* 10 bit */ 337 | [IMX283_MODE_1A] = { 0x04, 0x01, 0x20, 0x50 }, /* 10 bit */ 338 | [IMX283_MODE_1S] = { 0x04, 0x41, 0x20, 0x50 }, /* 10 bit */ 339 | 340 | /* Horizontal / Vertical 2/2-line binning */ 341 | [IMX283_MODE_2] = { 0x0d, 0x11, 0x50, 0x00 }, /* 12 bit */ 342 | [IMX283_MODE_2A] = { 0x0d, 0x11, 0x70, 0x50 }, /* 12 bit */ 343 | 344 | /* Horizontal / Vertical 3/3-line binning */ 345 | [IMX283_MODE_3] = { 0x1e, 0x18, 0x10, 0x00 }, /* 12 bit */ 346 | 347 | /* Veritcal 2/9 subsampling, horizontal 3 binning cropping */ 348 | [IMX283_MODE_4] = { 0x29, 0x18, 0x30, 0x50 }, /* 12 bit */ 349 | 350 | /* Vertical 2/19 subsampling binning, horizontal 3 binning */ 351 | [IMX283_MODE_5] = { 0x2d, 0x18, 0x10, 0x00 }, /* 12 bit */ 352 | 353 | /* Vertical 2 binning horizontal 2/4, subsampling 16:9 cropping */ 354 | [IMX283_MODE_6] = { 0x18, 0x21, 0x00, 0x09 }, /* 10 bit */ 355 | }; 356 | 357 | static const struct cci_reg_sequence mipi_data_rate_1440Mbps[] = { 358 | /* The default register settings provide the 1440Mbps rate */ 359 | #if 0 360 | { CCI_REG8(0x36c5), 0x00 }, /* Undocumented */ 361 | { CCI_REG8(0x3ac4), 0x00 }, /* Undocumented */ 362 | 363 | { CCI_REG8(0x320B), 0x00 }, /* STBPL */ 364 | { CCI_REG8(0x3018), 0xa7 }, /* TCLKPOST */ 365 | { CCI_REG8(0x301A), 0x6f }, /* THSPREPARE */ 366 | { CCI_REG8(0x301C), 0x9f }, /* THSZERO */ 367 | { CCI_REG8(0x301E), 0x5f }, /* THSTRAIL */ 368 | { CCI_REG8(0x3020), 0x5f }, /* TCLKTRAIL */ 369 | { CCI_REG8(0x3022), 0x6f }, /* TCLKPREPARE */ 370 | { CCI_REG8(0x3024), 0x7f }, /* TCLKZERO[7:0] */ 371 | { CCI_REG8(0x3025), 0x01 }, /* TCLKZERO[8] */ 372 | { CCI_REG8(0x3026), 0x4f }, /* TLPX*/ 373 | { CCI_REG8(0x3028), 0x47 }, /* THSEXIT */ 374 | { CCI_REG8(0x302A), 0x07 }, /* TCKLPRE */ 375 | { CCI_REG8(0x3104), 0x02 }, /* SYSMODE */ 376 | 377 | #endif 378 | }; 379 | 380 | static const struct cci_reg_sequence mipi_data_rate_720Mbps[] = { 381 | /* Undocumented Arducam Additions "For 720MBps" Setting */ 382 | { CCI_REG8(0x36c5), 0x01 }, /* Undocumented */ 383 | { CCI_REG8(0x3ac4), 0x01 }, /* Undocumented */ 384 | 385 | { CCI_REG8(0x320B), 0x00 }, /* STBPL */ 386 | { CCI_REG8(0x3018), 0x77 }, /* TCLKPOST */ 387 | { CCI_REG8(0x301A), 0x37 }, /* THSPREPARE */ 388 | { CCI_REG8(0x301C), 0x67 }, /* THSZERO */ 389 | { CCI_REG8(0x301E), 0x37 }, /* THSTRAIL */ 390 | { CCI_REG8(0x3020), 0x37 }, /* TCLKTRAIL */ 391 | { CCI_REG8(0x3022), 0x37 }, /* TCLKPREPARE */ 392 | { CCI_REG8(0x3024), 0xDF }, /* TCLKZERO[7:0] */ 393 | { CCI_REG8(0x3025), 0x00 }, /* TCLKZERO[8] */ 394 | { CCI_REG8(0x3026), 0x2F }, /* TLPX*/ 395 | { CCI_REG8(0x3028), 0x47 }, /* THSEXIT */ 396 | { CCI_REG8(0x302A), 0x0F }, /* TCKLPRE */ 397 | { CCI_REG8(0x3104), 0x02 }, /* SYSMODE */ 398 | }; 399 | 400 | static const s64 link_frequencies[] = { 401 | MHZ(720), /* 1440 Mbps lane data rate */ 402 | MHZ(360), /* 720 Mbps data lane rate */ 403 | }; 404 | 405 | static const struct IMX283_reg_list link_freq_reglist[] = { 406 | { /* MHZ(720)*/ 407 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_1440Mbps), 408 | .regs = mipi_data_rate_1440Mbps, 409 | }, 410 | { /* MHZ(360) */ 411 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_720Mbps), 412 | .regs = mipi_data_rate_720Mbps, 413 | }, 414 | }; 415 | 416 | #define CENTERED_RECTANGLE(rect, _width, _height) \ 417 | { \ 418 | .left = rect.left + ((rect.width - (_width)) / 2), \ 419 | .top = rect.top + ((rect.height - (_height)) / 2), \ 420 | .width = (_width), \ 421 | .height = (_height), \ 422 | } 423 | 424 | /* Mode configs */ 425 | static const struct imx283_mode supported_modes_12bit[] = { 426 | { 427 | /* 5568x3664 21.40fps readout mode 0 */ 428 | .mode = IMX283_MODE_0, 429 | .bpp = 12, 430 | .width = 5472 + 96, 431 | .height = 3648 + 16, 432 | .min_HMAX = 887, 433 | .min_VMAX = 3793, 434 | .default_HMAX = 900, 435 | .default_VMAX = 4000, 436 | .min_SHR = 12, 437 | .horizontal_ob = 96, 438 | .vertical_ob = 16, 439 | .crop = CENTERED_RECTANGLE(imx283_active_area, 5472, 3648), 440 | }, 441 | { 442 | /* 2784x1828 51.80fps readout mode 2 */ 443 | .mode = IMX283_MODE_2, 444 | .bpp = 12, 445 | .width = (5472 + 96)/2, 446 | .height = (3648 + 8)/2, 447 | .min_HMAX = 362, 448 | .min_VMAX = 3840, 449 | .default_HMAX = 375, 450 | .default_VMAX = 3840, 451 | .min_SHR = 12, 452 | .horizontal_ob = 96/2, 453 | .vertical_ob = 8/2, 454 | .crop = CENTERED_RECTANGLE(imx283_active_area, 5472, 3648), 455 | }, 456 | }; 457 | 458 | static const struct imx283_mode supported_modes_10bit[] = { 459 | { 460 | /* 5568x3664 25.48fps readout mode 1 */ 461 | .mode = IMX283_MODE_1, 462 | .bpp = 10, 463 | .width = 5472 + 96, 464 | .height = 3648 + 16, 465 | .min_HMAX = 745, 466 | .min_VMAX = 3793, 467 | .default_HMAX = 750, 468 | .default_VMAX = 3840, 469 | .min_SHR = 12, 470 | .horizontal_ob = 96, 471 | .vertical_ob = 16, 472 | .crop = CENTERED_RECTANGLE(imx283_active_area, 5472, 3648), 473 | }, 474 | { 475 | /* 5568x3094 30.17fps readout mode 1A */ 476 | .mode = IMX283_MODE_1A, 477 | .bpp = 10, 478 | .width = 5472 + 96, 479 | .height = 3078 + 16, 480 | .min_HMAX = 745, 481 | .min_VMAX = 3203, 482 | .default_HMAX = 750, 483 | .default_VMAX = 3840, 484 | .min_SHR = 12, 485 | .horizontal_ob = 96, 486 | .vertical_ob = 16, 487 | .crop = CENTERED_RECTANGLE(imx283_active_area, 5472, 3078), 488 | }, 489 | }; 490 | 491 | /* 492 | * The supported formats. 493 | * This table MUST contain 4 entries per format, to cover the various flip 494 | * combinations in the order 495 | * - no flip 496 | * - h flip 497 | * - v flip 498 | * - h&v flips 499 | */ 500 | static const u32 codes[] = { 501 | /* 12-bit modes. */ 502 | MEDIA_BUS_FMT_SRGGB12_1X12, 503 | MEDIA_BUS_FMT_SGRBG12_1X12, 504 | MEDIA_BUS_FMT_SGBRG12_1X12, 505 | MEDIA_BUS_FMT_SBGGR12_1X12, 506 | /* 10-bit modes. */ 507 | MEDIA_BUS_FMT_SRGGB10_1X10, 508 | MEDIA_BUS_FMT_SGRBG10_1X10, 509 | MEDIA_BUS_FMT_SGBRG10_1X10, 510 | MEDIA_BUS_FMT_SBGGR10_1X10, 511 | }; 512 | 513 | /* regulator supplies */ 514 | static const char * const imx283_supply_name[] = { 515 | /* Supplies can be enabled in any order */ 516 | "VANA", /* Analog (2.8V) supply */ 517 | "VDIG", /* Digital Core (1.1V) supply */ 518 | "VDDL", /* IF (1.8V) supply */ 519 | }; 520 | 521 | #define imx283_NUM_SUPPLIES ARRAY_SIZE(imx283_supply_name) 522 | 523 | /* 524 | * Initialisation delay between XCLR low->high and the moment when the sensor 525 | * can start capture (i.e. can leave software standby), given by T7 in the 526 | * datasheet is 8ms. This does include I2C setup time as well. 527 | * 528 | * Note, that delay between XCLR low->high and reading the CCI ID register (T6 529 | * in the datasheet) is much smaller - 600us. 530 | */ 531 | #define imx283_XCLR_MIN_DELAY_US 100000 532 | #define imx283_XCLR_DELAY_RANGE_US 1000 533 | 534 | struct imx283 { 535 | struct device *dev; 536 | 537 | const struct imx283_input_frequency *freq; 538 | 539 | /* Selected link_frequency */ 540 | unsigned int link_freq_idx; 541 | 542 | struct v4l2_subdev sd; 543 | struct media_pad pad; 544 | 545 | unsigned int fmt_code; 546 | 547 | struct clk *xclk; 548 | 549 | struct gpio_desc *reset_gpio; 550 | struct regulator_bulk_data supplies[imx283_NUM_SUPPLIES]; 551 | 552 | struct v4l2_ctrl_handler ctrl_handler; 553 | /* V4L2 Controls */ 554 | struct v4l2_ctrl *pixel_rate; 555 | struct v4l2_ctrl *link_freq; 556 | struct v4l2_ctrl *exposure; 557 | struct v4l2_ctrl *vflip; 558 | struct v4l2_ctrl *hflip; 559 | struct v4l2_ctrl *vblank; 560 | struct v4l2_ctrl *hblank; 561 | 562 | /* Current mode */ 563 | const struct imx283_mode *mode; 564 | 565 | u16 hmax; 566 | u32 vmax; 567 | 568 | /* 569 | * Mutex for serialized access: 570 | * Protect sensor module set pad format and start/stop streaming safely. 571 | */ 572 | struct mutex mutex; 573 | 574 | /* Streaming on/off */ 575 | bool streaming; 576 | }; 577 | 578 | 579 | 580 | int cci_read(struct imx283 *imx283, u32 reg, u64 *val, int *err) { 581 | if (err && *err) 582 | return *err; 583 | 584 | struct i2c_client *client = v4l2_get_subdevdata(&imx283->sd); 585 | u32 reg_addr = reg & CCI_REG_ADDR_MASK; 586 | u32 width = (reg & CCI_REG_WIDTH_MASK) >> CCI_REG_WIDTH_SHIFT; 587 | u8 addr_buf[2] = { reg_addr >> 8, reg_addr & 0xff }; 588 | u8 data_buf[8] = { 0 }; // Max 8 bytes for 64-bit data 589 | struct i2c_msg msgs[2]; 590 | int ret; 591 | 592 | if (width == 0 || width > 8) { 593 | if (err) *err = -EINVAL; 594 | return -EINVAL; 595 | } 596 | 597 | // Setup I2C message to write the register address 598 | msgs[0].addr = client->addr; 599 | msgs[0].flags = 0; 600 | msgs[0].len = sizeof(addr_buf); 601 | msgs[0].buf = addr_buf; 602 | 603 | // Setup I2C message to read data from the register 604 | msgs[1].addr = client->addr; 605 | msgs[1].flags = I2C_M_RD; 606 | msgs[1].len = width; 607 | msgs[1].buf = data_buf; 608 | 609 | ret = i2c_transfer(client->adapter, msgs, 2); 610 | if (ret != 2) { 611 | if (err) *err = -EIO; 612 | return -EIO; 613 | } 614 | 615 | // Assuming big-endian register format 616 | *val = 0; 617 | for (int i = 0; i < width; i++) { 618 | *val = (*val << 8) | data_buf[i]; 619 | } 620 | 621 | return 0; 622 | } 623 | 624 | 625 | int cci_write(struct imx283 *imx283, u32 reg, u64 val, int *err) { 626 | 627 | struct i2c_client *client = v4l2_get_subdevdata(&imx283->sd); 628 | u32 reg_addr = reg & CCI_REG_ADDR_MASK; 629 | u32 width = (reg & CCI_REG_WIDTH_MASK) >> CCI_REG_WIDTH_SHIFT; 630 | bool is_le = reg & CCI_REG_LE; 631 | u8 buf[10]; // Maximum size needed: 2 bytes for address + 8 bytes for data 632 | int ret, i; 633 | 634 | // Set the register address (big-endian) 635 | buf[0] = (reg_addr >> 8) & 0xff; 636 | buf[1] = reg_addr & 0xff; 637 | 638 | // Set the data 639 | for (i = 0; i < width; i++) { 640 | if (is_le) { 641 | // Little-endian: lower address bytes have lower value bytes 642 | buf[2 + i] = (val >> (8 * i)) & 0xff; 643 | } else { 644 | // Big-endian: lower address bytes have higher value bytes 645 | buf[2 + width - 1 - i] = (val >> (8 * i)) & 0xff; 646 | } 647 | } 648 | 649 | ret = i2c_master_send(client, buf, 2 + width); 650 | if (ret < 0) { 651 | if (err) *err = ret; 652 | return ret; 653 | } 654 | 655 | return 0; 656 | } 657 | 658 | 659 | int cci_multi_reg_write(struct imx283 *imx283, const struct cci_reg_sequence *regs, unsigned int num_regs, int *err) { 660 | 661 | for (unsigned int i = 0; i < num_regs; i++) { 662 | *err = cci_write(imx283, regs[i].reg, regs[i].val, err); 663 | if (*err) 664 | return *err; 665 | } 666 | 667 | return 0; 668 | } 669 | 670 | 671 | 672 | static inline struct imx283 *to_imx283(struct v4l2_subdev *_sd) 673 | { 674 | return container_of(_sd, struct imx283, sd); 675 | } 676 | 677 | static inline void get_mode_table(unsigned int code, 678 | const struct imx283_mode **mode_list, 679 | unsigned int *num_modes) 680 | { 681 | switch (code) { 682 | /* 12-bit */ 683 | case MEDIA_BUS_FMT_SRGGB12_1X12: 684 | case MEDIA_BUS_FMT_SGRBG12_1X12: 685 | case MEDIA_BUS_FMT_SGBRG12_1X12: 686 | case MEDIA_BUS_FMT_SBGGR12_1X12: 687 | *mode_list = supported_modes_12bit; 688 | *num_modes = ARRAY_SIZE(supported_modes_12bit); 689 | break; 690 | /* 10-bit */ 691 | case MEDIA_BUS_FMT_SRGGB10_1X10: 692 | case MEDIA_BUS_FMT_SGRBG10_1X10: 693 | case MEDIA_BUS_FMT_SGBRG10_1X10: 694 | case MEDIA_BUS_FMT_SBGGR10_1X10: 695 | *mode_list = supported_modes_10bit; 696 | *num_modes = ARRAY_SIZE(supported_modes_10bit); 697 | break; 698 | default: 699 | *mode_list = NULL; 700 | *num_modes = 0; 701 | } 702 | } 703 | 704 | /* Get bayer order based on flip setting. */ 705 | static u32 imx283_get_format_code(struct imx283 *imx283, u32 code) 706 | { 707 | unsigned int i; 708 | lockdep_assert_held(&imx283->mutex); 709 | for (i = 0; i < ARRAY_SIZE(codes); i++) 710 | if (codes[i] == code) 711 | break; 712 | 713 | return codes[i]; 714 | } 715 | 716 | static void imx283_set_default_format(struct imx283 *imx283) 717 | { 718 | /* Set default mode to max resolution */ 719 | imx283->mode = &supported_modes_12bit[0]; 720 | imx283->fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12; 721 | } 722 | 723 | // Move this to .init_cfg 724 | static int imx283_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 725 | { 726 | struct imx283 *imx283 = to_imx283(sd); 727 | struct v4l2_mbus_framefmt *try_fmt_img = 728 | v4l2_subdev_get_try_format(sd, fh->state, IMAGE_PAD); 729 | 730 | struct v4l2_rect *try_crop; 731 | 732 | mutex_lock(&imx283->mutex); 733 | 734 | /* Initialize try_fmt for the image pad */ 735 | try_fmt_img->width = supported_modes_12bit[0].width; 736 | try_fmt_img->height = supported_modes_12bit[0].height; 737 | try_fmt_img->code = imx283_get_format_code(imx283, 738 | MEDIA_BUS_FMT_SRGGB12_1X12); 739 | try_fmt_img->field = V4L2_FIELD_NONE; 740 | 741 | /* Initialize try_crop */ 742 | try_crop = v4l2_subdev_get_try_crop(sd, fh->state, IMAGE_PAD); 743 | *try_crop = imx283_active_area; 744 | 745 | mutex_unlock(&imx283->mutex); 746 | 747 | return 0; 748 | } 749 | 750 | static u64 calculate_v4l2_cid_exposure(u64 hmax, u64 vmax, u64 shr, u64 svr, u64 offset) { 751 | u64 numerator; 752 | numerator = (vmax * (svr + 1) - shr) * hmax + offset; 753 | 754 | do_div(numerator, hmax); 755 | numerator = clamp_t(uint32_t, numerator, 0, 0xFFFFFFFF); 756 | return numerator; 757 | } 758 | 759 | static void calculate_min_max_v4l2_cid_exposure(u64 hmax, u64 vmax, u64 min_shr, u64 svr, u64 offset, u64 *min_exposure, u64 *max_exposure) { 760 | u64 max_shr = (svr + 1) * vmax - 4; 761 | max_shr = min_t(uint64_t, max_shr, 0xFFFF); 762 | 763 | *min_exposure = calculate_v4l2_cid_exposure(hmax, vmax, max_shr, svr, offset); 764 | *max_exposure = calculate_v4l2_cid_exposure(hmax, vmax, min_shr, svr, offset); 765 | } 766 | 767 | 768 | /* 769 | Integration Time [s] = [{VMAX × (SVR + 1) – (SHR)} 770 | × HMAX + offset] / (72 × 10^6) 771 | 772 | Integration Time [s] = exposure * HMAX / (72 × 10^6) 773 | */ 774 | 775 | static uint32_t calculate_shr(uint32_t exposure, uint32_t hmax, uint64_t vmax, uint32_t svr, uint32_t offset) { 776 | uint64_t temp; 777 | uint32_t shr; 778 | 779 | temp = ((uint64_t)exposure * hmax - offset); 780 | do_div(temp, hmax); 781 | shr = (uint32_t)(vmax * (svr + 1) - temp); 782 | 783 | return shr; 784 | } 785 | 786 | static const char * const imx283_tpg_menu[] = { 787 | "Disabled", 788 | "All 000h", 789 | "All FFFh", 790 | "All 555h", 791 | "All AAAh", 792 | "Horizontal color bars", 793 | "Vertical color bars", 794 | }; 795 | 796 | static const int imx283_tpg_val[] = { 797 | IMX283_TPG_PAT_ALL_000, 798 | IMX283_TPG_PAT_ALL_000, 799 | IMX283_TPG_PAT_ALL_FFF, 800 | IMX283_TPG_PAT_ALL_555, 801 | IMX283_TPG_PAT_ALL_AAA, 802 | IMX283_TPG_PAT_H_COLOR_BARS, 803 | IMX283_TPG_PAT_V_COLOR_BARS, 804 | }; 805 | 806 | static int imx283_update_test_pattern(struct imx283 *imx283, u32 pattern_index) 807 | { 808 | int ret; 809 | 810 | if (pattern_index >= ARRAY_SIZE(imx283_tpg_val)) 811 | return -EINVAL; 812 | 813 | if (pattern_index) { 814 | ret = cci_write(imx283, IMX283_REG_TPG_PAT, 815 | imx283_tpg_val[pattern_index], NULL); 816 | if (ret) 817 | return ret; 818 | 819 | ret = cci_write(imx283, IMX283_REG_TPG_CTRL, 820 | IMX283_TPG_CTRL_CLKEN | IMX283_TPG_CTRL_PATEN, NULL); 821 | } else { 822 | ret = cci_write(imx283, IMX283_REG_TPG_CTRL, 0x00, NULL); 823 | } 824 | 825 | return ret; 826 | } 827 | 828 | static int imx283_set_ctrl(struct v4l2_ctrl *ctrl) 829 | { 830 | struct imx283 *imx283 = 831 | container_of(ctrl->handler, struct imx283, ctrl_handler); 832 | const struct imx283_mode *mode = imx283->mode; 833 | u64 shr, pixel_rate, hmax = 0; 834 | int ret = 0; 835 | 836 | //state = v4l2_subdev_get_locked_active_state(&imx283->sd); 837 | //format = v4l2_subdev_get_pad_format(&imx283->sd, state, 0); 838 | 839 | /* 840 | * The VBLANK control may change the limits of usable exposure, so check 841 | * and adjust if necessary. 842 | */ 843 | if (ctrl->id == V4L2_CID_VBLANK){ 844 | /* Honour the VBLANK limits when setting exposure. */ 845 | u64 current_exposure, max_exposure, min_exposure, vmax; 846 | vmax = ((u64)mode->height + ctrl->val) ; 847 | imx283->vmax = vmax; 848 | 849 | calculate_min_max_v4l2_cid_exposure(imx283->hmax, imx283->vmax, 850 | (u64)mode->min_SHR, 0, 209, 851 | &min_exposure, &max_exposure); 852 | 853 | current_exposure = clamp_t(uint32_t, current_exposure, min_exposure, max_exposure); 854 | 855 | dev_info(imx283->dev,"exposure_max:%lld, exposure_min:%lld, current_exposure:%lld\n",max_exposure, min_exposure, current_exposure); 856 | dev_info(imx283->dev, "\tVMAX:%d, HMAX:%d\n", imx283->vmax, imx283->hmax); 857 | __v4l2_ctrl_modify_range(imx283->exposure, min_exposure,max_exposure, 1,current_exposure); 858 | } 859 | 860 | /* 861 | * Applying V4L2 control value only happens 862 | * when power is up for streaming 863 | */ 864 | if (pm_runtime_get_if_in_use(imx283->dev) == 0) 865 | return 0; 866 | 867 | 868 | switch (ctrl->id) { 869 | case V4L2_CID_EXPOSURE: 870 | { 871 | dev_info(imx283->dev,"V4L2_CID_EXPOSURE : %d\n",ctrl->val); 872 | dev_info(imx283->dev,"\tvblank:%d, hblank:%d\n",imx283->vblank->val, imx283->hblank->val); 873 | dev_info(imx283->dev, "\tVMAX:%d, HMAX:%d\n", imx283->vmax, imx283->hmax); 874 | shr = calculate_shr(ctrl->val, imx283->hmax, imx283->vmax, 0, 209); 875 | dev_info(imx283->dev,"\tSHR:%lld\n",shr); 876 | ret = cci_write(imx283, IMX283_REG_SHR, shr, NULL); 877 | 878 | } 879 | break; 880 | 881 | case V4L2_CID_HBLANK: 882 | { 883 | dev_info(imx283->dev, "V4L2_CID_HBLANK : %d\n", ctrl->val); 884 | //int hmax = (IMX283_NATIVE_WIDTH + ctrl->val) * 72000000; / IMX283_PIXEL_RATE; 885 | pixel_rate = (u64)mode->width * 72000000; 886 | do_div(pixel_rate, mode->min_HMAX); 887 | hmax = (u64)(mode->width + ctrl->val) * 72000000; 888 | do_div(hmax, pixel_rate); 889 | imx283->hmax = hmax; 890 | dev_info(imx283->dev, "\tHMAX : %d\n", imx283->hmax); 891 | ret = cci_write(imx283, IMX283_REG_HMAX, hmax, NULL); 892 | } 893 | break; 894 | 895 | case V4L2_CID_VBLANK: 896 | { 897 | dev_info(imx283->dev,"V4L2_CID_VBLANK : %d\n",ctrl->val); 898 | imx283->vmax = ((u64)mode->height + ctrl->val); 899 | dev_info(imx283->dev, "\tVMAX : %d\n", imx283->vmax); 900 | ret = cci_write(imx283, IMX283_REG_VMAX, imx283->vmax, NULL); 901 | } 902 | break; 903 | 904 | case V4L2_CID_ANALOGUE_GAIN: 905 | dev_info(imx283->dev, "V4L2_CID_ANALOGUE_GAIN : %d\n", ctrl->val); 906 | ret = cci_write(imx283, IMX283_REG_ANALOG_GAIN, ctrl->val, NULL); 907 | break; 908 | 909 | case V4L2_CID_DIGITAL_GAIN: 910 | dev_info(imx283->dev, "V4L2_CID_DIGITAL_GAIN : %d\n", ctrl->val); 911 | ret = cci_write(imx283, IMX283_REG_DIGITAL_GAIN, ctrl->val, NULL); 912 | break; 913 | 914 | case V4L2_CID_HFLIP: 915 | case V4L2_CID_VFLIP: 916 | //dev_info(imx283->dev,"V4L2_CID_HFLIP : %d\n",imx283->hflip->val); 917 | //dev_info(imx283->dev,"V4L2_CID_VFLIP : %d\n",imx283->vflip->val); 918 | //ret = imx283_write_reg_1byte(imx283, IMX283_REG_VFLIP, imx283->vflip->val); 919 | break; 920 | 921 | case V4L2_CID_TEST_PATTERN: 922 | ret = imx283_update_test_pattern(imx283, ctrl->val); 923 | break; 924 | 925 | default: 926 | dev_info(imx283->dev, 927 | "ctrl(id:0x%x,val:0x%x) is not handled\n", 928 | ctrl->id, ctrl->val); 929 | //ret = -EINVAL; 930 | break; 931 | } 932 | 933 | pm_runtime_put(imx283->dev); 934 | 935 | return ret; 936 | } 937 | 938 | static const struct v4l2_ctrl_ops imx283_ctrl_ops = { 939 | .s_ctrl = imx283_set_ctrl, 940 | }; 941 | 942 | static int imx283_enum_mbus_code(struct v4l2_subdev *sd, 943 | struct v4l2_subdev_state *sd_state, 944 | struct v4l2_subdev_mbus_code_enum *code) 945 | { 946 | struct imx283 *imx283 = to_imx283(sd); 947 | 948 | if (code->index >= (ARRAY_SIZE(codes) / 4)) 949 | return -EINVAL; 950 | 951 | code->code = imx283_get_format_code(imx283, codes[code->index * 4]); 952 | 953 | return 0; 954 | } 955 | 956 | static int imx283_enum_frame_size(struct v4l2_subdev *sd, 957 | struct v4l2_subdev_state *sd_state, 958 | struct v4l2_subdev_frame_size_enum *fse) 959 | { 960 | struct imx283 *imx283 = to_imx283(sd); 961 | 962 | const struct imx283_mode *mode_list; 963 | unsigned int num_modes; 964 | 965 | get_mode_table(fse->code, &mode_list, &num_modes); 966 | 967 | if (fse->index >= num_modes) 968 | return -EINVAL; 969 | 970 | if (fse->code != imx283_get_format_code(imx283, fse->code)) 971 | return -EINVAL; 972 | 973 | fse->min_width = mode_list[fse->index].width; 974 | fse->max_width = fse->min_width; 975 | fse->min_height = mode_list[fse->index].height; 976 | fse->max_height = fse->min_height; 977 | 978 | return 0; 979 | } 980 | 981 | static void imx283_reset_colorspace(struct v4l2_mbus_framefmt *fmt) 982 | { 983 | fmt->colorspace = V4L2_COLORSPACE_RAW; 984 | fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); 985 | fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, 986 | fmt->colorspace, 987 | fmt->ycbcr_enc); 988 | fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace); 989 | } 990 | 991 | static void imx283_update_image_pad_format(struct imx283 *imx283, 992 | const struct imx283_mode *mode, 993 | struct v4l2_subdev_format *fmt) 994 | { 995 | fmt->format.width = mode->width; 996 | fmt->format.height = mode->height; 997 | fmt->format.field = V4L2_FIELD_NONE; 998 | imx283_reset_colorspace(&fmt->format); 999 | } 1000 | 1001 | static int imx283_get_pad_format(struct v4l2_subdev *sd, 1002 | struct v4l2_subdev_state *sd_state, 1003 | struct v4l2_subdev_format *fmt) 1004 | { 1005 | struct imx283 *imx283 = to_imx283(sd); 1006 | 1007 | mutex_lock(&imx283->mutex); 1008 | 1009 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1010 | struct v4l2_mbus_framefmt *try_fmt = 1011 | v4l2_subdev_get_try_format(&imx283->sd, sd_state, 1012 | fmt->pad); 1013 | /* update the code which could change due to vflip or hflip: */ 1014 | try_fmt->code = imx283_get_format_code(imx283, try_fmt->code); 1015 | fmt->format = *try_fmt; 1016 | } else { 1017 | imx283_update_image_pad_format(imx283, imx283->mode, fmt); 1018 | fmt->format.code = imx283_get_format_code(imx283, imx283->fmt_code); 1019 | } 1020 | 1021 | mutex_unlock(&imx283->mutex); 1022 | return 0; 1023 | } 1024 | 1025 | /* TODO */ 1026 | static void imx283_set_framing_limits(struct imx283 *imx283) 1027 | { 1028 | const struct imx283_mode *mode = imx283->mode; 1029 | u64 def_hblank; 1030 | u64 pixel_rate; 1031 | 1032 | 1033 | imx283->vmax = mode->default_VMAX; 1034 | imx283->hmax = mode->default_HMAX; 1035 | 1036 | pixel_rate = (u64)mode->width * 72000000; 1037 | do_div(pixel_rate,mode->min_HMAX); 1038 | dev_info(imx283->dev,"Pixel Rate : %lld\n",pixel_rate); 1039 | 1040 | 1041 | //int def_hblank = mode->default_HMAX * IMX283_PIXEL_RATE / 72000000 - IMX283_NATIVE_WIDTH; 1042 | def_hblank = mode->default_HMAX * pixel_rate; 1043 | do_div(def_hblank, 72000000); 1044 | def_hblank = def_hblank - mode->width; 1045 | __v4l2_ctrl_modify_range(imx283->hblank, 0, 1046 | IMX283_HMAX_MAX, 1, def_hblank); 1047 | __v4l2_ctrl_s_ctrl(imx283->hblank, def_hblank); 1048 | 1049 | /* Update limits and set FPS to default */ 1050 | __v4l2_ctrl_modify_range(imx283->vblank, mode->min_VMAX - mode->height, 1051 | IMX283_VMAX_MAX - mode->height, 1052 | 1, mode->default_VMAX - mode->height); 1053 | __v4l2_ctrl_s_ctrl(imx283->vblank, mode->default_VMAX - mode->height); 1054 | 1055 | /* Setting this will adjust the exposure limits as well. */ 1056 | 1057 | __v4l2_ctrl_modify_range(imx283->pixel_rate, pixel_rate, pixel_rate, 1, pixel_rate); 1058 | 1059 | dev_info(imx283->dev,"Setting default HBLANK : %lld, VBLANK : %lld with PixelRate: %lld\n",def_hblank,mode->default_VMAX - mode->height, pixel_rate); 1060 | 1061 | } 1062 | /* TODO */ 1063 | static int imx283_set_pad_format(struct v4l2_subdev *sd, 1064 | struct v4l2_subdev_state *sd_state, 1065 | struct v4l2_subdev_format *fmt) 1066 | { 1067 | struct v4l2_mbus_framefmt *framefmt; 1068 | const struct imx283_mode *mode; 1069 | struct imx283 *imx283 = to_imx283(sd); 1070 | const struct imx283_mode *mode_list; 1071 | unsigned int num_modes; 1072 | 1073 | mutex_lock(&imx283->mutex); 1074 | 1075 | /* Bayer order varies with flips */ 1076 | fmt->format.code = imx283_get_format_code(imx283, 1077 | fmt->format.code); 1078 | 1079 | get_mode_table(fmt->format.code, &mode_list, &num_modes); 1080 | 1081 | mode = v4l2_find_nearest_size(mode_list, 1082 | num_modes, 1083 | width, height, 1084 | fmt->format.width, 1085 | fmt->format.height); 1086 | imx283_update_image_pad_format(imx283, mode, fmt); 1087 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1088 | framefmt = v4l2_subdev_get_try_format(sd, sd_state, 1089 | fmt->pad); 1090 | *framefmt = fmt->format; 1091 | } else if (imx283->mode != mode) { 1092 | imx283->mode = mode; 1093 | imx283->fmt_code = fmt->format.code; 1094 | imx283_set_framing_limits(imx283); 1095 | } 1096 | 1097 | mutex_unlock(&imx283->mutex); 1098 | 1099 | return 0; 1100 | } 1101 | /* TODO */ 1102 | static const struct v4l2_rect * 1103 | __imx283_get_pad_crop(struct imx283 *imx283, 1104 | struct v4l2_subdev_state *sd_state, 1105 | unsigned int pad, enum v4l2_subdev_format_whence which) 1106 | { 1107 | switch (which) { 1108 | case V4L2_SUBDEV_FORMAT_TRY: 1109 | return v4l2_subdev_get_try_crop(&imx283->sd, sd_state, pad); 1110 | case V4L2_SUBDEV_FORMAT_ACTIVE: 1111 | return &imx283->mode->crop; 1112 | } 1113 | 1114 | return NULL; 1115 | } 1116 | 1117 | static int imx283_standby_cancel(struct imx283 *imx283) 1118 | { 1119 | int ret = 0; 1120 | 1121 | cci_write(imx283, IMX283_REG_STANDBY, 1122 | IMX283_STBLOGIC | IMX283_STBDV, &ret); 1123 | 1124 | /* Configure PLL clocks based on the xclk */ 1125 | cci_multi_reg_write(imx283, imx283->freq->regs, 1126 | imx283->freq->reg_count, &ret); 1127 | 1128 | dev_err(imx283->dev, "Using clk freq %d MHz", imx283->freq->mhz / MHZ(1)); 1129 | 1130 | /* Initialise communication */ 1131 | cci_write(imx283, IMX283_REG_PLSTMG08, IMX283_PLSTMG08_VAL, &ret); 1132 | cci_write(imx283, IMX283_REG_PLSTMG02, IMX283_PLSTMG02_VAL, &ret); 1133 | 1134 | /* Enable PLL */ 1135 | cci_write(imx283, IMX283_REG_STBPL, IMX283_STBPL_NORMAL, &ret); 1136 | 1137 | /* Configure the MIPI link speed */ 1138 | cci_multi_reg_write(imx283, 1139 | link_freq_reglist[imx283->link_freq_idx].regs, 1140 | link_freq_reglist[imx283->link_freq_idx].num_of_regs, 1141 | &ret); 1142 | 1143 | usleep_range(1000, 2000); /* 1st Stabilisation period of 1 ms or more */ 1144 | 1145 | /* Activate */ 1146 | cci_write(imx283, IMX283_REG_STANDBY, IMX283_ACTIVE, &ret); 1147 | usleep_range(19000, 20000); /* 2nd Stabilisation period of 19ms or more */ 1148 | 1149 | cci_write(imx283, IMX283_REG_CLAMP, IMX283_CLPSQRST, &ret); 1150 | cci_write(imx283, IMX283_REG_XMSTA, 0, &ret); 1151 | cci_write(imx283, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret); 1152 | 1153 | return ret; 1154 | } 1155 | 1156 | /* Start streaming */ 1157 | static int imx283_start_streaming(struct imx283 *imx283) 1158 | { 1159 | const struct imx283_readout_mode *readout; 1160 | const struct imx283_mode *mode = imx283->mode; 1161 | int ret; 1162 | 1163 | ret = imx283_standby_cancel(imx283); 1164 | if (ret) { 1165 | dev_err(imx283->dev, "failed to cancel standby\n"); 1166 | return ret; 1167 | } 1168 | 1169 | /* Set the readout mode registers */ 1170 | readout = &imx283_readout_modes[imx283->mode->mode]; 1171 | cci_write(imx283, IMX283_REG_MDSEL1, readout->mdsel1, &ret); 1172 | cci_write(imx283, IMX283_REG_MDSEL2, readout->mdsel2, &ret); 1173 | cci_write(imx283, IMX283_REG_MDSEL3, readout->mdsel3, &ret); 1174 | cci_write(imx283, IMX283_REG_MDSEL4, readout->mdsel4, &ret); 1175 | 1176 | /* Mode 1S specific entries from the Readout Drive Mode Tables */ 1177 | if (mode->mode == IMX283_MODE_1S) { 1178 | cci_write(imx283, IMX283_REG_MDSEL7, 0x01, &ret); 1179 | cci_write(imx283, IMX283_REG_MDSEL18, 0x1098, &ret); 1180 | } 1181 | 1182 | if (ret) { 1183 | dev_err(imx283->dev, "%s failed to set readout\n", __func__); 1184 | return ret; 1185 | } 1186 | 1187 | /* Initialise SVR. Unsupported for now - Always 0 */ 1188 | cci_write(imx283, IMX283_REG_SVR, 0x00, &ret); 1189 | 1190 | dev_err(imx283->dev, "Mode: Size %d x %d\n", mode->width, mode->height); 1191 | 1192 | dev_err(imx283->dev, "Analogue Crop (in the mode) %d,%d %dx%d\n", 1193 | mode->crop.left, 1194 | mode->crop.top, 1195 | mode->crop.width, 1196 | mode->crop.height); 1197 | 1198 | /* Todo: Update for arbitrary vertical cropping */ 1199 | cci_write(imx283, IMX283_REG_Y_OUT_SIZE, 1200 | mode->height - mode->vertical_ob, &ret); 1201 | cci_write(imx283, IMX283_REG_WRITE_VSIZE, mode->height, &ret); 1202 | cci_write(imx283, IMX283_REG_OB_SIZE_V, mode->vertical_ob, &ret); 1203 | 1204 | /* Configure cropping */ 1205 | cci_write(imx283, IMX283_REG_HTRIMMING, 1206 | IMX283_HTRIMMING_EN | IMX283_HTRIMMING_RESERVED, &ret); 1207 | 1208 | /* Todo: Validate mode->crop is fully contained within imx283_native_area */ 1209 | /* Todo: Validate with an adjustable crop */ 1210 | cci_write(imx283, IMX283_REG_HTRIMMING_START, mode->crop.left, &ret); 1211 | cci_write(imx283, IMX283_REG_HTRIMMING_END, 1212 | mode->crop.left + mode->crop.width + 1, &ret); 1213 | 1214 | /* Todo: These must be calculated based on the link-freq and mode */ 1215 | cci_write(imx283, IMX283_REG_HMAX, mode->default_HMAX, &ret); 1216 | cci_write(imx283, IMX283_REG_VMAX, mode->default_VMAX, &ret); 1217 | cci_write(imx283, IMX283_REG_SHR, mode->min_SHR, &ret); 1218 | 1219 | /* Disable embedded data */ 1220 | cci_write(imx283, IMX283_REG_EBD_X_OUT_SIZE, 0, &ret); 1221 | 1222 | /* Apply customized values from user */ 1223 | ret = __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler); 1224 | 1225 | return ret; 1226 | } 1227 | 1228 | /* Stop streaming */ 1229 | static void imx283_stop_streaming(struct imx283 *imx283) 1230 | { 1231 | int ret; 1232 | 1233 | ret = cci_write(imx283, IMX283_REG_STANDBY, IMX283_STBLOGIC, NULL); 1234 | if (ret) 1235 | dev_err(imx283->dev, "%s failed to set stream\n", __func__); 1236 | } 1237 | 1238 | static int imx283_set_stream(struct v4l2_subdev *sd, int enable) 1239 | { 1240 | struct imx283 *imx283 = to_imx283(sd); 1241 | int ret = 0; 1242 | 1243 | mutex_lock(&imx283->mutex); 1244 | if (imx283->streaming == enable) { 1245 | mutex_unlock(&imx283->mutex); 1246 | return 0; 1247 | } 1248 | 1249 | if (enable) { 1250 | ret = pm_runtime_get_sync(imx283->dev); 1251 | if (ret < 0) { 1252 | pm_runtime_put_noidle(imx283->dev); 1253 | goto err_unlock; 1254 | } 1255 | 1256 | /* 1257 | * Apply default & customized values 1258 | * and then start streaming. 1259 | */ 1260 | ret = imx283_start_streaming(imx283); 1261 | if (ret) 1262 | goto err_rpm_put; 1263 | } else { 1264 | imx283_stop_streaming(imx283); 1265 | pm_runtime_put(imx283->dev); 1266 | } 1267 | 1268 | imx283->streaming = enable; 1269 | 1270 | /* vflip and hflip cannot change during streaming */ 1271 | __v4l2_ctrl_grab(imx283->vflip, enable); 1272 | __v4l2_ctrl_grab(imx283->hflip, enable); 1273 | 1274 | mutex_unlock(&imx283->mutex); 1275 | 1276 | return ret; 1277 | 1278 | err_rpm_put: 1279 | pm_runtime_put(imx283->dev); 1280 | err_unlock: 1281 | mutex_unlock(&imx283->mutex); 1282 | 1283 | return ret; 1284 | } 1285 | 1286 | /* Power/clock management functions */ 1287 | static int imx283_power_on(struct device *dev) 1288 | { 1289 | struct i2c_client *client = to_i2c_client(dev); 1290 | struct v4l2_subdev *sd = i2c_get_clientdata(client); 1291 | struct imx283 *imx283 = to_imx283(sd); 1292 | int ret; 1293 | 1294 | ret = regulator_bulk_enable(imx283_NUM_SUPPLIES, 1295 | imx283->supplies); 1296 | if (ret) { 1297 | dev_err(imx283->dev, "%s: failed to enable regulators\n", 1298 | __func__); 1299 | return ret; 1300 | } 1301 | 1302 | ret = clk_prepare_enable(imx283->xclk); 1303 | if (ret) { 1304 | dev_err(imx283->dev, "%s: failed to enable clock\n", 1305 | __func__); 1306 | goto reg_off; 1307 | } 1308 | 1309 | gpiod_set_value_cansleep(imx283->reset_gpio, 1); 1310 | usleep_range(imx283_XCLR_MIN_DELAY_US, 1311 | imx283_XCLR_MIN_DELAY_US + imx283_XCLR_DELAY_RANGE_US); 1312 | 1313 | return 0; 1314 | 1315 | reg_off: 1316 | regulator_bulk_disable(imx283_NUM_SUPPLIES, imx283->supplies); 1317 | return ret; 1318 | } 1319 | 1320 | static int imx283_power_off(struct device *dev) 1321 | { 1322 | struct i2c_client *client = to_i2c_client(dev); 1323 | struct v4l2_subdev *sd = i2c_get_clientdata(client); 1324 | struct imx283 *imx283 = to_imx283(sd); 1325 | 1326 | gpiod_set_value_cansleep(imx283->reset_gpio, 0); 1327 | regulator_bulk_disable(imx283_NUM_SUPPLIES, imx283->supplies); 1328 | clk_disable_unprepare(imx283->xclk); 1329 | 1330 | return 0; 1331 | } 1332 | 1333 | static int __maybe_unused imx283_suspend(struct device *dev) 1334 | { 1335 | struct i2c_client *client = to_i2c_client(dev); 1336 | struct v4l2_subdev *sd = i2c_get_clientdata(client); 1337 | struct imx283 *imx283 = to_imx283(sd); 1338 | 1339 | if (imx283->streaming) 1340 | imx283_stop_streaming(imx283); 1341 | 1342 | return 0; 1343 | } 1344 | 1345 | static int __maybe_unused imx283_resume(struct device *dev) 1346 | { 1347 | struct i2c_client *client = to_i2c_client(dev); 1348 | struct v4l2_subdev *sd = i2c_get_clientdata(client); 1349 | struct imx283 *imx283 = to_imx283(sd); 1350 | int ret; 1351 | 1352 | if (imx283->streaming) { 1353 | ret = imx283_start_streaming(imx283); 1354 | if (ret) 1355 | goto error; 1356 | } 1357 | 1358 | return 0; 1359 | 1360 | error: 1361 | imx283_stop_streaming(imx283); 1362 | imx283->streaming = 0; 1363 | return ret; 1364 | } 1365 | 1366 | static int imx283_get_regulators(struct imx283 *imx283) 1367 | { 1368 | unsigned int i; 1369 | 1370 | for (i = 0; i < imx283_NUM_SUPPLIES; i++) 1371 | imx283->supplies[i].supply = imx283_supply_name[i]; 1372 | 1373 | return devm_regulator_bulk_get(imx283->dev, 1374 | imx283_NUM_SUPPLIES, 1375 | imx283->supplies); 1376 | } 1377 | 1378 | /* Verify chip ID */ 1379 | static int imx283_identify_module(struct imx283 *imx283) 1380 | { 1381 | int ret; 1382 | u64 val; 1383 | 1384 | ret = cci_read(imx283, IMX283_REG_CHIP_ID, &val, NULL); 1385 | if (ret) { 1386 | dev_err(imx283->dev, "failed to read chip id %x, with error %d\n", 1387 | IMX283_CHIP_ID, ret); 1388 | return ret; 1389 | } 1390 | 1391 | if (val != IMX283_CHIP_ID) { 1392 | dev_err(imx283->dev, "chip id mismatch: %x!=%llx\n", 1393 | IMX283_CHIP_ID, val); 1394 | return -EIO; 1395 | } 1396 | 1397 | dev_info(imx283->dev, "Device found\n"); 1398 | 1399 | return 0; 1400 | } 1401 | 1402 | static int imx283_get_selection(struct v4l2_subdev *sd, 1403 | struct v4l2_subdev_state *sd_state, 1404 | struct v4l2_subdev_selection *sel) 1405 | { 1406 | switch (sel->target) { 1407 | case V4L2_SEL_TGT_CROP: { 1408 | struct imx283 *imx283 = to_imx283(sd); 1409 | 1410 | mutex_lock(&imx283->mutex); 1411 | sel->r = *__imx283_get_pad_crop(imx283, sd_state, sel->pad, 1412 | sel->which); 1413 | mutex_unlock(&imx283->mutex); 1414 | 1415 | return 0; 1416 | } 1417 | 1418 | case V4L2_SEL_TGT_NATIVE_SIZE: 1419 | sel->r = imx283_native_area; 1420 | 1421 | return 0; 1422 | 1423 | case V4L2_SEL_TGT_CROP_DEFAULT: 1424 | case V4L2_SEL_TGT_CROP_BOUNDS: 1425 | sel->r = imx283_active_area; 1426 | 1427 | return 0; 1428 | } 1429 | 1430 | return -EINVAL; 1431 | } 1432 | 1433 | 1434 | static const struct v4l2_subdev_core_ops imx283_core_ops = { 1435 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, 1436 | .unsubscribe_event = v4l2_event_subdev_unsubscribe, 1437 | }; 1438 | 1439 | static const struct v4l2_subdev_video_ops imx283_video_ops = { 1440 | .s_stream = imx283_set_stream, 1441 | }; 1442 | 1443 | static const struct v4l2_subdev_pad_ops imx283_pad_ops = { 1444 | .enum_mbus_code = imx283_enum_mbus_code, 1445 | .get_fmt = imx283_get_pad_format, 1446 | .set_fmt = imx283_set_pad_format, 1447 | .get_selection = imx283_get_selection, 1448 | .enum_frame_size = imx283_enum_frame_size, 1449 | }; 1450 | 1451 | static const struct v4l2_subdev_ops imx283_subdev_ops = { 1452 | .core = &imx283_core_ops, 1453 | .video = &imx283_video_ops, 1454 | .pad = &imx283_pad_ops, 1455 | }; 1456 | 1457 | static const struct v4l2_subdev_internal_ops imx283_internal_ops = { 1458 | .open = imx283_open, 1459 | }; 1460 | 1461 | /* Initialize control handlers */ 1462 | static int imx283_init_controls(struct imx283 *imx283) 1463 | { 1464 | struct v4l2_ctrl_handler *ctrl_hdlr; 1465 | struct i2c_client *client = v4l2_get_subdevdata(&imx283->sd); 1466 | struct v4l2_fwnode_device_properties props; 1467 | const struct imx283_mode *mode = imx283->mode; 1468 | int ret; 1469 | 1470 | ctrl_hdlr = &imx283->ctrl_handler; 1471 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16); 1472 | if (ret) 1473 | return ret; 1474 | 1475 | mutex_init(&imx283->mutex); 1476 | ctrl_hdlr->lock = &imx283->mutex; 1477 | 1478 | 1479 | /* 1480 | * Create the controls here, but mode specific limits are setup 1481 | * in the imx283_set_framing_limits() call below. 1482 | */ 1483 | /* By default, PIXEL_RATE is read only */ 1484 | imx283->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1485 | V4L2_CID_PIXEL_RATE, 1486 | 0xffff, 1487 | 0xffff, 1, 1488 | 0xffff); 1489 | 1490 | imx283->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, 1491 | &imx283_ctrl_ops, 1492 | V4L2_CID_LINK_FREQ, 1493 | ARRAY_SIZE(link_frequencies) - 1, 1494 | 0, link_frequencies); 1495 | if (imx283->link_freq) 1496 | imx283->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; 1497 | 1498 | /* Initial vblank/hblank/exposure based on the current mode. */ 1499 | imx283->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1500 | V4L2_CID_VBLANK, 1501 | mode->min_VMAX - mode->height, 1502 | IMX283_VMAX_MAX, 1, 1503 | mode->default_VMAX - mode->height); 1504 | 1505 | imx283->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1506 | V4L2_CID_HBLANK, 0, 0xffff, 1, 0); 1507 | 1508 | imx283->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1509 | V4L2_CID_EXPOSURE, 1510 | IMX283_EXPOSURE_MIN, 1511 | IMX283_EXPOSURE_MAX, 1512 | IMX283_EXPOSURE_STEP, 1513 | IMX283_EXPOSURE_DEFAULT); 1514 | 1515 | v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, 1516 | IMX283_ANA_GAIN_MIN, IMX283_ANA_GAIN_MAX, 1517 | IMX283_ANA_GAIN_STEP, IMX283_ANA_GAIN_DEFAULT); 1518 | 1519 | v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, V4L2_CID_DIGITAL_GAIN, 1520 | IMX283_DGTL_GAIN_MIN, IMX283_DGTL_GAIN_MAX, 1521 | IMX283_DGTL_GAIN_STEP, IMX283_DGTL_GAIN_DEFAULT); 1522 | 1523 | imx283->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1524 | V4L2_CID_HFLIP, 0, 1, 1, 0); 1525 | if (imx283->hflip) 1526 | imx283->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 1527 | 1528 | imx283->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, 1529 | V4L2_CID_VFLIP, 0, 1, 1, 0); 1530 | if (imx283->vflip) 1531 | imx283->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 1532 | 1533 | v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx283_ctrl_ops, 1534 | V4L2_CID_TEST_PATTERN, 1535 | ARRAY_SIZE(imx283_tpg_menu) - 1, 1536 | 0, 0, imx283_tpg_menu); 1537 | 1538 | if (ctrl_hdlr->error) { 1539 | ret = ctrl_hdlr->error; 1540 | dev_err(&client->dev, "%s control init failed (%d)\n", 1541 | __func__, ret); 1542 | goto error; 1543 | } 1544 | 1545 | ret = v4l2_fwnode_device_parse(&client->dev, &props); 1546 | if (ret) 1547 | goto error; 1548 | 1549 | ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx283_ctrl_ops, 1550 | &props); 1551 | if (ret) 1552 | goto error; 1553 | 1554 | imx283->sd.ctrl_handler = ctrl_hdlr; 1555 | 1556 | /* Setup exposure and frame/line length limits. */ 1557 | imx283_set_framing_limits(imx283); 1558 | 1559 | return 0; 1560 | 1561 | error: 1562 | v4l2_ctrl_handler_free(ctrl_hdlr); 1563 | mutex_destroy(&imx283->mutex); 1564 | 1565 | return ret; 1566 | } 1567 | 1568 | static void imx283_free_controls(struct imx283 *imx283) 1569 | { 1570 | v4l2_ctrl_handler_free(imx283->sd.ctrl_handler); 1571 | mutex_destroy(&imx283->mutex); 1572 | } 1573 | 1574 | static const struct of_device_id imx283_dt_ids[] = { 1575 | { .compatible = "sony,imx283", }, 1576 | { /* sentinel */ } 1577 | }; 1578 | 1579 | static int imx283_parse_endpoint(struct imx283 *imx283) 1580 | { 1581 | struct fwnode_handle *fwnode = dev_fwnode(imx283->dev); 1582 | struct v4l2_fwnode_endpoint bus_cfg = { 1583 | .bus_type = V4L2_MBUS_CSI2_DPHY 1584 | }; 1585 | struct fwnode_handle *ep; 1586 | int ret; 1587 | int i, j; 1588 | 1589 | if (!fwnode) 1590 | return -ENXIO; 1591 | 1592 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); 1593 | if (!ep) { 1594 | dev_err(imx283->dev, "Failed to get next endpoint\n"); 1595 | return -ENXIO; 1596 | } 1597 | 1598 | ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); 1599 | fwnode_handle_put(ep); 1600 | if (ret) 1601 | return ret; 1602 | 1603 | if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { 1604 | dev_err(imx283->dev, 1605 | "number of CSI2 data lanes %d is not supported\n", 1606 | bus_cfg.bus.mipi_csi2.num_data_lanes); 1607 | ret = -EINVAL; 1608 | goto done_endpoint_free; 1609 | } 1610 | 1611 | if (!bus_cfg.nr_of_link_frequencies) { 1612 | dev_err(imx283->dev, "no link frequencies defined\n"); 1613 | ret = -EINVAL; 1614 | goto done_endpoint_free; 1615 | } 1616 | 1617 | for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { 1618 | for (j = 0; j < ARRAY_SIZE(link_frequencies); j++) { 1619 | if (bus_cfg.link_frequencies[i] == link_frequencies[j]) { 1620 | imx283->link_freq_idx = j; 1621 | break; 1622 | } 1623 | } 1624 | 1625 | if (j == ARRAY_SIZE(link_frequencies)) { 1626 | ret = dev_err_probe(imx283->dev, -EINVAL, 1627 | "no supported link freq found\n"); 1628 | goto done_endpoint_free; 1629 | } 1630 | } 1631 | 1632 | done_endpoint_free: 1633 | v4l2_fwnode_endpoint_free(&bus_cfg); 1634 | 1635 | return ret; 1636 | }; 1637 | 1638 | static int imx283_probe(struct i2c_client *client) 1639 | { 1640 | struct imx283 *imx283; 1641 | int ret; 1642 | unsigned int i; 1643 | unsigned int xclk_freq; 1644 | 1645 | imx283 = devm_kzalloc(&client->dev, sizeof(*imx283), GFP_KERNEL); 1646 | if (!imx283) 1647 | return -ENOMEM; 1648 | 1649 | imx283->dev = &client->dev; 1650 | 1651 | struct device *dev = &client->dev; 1652 | 1653 | v4l2_i2c_subdev_init(&imx283->sd, client, &imx283_subdev_ops); 1654 | 1655 | /* 1656 | imx283 = devm_cci_regmap_init_i2c(client, 16); 1657 | if (IS_ERR(imx283)) { 1658 | ret = PTR_ERR(imx283); 1659 | dev_err(imx283->dev, "failed to initialize CCI: %d\n", ret); 1660 | return ret; 1661 | } 1662 | */ 1663 | 1664 | /* Get system clock (xclk) */ 1665 | imx283->xclk = devm_clk_get(imx283->dev, NULL); 1666 | if (IS_ERR(imx283->xclk)) { 1667 | dev_err(imx283->dev, "failed to get xclk\n"); 1668 | return PTR_ERR(imx283->xclk); 1669 | } 1670 | 1671 | xclk_freq = clk_get_rate(imx283->xclk); 1672 | for (i = 0; i < ARRAY_SIZE(imx283_frequencies); i++) { 1673 | if (xclk_freq == imx283_frequencies[i].mhz) { 1674 | imx283->freq = &imx283_frequencies[i]; 1675 | break; 1676 | } 1677 | } 1678 | if (!imx283->freq) { 1679 | dev_err(imx283->dev, "xclk frequency unsupported: %d Hz\n", xclk_freq); 1680 | return -EINVAL; 1681 | } 1682 | 1683 | ret = imx283_get_regulators(imx283); 1684 | if (ret) { 1685 | dev_err(imx283->dev, "failed to get regulators\n"); 1686 | return ret; 1687 | } 1688 | 1689 | ret = imx283_parse_endpoint(imx283); 1690 | if (ret) { 1691 | dev_err(imx283->dev, "failed to parse endpoint configuration\n"); 1692 | return ret; 1693 | } 1694 | 1695 | /* Request optional enable pin */ 1696 | imx283->reset_gpio = devm_gpiod_get_optional(dev, "reset", 1697 | GPIOD_OUT_HIGH); 1698 | 1699 | /* 1700 | * The sensor must be powered for imx283_identify_module() 1701 | * to be able to read the CHIP_ID register 1702 | */ 1703 | ret = imx283_power_on(dev); 1704 | if (ret) 1705 | return ret; 1706 | 1707 | ret = imx283_identify_module(imx283); 1708 | if (ret) 1709 | goto error_power_off; 1710 | 1711 | /* Initialize default format */ 1712 | imx283_set_default_format(imx283); 1713 | 1714 | /* Enable runtime PM and turn off the device */ 1715 | pm_runtime_set_active(dev); 1716 | pm_runtime_enable(dev); 1717 | pm_runtime_idle(dev); 1718 | 1719 | /* This needs the pm runtime to be registered. */ 1720 | ret = imx283_init_controls(imx283); 1721 | if (ret) 1722 | goto error_pm; 1723 | 1724 | /* Initialize subdev */ 1725 | imx283->sd.internal_ops = &imx283_internal_ops; 1726 | imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | 1727 | V4L2_SUBDEV_FL_HAS_EVENTS; 1728 | imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 1729 | 1730 | /* Initialize source pads */ 1731 | imx283->pad.flags = MEDIA_PAD_FL_SOURCE; 1732 | 1733 | ret = media_entity_pads_init(&imx283->sd.entity, 1, &imx283->pad); 1734 | if (ret) { 1735 | dev_err(imx283->dev, "failed to init entity pads: %d\n", ret); 1736 | goto error_handler_free; 1737 | } 1738 | 1739 | ret = v4l2_async_register_subdev_sensor(&imx283->sd); 1740 | if (ret < 0) { 1741 | dev_err(imx283->dev, "failed to register sensor sub-device: %d\n", ret); 1742 | goto error_media_entity; 1743 | } 1744 | 1745 | return 0; 1746 | 1747 | error_media_entity: 1748 | media_entity_cleanup(&imx283->sd.entity); 1749 | 1750 | error_handler_free: 1751 | imx283_free_controls(imx283); 1752 | 1753 | error_pm: 1754 | pm_runtime_disable(imx283->dev); 1755 | pm_runtime_set_suspended(imx283->dev); 1756 | error_power_off: 1757 | imx283_power_off(imx283->dev); 1758 | 1759 | return ret; 1760 | } 1761 | 1762 | static void imx283_remove(struct i2c_client *client) 1763 | { 1764 | struct v4l2_subdev *sd = i2c_get_clientdata(client); 1765 | struct imx283 *imx283 = to_imx283(sd); 1766 | 1767 | v4l2_async_unregister_subdev(sd); 1768 | media_entity_cleanup(&sd->entity); 1769 | imx283_free_controls(imx283); 1770 | 1771 | pm_runtime_disable(imx283->dev); 1772 | if (!pm_runtime_status_suspended(imx283->dev)) 1773 | imx283_power_off(imx283->dev); 1774 | pm_runtime_set_suspended(imx283->dev); 1775 | 1776 | } 1777 | 1778 | MODULE_DEVICE_TABLE(of, imx283_dt_ids); 1779 | 1780 | static const struct dev_pm_ops imx283_pm_ops = { 1781 | SET_SYSTEM_SLEEP_PM_OPS(imx283_suspend, imx283_resume) 1782 | SET_RUNTIME_PM_OPS(imx283_power_off, imx283_power_on, NULL) 1783 | }; 1784 | 1785 | static struct i2c_driver imx283_i2c_driver = { 1786 | .driver = { 1787 | .name = "imx283", 1788 | .of_match_table = imx283_dt_ids, 1789 | .pm = &imx283_pm_ops, 1790 | }, 1791 | .probe = imx283_probe, 1792 | .remove = imx283_remove, 1793 | }; 1794 | 1795 | module_i2c_driver(imx283_i2c_driver); 1796 | 1797 | MODULE_DESCRIPTION("Sony IMX283 Sensor Driver"); 1798 | MODULE_LICENSE("GPL v2"); 1799 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | DRV_VERSION=0.0.1 4 | 5 | DRV_IMX=imx283 6 | 7 | echo "Uninstalling any previous ${DRV_IMX} module" 8 | #dkms status ${DRV_IMX} | awk -F', ' '{print $2}' | xargs -n1 sudo dkms remove -m ${DRV_IMX} -v 9 | sudo dkms remove -m ${DRV_IMX} -v ${DRV_VERSION} --all 10 | 11 | sudo mkdir -p /usr/src/${DRV_IMX}-${DRV_VERSION} 12 | 13 | sudo cp -r $(pwd)/* /usr/src/${DRV_IMX}-${DRV_VERSION} 14 | 15 | sudo dkms add -m ${DRV_IMX} -v ${DRV_VERSION} 16 | sudo dkms build -m ${DRV_IMX} -v ${DRV_VERSION} 17 | sudo dkms install -m ${DRV_IMX} -v ${DRV_VERSION} 18 | --------------------------------------------------------------------------------