linux/drivers/media/video/ov2640.c
<<
>>
Prefs
   1/*
   2 * ov2640 Camera Driver
   3 *
   4 * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>
   5 *
   6 * Based on ov772x, ov9640 drivers and previous non merged implementations.
   7 *
   8 * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
   9 * Copyright (C) 2006, OmniVision
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/init.h>
  17#include <linux/module.h>
  18#include <linux/i2c.h>
  19#include <linux/slab.h>
  20#include <linux/delay.h>
  21#include <linux/videodev2.h>
  22#include <media/v4l2-chip-ident.h>
  23#include <media/v4l2-subdev.h>
  24#include <media/soc_camera.h>
  25#include <media/soc_mediabus.h>
  26
  27#define VAL_SET(x, mask, rshift, lshift)  \
  28                ((((x) >> rshift) & mask) << lshift)
  29/*
  30 * DSP registers
  31 * register offset for BANK_SEL == BANK_SEL_DSP
  32 */
  33#define R_BYPASS    0x05 /* Bypass DSP */
  34#define   R_BYPASS_DSP_BYPAS    0x01 /* Bypass DSP, sensor out directly */
  35#define   R_BYPASS_USE_DSP      0x00 /* Use the internal DSP */
  36#define QS          0x44 /* Quantization Scale Factor */
  37#define CTRLI       0x50
  38#define   CTRLI_LP_DP           0x80
  39#define   CTRLI_ROUND           0x40
  40#define   CTRLI_V_DIV_SET(x)    VAL_SET(x, 0x3, 0, 3)
  41#define   CTRLI_H_DIV_SET(x)    VAL_SET(x, 0x3, 0, 0)
  42#define HSIZE       0x51 /* H_SIZE[7:0] (real/4) */
  43#define   HSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
  44#define VSIZE       0x52 /* V_SIZE[7:0] (real/4) */
  45#define   VSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
  46#define XOFFL       0x53 /* OFFSET_X[7:0] */
  47#define   XOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
  48#define YOFFL       0x54 /* OFFSET_Y[7:0] */
  49#define   YOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
  50#define VHYX        0x55 /* Offset and size completion */
  51#define   VHYX_VSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 7)
  52#define   VHYX_HSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 3)
  53#define   VHYX_YOFF_SET(x)      VAL_SET(x, 0x3, 8, 4)
  54#define   VHYX_XOFF_SET(x)      VAL_SET(x, 0x3, 8, 0)
  55#define DPRP        0x56
  56#define TEST        0x57 /* Horizontal size completion */
  57#define   TEST_HSIZE_SET(x)     VAL_SET(x, 0x1, (9+2), 7)
  58#define ZMOW        0x5A /* Zoom: Out Width  OUTW[7:0] (real/4) */
  59#define   ZMOW_OUTW_SET(x)      VAL_SET(x, 0xFF, 2, 0)
  60#define ZMOH        0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */
  61#define   ZMOH_OUTH_SET(x)      VAL_SET(x, 0xFF, 2, 0)
  62#define ZMHH        0x5C /* Zoom: Speed and H&W completion */
  63#define   ZMHH_ZSPEED_SET(x)    VAL_SET(x, 0x0F, 0, 4)
  64#define   ZMHH_OUTH_SET(x)      VAL_SET(x, 0x1, (8+2), 2)
  65#define   ZMHH_OUTW_SET(x)      VAL_SET(x, 0x3, (8+2), 0)
  66#define BPADDR      0x7C /* SDE Indirect Register Access: Address */
  67#define BPDATA      0x7D /* SDE Indirect Register Access: Data */
  68#define CTRL2       0x86 /* DSP Module enable 2 */
  69#define   CTRL2_DCW_EN          0x20
  70#define   CTRL2_SDE_EN          0x10
  71#define   CTRL2_UV_ADJ_EN       0x08
  72#define   CTRL2_UV_AVG_EN       0x04
  73#define   CTRL2_CMX_EN          0x01
  74#define CTRL3       0x87 /* DSP Module enable 3 */
  75#define   CTRL3_BPC_EN          0x80
  76#define   CTRL3_WPC_EN          0x40
  77#define SIZEL       0x8C /* Image Size Completion */
  78#define   SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6)
  79#define   SIZEL_HSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 3)
  80#define   SIZEL_VSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 0)
  81#define HSIZE8      0xC0 /* Image Horizontal Size HSIZE[10:3] */
  82#define   HSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
  83#define VSIZE8      0xC1 /* Image Vertical Size VSIZE[10:3] */
  84#define   VSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
  85#define CTRL0       0xC2 /* DSP Module enable 0 */
  86#define   CTRL0_AEC_EN       0x80
  87#define   CTRL0_AEC_SEL      0x40
  88#define   CTRL0_STAT_SEL     0x20
  89#define   CTRL0_VFIRST       0x10
  90#define   CTRL0_YUV422       0x08
  91#define   CTRL0_YUV_EN       0x04
  92#define   CTRL0_RGB_EN       0x02
  93#define   CTRL0_RAW_EN       0x01
  94#define CTRL1       0xC3 /* DSP Module enable 1 */
  95#define   CTRL1_CIP          0x80
  96#define   CTRL1_DMY          0x40
  97#define   CTRL1_RAW_GMA      0x20
  98#define   CTRL1_DG           0x10
  99#define   CTRL1_AWB          0x08
 100#define   CTRL1_AWB_GAIN     0x04
 101#define   CTRL1_LENC         0x02
 102#define   CTRL1_PRE          0x01
 103#define R_DVP_SP    0xD3 /* DVP output speed control */
 104#define   R_DVP_SP_AUTO_MODE 0x80
 105#define   R_DVP_SP_DVP_MASK  0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);
 106                                   *          = sysclk (48)/(2*[6:0]) (RAW);*/
 107#define IMAGE_MODE  0xDA /* Image Output Format Select */
 108#define   IMAGE_MODE_Y8_DVP_EN   0x40
 109#define   IMAGE_MODE_JPEG_EN     0x10
 110#define   IMAGE_MODE_YUV422      0x00
 111#define   IMAGE_MODE_RAW10       0x04 /* (DVP) */
 112#define   IMAGE_MODE_RGB565      0x08
 113#define   IMAGE_MODE_HREF_VSYNC  0x02 /* HREF timing select in DVP JPEG output
 114                                       * mode (0 for HREF is same as sensor) */
 115#define   IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP
 116                                       *    1: Low byte first UYVY (C2[4] =0)
 117                                       *        VYUY (C2[4] =1)
 118                                       *    0: High byte first YUYV (C2[4]=0)
 119                                       *        YVYU (C2[4] = 1) */
 120#define RESET       0xE0 /* Reset */
 121#define   RESET_MICROC       0x40
 122#define   RESET_SCCB         0x20
 123#define   RESET_JPEG         0x10
 124#define   RESET_DVP          0x04
 125#define   RESET_IPU          0x02
 126#define   RESET_CIF          0x01
 127#define REGED       0xED /* Register ED */
 128#define   REGED_CLK_OUT_DIS  0x10
 129#define MS_SP       0xF0 /* SCCB Master Speed */
 130#define SS_ID       0xF7 /* SCCB Slave ID */
 131#define SS_CTRL     0xF8 /* SCCB Slave Control */
 132#define   SS_CTRL_ADD_AUTO_INC  0x20
 133#define   SS_CTRL_EN            0x08
 134#define   SS_CTRL_DELAY_CLK     0x04
 135#define   SS_CTRL_ACC_EN        0x02
 136#define   SS_CTRL_SEN_PASS_THR  0x01
 137#define MC_BIST     0xF9 /* Microcontroller misc register */
 138#define   MC_BIST_RESET           0x80 /* Microcontroller Reset */
 139#define   MC_BIST_BOOT_ROM_SEL    0x40
 140#define   MC_BIST_12KB_SEL        0x20
 141#define   MC_BIST_12KB_MASK       0x30
 142#define   MC_BIST_512KB_SEL       0x08
 143#define   MC_BIST_512KB_MASK      0x0C
 144#define   MC_BIST_BUSY_BIT_R      0x02
 145#define   MC_BIST_MC_RES_ONE_SH_W 0x02
 146#define   MC_BIST_LAUNCH          0x01
 147#define BANK_SEL    0xFF /* Register Bank Select */
 148#define   BANK_SEL_DSP     0x00
 149#define   BANK_SEL_SENS    0x01
 150
 151/*
 152 * Sensor registers
 153 * register offset for BANK_SEL == BANK_SEL_SENS
 154 */
 155#define GAIN        0x00 /* AGC - Gain control gain setting */
 156#define COM1        0x03 /* Common control 1 */
 157#define   COM1_1_DUMMY_FR          0x40
 158#define   COM1_3_DUMMY_FR          0x80
 159#define   COM1_7_DUMMY_FR          0xC0
 160#define   COM1_VWIN_LSB_UXGA       0x0F
 161#define   COM1_VWIN_LSB_SVGA       0x0A
 162#define   COM1_VWIN_LSB_CIF        0x06
 163#define REG04       0x04 /* Register 04 */
 164#define   REG04_DEF             0x20 /* Always set */
 165#define   REG04_HFLIP_IMG       0x80 /* Horizontal mirror image ON/OFF */
 166#define   REG04_VFLIP_IMG       0x40 /* Vertical flip image ON/OFF */
 167#define   REG04_VREF_EN         0x10
 168#define   REG04_HREF_EN         0x08
 169#define   REG04_AEC_SET(x)      VAL_SET(x, 0x3, 0, 0)
 170#define REG08       0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */
 171#define COM2        0x09 /* Common control 2 */
 172#define   COM2_SOFT_SLEEP_MODE  0x10 /* Soft sleep mode */
 173                                     /* Output drive capability */
 174#define   COM2_OCAP_Nx_SET(N)   (((N) - 1) & 0x03) /* N = [1x .. 4x] */
 175#define PID         0x0A /* Product ID Number MSB */
 176#define VER         0x0B /* Product ID Number LSB */
 177#define COM3        0x0C /* Common control 3 */
 178#define   COM3_BAND_50H        0x04 /* 0 For Banding at 60H */
 179#define   COM3_BAND_AUTO       0x02 /* Auto Banding */
 180#define   COM3_SING_FR_SNAPSH  0x01 /* 0 For enable live video output after the
 181                                     * snapshot sequence*/
 182#define AEC         0x10 /* AEC[9:2] Exposure Value */
 183#define CLKRC       0x11 /* Internal clock */
 184#define   CLKRC_EN             0x80
 185#define   CLKRC_DIV_SET(x)     (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */
 186#define COM7        0x12 /* Common control 7 */
 187#define   COM7_SRST            0x80 /* Initiates system reset. All registers are
 188                                     * set to factory default values after which
 189                                     * the chip resumes normal operation */
 190#define   COM7_RES_UXGA        0x00 /* Resolution selectors for UXGA */
 191#define   COM7_RES_SVGA        0x40 /* SVGA */
 192#define   COM7_RES_CIF         0x20 /* CIF */
 193#define   COM7_ZOOM_EN         0x04 /* Enable Zoom mode */
 194#define   COM7_COLOR_BAR_TEST  0x02 /* Enable Color Bar Test Pattern */
 195#define COM8        0x13 /* Common control 8 */
 196#define   COM8_DEF             0xC0 /* Banding filter ON/OFF */
 197#define   COM8_BNDF_EN         0x20 /* Banding filter ON/OFF */
 198#define   COM8_AGC_EN          0x04 /* AGC Auto/Manual control selection */
 199#define   COM8_AEC_EN          0x01 /* Auto/Manual Exposure control */
 200#define COM9        0x14 /* Common control 9
 201                          * Automatic gain ceiling - maximum AGC value [7:5]*/
 202#define   COM9_AGC_GAIN_2x     0x00 /* 000 :   2x */
 203#define   COM9_AGC_GAIN_4x     0x20 /* 001 :   4x */
 204#define   COM9_AGC_GAIN_8x     0x40 /* 010 :   8x */
 205#define   COM9_AGC_GAIN_16x    0x60 /* 011 :  16x */
 206#define   COM9_AGC_GAIN_32x    0x80 /* 100 :  32x */
 207#define   COM9_AGC_GAIN_64x    0xA0 /* 101 :  64x */
 208#define   COM9_AGC_GAIN_128x   0xC0 /* 110 : 128x */
 209#define COM10       0x15 /* Common control 10 */
 210#define   COM10_PCLK_HREF      0x20 /* PCLK output qualified by HREF */
 211#define   COM10_PCLK_RISE      0x10 /* Data is updated at the rising edge of
 212                                     * PCLK (user can latch data at the next
 213                                     * falling edge of PCLK).
 214                                     * 0 otherwise. */
 215#define   COM10_HREF_INV       0x08 /* Invert HREF polarity:
 216                                     * HREF negative for valid data*/
 217#define   COM10_VSINC_INV      0x02 /* Invert VSYNC polarity */
 218#define HSTART      0x17 /* Horizontal Window start MSB 8 bit */
 219#define HEND        0x18 /* Horizontal Window end MSB 8 bit */
 220#define VSTART      0x19 /* Vertical Window start MSB 8 bit */
 221#define VEND        0x1A /* Vertical Window end MSB 8 bit */
 222#define MIDH        0x1C /* Manufacturer ID byte - high */
 223#define MIDL        0x1D /* Manufacturer ID byte - low  */
 224#define AEW         0x24 /* AGC/AEC - Stable operating region (upper limit) */
 225#define AEB         0x25 /* AGC/AEC - Stable operating region (lower limit) */
 226#define VV          0x26 /* AGC/AEC Fast mode operating region */
 227#define   VV_HIGH_TH_SET(x)      VAL_SET(x, 0xF, 0, 4)
 228#define   VV_LOW_TH_SET(x)       VAL_SET(x, 0xF, 0, 0)
 229#define REG2A       0x2A /* Dummy pixel insert MSB */
 230#define FRARL       0x2B /* Dummy pixel insert LSB */
 231#define ADDVFL      0x2D /* LSB of insert dummy lines in Vertical direction */
 232#define ADDVFH      0x2E /* MSB of insert dummy lines in Vertical direction */
 233#define YAVG        0x2F /* Y/G Channel Average value */
 234#define REG32       0x32 /* Common Control 32 */
 235#define   REG32_PCLK_DIV_2    0x80 /* PCLK freq divided by 2 */
 236#define   REG32_PCLK_DIV_4    0xC0 /* PCLK freq divided by 4 */
 237#define ARCOM2      0x34 /* Zoom: Horizontal start point */
 238#define REG45       0x45 /* Register 45 */
 239#define FLL         0x46 /* Frame Length Adjustment LSBs */
 240#define FLH         0x47 /* Frame Length Adjustment MSBs */
 241#define COM19       0x48 /* Zoom: Vertical start point */
 242#define ZOOMS       0x49 /* Zoom: Vertical start point */
 243#define COM22       0x4B /* Flash light control */
 244#define COM25       0x4E /* For Banding operations */
 245#define BD50        0x4F /* 50Hz Banding AEC 8 LSBs */
 246#define BD60        0x50 /* 60Hz Banding AEC 8 LSBs */
 247#define REG5D       0x5D /* AVGsel[7:0],   16-zone average weight option */
 248#define REG5E       0x5E /* AVGsel[15:8],  16-zone average weight option */
 249#define REG5F       0x5F /* AVGsel[23:16], 16-zone average weight option */
 250#define REG60       0x60 /* AVGsel[31:24], 16-zone average weight option */
 251#define HISTO_LOW   0x61 /* Histogram Algorithm Low Level */
 252#define HISTO_HIGH  0x62 /* Histogram Algorithm High Level */
 253
 254/*
 255 * ID
 256 */
 257#define MANUFACTURER_ID 0x7FA2
 258#define PID_OV2640      0x2642
 259#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF))
 260
 261/*
 262 * Struct
 263 */
 264struct regval_list {
 265        u8 reg_num;
 266        u8 value;
 267};
 268
 269/* Supported resolutions */
 270enum ov2640_width {
 271        W_QCIF  = 176,
 272        W_QVGA  = 320,
 273        W_CIF   = 352,
 274        W_VGA   = 640,
 275        W_SVGA  = 800,
 276        W_XGA   = 1024,
 277        W_SXGA  = 1280,
 278        W_UXGA  = 1600,
 279};
 280
 281enum ov2640_height {
 282        H_QCIF  = 144,
 283        H_QVGA  = 240,
 284        H_CIF   = 288,
 285        H_VGA   = 480,
 286        H_SVGA  = 600,
 287        H_XGA   = 768,
 288        H_SXGA  = 1024,
 289        H_UXGA  = 1200,
 290};
 291
 292struct ov2640_win_size {
 293        char                            *name;
 294        enum ov2640_width               width;
 295        enum ov2640_height              height;
 296        const struct regval_list        *regs;
 297};
 298
 299
 300struct ov2640_priv {
 301        struct v4l2_subdev              subdev;
 302        struct ov2640_camera_info       *info;
 303        enum v4l2_mbus_pixelcode        cfmt_code;
 304        const struct ov2640_win_size    *win;
 305        int                             model;
 306        u16                             flag_vflip:1;
 307        u16                             flag_hflip:1;
 308};
 309
 310/*
 311 * Registers settings
 312 */
 313
 314#define ENDMARKER { 0xff, 0xff }
 315
 316static const struct regval_list ov2640_init_regs[] = {
 317        { BANK_SEL, BANK_SEL_DSP },
 318        { 0x2c,   0xff },
 319        { 0x2e,   0xdf },
 320        { BANK_SEL, BANK_SEL_SENS },
 321        { 0x3c,   0x32 },
 322        { CLKRC, CLKRC_DIV_SET(1) },
 323        { COM2, COM2_OCAP_Nx_SET(3) },
 324        { REG04, REG04_DEF | REG04_HREF_EN },
 325        { COM8,  COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN },
 326        { COM9, COM9_AGC_GAIN_8x | 0x08},
 327        { 0x2c,   0x0c },
 328        { 0x33,   0x78 },
 329        { 0x3a,   0x33 },
 330        { 0x3b,   0xfb },
 331        { 0x3e,   0x00 },
 332        { 0x43,   0x11 },
 333        { 0x16,   0x10 },
 334        { 0x39,   0x02 },
 335        { 0x35,   0x88 },
 336        { 0x22,   0x0a },
 337        { 0x37,   0x40 },
 338        { 0x23,   0x00 },
 339        { ARCOM2, 0xa0 },
 340        { 0x06,   0x02 },
 341        { 0x06,   0x88 },
 342        { 0x07,   0xc0 },
 343        { 0x0d,   0xb7 },
 344        { 0x0e,   0x01 },
 345        { 0x4c,   0x00 },
 346        { 0x4a,   0x81 },
 347        { 0x21,   0x99 },
 348        { AEW,    0x40 },
 349        { AEB,    0x38 },
 350        { VV,     VV_HIGH_TH_SET(0x08) | VV_LOW_TH_SET(0x02) },
 351        { 0x5c,   0x00 },
 352        { 0x63,   0x00 },
 353        { FLL,    0x22 },
 354        { COM3,   0x38 | COM3_BAND_AUTO },
 355        { REG5D,  0x55 },
 356        { REG5E,  0x7d },
 357        { REG5F,  0x7d },
 358        { REG60,  0x55 },
 359        { HISTO_LOW,   0x70 },
 360        { HISTO_HIGH,  0x80 },
 361        { 0x7c,   0x05 },
 362        { 0x20,   0x80 },
 363        { 0x28,   0x30 },
 364        { 0x6c,   0x00 },
 365        { 0x6d,   0x80 },
 366        { 0x6e,   0x00 },
 367        { 0x70,   0x02 },
 368        { 0x71,   0x94 },
 369        { 0x73,   0xc1 },
 370        { 0x3d,   0x34 },
 371        { COM7, COM7_RES_UXGA | COM7_ZOOM_EN },
 372        { 0x5a,   0x57 },
 373        { BD50,   0xbb },
 374        { BD60,   0x9c },
 375        { BANK_SEL, BANK_SEL_DSP },
 376        { 0xe5,   0x7f },
 377        { MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },
 378        { 0x41,   0x24 },
 379        { RESET, RESET_JPEG | RESET_DVP },
 380        { 0x76,   0xff },
 381        { 0x33,   0xa0 },
 382        { 0x42,   0x20 },
 383        { 0x43,   0x18 },
 384        { 0x4c,   0x00 },
 385        { CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },
 386        { 0x88,   0x3f },
 387        { 0xd7,   0x03 },
 388        { 0xd9,   0x10 },
 389        { R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 },
 390        { 0xc8,   0x08 },
 391        { 0xc9,   0x80 },
 392        { BPADDR, 0x00 },
 393        { BPDATA, 0x00 },
 394        { BPADDR, 0x03 },
 395        { BPDATA, 0x48 },
 396        { BPDATA, 0x48 },
 397        { BPADDR, 0x08 },
 398        { BPDATA, 0x20 },
 399        { BPDATA, 0x10 },
 400        { BPDATA, 0x0e },
 401        { 0x90,   0x00 },
 402        { 0x91,   0x0e },
 403        { 0x91,   0x1a },
 404        { 0x91,   0x31 },
 405        { 0x91,   0x5a },
 406        { 0x91,   0x69 },
 407        { 0x91,   0x75 },
 408        { 0x91,   0x7e },
 409        { 0x91,   0x88 },
 410        { 0x91,   0x8f },
 411        { 0x91,   0x96 },
 412        { 0x91,   0xa3 },
 413        { 0x91,   0xaf },
 414        { 0x91,   0xc4 },
 415        { 0x91,   0xd7 },
 416        { 0x91,   0xe8 },
 417        { 0x91,   0x20 },
 418        { 0x92,   0x00 },
 419        { 0x93,   0x06 },
 420        { 0x93,   0xe3 },
 421        { 0x93,   0x03 },
 422        { 0x93,   0x03 },
 423        { 0x93,   0x00 },
 424        { 0x93,   0x02 },
 425        { 0x93,   0x00 },
 426        { 0x93,   0x00 },
 427        { 0x93,   0x00 },
 428        { 0x93,   0x00 },
 429        { 0x93,   0x00 },
 430        { 0x93,   0x00 },
 431        { 0x93,   0x00 },
 432        { 0x96,   0x00 },
 433        { 0x97,   0x08 },
 434        { 0x97,   0x19 },
 435        { 0x97,   0x02 },
 436        { 0x97,   0x0c },
 437        { 0x97,   0x24 },
 438        { 0x97,   0x30 },
 439        { 0x97,   0x28 },
 440        { 0x97,   0x26 },
 441        { 0x97,   0x02 },
 442        { 0x97,   0x98 },
 443        { 0x97,   0x80 },
 444        { 0x97,   0x00 },
 445        { 0x97,   0x00 },
 446        { 0xa4,   0x00 },
 447        { 0xa8,   0x00 },
 448        { 0xc5,   0x11 },
 449        { 0xc6,   0x51 },
 450        { 0xbf,   0x80 },
 451        { 0xc7,   0x10 },
 452        { 0xb6,   0x66 },
 453        { 0xb8,   0xA5 },
 454        { 0xb7,   0x64 },
 455        { 0xb9,   0x7C },
 456        { 0xb3,   0xaf },
 457        { 0xb4,   0x97 },
 458        { 0xb5,   0xFF },
 459        { 0xb0,   0xC5 },
 460        { 0xb1,   0x94 },
 461        { 0xb2,   0x0f },
 462        { 0xc4,   0x5c },
 463        { 0xa6,   0x00 },
 464        { 0xa7,   0x20 },
 465        { 0xa7,   0xd8 },
 466        { 0xa7,   0x1b },
 467        { 0xa7,   0x31 },
 468        { 0xa7,   0x00 },
 469        { 0xa7,   0x18 },
 470        { 0xa7,   0x20 },
 471        { 0xa7,   0xd8 },
 472        { 0xa7,   0x19 },
 473        { 0xa7,   0x31 },
 474        { 0xa7,   0x00 },
 475        { 0xa7,   0x18 },
 476        { 0xa7,   0x20 },
 477        { 0xa7,   0xd8 },
 478        { 0xa7,   0x19 },
 479        { 0xa7,   0x31 },
 480        { 0xa7,   0x00 },
 481        { 0xa7,   0x18 },
 482        { 0x7f,   0x00 },
 483        { 0xe5,   0x1f },
 484        { 0xe1,   0x77 },
 485        { 0xdd,   0x7f },
 486        { CTRL0,  CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN },
 487        ENDMARKER,
 488};
 489
 490/*
 491 * Register settings for window size
 492 * The preamble, setup the internal DSP to input an UXGA (1600x1200) image.
 493 * Then the different zooming configurations will setup the output image size.
 494 */
 495static const struct regval_list ov2640_size_change_preamble_regs[] = {
 496        { BANK_SEL, BANK_SEL_DSP },
 497        { RESET, RESET_DVP },
 498        { HSIZE8, HSIZE8_SET(W_UXGA) },
 499        { VSIZE8, VSIZE8_SET(H_UXGA) },
 500        { CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
 501                 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
 502        { HSIZE, HSIZE_SET(W_UXGA) },
 503        { VSIZE, VSIZE_SET(H_UXGA) },
 504        { XOFFL, XOFFL_SET(0) },
 505        { YOFFL, YOFFL_SET(0) },
 506        { VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) |
 507                VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
 508        { TEST, TEST_HSIZE_SET(W_UXGA) },
 509        ENDMARKER,
 510};
 511
 512#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div)  \
 513        { CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) | \
 514                 CTRLI_H_DIV_SET(h_div)},               \
 515        { ZMOW, ZMOW_OUTW_SET(x) },                     \
 516        { ZMOH, ZMOH_OUTH_SET(y) },                     \
 517        { ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) },  \
 518        { R_DVP_SP, pclk_div },                         \
 519        { RESET, 0x00}
 520
 521static const struct regval_list ov2640_qcif_regs[] = {
 522        PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4),
 523        ENDMARKER,
 524};
 525
 526static const struct regval_list ov2640_qvga_regs[] = {
 527        PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4),
 528        ENDMARKER,
 529};
 530
 531static const struct regval_list ov2640_cif_regs[] = {
 532        PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8),
 533        ENDMARKER,
 534};
 535
 536static const struct regval_list ov2640_vga_regs[] = {
 537        PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2),
 538        ENDMARKER,
 539};
 540
 541static const struct regval_list ov2640_svga_regs[] = {
 542        PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2),
 543        ENDMARKER,
 544};
 545
 546static const struct regval_list ov2640_xga_regs[] = {
 547        PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2),
 548        { CTRLI,    0x00},
 549        ENDMARKER,
 550};
 551
 552static const struct regval_list ov2640_sxga_regs[] = {
 553        PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2),
 554        { CTRLI,    0x00},
 555        { R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
 556        ENDMARKER,
 557};
 558
 559static const struct regval_list ov2640_uxga_regs[] = {
 560        PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0),
 561        { CTRLI,    0x00},
 562        { R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
 563        ENDMARKER,
 564};
 565
 566#define OV2640_SIZE(n, w, h, r) \
 567        {.name = n, .width = w , .height = h, .regs = r }
 568
 569static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
 570        OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
 571        OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
 572        OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
 573        OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
 574        OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
 575        OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
 576        OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
 577        OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
 578};
 579
 580/*
 581 * Register settings for pixel formats
 582 */
 583static const struct regval_list ov2640_format_change_preamble_regs[] = {
 584        { BANK_SEL, BANK_SEL_DSP },
 585        { R_BYPASS, R_BYPASS_USE_DSP },
 586        ENDMARKER,
 587};
 588
 589static const struct regval_list ov2640_yuv422_regs[] = {
 590        { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
 591        { 0xD7, 0x01 },
 592        { 0x33, 0xa0 },
 593        { 0xe1, 0x67 },
 594        { RESET,  0x00 },
 595        { R_BYPASS, R_BYPASS_USE_DSP },
 596        ENDMARKER,
 597};
 598
 599static const struct regval_list ov2640_rgb565_regs[] = {
 600        { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
 601        { 0xd7, 0x03 },
 602        { RESET,  0x00 },
 603        { R_BYPASS, R_BYPASS_USE_DSP },
 604        ENDMARKER,
 605};
 606
 607static enum v4l2_mbus_pixelcode ov2640_codes[] = {
 608        V4L2_MBUS_FMT_UYVY8_2X8,
 609        V4L2_MBUS_FMT_RGB565_2X8_LE,
 610};
 611
 612/*
 613 * Supported controls
 614 */
 615static const struct v4l2_queryctrl ov2640_controls[] = {
 616        {
 617                .id             = V4L2_CID_VFLIP,
 618                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 619                .name           = "Flip Vertically",
 620                .minimum        = 0,
 621                .maximum        = 1,
 622                .step           = 1,
 623                .default_value  = 0,
 624        }, {
 625                .id             = V4L2_CID_HFLIP,
 626                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 627                .name           = "Flip Horizontally",
 628                .minimum        = 0,
 629                .maximum        = 1,
 630                .step           = 1,
 631                .default_value  = 0,
 632        },
 633};
 634
 635/*
 636 * General functions
 637 */
 638static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
 639{
 640        return container_of(i2c_get_clientdata(client), struct ov2640_priv,
 641                            subdev);
 642}
 643
 644static int ov2640_write_array(struct i2c_client *client,
 645                              const struct regval_list *vals)
 646{
 647        int ret;
 648
 649        while ((vals->reg_num != 0xff) || (vals->value != 0xff)) {
 650                ret = i2c_smbus_write_byte_data(client,
 651                                                vals->reg_num, vals->value);
 652                dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x",
 653                         vals->reg_num, vals->value);
 654
 655                if (ret < 0)
 656                        return ret;
 657                vals++;
 658        }
 659        return 0;
 660}
 661
 662static int ov2640_mask_set(struct i2c_client *client,
 663                           u8  reg, u8  mask, u8  set)
 664{
 665        s32 val = i2c_smbus_read_byte_data(client, reg);
 666        if (val < 0)
 667                return val;
 668
 669        val &= ~mask;
 670        val |= set & mask;
 671
 672        dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val);
 673
 674        return i2c_smbus_write_byte_data(client, reg, val);
 675}
 676
 677static int ov2640_reset(struct i2c_client *client)
 678{
 679        int ret;
 680        const struct regval_list reset_seq[] = {
 681                {BANK_SEL, BANK_SEL_SENS},
 682                {COM7, COM7_SRST},
 683                ENDMARKER,
 684        };
 685
 686        ret = ov2640_write_array(client, reset_seq);
 687        if (ret)
 688                goto err;
 689
 690        msleep(5);
 691err:
 692        dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret);
 693        return ret;
 694}
 695
 696/*
 697 * soc_camera_ops functions
 698 */
 699static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
 700{
 701        return 0;
 702}
 703
 704static int ov2640_set_bus_param(struct soc_camera_device *icd,
 705                                unsigned long flags)
 706{
 707        struct soc_camera_link *icl = to_soc_camera_link(icd);
 708        unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
 709
 710        /* Only one width bit may be set */
 711        if (!is_power_of_2(width_flag))
 712                return -EINVAL;
 713
 714        if (icl->set_bus_param)
 715                return icl->set_bus_param(icl, width_flag);
 716
 717        /*
 718         * Without board specific bus width settings we support only the
 719         * sensors native bus width witch are tested working
 720         */
 721        if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8))
 722                return 0;
 723
 724        return 0;
 725}
 726
 727static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd)
 728{
 729        struct soc_camera_link *icl = to_soc_camera_link(icd);
 730        unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
 731                SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
 732                SOCAM_DATA_ACTIVE_HIGH;
 733
 734        if (icl->query_bus_param)
 735                flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
 736        else
 737                flags |= SOCAM_DATAWIDTH_10;
 738
 739        return soc_camera_apply_sensor_flags(icl, flags);
 740}
 741
 742static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 743{
 744        struct i2c_client  *client = v4l2_get_subdevdata(sd);
 745        struct ov2640_priv *priv = to_ov2640(client);
 746
 747        switch (ctrl->id) {
 748        case V4L2_CID_VFLIP:
 749                ctrl->value = priv->flag_vflip;
 750                break;
 751        case V4L2_CID_HFLIP:
 752                ctrl->value = priv->flag_hflip;
 753                break;
 754        }
 755        return 0;
 756}
 757
 758static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 759{
 760        struct i2c_client  *client = v4l2_get_subdevdata(sd);
 761        struct ov2640_priv *priv = to_ov2640(client);
 762        int ret = 0;
 763        u8 val;
 764
 765        switch (ctrl->id) {
 766        case V4L2_CID_VFLIP:
 767                val = ctrl->value ? REG04_VFLIP_IMG : 0x00;
 768                priv->flag_vflip = ctrl->value ? 1 : 0;
 769                ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
 770                break;
 771        case V4L2_CID_HFLIP:
 772                val = ctrl->value ? REG04_HFLIP_IMG : 0x00;
 773                priv->flag_hflip = ctrl->value ? 1 : 0;
 774                ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
 775                break;
 776        }
 777
 778        return ret;
 779}
 780
 781static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
 782                               struct v4l2_dbg_chip_ident *id)
 783{
 784        struct i2c_client *client = v4l2_get_subdevdata(sd);
 785        struct ov2640_priv *priv = to_ov2640(client);
 786
 787        id->ident    = priv->model;
 788        id->revision = 0;
 789
 790        return 0;
 791}
 792
 793#ifdef CONFIG_VIDEO_ADV_DEBUG
 794static int ov2640_g_register(struct v4l2_subdev *sd,
 795                             struct v4l2_dbg_register *reg)
 796{
 797        struct i2c_client *client = v4l2_get_subdevdata(sd);
 798        int ret;
 799
 800        reg->size = 1;
 801        if (reg->reg > 0xff)
 802                return -EINVAL;
 803
 804        ret = i2c_smbus_read_byte_data(client, reg->reg);
 805        if (ret < 0)
 806                return ret;
 807
 808        reg->val = ret;
 809
 810        return 0;
 811}
 812
 813static int ov2640_s_register(struct v4l2_subdev *sd,
 814                             struct v4l2_dbg_register *reg)
 815{
 816        struct i2c_client *client = v4l2_get_subdevdata(sd);
 817
 818        if (reg->reg > 0xff ||
 819            reg->val > 0xff)
 820                return -EINVAL;
 821
 822        return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
 823}
 824#endif
 825
 826/* Select the nearest higher resolution for capture */
 827static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
 828{
 829        int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1;
 830
 831        for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) {
 832                if (ov2640_supported_win_sizes[i].width  >= *width &&
 833                    ov2640_supported_win_sizes[i].height >= *height) {
 834                        *width = ov2640_supported_win_sizes[i].width;
 835                        *height = ov2640_supported_win_sizes[i].height;
 836                        return &ov2640_supported_win_sizes[i];
 837                }
 838        }
 839
 840        *width = ov2640_supported_win_sizes[default_size].width;
 841        *height = ov2640_supported_win_sizes[default_size].height;
 842        return &ov2640_supported_win_sizes[default_size];
 843}
 844
 845static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
 846                             enum v4l2_mbus_pixelcode code)
 847{
 848        struct ov2640_priv       *priv = to_ov2640(client);
 849        const struct regval_list *selected_cfmt_regs;
 850        int ret;
 851
 852        /* select win */
 853        priv->win = ov2640_select_win(width, height);
 854
 855        /* select format */
 856        priv->cfmt_code = 0;
 857        switch (code) {
 858        case V4L2_MBUS_FMT_RGB565_2X8_LE:
 859                dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__);
 860                selected_cfmt_regs = ov2640_rgb565_regs;
 861                break;
 862        default:
 863        case V4L2_MBUS_FMT_UYVY8_2X8:
 864                dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__);
 865                selected_cfmt_regs = ov2640_yuv422_regs;
 866        }
 867
 868        /* reset hardware */
 869        ov2640_reset(client);
 870
 871        /* initialize the sensor with default data */
 872        dev_dbg(&client->dev, "%s: Init default", __func__);
 873        ret = ov2640_write_array(client, ov2640_init_regs);
 874        if (ret < 0)
 875                goto err;
 876
 877        /* select preamble */
 878        dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name);
 879        ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);
 880        if (ret < 0)
 881                goto err;
 882
 883        /* set size win */
 884        ret = ov2640_write_array(client, priv->win->regs);
 885        if (ret < 0)
 886                goto err;
 887
 888        /* cfmt preamble */
 889        dev_dbg(&client->dev, "%s: Set cfmt", __func__);
 890        ret = ov2640_write_array(client, ov2640_format_change_preamble_regs);
 891        if (ret < 0)
 892                goto err;
 893
 894        /* set cfmt */
 895        ret = ov2640_write_array(client, selected_cfmt_regs);
 896        if (ret < 0)
 897                goto err;
 898
 899        priv->cfmt_code = code;
 900        *width = priv->win->width;
 901        *height = priv->win->height;
 902
 903        return 0;
 904
 905err:
 906        dev_err(&client->dev, "%s: Error %d", __func__, ret);
 907        ov2640_reset(client);
 908        priv->win = NULL;
 909
 910        return ret;
 911}
 912
 913static int ov2640_g_fmt(struct v4l2_subdev *sd,
 914                        struct v4l2_mbus_framefmt *mf)
 915{
 916        struct i2c_client  *client = v4l2_get_subdevdata(sd);
 917        struct ov2640_priv *priv = to_ov2640(client);
 918
 919        if (!priv->win) {
 920                u32 width = W_SVGA, height = H_SVGA;
 921                int ret = ov2640_set_params(client, &width, &height,
 922                                            V4L2_MBUS_FMT_UYVY8_2X8);
 923                if (ret < 0)
 924                        return ret;
 925        }
 926
 927        mf->width       = priv->win->width;
 928        mf->height      = priv->win->height;
 929        mf->code        = priv->cfmt_code;
 930
 931        switch (mf->code) {
 932        case V4L2_MBUS_FMT_RGB565_2X8_LE:
 933                mf->colorspace = V4L2_COLORSPACE_SRGB;
 934                break;
 935        default:
 936        case V4L2_MBUS_FMT_UYVY8_2X8:
 937                mf->colorspace = V4L2_COLORSPACE_JPEG;
 938        }
 939        mf->field       = V4L2_FIELD_NONE;
 940
 941        return 0;
 942}
 943
 944static int ov2640_s_fmt(struct v4l2_subdev *sd,
 945                        struct v4l2_mbus_framefmt *mf)
 946{
 947        struct i2c_client *client = v4l2_get_subdevdata(sd);
 948        int ret;
 949
 950
 951        switch (mf->code) {
 952        case V4L2_MBUS_FMT_RGB565_2X8_LE:
 953                mf->colorspace = V4L2_COLORSPACE_SRGB;
 954                break;
 955        default:
 956                mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 957        case V4L2_MBUS_FMT_UYVY8_2X8:
 958                mf->colorspace = V4L2_COLORSPACE_JPEG;
 959        }
 960
 961        ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code);
 962
 963        return ret;
 964}
 965
 966static int ov2640_try_fmt(struct v4l2_subdev *sd,
 967                          struct v4l2_mbus_framefmt *mf)
 968{
 969        const struct ov2640_win_size *win;
 970
 971        /*
 972         * select suitable win
 973         */
 974        win = ov2640_select_win(&mf->width, &mf->height);
 975
 976        mf->field       = V4L2_FIELD_NONE;
 977
 978        switch (mf->code) {
 979        case V4L2_MBUS_FMT_RGB565_2X8_LE:
 980                mf->colorspace = V4L2_COLORSPACE_SRGB;
 981                break;
 982        default:
 983                mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 984        case V4L2_MBUS_FMT_UYVY8_2X8:
 985                mf->colorspace = V4L2_COLORSPACE_JPEG;
 986        }
 987
 988        return 0;
 989}
 990
 991static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
 992                           enum v4l2_mbus_pixelcode *code)
 993{
 994        if (index >= ARRAY_SIZE(ov2640_codes))
 995                return -EINVAL;
 996
 997        *code = ov2640_codes[index];
 998        return 0;
 999}
1000
1001static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
1002{
1003        a->c.left       = 0;
1004        a->c.top        = 0;
1005        a->c.width      = W_UXGA;
1006        a->c.height     = H_UXGA;
1007        a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1008
1009        return 0;
1010}
1011
1012static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
1013{
1014        a->bounds.left                  = 0;
1015        a->bounds.top                   = 0;
1016        a->bounds.width                 = W_UXGA;
1017        a->bounds.height                = H_UXGA;
1018        a->defrect                      = a->bounds;
1019        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1020        a->pixelaspect.numerator        = 1;
1021        a->pixelaspect.denominator      = 1;
1022
1023        return 0;
1024}
1025
1026static int ov2640_video_probe(struct soc_camera_device *icd,
1027                              struct i2c_client *client)
1028{
1029        struct ov2640_priv *priv = to_ov2640(client);
1030        u8 pid, ver, midh, midl;
1031        const char *devname;
1032        int ret;
1033
1034        /*
1035         * we must have a parent by now. And it cannot be a wrong one.
1036         * So this entire test is completely redundant.
1037         */
1038        if (!icd->dev.parent ||
1039            to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
1040                dev_err(&client->dev, "Parent missing or invalid!\n");
1041                ret = -ENODEV;
1042                goto err;
1043        }
1044
1045        /*
1046         * check and show product ID and manufacturer ID
1047         */
1048        i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
1049        pid  = i2c_smbus_read_byte_data(client, PID);
1050        ver  = i2c_smbus_read_byte_data(client, VER);
1051        midh = i2c_smbus_read_byte_data(client, MIDH);
1052        midl = i2c_smbus_read_byte_data(client, MIDL);
1053
1054        switch (VERSION(pid, ver)) {
1055        case PID_OV2640:
1056                devname     = "ov2640";
1057                priv->model = V4L2_IDENT_OV2640;
1058                break;
1059        default:
1060                dev_err(&client->dev,
1061                        "Product ID error %x:%x\n", pid, ver);
1062                ret = -ENODEV;
1063                goto err;
1064        }
1065
1066        dev_info(&client->dev,
1067                 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
1068                 devname, pid, ver, midh, midl);
1069
1070        return 0;
1071
1072err:
1073        return ret;
1074}
1075
1076static struct soc_camera_ops ov2640_ops = {
1077        .set_bus_param          = ov2640_set_bus_param,
1078        .query_bus_param        = ov2640_query_bus_param,
1079        .controls               = ov2640_controls,
1080        .num_controls           = ARRAY_SIZE(ov2640_controls),
1081};
1082
1083static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
1084        .g_ctrl         = ov2640_g_ctrl,
1085        .s_ctrl         = ov2640_s_ctrl,
1086        .g_chip_ident   = ov2640_g_chip_ident,
1087#ifdef CONFIG_VIDEO_ADV_DEBUG
1088        .g_register     = ov2640_g_register,
1089        .s_register     = ov2640_s_register,
1090#endif
1091};
1092
1093static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
1094        .s_stream       = ov2640_s_stream,
1095        .g_mbus_fmt     = ov2640_g_fmt,
1096        .s_mbus_fmt     = ov2640_s_fmt,
1097        .try_mbus_fmt   = ov2640_try_fmt,
1098        .cropcap        = ov2640_cropcap,
1099        .g_crop         = ov2640_g_crop,
1100        .enum_mbus_fmt  = ov2640_enum_fmt,
1101};
1102
1103static struct v4l2_subdev_ops ov2640_subdev_ops = {
1104        .core   = &ov2640_subdev_core_ops,
1105        .video  = &ov2640_subdev_video_ops,
1106};
1107
1108/*
1109 * i2c_driver functions
1110 */
1111static int ov2640_probe(struct i2c_client *client,
1112                        const struct i2c_device_id *did)
1113{
1114        struct ov2640_priv        *priv;
1115        struct soc_camera_device  *icd = client->dev.platform_data;
1116        struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
1117        struct soc_camera_link    *icl;
1118        int                        ret;
1119
1120        if (!icd) {
1121                dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n");
1122                return -EINVAL;
1123        }
1124
1125        icl = to_soc_camera_link(icd);
1126        if (!icl) {
1127                dev_err(&adapter->dev,
1128                        "OV2640: Missing platform_data for driver\n");
1129                return -EINVAL;
1130        }
1131
1132        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1133                dev_err(&adapter->dev,
1134                        "OV2640: I2C-Adapter doesn't support SMBUS\n");
1135                return -EIO;
1136        }
1137
1138        priv = kzalloc(sizeof(struct ov2640_priv), GFP_KERNEL);
1139        if (!priv) {
1140                dev_err(&adapter->dev,
1141                        "Failed to allocate memory for private data!\n");
1142                return -ENOMEM;
1143        }
1144
1145        priv->info = icl->priv;
1146
1147        v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
1148
1149        icd->ops = &ov2640_ops;
1150
1151        ret = ov2640_video_probe(icd, client);
1152        if (ret) {
1153                icd->ops = NULL;
1154                kfree(priv);
1155        } else {
1156                dev_info(&adapter->dev, "OV2640 Probed\n");
1157        }
1158
1159        return ret;
1160}
1161
1162static int ov2640_remove(struct i2c_client *client)
1163{
1164        struct ov2640_priv       *priv = to_ov2640(client);
1165        struct soc_camera_device *icd = client->dev.platform_data;
1166
1167        icd->ops = NULL;
1168        kfree(priv);
1169        return 0;
1170}
1171
1172static const struct i2c_device_id ov2640_id[] = {
1173        { "ov2640", 0 },
1174        { }
1175};
1176MODULE_DEVICE_TABLE(i2c, ov2640_id);
1177
1178static struct i2c_driver ov2640_i2c_driver = {
1179        .driver = {
1180                .name = "ov2640",
1181        },
1182        .probe    = ov2640_probe,
1183        .remove   = ov2640_remove,
1184        .id_table = ov2640_id,
1185};
1186
1187/*
1188 * Module functions
1189 */
1190static int __init ov2640_module_init(void)
1191{
1192        return i2c_add_driver(&ov2640_i2c_driver);
1193}
1194
1195static void __exit ov2640_module_exit(void)
1196{
1197        i2c_del_driver(&ov2640_i2c_driver);
1198}
1199
1200module_init(ov2640_module_init);
1201module_exit(ov2640_module_exit);
1202
1203MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor");
1204MODULE_AUTHOR("Alberto Panizzo");
1205MODULE_LICENSE("GPL v2");
1206