1 /* 2 * ov772x Camera Driver 3 * 4 * Copyright (C) 2008 Renesas Solutions Corp. 5 * Kuninori Morimoto <morimoto.kuninori@renesas.com> 6 * 7 * Based on ov7670 and soc_camera_platform driver, 8 * 9 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> 10 * Copyright (C) 2008 Magnus Damm 11 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 */ 17 18 #include <linux/init.h> 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/i2c.h> 22 #include <linux/slab.h> 23 #include <linux/delay.h> 24 #include <linux/v4l2-mediabus.h> 25 #include <linux/videodev2.h> 26 27 #include <media/i2c/ov772x.h> 28 #include <media/soc_camera.h> 29 #include <media/v4l2-clk.h> 30 #include <media/v4l2-ctrls.h> 31 #include <media/v4l2-subdev.h> 32 #include <media/v4l2-image-sizes.h> 33 34 /* 35 * register offset 36 */ 37 #define GAIN 0x00 /* AGC - Gain control gain setting */ 38 #define BLUE 0x01 /* AWB - Blue channel gain setting */ 39 #define RED 0x02 /* AWB - Red channel gain setting */ 40 #define GREEN 0x03 /* AWB - Green channel gain setting */ 41 #define COM1 0x04 /* Common control 1 */ 42 #define BAVG 0x05 /* U/B Average Level */ 43 #define GAVG 0x06 /* Y/Gb Average Level */ 44 #define RAVG 0x07 /* V/R Average Level */ 45 #define AECH 0x08 /* Exposure Value - AEC MSBs */ 46 #define COM2 0x09 /* Common control 2 */ 47 #define PID 0x0A /* Product ID Number MSB */ 48 #define VER 0x0B /* Product ID Number LSB */ 49 #define COM3 0x0C /* Common control 3 */ 50 #define COM4 0x0D /* Common control 4 */ 51 #define COM5 0x0E /* Common control 5 */ 52 #define COM6 0x0F /* Common control 6 */ 53 #define AEC 0x10 /* Exposure Value */ 54 #define CLKRC 0x11 /* Internal clock */ 55 #define COM7 0x12 /* Common control 7 */ 56 #define COM8 0x13 /* Common control 8 */ 57 #define COM9 0x14 /* Common control 9 */ 58 #define COM10 0x15 /* Common control 10 */ 59 #define REG16 0x16 /* Register 16 */ 60 #define HSTART 0x17 /* Horizontal sensor size */ 61 #define HSIZE 0x18 /* Horizontal frame (HREF column) end high 8-bit */ 62 #define VSTART 0x19 /* Vertical frame (row) start high 8-bit */ 63 #define VSIZE 0x1A /* Vertical sensor size */ 64 #define PSHFT 0x1B /* Data format - pixel delay select */ 65 #define MIDH 0x1C /* Manufacturer ID byte - high */ 66 #define MIDL 0x1D /* Manufacturer ID byte - low */ 67 #define LAEC 0x1F /* Fine AEC value */ 68 #define COM11 0x20 /* Common control 11 */ 69 #define BDBASE 0x22 /* Banding filter Minimum AEC value */ 70 #define DBSTEP 0x23 /* Banding filter Maximum Setp */ 71 #define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */ 72 #define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */ 73 #define VPT 0x26 /* AGC/AEC Fast mode operating region */ 74 #define REG28 0x28 /* Register 28 */ 75 #define HOUTSIZE 0x29 /* Horizontal data output size MSBs */ 76 #define EXHCH 0x2A /* Dummy pixel insert MSB */ 77 #define EXHCL 0x2B /* Dummy pixel insert LSB */ 78 #define VOUTSIZE 0x2C /* Vertical data output size MSBs */ 79 #define ADVFL 0x2D /* LSB of insert dummy lines in Vertical direction */ 80 #define ADVFH 0x2E /* MSG of insert dummy lines in Vertical direction */ 81 #define YAVE 0x2F /* Y/G Channel Average value */ 82 #define LUMHTH 0x30 /* Histogram AEC/AGC Luminance high level threshold */ 83 #define LUMLTH 0x31 /* Histogram AEC/AGC Luminance low level threshold */ 84 #define HREF 0x32 /* Image start and size control */ 85 #define DM_LNL 0x33 /* Dummy line low 8 bits */ 86 #define DM_LNH 0x34 /* Dummy line high 8 bits */ 87 #define ADOFF_B 0x35 /* AD offset compensation value for B channel */ 88 #define ADOFF_R 0x36 /* AD offset compensation value for R channel */ 89 #define ADOFF_GB 0x37 /* AD offset compensation value for Gb channel */ 90 #define ADOFF_GR 0x38 /* AD offset compensation value for Gr channel */ 91 #define OFF_B 0x39 /* Analog process B channel offset value */ 92 #define OFF_R 0x3A /* Analog process R channel offset value */ 93 #define OFF_GB 0x3B /* Analog process Gb channel offset value */ 94 #define OFF_GR 0x3C /* Analog process Gr channel offset value */ 95 #define COM12 0x3D /* Common control 12 */ 96 #define COM13 0x3E /* Common control 13 */ 97 #define COM14 0x3F /* Common control 14 */ 98 #define COM15 0x40 /* Common control 15*/ 99 #define COM16 0x41 /* Common control 16 */ 100 #define TGT_B 0x42 /* BLC blue channel target value */ 101 #define TGT_R 0x43 /* BLC red channel target value */ 102 #define TGT_GB 0x44 /* BLC Gb channel target value */ 103 #define TGT_GR 0x45 /* BLC Gr channel target value */ 104 /* for ov7720 */ 105 #define LCC0 0x46 /* Lens correction control 0 */ 106 #define LCC1 0x47 /* Lens correction option 1 - X coordinate */ 107 #define LCC2 0x48 /* Lens correction option 2 - Y coordinate */ 108 #define LCC3 0x49 /* Lens correction option 3 */ 109 #define LCC4 0x4A /* Lens correction option 4 - radius of the circular */ 110 #define LCC5 0x4B /* Lens correction option 5 */ 111 #define LCC6 0x4C /* Lens correction option 6 */ 112 /* for ov7725 */ 113 #define LC_CTR 0x46 /* Lens correction control */ 114 #define LC_XC 0x47 /* X coordinate of lens correction center relative */ 115 #define LC_YC 0x48 /* Y coordinate of lens correction center relative */ 116 #define LC_COEF 0x49 /* Lens correction coefficient */ 117 #define LC_RADI 0x4A /* Lens correction radius */ 118 #define LC_COEFB 0x4B /* Lens B channel compensation coefficient */ 119 #define LC_COEFR 0x4C /* Lens R channel compensation coefficient */ 120 121 #define FIXGAIN 0x4D /* Analog fix gain amplifer */ 122 #define AREF0 0x4E /* Sensor reference control */ 123 #define AREF1 0x4F /* Sensor reference current control */ 124 #define AREF2 0x50 /* Analog reference control */ 125 #define AREF3 0x51 /* ADC reference control */ 126 #define AREF4 0x52 /* ADC reference control */ 127 #define AREF5 0x53 /* ADC reference control */ 128 #define AREF6 0x54 /* Analog reference control */ 129 #define AREF7 0x55 /* Analog reference control */ 130 #define UFIX 0x60 /* U channel fixed value output */ 131 #define VFIX 0x61 /* V channel fixed value output */ 132 #define AWBB_BLK 0x62 /* AWB option for advanced AWB */ 133 #define AWB_CTRL0 0x63 /* AWB control byte 0 */ 134 #define DSP_CTRL1 0x64 /* DSP control byte 1 */ 135 #define DSP_CTRL2 0x65 /* DSP control byte 2 */ 136 #define DSP_CTRL3 0x66 /* DSP control byte 3 */ 137 #define DSP_CTRL4 0x67 /* DSP control byte 4 */ 138 #define AWB_BIAS 0x68 /* AWB BLC level clip */ 139 #define AWB_CTRL1 0x69 /* AWB control 1 */ 140 #define AWB_CTRL2 0x6A /* AWB control 2 */ 141 #define AWB_CTRL3 0x6B /* AWB control 3 */ 142 #define AWB_CTRL4 0x6C /* AWB control 4 */ 143 #define AWB_CTRL5 0x6D /* AWB control 5 */ 144 #define AWB_CTRL6 0x6E /* AWB control 6 */ 145 #define AWB_CTRL7 0x6F /* AWB control 7 */ 146 #define AWB_CTRL8 0x70 /* AWB control 8 */ 147 #define AWB_CTRL9 0x71 /* AWB control 9 */ 148 #define AWB_CTRL10 0x72 /* AWB control 10 */ 149 #define AWB_CTRL11 0x73 /* AWB control 11 */ 150 #define AWB_CTRL12 0x74 /* AWB control 12 */ 151 #define AWB_CTRL13 0x75 /* AWB control 13 */ 152 #define AWB_CTRL14 0x76 /* AWB control 14 */ 153 #define AWB_CTRL15 0x77 /* AWB control 15 */ 154 #define AWB_CTRL16 0x78 /* AWB control 16 */ 155 #define AWB_CTRL17 0x79 /* AWB control 17 */ 156 #define AWB_CTRL18 0x7A /* AWB control 18 */ 157 #define AWB_CTRL19 0x7B /* AWB control 19 */ 158 #define AWB_CTRL20 0x7C /* AWB control 20 */ 159 #define AWB_CTRL21 0x7D /* AWB control 21 */ 160 #define GAM1 0x7E /* Gamma Curve 1st segment input end point */ 161 #define GAM2 0x7F /* Gamma Curve 2nd segment input end point */ 162 #define GAM3 0x80 /* Gamma Curve 3rd segment input end point */ 163 #define GAM4 0x81 /* Gamma Curve 4th segment input end point */ 164 #define GAM5 0x82 /* Gamma Curve 5th segment input end point */ 165 #define GAM6 0x83 /* Gamma Curve 6th segment input end point */ 166 #define GAM7 0x84 /* Gamma Curve 7th segment input end point */ 167 #define GAM8 0x85 /* Gamma Curve 8th segment input end point */ 168 #define GAM9 0x86 /* Gamma Curve 9th segment input end point */ 169 #define GAM10 0x87 /* Gamma Curve 10th segment input end point */ 170 #define GAM11 0x88 /* Gamma Curve 11th segment input end point */ 171 #define GAM12 0x89 /* Gamma Curve 12th segment input end point */ 172 #define GAM13 0x8A /* Gamma Curve 13th segment input end point */ 173 #define GAM14 0x8B /* Gamma Curve 14th segment input end point */ 174 #define GAM15 0x8C /* Gamma Curve 15th segment input end point */ 175 #define SLOP 0x8D /* Gamma curve highest segment slope */ 176 #define DNSTH 0x8E /* De-noise threshold */ 177 #define EDGE_STRNGT 0x8F /* Edge strength control when manual mode */ 178 #define EDGE_TRSHLD 0x90 /* Edge threshold control when manual mode */ 179 #define DNSOFF 0x91 /* Auto De-noise threshold control */ 180 #define EDGE_UPPER 0x92 /* Edge strength upper limit when Auto mode */ 181 #define EDGE_LOWER 0x93 /* Edge strength lower limit when Auto mode */ 182 #define MTX1 0x94 /* Matrix coefficient 1 */ 183 #define MTX2 0x95 /* Matrix coefficient 2 */ 184 #define MTX3 0x96 /* Matrix coefficient 3 */ 185 #define MTX4 0x97 /* Matrix coefficient 4 */ 186 #define MTX5 0x98 /* Matrix coefficient 5 */ 187 #define MTX6 0x99 /* Matrix coefficient 6 */ 188 #define MTX_CTRL 0x9A /* Matrix control */ 189 #define BRIGHT 0x9B /* Brightness control */ 190 #define CNTRST 0x9C /* Contrast contrast */ 191 #define CNTRST_CTRL 0x9D /* Contrast contrast center */ 192 #define UVAD_J0 0x9E /* Auto UV adjust contrast 0 */ 193 #define UVAD_J1 0x9F /* Auto UV adjust contrast 1 */ 194 #define SCAL0 0xA0 /* Scaling control 0 */ 195 #define SCAL1 0xA1 /* Scaling control 1 */ 196 #define SCAL2 0xA2 /* Scaling control 2 */ 197 #define FIFODLYM 0xA3 /* FIFO manual mode delay control */ 198 #define FIFODLYA 0xA4 /* FIFO auto mode delay control */ 199 #define SDE 0xA6 /* Special digital effect control */ 200 #define USAT 0xA7 /* U component saturation control */ 201 #define VSAT 0xA8 /* V component saturation control */ 202 /* for ov7720 */ 203 #define HUE0 0xA9 /* Hue control 0 */ 204 #define HUE1 0xAA /* Hue control 1 */ 205 /* for ov7725 */ 206 #define HUECOS 0xA9 /* Cosine value */ 207 #define HUESIN 0xAA /* Sine value */ 208 209 #define SIGN 0xAB /* Sign bit for Hue and contrast */ 210 #define DSPAUTO 0xAC /* DSP auto function ON/OFF control */ 211 212 /* 213 * register detail 214 */ 215 216 /* COM2 */ 217 #define SOFT_SLEEP_MODE 0x10 /* Soft sleep mode */ 218 /* Output drive capability */ 219 #define OCAP_1x 0x00 /* 1x */ 220 #define OCAP_2x 0x01 /* 2x */ 221 #define OCAP_3x 0x02 /* 3x */ 222 #define OCAP_4x 0x03 /* 4x */ 223 224 /* COM3 */ 225 #define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML) 226 #define IMG_MASK (VFLIP_IMG | HFLIP_IMG) 227 228 #define VFLIP_IMG 0x80 /* Vertical flip image ON/OFF selection */ 229 #define HFLIP_IMG 0x40 /* Horizontal mirror image ON/OFF selection */ 230 #define SWAP_RGB 0x20 /* Swap B/R output sequence in RGB mode */ 231 #define SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV mode */ 232 #define SWAP_ML 0x08 /* Swap output MSB/LSB */ 233 /* Tri-state option for output clock */ 234 #define NOTRI_CLOCK 0x04 /* 0: Tri-state at this period */ 235 /* 1: No tri-state at this period */ 236 /* Tri-state option for output data */ 237 #define NOTRI_DATA 0x02 /* 0: Tri-state at this period */ 238 /* 1: No tri-state at this period */ 239 #define SCOLOR_TEST 0x01 /* Sensor color bar test pattern */ 240 241 /* COM4 */ 242 /* PLL frequency control */ 243 #define PLL_BYPASS 0x00 /* 00: Bypass PLL */ 244 #define PLL_4x 0x40 /* 01: PLL 4x */ 245 #define PLL_6x 0x80 /* 10: PLL 6x */ 246 #define PLL_8x 0xc0 /* 11: PLL 8x */ 247 /* AEC evaluate window */ 248 #define AEC_FULL 0x00 /* 00: Full window */ 249 #define AEC_1p2 0x10 /* 01: 1/2 window */ 250 #define AEC_1p4 0x20 /* 10: 1/4 window */ 251 #define AEC_2p3 0x30 /* 11: Low 2/3 window */ 252 253 /* COM5 */ 254 #define AFR_ON_OFF 0x80 /* Auto frame rate control ON/OFF selection */ 255 #define AFR_SPPED 0x40 /* Auto frame rate control speed selection */ 256 /* Auto frame rate max rate control */ 257 #define AFR_NO_RATE 0x00 /* No reduction of frame rate */ 258 #define AFR_1p2 0x10 /* Max reduction to 1/2 frame rate */ 259 #define AFR_1p4 0x20 /* Max reduction to 1/4 frame rate */ 260 #define AFR_1p8 0x30 /* Max reduction to 1/8 frame rate */ 261 /* Auto frame rate active point control */ 262 #define AF_2x 0x00 /* Add frame when AGC reaches 2x gain */ 263 #define AF_4x 0x04 /* Add frame when AGC reaches 4x gain */ 264 #define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */ 265 #define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */ 266 /* AEC max step control */ 267 #define AEC_NO_LIMIT 0x01 /* 0 : AEC incease step has limit */ 268 /* 1 : No limit to AEC increase step */ 269 270 /* COM7 */ 271 /* SCCB Register Reset */ 272 #define SCCB_RESET 0x80 /* 0 : No change */ 273 /* 1 : Resets all registers to default */ 274 /* Resolution selection */ 275 #define SLCT_MASK 0x40 /* Mask of VGA or QVGA */ 276 #define SLCT_VGA 0x00 /* 0 : VGA */ 277 #define SLCT_QVGA 0x40 /* 1 : QVGA */ 278 #define ITU656_ON_OFF 0x20 /* ITU656 protocol ON/OFF selection */ 279 #define SENSOR_RAW 0x10 /* Sensor RAW */ 280 /* RGB output format control */ 281 #define FMT_MASK 0x0c /* Mask of color format */ 282 #define FMT_GBR422 0x00 /* 00 : GBR 4:2:2 */ 283 #define FMT_RGB565 0x04 /* 01 : RGB 565 */ 284 #define FMT_RGB555 0x08 /* 10 : RGB 555 */ 285 #define FMT_RGB444 0x0c /* 11 : RGB 444 */ 286 /* Output format control */ 287 #define OFMT_MASK 0x03 /* Mask of output format */ 288 #define OFMT_YUV 0x00 /* 00 : YUV */ 289 #define OFMT_P_BRAW 0x01 /* 01 : Processed Bayer RAW */ 290 #define OFMT_RGB 0x02 /* 10 : RGB */ 291 #define OFMT_BRAW 0x03 /* 11 : Bayer RAW */ 292 293 /* COM8 */ 294 #define FAST_ALGO 0x80 /* Enable fast AGC/AEC algorithm */ 295 /* AEC Setp size limit */ 296 #define UNLMT_STEP 0x40 /* 0 : Step size is limited */ 297 /* 1 : Unlimited step size */ 298 #define BNDF_ON_OFF 0x20 /* Banding filter ON/OFF */ 299 #define AEC_BND 0x10 /* Enable AEC below banding value */ 300 #define AEC_ON_OFF 0x08 /* Fine AEC ON/OFF control */ 301 #define AGC_ON 0x04 /* AGC Enable */ 302 #define AWB_ON 0x02 /* AWB Enable */ 303 #define AEC_ON 0x01 /* AEC Enable */ 304 305 /* COM9 */ 306 #define BASE_AECAGC 0x80 /* Histogram or average based AEC/AGC */ 307 /* Automatic gain ceiling - maximum AGC value */ 308 #define GAIN_2x 0x00 /* 000 : 2x */ 309 #define GAIN_4x 0x10 /* 001 : 4x */ 310 #define GAIN_8x 0x20 /* 010 : 8x */ 311 #define GAIN_16x 0x30 /* 011 : 16x */ 312 #define GAIN_32x 0x40 /* 100 : 32x */ 313 #define GAIN_64x 0x50 /* 101 : 64x */ 314 #define GAIN_128x 0x60 /* 110 : 128x */ 315 #define DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ 316 #define DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ 317 318 /* COM11 */ 319 #define SGLF_ON_OFF 0x02 /* Single frame ON/OFF selection */ 320 #define SGLF_TRIG 0x01 /* Single frame transfer trigger */ 321 322 /* HREF */ 323 #define HREF_VSTART_SHIFT 6 /* VSTART LSB */ 324 #define HREF_HSTART_SHIFT 4 /* HSTART 2 LSBs */ 325 #define HREF_VSIZE_SHIFT 2 /* VSIZE LSB */ 326 #define HREF_HSIZE_SHIFT 0 /* HSIZE 2 LSBs */ 327 328 /* EXHCH */ 329 #define EXHCH_VSIZE_SHIFT 2 /* VOUTSIZE LSB */ 330 #define EXHCH_HSIZE_SHIFT 0 /* HOUTSIZE 2 LSBs */ 331 332 /* DSP_CTRL1 */ 333 #define FIFO_ON 0x80 /* FIFO enable/disable selection */ 334 #define UV_ON_OFF 0x40 /* UV adjust function ON/OFF selection */ 335 #define YUV444_2_422 0x20 /* YUV444 to 422 UV channel option selection */ 336 #define CLR_MTRX_ON_OFF 0x10 /* Color matrix ON/OFF selection */ 337 #define INTPLT_ON_OFF 0x08 /* Interpolation ON/OFF selection */ 338 #define GMM_ON_OFF 0x04 /* Gamma function ON/OFF selection */ 339 #define AUTO_BLK_ON_OFF 0x02 /* Black defect auto correction ON/OFF */ 340 #define AUTO_WHT_ON_OFF 0x01 /* White define auto correction ON/OFF */ 341 342 /* DSP_CTRL3 */ 343 #define UV_MASK 0x80 /* UV output sequence option */ 344 #define UV_ON 0x80 /* ON */ 345 #define UV_OFF 0x00 /* OFF */ 346 #define CBAR_MASK 0x20 /* DSP Color bar mask */ 347 #define CBAR_ON 0x20 /* ON */ 348 #define CBAR_OFF 0x00 /* OFF */ 349 350 /* DSP_CTRL4 */ 351 #define DSP_OFMT_YUV 0x00 352 #define DSP_OFMT_RGB 0x00 353 #define DSP_OFMT_RAW8 0x02 354 #define DSP_OFMT_RAW10 0x03 355 356 /* DSPAUTO (DSP Auto Function ON/OFF Control) */ 357 #define AWB_ACTRL 0x80 /* AWB auto threshold control */ 358 #define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */ 359 #define EDGE_ACTRL 0x20 /* Edge enhancement auto strength control */ 360 #define UV_ACTRL 0x10 /* UV adjust auto slope control */ 361 #define SCAL0_ACTRL 0x08 /* Auto scaling factor control */ 362 #define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */ 363 364 #define OV772X_MAX_WIDTH VGA_WIDTH 365 #define OV772X_MAX_HEIGHT VGA_HEIGHT 366 367 /* 368 * ID 369 */ 370 #define OV7720 0x7720 371 #define OV7725 0x7721 372 #define VERSION(pid, ver) ((pid<<8)|(ver&0xFF)) 373 374 /* 375 * struct 376 */ 377 378 struct ov772x_color_format { 379 u32 code; 380 enum v4l2_colorspace colorspace; 381 u8 dsp3; 382 u8 dsp4; 383 u8 com3; 384 u8 com7; 385 }; 386 387 struct ov772x_win_size { 388 char *name; 389 unsigned char com7_bit; 390 struct v4l2_rect rect; 391 }; 392 393 struct ov772x_priv { 394 struct v4l2_subdev subdev; 395 struct v4l2_ctrl_handler hdl; 396 struct v4l2_clk *clk; 397 struct ov772x_camera_info *info; 398 const struct ov772x_color_format *cfmt; 399 const struct ov772x_win_size *win; 400 unsigned short flag_vflip:1; 401 unsigned short flag_hflip:1; 402 /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ 403 unsigned short band_filter; 404 }; 405 406 /* 407 * supported color format list 408 */ 409 static const struct ov772x_color_format ov772x_cfmts[] = { 410 { 411 .code = MEDIA_BUS_FMT_YUYV8_2X8, 412 .colorspace = V4L2_COLORSPACE_JPEG, 413 .dsp3 = 0x0, 414 .dsp4 = DSP_OFMT_YUV, 415 .com3 = SWAP_YUV, 416 .com7 = OFMT_YUV, 417 }, 418 { 419 .code = MEDIA_BUS_FMT_YVYU8_2X8, 420 .colorspace = V4L2_COLORSPACE_JPEG, 421 .dsp3 = UV_ON, 422 .dsp4 = DSP_OFMT_YUV, 423 .com3 = SWAP_YUV, 424 .com7 = OFMT_YUV, 425 }, 426 { 427 .code = MEDIA_BUS_FMT_UYVY8_2X8, 428 .colorspace = V4L2_COLORSPACE_JPEG, 429 .dsp3 = 0x0, 430 .dsp4 = DSP_OFMT_YUV, 431 .com3 = 0x0, 432 .com7 = OFMT_YUV, 433 }, 434 { 435 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, 436 .colorspace = V4L2_COLORSPACE_SRGB, 437 .dsp3 = 0x0, 438 .dsp4 = DSP_OFMT_YUV, 439 .com3 = SWAP_RGB, 440 .com7 = FMT_RGB555 | OFMT_RGB, 441 }, 442 { 443 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, 444 .colorspace = V4L2_COLORSPACE_SRGB, 445 .dsp3 = 0x0, 446 .dsp4 = DSP_OFMT_YUV, 447 .com3 = 0x0, 448 .com7 = FMT_RGB555 | OFMT_RGB, 449 }, 450 { 451 .code = MEDIA_BUS_FMT_RGB565_2X8_LE, 452 .colorspace = V4L2_COLORSPACE_SRGB, 453 .dsp3 = 0x0, 454 .dsp4 = DSP_OFMT_YUV, 455 .com3 = SWAP_RGB, 456 .com7 = FMT_RGB565 | OFMT_RGB, 457 }, 458 { 459 .code = MEDIA_BUS_FMT_RGB565_2X8_BE, 460 .colorspace = V4L2_COLORSPACE_SRGB, 461 .dsp3 = 0x0, 462 .dsp4 = DSP_OFMT_YUV, 463 .com3 = 0x0, 464 .com7 = FMT_RGB565 | OFMT_RGB, 465 }, 466 { 467 /* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output, 468 * regardless of the COM7 value. We can thus only support 10-bit 469 * Bayer until someone figures it out. 470 */ 471 .code = MEDIA_BUS_FMT_SBGGR10_1X10, 472 .colorspace = V4L2_COLORSPACE_SRGB, 473 .dsp3 = 0x0, 474 .dsp4 = DSP_OFMT_RAW10, 475 .com3 = 0x0, 476 .com7 = SENSOR_RAW | OFMT_BRAW, 477 }, 478 }; 479 480 481 /* 482 * window size list 483 */ 484 485 static const struct ov772x_win_size ov772x_win_sizes[] = { 486 { 487 .name = "VGA", 488 .com7_bit = SLCT_VGA, 489 .rect = { 490 .left = 140, 491 .top = 14, 492 .width = VGA_WIDTH, 493 .height = VGA_HEIGHT, 494 }, 495 }, { 496 .name = "QVGA", 497 .com7_bit = SLCT_QVGA, 498 .rect = { 499 .left = 252, 500 .top = 6, 501 .width = QVGA_WIDTH, 502 .height = QVGA_HEIGHT, 503 }, 504 }, 505 }; 506 507 /* 508 * general function 509 */ 510 511 static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd) 512 { 513 return container_of(sd, struct ov772x_priv, subdev); 514 } 515 516 static inline int ov772x_read(struct i2c_client *client, u8 addr) 517 { 518 return i2c_smbus_read_byte_data(client, addr); 519 } 520 521 static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value) 522 { 523 return i2c_smbus_write_byte_data(client, addr, value); 524 } 525 526 static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask, 527 u8 set) 528 { 529 s32 val = ov772x_read(client, command); 530 if (val < 0) 531 return val; 532 533 val &= ~mask; 534 val |= set & mask; 535 536 return ov772x_write(client, command, val); 537 } 538 539 static int ov772x_reset(struct i2c_client *client) 540 { 541 int ret; 542 543 ret = ov772x_write(client, COM7, SCCB_RESET); 544 if (ret < 0) 545 return ret; 546 547 msleep(1); 548 549 return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); 550 } 551 552 /* 553 * soc_camera_ops function 554 */ 555 556 static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) 557 { 558 struct i2c_client *client = v4l2_get_subdevdata(sd); 559 struct ov772x_priv *priv = to_ov772x(sd); 560 561 if (!enable) { 562 ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); 563 return 0; 564 } 565 566 ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); 567 568 dev_dbg(&client->dev, "format %d, win %s\n", 569 priv->cfmt->code, priv->win->name); 570 571 return 0; 572 } 573 574 static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) 575 { 576 struct ov772x_priv *priv = container_of(ctrl->handler, 577 struct ov772x_priv, hdl); 578 struct v4l2_subdev *sd = &priv->subdev; 579 struct i2c_client *client = v4l2_get_subdevdata(sd); 580 int ret = 0; 581 u8 val; 582 583 switch (ctrl->id) { 584 case V4L2_CID_VFLIP: 585 val = ctrl->val ? VFLIP_IMG : 0x00; 586 priv->flag_vflip = ctrl->val; 587 if (priv->info->flags & OV772X_FLAG_VFLIP) 588 val ^= VFLIP_IMG; 589 return ov772x_mask_set(client, COM3, VFLIP_IMG, val); 590 case V4L2_CID_HFLIP: 591 val = ctrl->val ? HFLIP_IMG : 0x00; 592 priv->flag_hflip = ctrl->val; 593 if (priv->info->flags & OV772X_FLAG_HFLIP) 594 val ^= HFLIP_IMG; 595 return ov772x_mask_set(client, COM3, HFLIP_IMG, val); 596 case V4L2_CID_BAND_STOP_FILTER: 597 if (!ctrl->val) { 598 /* Switch the filter off, it is on now */ 599 ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); 600 if (!ret) 601 ret = ov772x_mask_set(client, COM8, 602 BNDF_ON_OFF, 0); 603 } else { 604 /* Switch the filter on, set AEC low limit */ 605 val = 256 - ctrl->val; 606 ret = ov772x_mask_set(client, COM8, 607 BNDF_ON_OFF, BNDF_ON_OFF); 608 if (!ret) 609 ret = ov772x_mask_set(client, BDBASE, 610 0xff, val); 611 } 612 if (!ret) 613 priv->band_filter = ctrl->val; 614 return ret; 615 } 616 617 return -EINVAL; 618 } 619 620 #ifdef CONFIG_VIDEO_ADV_DEBUG 621 static int ov772x_g_register(struct v4l2_subdev *sd, 622 struct v4l2_dbg_register *reg) 623 { 624 struct i2c_client *client = v4l2_get_subdevdata(sd); 625 int ret; 626 627 reg->size = 1; 628 if (reg->reg > 0xff) 629 return -EINVAL; 630 631 ret = ov772x_read(client, reg->reg); 632 if (ret < 0) 633 return ret; 634 635 reg->val = (__u64)ret; 636 637 return 0; 638 } 639 640 static int ov772x_s_register(struct v4l2_subdev *sd, 641 const struct v4l2_dbg_register *reg) 642 { 643 struct i2c_client *client = v4l2_get_subdevdata(sd); 644 645 if (reg->reg > 0xff || 646 reg->val > 0xff) 647 return -EINVAL; 648 649 return ov772x_write(client, reg->reg, reg->val); 650 } 651 #endif 652 653 static int ov772x_s_power(struct v4l2_subdev *sd, int on) 654 { 655 struct i2c_client *client = v4l2_get_subdevdata(sd); 656 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 657 struct ov772x_priv *priv = to_ov772x(sd); 658 659 return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); 660 } 661 662 static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) 663 { 664 const struct ov772x_win_size *win = &ov772x_win_sizes[0]; 665 u32 best_diff = UINT_MAX; 666 unsigned int i; 667 668 for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) { 669 u32 diff = abs(width - ov772x_win_sizes[i].rect.width) 670 + abs(height - ov772x_win_sizes[i].rect.height); 671 if (diff < best_diff) { 672 best_diff = diff; 673 win = &ov772x_win_sizes[i]; 674 } 675 } 676 677 return win; 678 } 679 680 static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf, 681 const struct ov772x_color_format **cfmt, 682 const struct ov772x_win_size **win) 683 { 684 unsigned int i; 685 686 /* Select a format. */ 687 *cfmt = &ov772x_cfmts[0]; 688 689 for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { 690 if (mf->code == ov772x_cfmts[i].code) { 691 *cfmt = &ov772x_cfmts[i]; 692 break; 693 } 694 } 695 696 /* Select a window size. */ 697 *win = ov772x_select_win(mf->width, mf->height); 698 } 699 700 static int ov772x_set_params(struct ov772x_priv *priv, 701 const struct ov772x_color_format *cfmt, 702 const struct ov772x_win_size *win) 703 { 704 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); 705 int ret; 706 u8 val; 707 708 /* 709 * reset hardware 710 */ 711 ov772x_reset(client); 712 713 /* 714 * Edge Ctrl 715 */ 716 if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) { 717 718 /* 719 * Manual Edge Control Mode 720 * 721 * Edge auto strength bit is set by default. 722 * Remove it when manual mode. 723 */ 724 725 ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); 726 if (ret < 0) 727 goto ov772x_set_fmt_error; 728 729 ret = ov772x_mask_set(client, 730 EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK, 731 priv->info->edgectrl.threshold); 732 if (ret < 0) 733 goto ov772x_set_fmt_error; 734 735 ret = ov772x_mask_set(client, 736 EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK, 737 priv->info->edgectrl.strength); 738 if (ret < 0) 739 goto ov772x_set_fmt_error; 740 741 } else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) { 742 /* 743 * Auto Edge Control Mode 744 * 745 * set upper and lower limit 746 */ 747 ret = ov772x_mask_set(client, 748 EDGE_UPPER, OV772X_EDGE_UPPER_MASK, 749 priv->info->edgectrl.upper); 750 if (ret < 0) 751 goto ov772x_set_fmt_error; 752 753 ret = ov772x_mask_set(client, 754 EDGE_LOWER, OV772X_EDGE_LOWER_MASK, 755 priv->info->edgectrl.lower); 756 if (ret < 0) 757 goto ov772x_set_fmt_error; 758 } 759 760 /* Format and window size */ 761 ret = ov772x_write(client, HSTART, win->rect.left >> 2); 762 if (ret < 0) 763 goto ov772x_set_fmt_error; 764 ret = ov772x_write(client, HSIZE, win->rect.width >> 2); 765 if (ret < 0) 766 goto ov772x_set_fmt_error; 767 ret = ov772x_write(client, VSTART, win->rect.top >> 1); 768 if (ret < 0) 769 goto ov772x_set_fmt_error; 770 ret = ov772x_write(client, VSIZE, win->rect.height >> 1); 771 if (ret < 0) 772 goto ov772x_set_fmt_error; 773 ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2); 774 if (ret < 0) 775 goto ov772x_set_fmt_error; 776 ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1); 777 if (ret < 0) 778 goto ov772x_set_fmt_error; 779 ret = ov772x_write(client, HREF, 780 ((win->rect.top & 1) << HREF_VSTART_SHIFT) | 781 ((win->rect.left & 3) << HREF_HSTART_SHIFT) | 782 ((win->rect.height & 1) << HREF_VSIZE_SHIFT) | 783 ((win->rect.width & 3) << HREF_HSIZE_SHIFT)); 784 if (ret < 0) 785 goto ov772x_set_fmt_error; 786 ret = ov772x_write(client, EXHCH, 787 ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) | 788 ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT)); 789 if (ret < 0) 790 goto ov772x_set_fmt_error; 791 792 /* 793 * set DSP_CTRL3 794 */ 795 val = cfmt->dsp3; 796 if (val) { 797 ret = ov772x_mask_set(client, 798 DSP_CTRL3, UV_MASK, val); 799 if (ret < 0) 800 goto ov772x_set_fmt_error; 801 } 802 803 /* DSP_CTRL4: AEC reference point and DSP output format. */ 804 if (cfmt->dsp4) { 805 ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4); 806 if (ret < 0) 807 goto ov772x_set_fmt_error; 808 } 809 810 /* 811 * set COM3 812 */ 813 val = cfmt->com3; 814 if (priv->info->flags & OV772X_FLAG_VFLIP) 815 val |= VFLIP_IMG; 816 if (priv->info->flags & OV772X_FLAG_HFLIP) 817 val |= HFLIP_IMG; 818 if (priv->flag_vflip) 819 val ^= VFLIP_IMG; 820 if (priv->flag_hflip) 821 val ^= HFLIP_IMG; 822 823 ret = ov772x_mask_set(client, 824 COM3, SWAP_MASK | IMG_MASK, val); 825 if (ret < 0) 826 goto ov772x_set_fmt_error; 827 828 /* COM7: Sensor resolution and output format control. */ 829 ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7); 830 if (ret < 0) 831 goto ov772x_set_fmt_error; 832 833 /* 834 * set COM8 835 */ 836 if (priv->band_filter) { 837 ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1); 838 if (!ret) 839 ret = ov772x_mask_set(client, BDBASE, 840 0xff, 256 - priv->band_filter); 841 if (ret < 0) 842 goto ov772x_set_fmt_error; 843 } 844 845 return ret; 846 847 ov772x_set_fmt_error: 848 849 ov772x_reset(client); 850 851 return ret; 852 } 853 854 static int ov772x_get_selection(struct v4l2_subdev *sd, 855 struct v4l2_subdev_pad_config *cfg, 856 struct v4l2_subdev_selection *sel) 857 { 858 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) 859 return -EINVAL; 860 861 sel->r.left = 0; 862 sel->r.top = 0; 863 switch (sel->target) { 864 case V4L2_SEL_TGT_CROP_BOUNDS: 865 case V4L2_SEL_TGT_CROP_DEFAULT: 866 sel->r.width = OV772X_MAX_WIDTH; 867 sel->r.height = OV772X_MAX_HEIGHT; 868 return 0; 869 case V4L2_SEL_TGT_CROP: 870 sel->r.width = VGA_WIDTH; 871 sel->r.height = VGA_HEIGHT; 872 return 0; 873 default: 874 return -EINVAL; 875 } 876 } 877 878 static int ov772x_get_fmt(struct v4l2_subdev *sd, 879 struct v4l2_subdev_pad_config *cfg, 880 struct v4l2_subdev_format *format) 881 { 882 struct v4l2_mbus_framefmt *mf = &format->format; 883 struct ov772x_priv *priv = to_ov772x(sd); 884 885 if (format->pad) 886 return -EINVAL; 887 888 mf->width = priv->win->rect.width; 889 mf->height = priv->win->rect.height; 890 mf->code = priv->cfmt->code; 891 mf->colorspace = priv->cfmt->colorspace; 892 mf->field = V4L2_FIELD_NONE; 893 894 return 0; 895 } 896 897 static int ov772x_set_fmt(struct v4l2_subdev *sd, 898 struct v4l2_subdev_pad_config *cfg, 899 struct v4l2_subdev_format *format) 900 { 901 struct ov772x_priv *priv = to_ov772x(sd); 902 struct v4l2_mbus_framefmt *mf = &format->format; 903 const struct ov772x_color_format *cfmt; 904 const struct ov772x_win_size *win; 905 int ret; 906 907 if (format->pad) 908 return -EINVAL; 909 910 ov772x_select_params(mf, &cfmt, &win); 911 912 mf->code = cfmt->code; 913 mf->width = win->rect.width; 914 mf->height = win->rect.height; 915 mf->field = V4L2_FIELD_NONE; 916 mf->colorspace = cfmt->colorspace; 917 918 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 919 cfg->try_fmt = *mf; 920 return 0; 921 } 922 923 ret = ov772x_set_params(priv, cfmt, win); 924 if (ret < 0) 925 return ret; 926 927 priv->win = win; 928 priv->cfmt = cfmt; 929 return 0; 930 } 931 932 static int ov772x_video_probe(struct ov772x_priv *priv) 933 { 934 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); 935 u8 pid, ver; 936 const char *devname; 937 int ret; 938 939 ret = ov772x_s_power(&priv->subdev, 1); 940 if (ret < 0) 941 return ret; 942 943 /* 944 * check and show product ID and manufacturer ID 945 */ 946 pid = ov772x_read(client, PID); 947 ver = ov772x_read(client, VER); 948 949 switch (VERSION(pid, ver)) { 950 case OV7720: 951 devname = "ov7720"; 952 break; 953 case OV7725: 954 devname = "ov7725"; 955 break; 956 default: 957 dev_err(&client->dev, 958 "Product ID error %x:%x\n", pid, ver); 959 ret = -ENODEV; 960 goto done; 961 } 962 963 dev_info(&client->dev, 964 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", 965 devname, 966 pid, 967 ver, 968 ov772x_read(client, MIDH), 969 ov772x_read(client, MIDL)); 970 ret = v4l2_ctrl_handler_setup(&priv->hdl); 971 972 done: 973 ov772x_s_power(&priv->subdev, 0); 974 return ret; 975 } 976 977 static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { 978 .s_ctrl = ov772x_s_ctrl, 979 }; 980 981 static const struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { 982 #ifdef CONFIG_VIDEO_ADV_DEBUG 983 .g_register = ov772x_g_register, 984 .s_register = ov772x_s_register, 985 #endif 986 .s_power = ov772x_s_power, 987 }; 988 989 static int ov772x_enum_mbus_code(struct v4l2_subdev *sd, 990 struct v4l2_subdev_pad_config *cfg, 991 struct v4l2_subdev_mbus_code_enum *code) 992 { 993 if (code->pad || code->index >= ARRAY_SIZE(ov772x_cfmts)) 994 return -EINVAL; 995 996 code->code = ov772x_cfmts[code->index].code; 997 return 0; 998 } 999 1000 static int ov772x_g_mbus_config(struct v4l2_subdev *sd, 1001 struct v4l2_mbus_config *cfg) 1002 { 1003 struct i2c_client *client = v4l2_get_subdevdata(sd); 1004 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 1005 1006 cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER | 1007 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH | 1008 V4L2_MBUS_DATA_ACTIVE_HIGH; 1009 cfg->type = V4L2_MBUS_PARALLEL; 1010 cfg->flags = soc_camera_apply_board_flags(ssdd, cfg); 1011 1012 return 0; 1013 } 1014 1015 static const struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { 1016 .s_stream = ov772x_s_stream, 1017 .g_mbus_config = ov772x_g_mbus_config, 1018 }; 1019 1020 static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = { 1021 .enum_mbus_code = ov772x_enum_mbus_code, 1022 .get_selection = ov772x_get_selection, 1023 .get_fmt = ov772x_get_fmt, 1024 .set_fmt = ov772x_set_fmt, 1025 }; 1026 1027 static const struct v4l2_subdev_ops ov772x_subdev_ops = { 1028 .core = &ov772x_subdev_core_ops, 1029 .video = &ov772x_subdev_video_ops, 1030 .pad = &ov772x_subdev_pad_ops, 1031 }; 1032 1033 /* 1034 * i2c_driver function 1035 */ 1036 1037 static int ov772x_probe(struct i2c_client *client, 1038 const struct i2c_device_id *did) 1039 { 1040 struct ov772x_priv *priv; 1041 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 1042 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1043 int ret; 1044 1045 if (!ssdd || !ssdd->drv_priv) { 1046 dev_err(&client->dev, "OV772X: missing platform data!\n"); 1047 return -EINVAL; 1048 } 1049 1050 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | 1051 I2C_FUNC_PROTOCOL_MANGLING)) { 1052 dev_err(&adapter->dev, 1053 "I2C-Adapter doesn't support SMBUS_BYTE_DATA or PROTOCOL_MANGLING\n"); 1054 return -EIO; 1055 } 1056 client->flags |= I2C_CLIENT_SCCB; 1057 1058 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 1059 if (!priv) 1060 return -ENOMEM; 1061 1062 priv->info = ssdd->drv_priv; 1063 1064 v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); 1065 v4l2_ctrl_handler_init(&priv->hdl, 3); 1066 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1067 V4L2_CID_VFLIP, 0, 1, 1, 0); 1068 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1069 V4L2_CID_HFLIP, 0, 1, 1, 0); 1070 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1071 V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0); 1072 priv->subdev.ctrl_handler = &priv->hdl; 1073 if (priv->hdl.error) 1074 return priv->hdl.error; 1075 1076 priv->clk = v4l2_clk_get(&client->dev, "mclk"); 1077 if (IS_ERR(priv->clk)) { 1078 ret = PTR_ERR(priv->clk); 1079 goto eclkget; 1080 } 1081 1082 ret = ov772x_video_probe(priv); 1083 if (ret < 0) { 1084 v4l2_clk_put(priv->clk); 1085 eclkget: 1086 v4l2_ctrl_handler_free(&priv->hdl); 1087 } else { 1088 priv->cfmt = &ov772x_cfmts[0]; 1089 priv->win = &ov772x_win_sizes[0]; 1090 } 1091 1092 return ret; 1093 } 1094 1095 static int ov772x_remove(struct i2c_client *client) 1096 { 1097 struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); 1098 1099 v4l2_clk_put(priv->clk); 1100 v4l2_device_unregister_subdev(&priv->subdev); 1101 v4l2_ctrl_handler_free(&priv->hdl); 1102 return 0; 1103 } 1104 1105 static const struct i2c_device_id ov772x_id[] = { 1106 { "ov772x", 0 }, 1107 { } 1108 }; 1109 MODULE_DEVICE_TABLE(i2c, ov772x_id); 1110 1111 static struct i2c_driver ov772x_i2c_driver = { 1112 .driver = { 1113 .name = "ov772x", 1114 }, 1115 .probe = ov772x_probe, 1116 .remove = ov772x_remove, 1117 .id_table = ov772x_id, 1118 }; 1119 1120 module_i2c_driver(ov772x_i2c_driver); 1121 1122 MODULE_DESCRIPTION("SoC Camera driver for ov772x"); 1123 MODULE_AUTHOR("Kuninori Morimoto"); 1124 MODULE_LICENSE("GPL v2"); 1125