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/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 378struct 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 387struct ov772x_win_size { 388 char *name; 389 unsigned char com7_bit; 390 struct v4l2_rect rect; 391}; 392 393struct 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 */ 409static 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 485static 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 511static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd) 512{ 513 return container_of(sd, struct ov772x_priv, subdev); 514} 515 516static inline int ov772x_read(struct i2c_client *client, u8 addr) 517{ 518 return i2c_smbus_read_byte_data(client, addr); 519} 520 521static 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 526static 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 539static 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 556static 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 574static 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 621static 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 640static 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 653static 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 662static 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 680static 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 700static 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 847ov772x_set_fmt_error: 848 849 ov772x_reset(client); 850 851 return ret; 852} 853 854static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 855{ 856 a->c.left = 0; 857 a->c.top = 0; 858 a->c.width = VGA_WIDTH; 859 a->c.height = VGA_HEIGHT; 860 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 861 862 return 0; 863} 864 865static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 866{ 867 a->bounds.left = 0; 868 a->bounds.top = 0; 869 a->bounds.width = OV772X_MAX_WIDTH; 870 a->bounds.height = OV772X_MAX_HEIGHT; 871 a->defrect = a->bounds; 872 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 873 a->pixelaspect.numerator = 1; 874 a->pixelaspect.denominator = 1; 875 876 return 0; 877} 878 879static int ov772x_g_fmt(struct v4l2_subdev *sd, 880 struct v4l2_mbus_framefmt *mf) 881{ 882 struct ov772x_priv *priv = to_ov772x(sd); 883 884 mf->width = priv->win->rect.width; 885 mf->height = priv->win->rect.height; 886 mf->code = priv->cfmt->code; 887 mf->colorspace = priv->cfmt->colorspace; 888 mf->field = V4L2_FIELD_NONE; 889 890 return 0; 891} 892 893static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) 894{ 895 struct ov772x_priv *priv = to_ov772x(sd); 896 const struct ov772x_color_format *cfmt; 897 const struct ov772x_win_size *win; 898 int ret; 899 900 ov772x_select_params(mf, &cfmt, &win); 901 902 ret = ov772x_set_params(priv, cfmt, win); 903 if (ret < 0) 904 return ret; 905 906 priv->win = win; 907 priv->cfmt = cfmt; 908 909 mf->code = cfmt->code; 910 mf->width = win->rect.width; 911 mf->height = win->rect.height; 912 mf->field = V4L2_FIELD_NONE; 913 mf->colorspace = cfmt->colorspace; 914 915 return 0; 916} 917 918static int ov772x_try_fmt(struct v4l2_subdev *sd, 919 struct v4l2_mbus_framefmt *mf) 920{ 921 const struct ov772x_color_format *cfmt; 922 const struct ov772x_win_size *win; 923 924 ov772x_select_params(mf, &cfmt, &win); 925 926 mf->code = cfmt->code; 927 mf->width = win->rect.width; 928 mf->height = win->rect.height; 929 mf->field = V4L2_FIELD_NONE; 930 mf->colorspace = cfmt->colorspace; 931 932 return 0; 933} 934 935static int ov772x_video_probe(struct ov772x_priv *priv) 936{ 937 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); 938 u8 pid, ver; 939 const char *devname; 940 int ret; 941 942 ret = ov772x_s_power(&priv->subdev, 1); 943 if (ret < 0) 944 return ret; 945 946 /* 947 * check and show product ID and manufacturer ID 948 */ 949 pid = ov772x_read(client, PID); 950 ver = ov772x_read(client, VER); 951 952 switch (VERSION(pid, ver)) { 953 case OV7720: 954 devname = "ov7720"; 955 break; 956 case OV7725: 957 devname = "ov7725"; 958 break; 959 default: 960 dev_err(&client->dev, 961 "Product ID error %x:%x\n", pid, ver); 962 ret = -ENODEV; 963 goto done; 964 } 965 966 dev_info(&client->dev, 967 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", 968 devname, 969 pid, 970 ver, 971 ov772x_read(client, MIDH), 972 ov772x_read(client, MIDL)); 973 ret = v4l2_ctrl_handler_setup(&priv->hdl); 974 975done: 976 ov772x_s_power(&priv->subdev, 0); 977 return ret; 978} 979 980static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { 981 .s_ctrl = ov772x_s_ctrl, 982}; 983 984static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { 985#ifdef CONFIG_VIDEO_ADV_DEBUG 986 .g_register = ov772x_g_register, 987 .s_register = ov772x_s_register, 988#endif 989 .s_power = ov772x_s_power, 990}; 991 992static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index, 993 u32 *code) 994{ 995 if (index >= ARRAY_SIZE(ov772x_cfmts)) 996 return -EINVAL; 997 998 *code = ov772x_cfmts[index].code; 999 return 0; 1000} 1001 1002static int ov772x_g_mbus_config(struct v4l2_subdev *sd, 1003 struct v4l2_mbus_config *cfg) 1004{ 1005 struct i2c_client *client = v4l2_get_subdevdata(sd); 1006 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 1007 1008 cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER | 1009 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH | 1010 V4L2_MBUS_DATA_ACTIVE_HIGH; 1011 cfg->type = V4L2_MBUS_PARALLEL; 1012 cfg->flags = soc_camera_apply_board_flags(ssdd, cfg); 1013 1014 return 0; 1015} 1016 1017static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { 1018 .s_stream = ov772x_s_stream, 1019 .g_mbus_fmt = ov772x_g_fmt, 1020 .s_mbus_fmt = ov772x_s_fmt, 1021 .try_mbus_fmt = ov772x_try_fmt, 1022 .cropcap = ov772x_cropcap, 1023 .g_crop = ov772x_g_crop, 1024 .enum_mbus_fmt = ov772x_enum_fmt, 1025 .g_mbus_config = ov772x_g_mbus_config, 1026}; 1027 1028static struct v4l2_subdev_ops ov772x_subdev_ops = { 1029 .core = &ov772x_subdev_core_ops, 1030 .video = &ov772x_subdev_video_ops, 1031}; 1032 1033/* 1034 * i2c_driver function 1035 */ 1036 1037static 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 dev_err(&adapter->dev, 1052 "I2C-Adapter doesn't support " 1053 "I2C_FUNC_SMBUS_BYTE_DATA\n"); 1054 return -EIO; 1055 } 1056 1057 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 1058 if (!priv) 1059 return -ENOMEM; 1060 1061 priv->info = ssdd->drv_priv; 1062 1063 v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); 1064 v4l2_ctrl_handler_init(&priv->hdl, 3); 1065 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1066 V4L2_CID_VFLIP, 0, 1, 1, 0); 1067 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1068 V4L2_CID_HFLIP, 0, 1, 1, 0); 1069 v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, 1070 V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0); 1071 priv->subdev.ctrl_handler = &priv->hdl; 1072 if (priv->hdl.error) 1073 return priv->hdl.error; 1074 1075 priv->clk = v4l2_clk_get(&client->dev, "mclk"); 1076 if (IS_ERR(priv->clk)) { 1077 ret = PTR_ERR(priv->clk); 1078 goto eclkget; 1079 } 1080 1081 ret = ov772x_video_probe(priv); 1082 if (ret < 0) { 1083 v4l2_clk_put(priv->clk); 1084eclkget: 1085 v4l2_ctrl_handler_free(&priv->hdl); 1086 } else { 1087 priv->cfmt = &ov772x_cfmts[0]; 1088 priv->win = &ov772x_win_sizes[0]; 1089 } 1090 1091 return ret; 1092} 1093 1094static int ov772x_remove(struct i2c_client *client) 1095{ 1096 struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); 1097 1098 v4l2_clk_put(priv->clk); 1099 v4l2_device_unregister_subdev(&priv->subdev); 1100 v4l2_ctrl_handler_free(&priv->hdl); 1101 return 0; 1102} 1103 1104static const struct i2c_device_id ov772x_id[] = { 1105 { "ov772x", 0 }, 1106 { } 1107}; 1108MODULE_DEVICE_TABLE(i2c, ov772x_id); 1109 1110static struct i2c_driver ov772x_i2c_driver = { 1111 .driver = { 1112 .name = "ov772x", 1113 }, 1114 .probe = ov772x_probe, 1115 .remove = ov772x_remove, 1116 .id_table = ov772x_id, 1117}; 1118 1119module_i2c_driver(ov772x_i2c_driver); 1120 1121MODULE_DESCRIPTION("SoC Camera driver for ov772x"); 1122MODULE_AUTHOR("Kuninori Morimoto"); 1123MODULE_LICENSE("GPL v2"); 1124