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