brintos

brintos / linux-shallow public Read only

0
0
Text · 37.3 KiB · d27fc2d Raw
1300 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ov2640 Camera Driver4 *5 * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>6 *7 * Based on ov772x, ov9640 drivers and previous non merged implementations.8 *9 * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.10 * Copyright (C) 2006, OmniVision11 */12 13#include <linux/init.h>14#include <linux/module.h>15#include <linux/i2c.h>16#include <linux/clk.h>17#include <linux/slab.h>18#include <linux/delay.h>19#include <linux/gpio/consumer.h>20#include <linux/v4l2-mediabus.h>21#include <linux/videodev2.h>22 23#include <media/v4l2-device.h>24#include <media/v4l2-event.h>25#include <media/v4l2-subdev.h>26#include <media/v4l2-ctrls.h>27#include <media/v4l2-image-sizes.h>28 29#define VAL_SET(x, mask, rshift, lshift)  \30		((((x) >> rshift) & mask) << lshift)31/*32 * DSP registers33 * register offset for BANK_SEL == BANK_SEL_DSP34 */35#define R_BYPASS    0x05 /* Bypass DSP */36#define   R_BYPASS_DSP_BYPAS    0x01 /* Bypass DSP, sensor out directly */37#define   R_BYPASS_USE_DSP      0x00 /* Use the internal DSP */38#define QS          0x44 /* Quantization Scale Factor */39#define CTRLI       0x5040#define   CTRLI_LP_DP           0x8041#define   CTRLI_ROUND           0x4042#define   CTRLI_V_DIV_SET(x)    VAL_SET(x, 0x3, 0, 3)43#define   CTRLI_H_DIV_SET(x)    VAL_SET(x, 0x3, 0, 0)44#define HSIZE       0x51 /* H_SIZE[7:0] (real/4) */45#define   HSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)46#define VSIZE       0x52 /* V_SIZE[7:0] (real/4) */47#define   VSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)48#define XOFFL       0x53 /* OFFSET_X[7:0] */49#define   XOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)50#define YOFFL       0x54 /* OFFSET_Y[7:0] */51#define   YOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)52#define VHYX        0x55 /* Offset and size completion */53#define   VHYX_VSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 7)54#define   VHYX_HSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 3)55#define   VHYX_YOFF_SET(x)      VAL_SET(x, 0x3, 8, 4)56#define   VHYX_XOFF_SET(x)      VAL_SET(x, 0x3, 8, 0)57#define DPRP        0x5658#define TEST        0x57 /* Horizontal size completion */59#define   TEST_HSIZE_SET(x)     VAL_SET(x, 0x1, (9+2), 7)60#define ZMOW        0x5A /* Zoom: Out Width  OUTW[7:0] (real/4) */61#define   ZMOW_OUTW_SET(x)      VAL_SET(x, 0xFF, 2, 0)62#define ZMOH        0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */63#define   ZMOH_OUTH_SET(x)      VAL_SET(x, 0xFF, 2, 0)64#define ZMHH        0x5C /* Zoom: Speed and H&W completion */65#define   ZMHH_ZSPEED_SET(x)    VAL_SET(x, 0x0F, 0, 4)66#define   ZMHH_OUTH_SET(x)      VAL_SET(x, 0x1, (8+2), 2)67#define   ZMHH_OUTW_SET(x)      VAL_SET(x, 0x3, (8+2), 0)68#define BPADDR      0x7C /* SDE Indirect Register Access: Address */69#define BPDATA      0x7D /* SDE Indirect Register Access: Data */70#define CTRL2       0x86 /* DSP Module enable 2 */71#define   CTRL2_DCW_EN          0x2072#define   CTRL2_SDE_EN          0x1073#define   CTRL2_UV_ADJ_EN       0x0874#define   CTRL2_UV_AVG_EN       0x0475#define   CTRL2_CMX_EN          0x0176#define CTRL3       0x87 /* DSP Module enable 3 */77#define   CTRL3_BPC_EN          0x8078#define   CTRL3_WPC_EN          0x4079#define SIZEL       0x8C /* Image Size Completion */80#define   SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6)81#define   SIZEL_HSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 3)82#define   SIZEL_VSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 0)83#define HSIZE8      0xC0 /* Image Horizontal Size HSIZE[10:3] */84#define   HSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)85#define VSIZE8      0xC1 /* Image Vertical Size VSIZE[10:3] */86#define   VSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)87#define CTRL0       0xC2 /* DSP Module enable 0 */88#define   CTRL0_AEC_EN       0x8089#define   CTRL0_AEC_SEL      0x4090#define   CTRL0_STAT_SEL     0x2091#define   CTRL0_VFIRST       0x1092#define   CTRL0_YUV422       0x0893#define   CTRL0_YUV_EN       0x0494#define   CTRL0_RGB_EN       0x0295#define   CTRL0_RAW_EN       0x0196#define CTRL1       0xC3 /* DSP Module enable 1 */97#define   CTRL1_CIP          0x8098#define   CTRL1_DMY          0x4099#define   CTRL1_RAW_GMA      0x20100#define   CTRL1_DG           0x10101#define   CTRL1_AWB          0x08102#define   CTRL1_AWB_GAIN     0x04103#define   CTRL1_LENC         0x02104#define   CTRL1_PRE          0x01105/*      REG 0xC7 (unknown name): affects Auto White Balance (AWB)106 *	  AWB_OFF            0x40107 *	  AWB_SIMPLE         0x10108 *	  AWB_ON             0x00	(Advanced AWB ?) */109#define R_DVP_SP    0xD3 /* DVP output speed control */110#define   R_DVP_SP_AUTO_MODE 0x80111#define   R_DVP_SP_DVP_MASK  0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);112				   *          = sysclk (48)/(2*[6:0]) (RAW);*/113#define IMAGE_MODE  0xDA /* Image Output Format Select */114#define   IMAGE_MODE_Y8_DVP_EN   0x40115#define   IMAGE_MODE_JPEG_EN     0x10116#define   IMAGE_MODE_YUV422      0x00117#define   IMAGE_MODE_RAW10       0x04 /* (DVP) */118#define   IMAGE_MODE_RGB565      0x08119#define   IMAGE_MODE_HREF_VSYNC  0x02 /* HREF timing select in DVP JPEG output120				       * mode (0 for HREF is same as sensor) */121#define   IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP122				       *    1: Low byte first UYVY (C2[4] =0)123				       *        VYUY (C2[4] =1)124				       *    0: High byte first YUYV (C2[4]=0)125				       *        YVYU (C2[4] = 1) */126#define RESET       0xE0 /* Reset */127#define   RESET_MICROC       0x40128#define   RESET_SCCB         0x20129#define   RESET_JPEG         0x10130#define   RESET_DVP          0x04131#define   RESET_IPU          0x02132#define   RESET_CIF          0x01133#define REGED       0xED /* Register ED */134#define   REGED_CLK_OUT_DIS  0x10135#define MS_SP       0xF0 /* SCCB Master Speed */136#define SS_ID       0xF7 /* SCCB Slave ID */137#define SS_CTRL     0xF8 /* SCCB Slave Control */138#define   SS_CTRL_ADD_AUTO_INC  0x20139#define   SS_CTRL_EN            0x08140#define   SS_CTRL_DELAY_CLK     0x04141#define   SS_CTRL_ACC_EN        0x02142#define   SS_CTRL_SEN_PASS_THR  0x01143#define MC_BIST     0xF9 /* Microcontroller misc register */144#define   MC_BIST_RESET           0x80 /* Microcontroller Reset */145#define   MC_BIST_BOOT_ROM_SEL    0x40146#define   MC_BIST_12KB_SEL        0x20147#define   MC_BIST_12KB_MASK       0x30148#define   MC_BIST_512KB_SEL       0x08149#define   MC_BIST_512KB_MASK      0x0C150#define   MC_BIST_BUSY_BIT_R      0x02151#define   MC_BIST_MC_RES_ONE_SH_W 0x02152#define   MC_BIST_LAUNCH          0x01153#define BANK_SEL    0xFF /* Register Bank Select */154#define   BANK_SEL_DSP     0x00155#define   BANK_SEL_SENS    0x01156 157/*158 * Sensor registers159 * register offset for BANK_SEL == BANK_SEL_SENS160 */161#define GAIN        0x00 /* AGC - Gain control gain setting */162#define COM1        0x03 /* Common control 1 */163#define   COM1_1_DUMMY_FR          0x40164#define   COM1_3_DUMMY_FR          0x80165#define   COM1_7_DUMMY_FR          0xC0166#define   COM1_VWIN_LSB_UXGA       0x0F167#define   COM1_VWIN_LSB_SVGA       0x0A168#define   COM1_VWIN_LSB_CIF        0x06169#define REG04       0x04 /* Register 04 */170#define   REG04_DEF             0x20 /* Always set */171#define   REG04_HFLIP_IMG       0x80 /* Horizontal mirror image ON/OFF */172#define   REG04_VFLIP_IMG       0x40 /* Vertical flip image ON/OFF */173#define   REG04_VREF_EN         0x10174#define   REG04_HREF_EN         0x08175#define   REG04_AEC_SET(x)      VAL_SET(x, 0x3, 0, 0)176#define REG08       0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */177#define COM2        0x09 /* Common control 2 */178#define   COM2_SOFT_SLEEP_MODE  0x10 /* Soft sleep mode */179				     /* Output drive capability */180#define   COM2_OCAP_Nx_SET(N)   (((N) - 1) & 0x03) /* N = [1x .. 4x] */181#define PID         0x0A /* Product ID Number MSB */182#define VER         0x0B /* Product ID Number LSB */183#define COM3        0x0C /* Common control 3 */184#define   COM3_BAND_50H        0x04 /* 0 For Banding at 60H */185#define   COM3_BAND_AUTO       0x02 /* Auto Banding */186#define   COM3_SING_FR_SNAPSH  0x01 /* 0 For enable live video output after the187				     * snapshot sequence*/188#define AEC         0x10 /* AEC[9:2] Exposure Value */189#define CLKRC       0x11 /* Internal clock */190#define   CLKRC_EN             0x80191#define   CLKRC_DIV_SET(x)     (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */192#define COM7        0x12 /* Common control 7 */193#define   COM7_SRST            0x80 /* Initiates system reset. All registers are194				     * set to factory default values after which195				     * the chip resumes normal operation */196#define   COM7_RES_UXGA        0x00 /* Resolution selectors for UXGA */197#define   COM7_RES_SVGA        0x40 /* SVGA */198#define   COM7_RES_CIF         0x20 /* CIF */199#define   COM7_ZOOM_EN         0x04 /* Enable Zoom mode */200#define   COM7_COLOR_BAR_TEST  0x02 /* Enable Color Bar Test Pattern */201#define COM8        0x13 /* Common control 8 */202#define   COM8_DEF             0xC0203#define   COM8_BNDF_EN         0x20 /* Banding filter ON/OFF */204#define   COM8_AGC_EN          0x04 /* AGC Auto/Manual control selection */205#define   COM8_AEC_EN          0x01 /* Auto/Manual Exposure control */206#define COM9        0x14 /* Common control 9207			  * Automatic gain ceiling - maximum AGC value [7:5]*/208#define   COM9_AGC_GAIN_2x     0x00 /* 000 :   2x */209#define   COM9_AGC_GAIN_4x     0x20 /* 001 :   4x */210#define   COM9_AGC_GAIN_8x     0x40 /* 010 :   8x */211#define   COM9_AGC_GAIN_16x    0x60 /* 011 :  16x */212#define   COM9_AGC_GAIN_32x    0x80 /* 100 :  32x */213#define   COM9_AGC_GAIN_64x    0xA0 /* 101 :  64x */214#define   COM9_AGC_GAIN_128x   0xC0 /* 110 : 128x */215#define COM10       0x15 /* Common control 10 */216#define   COM10_PCLK_HREF      0x20 /* PCLK output qualified by HREF */217#define   COM10_PCLK_RISE      0x10 /* Data is updated at the rising edge of218				     * PCLK (user can latch data at the next219				     * falling edge of PCLK).220				     * 0 otherwise. */221#define   COM10_HREF_INV       0x08 /* Invert HREF polarity:222				     * HREF negative for valid data*/223#define   COM10_VSINC_INV      0x02 /* Invert VSYNC polarity */224#define HSTART      0x17 /* Horizontal Window start MSB 8 bit */225#define HEND        0x18 /* Horizontal Window end MSB 8 bit */226#define VSTART      0x19 /* Vertical Window start MSB 8 bit */227#define VEND        0x1A /* Vertical Window end MSB 8 bit */228#define MIDH        0x1C /* Manufacturer ID byte - high */229#define MIDL        0x1D /* Manufacturer ID byte - low  */230#define AEW         0x24 /* AGC/AEC - Stable operating region (upper limit) */231#define AEB         0x25 /* AGC/AEC - Stable operating region (lower limit) */232#define VV          0x26 /* AGC/AEC Fast mode operating region */233#define   VV_HIGH_TH_SET(x)      VAL_SET(x, 0xF, 0, 4)234#define   VV_LOW_TH_SET(x)       VAL_SET(x, 0xF, 0, 0)235#define REG2A       0x2A /* Dummy pixel insert MSB */236#define FRARL       0x2B /* Dummy pixel insert LSB */237#define ADDVFL      0x2D /* LSB of insert dummy lines in Vertical direction */238#define ADDVFH      0x2E /* MSB of insert dummy lines in Vertical direction */239#define YAVG        0x2F /* Y/G Channel Average value */240#define REG32       0x32 /* Common Control 32 */241#define   REG32_PCLK_DIV_2    0x80 /* PCLK freq divided by 2 */242#define   REG32_PCLK_DIV_4    0xC0 /* PCLK freq divided by 4 */243#define ARCOM2      0x34 /* Zoom: Horizontal start point */244#define REG45       0x45 /* Register 45 */245#define FLL         0x46 /* Frame Length Adjustment LSBs */246#define FLH         0x47 /* Frame Length Adjustment MSBs */247#define COM19       0x48 /* Zoom: Vertical start point */248#define ZOOMS       0x49 /* Zoom: Vertical start point */249#define COM22       0x4B /* Flash light control */250#define COM25       0x4E /* For Banding operations */251#define   COM25_50HZ_BANDING_AEC_MSBS_MASK      0xC0 /* 50Hz Bd. AEC 2 MSBs */252#define   COM25_60HZ_BANDING_AEC_MSBS_MASK      0x30 /* 60Hz Bd. AEC 2 MSBs */253#define   COM25_50HZ_BANDING_AEC_MSBS_SET(x)    VAL_SET(x, 0x3, 8, 6)254#define   COM25_60HZ_BANDING_AEC_MSBS_SET(x)    VAL_SET(x, 0x3, 8, 4)255#define BD50        0x4F /* 50Hz Banding AEC 8 LSBs */256#define   BD50_50HZ_BANDING_AEC_LSBS_SET(x)     VAL_SET(x, 0xFF, 0, 0)257#define BD60        0x50 /* 60Hz Banding AEC 8 LSBs */258#define   BD60_60HZ_BANDING_AEC_LSBS_SET(x)     VAL_SET(x, 0xFF, 0, 0)259#define REG5A       0x5A /* 50/60Hz Banding Maximum AEC Step */260#define   BD50_MAX_AEC_STEP_MASK         0xF0 /* 50Hz Banding Max. AEC Step */261#define   BD60_MAX_AEC_STEP_MASK         0x0F /* 60Hz Banding Max. AEC Step */262#define   BD50_MAX_AEC_STEP_SET(x)       VAL_SET((x - 1), 0x0F, 0, 4)263#define   BD60_MAX_AEC_STEP_SET(x)       VAL_SET((x - 1), 0x0F, 0, 0)264#define REG5D       0x5D /* AVGsel[7:0],   16-zone average weight option */265#define REG5E       0x5E /* AVGsel[15:8],  16-zone average weight option */266#define REG5F       0x5F /* AVGsel[23:16], 16-zone average weight option */267#define REG60       0x60 /* AVGsel[31:24], 16-zone average weight option */268#define HISTO_LOW   0x61 /* Histogram Algorithm Low Level */269#define HISTO_HIGH  0x62 /* Histogram Algorithm High Level */270 271/*272 * ID273 */274#define MANUFACTURER_ID	0x7FA2275#define PID_OV2640	0x2642276#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF))277 278/*279 * Struct280 */281struct regval_list {282	u8 reg_num;283	u8 value;284};285 286struct ov2640_win_size {287	char				*name;288	u32				width;289	u32				height;290	const struct regval_list	*regs;291};292 293 294struct ov2640_priv {295	struct v4l2_subdev		subdev;296	struct media_pad pad;297	struct v4l2_ctrl_handler	hdl;298	u32	cfmt_code;299	struct clk			*clk;300	const struct ov2640_win_size	*win;301 302	struct gpio_desc *resetb_gpio;303	struct gpio_desc *pwdn_gpio;304 305	struct mutex lock; /* lock to protect streaming and power_count */306	bool streaming;307	int power_count;308};309 310/*311 * Registers settings312 */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	{ REG5A,  BD50_MAX_AEC_STEP_SET(6)373		   | BD60_MAX_AEC_STEP_SET(8) },		/* 0x57 */374	{ COM25,  COM25_50HZ_BANDING_AEC_MSBS_SET(0x0bb)375		   | COM25_60HZ_BANDING_AEC_MSBS_SET(0x09c) },	/* 0x00 */376	{ BD50,   BD50_50HZ_BANDING_AEC_LSBS_SET(0x0bb) },	/* 0xbb */377	{ BD60,   BD60_60HZ_BANDING_AEC_LSBS_SET(0x09c) },	/* 0x9c */378	{ BANK_SEL,  BANK_SEL_DSP },379	{ 0xe5,   0x7f },380	{ MC_BIST,  MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },381	{ 0x41,   0x24 },382	{ RESET,  RESET_JPEG | RESET_DVP },383	{ 0x76,   0xff },384	{ 0x33,   0xa0 },385	{ 0x42,   0x20 },386	{ 0x43,   0x18 },387	{ 0x4c,   0x00 },388	{ CTRL3,  CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },389	{ 0x88,   0x3f },390	{ 0xd7,   0x03 },391	{ 0xd9,   0x10 },392	{ R_DVP_SP,  R_DVP_SP_AUTO_MODE | 0x2 },393	{ 0xc8,   0x08 },394	{ 0xc9,   0x80 },395	{ BPADDR, 0x00 },396	{ BPDATA, 0x00 },397	{ BPADDR, 0x03 },398	{ BPDATA, 0x48 },399	{ BPDATA, 0x48 },400	{ BPADDR, 0x08 },401	{ BPDATA, 0x20 },402	{ BPDATA, 0x10 },403	{ BPDATA, 0x0e },404	{ 0x90,   0x00 },405	{ 0x91,   0x0e },406	{ 0x91,   0x1a },407	{ 0x91,   0x31 },408	{ 0x91,   0x5a },409	{ 0x91,   0x69 },410	{ 0x91,   0x75 },411	{ 0x91,   0x7e },412	{ 0x91,   0x88 },413	{ 0x91,   0x8f },414	{ 0x91,   0x96 },415	{ 0x91,   0xa3 },416	{ 0x91,   0xaf },417	{ 0x91,   0xc4 },418	{ 0x91,   0xd7 },419	{ 0x91,   0xe8 },420	{ 0x91,   0x20 },421	{ 0x92,   0x00 },422	{ 0x93,   0x06 },423	{ 0x93,   0xe3 },424	{ 0x93,   0x03 },425	{ 0x93,   0x03 },426	{ 0x93,   0x00 },427	{ 0x93,   0x02 },428	{ 0x93,   0x00 },429	{ 0x93,   0x00 },430	{ 0x93,   0x00 },431	{ 0x93,   0x00 },432	{ 0x93,   0x00 },433	{ 0x93,   0x00 },434	{ 0x93,   0x00 },435	{ 0x96,   0x00 },436	{ 0x97,   0x08 },437	{ 0x97,   0x19 },438	{ 0x97,   0x02 },439	{ 0x97,   0x0c },440	{ 0x97,   0x24 },441	{ 0x97,   0x30 },442	{ 0x97,   0x28 },443	{ 0x97,   0x26 },444	{ 0x97,   0x02 },445	{ 0x97,   0x98 },446	{ 0x97,   0x80 },447	{ 0x97,   0x00 },448	{ 0x97,   0x00 },449	{ 0xa4,   0x00 },450	{ 0xa8,   0x00 },451	{ 0xc5,   0x11 },452	{ 0xc6,   0x51 },453	{ 0xbf,   0x80 },454	{ 0xc7,   0x10 },	/* simple AWB */455	{ 0xb6,   0x66 },456	{ 0xb8,   0xA5 },457	{ 0xb7,   0x64 },458	{ 0xb9,   0x7C },459	{ 0xb3,   0xaf },460	{ 0xb4,   0x97 },461	{ 0xb5,   0xFF },462	{ 0xb0,   0xC5 },463	{ 0xb1,   0x94 },464	{ 0xb2,   0x0f },465	{ 0xc4,   0x5c },466	{ 0xa6,   0x00 },467	{ 0xa7,   0x20 },468	{ 0xa7,   0xd8 },469	{ 0xa7,   0x1b },470	{ 0xa7,   0x31 },471	{ 0xa7,   0x00 },472	{ 0xa7,   0x18 },473	{ 0xa7,   0x20 },474	{ 0xa7,   0xd8 },475	{ 0xa7,   0x19 },476	{ 0xa7,   0x31 },477	{ 0xa7,   0x00 },478	{ 0xa7,   0x18 },479	{ 0xa7,   0x20 },480	{ 0xa7,   0xd8 },481	{ 0xa7,   0x19 },482	{ 0xa7,   0x31 },483	{ 0xa7,   0x00 },484	{ 0xa7,   0x18 },485	{ 0x7f,   0x00 },486	{ 0xe5,   0x1f },487	{ 0xe1,   0x77 },488	{ 0xdd,   0x7f },489	{ CTRL0,  CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN },490	ENDMARKER,491};492 493/*494 * Register settings for window size495 * The preamble, setup the internal DSP to input an UXGA (1600x1200) image.496 * Then the different zooming configurations will setup the output image size.497 */498static const struct regval_list ov2640_size_change_preamble_regs[] = {499	{ BANK_SEL, BANK_SEL_DSP },500	{ RESET, RESET_DVP },501	{ SIZEL, SIZEL_HSIZE8_11_SET(UXGA_WIDTH) |502		 SIZEL_HSIZE8_SET(UXGA_WIDTH) |503		 SIZEL_VSIZE8_SET(UXGA_HEIGHT) },504	{ HSIZE8, HSIZE8_SET(UXGA_WIDTH) },505	{ VSIZE8, VSIZE8_SET(UXGA_HEIGHT) },506	{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |507		 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },508	{ HSIZE, HSIZE_SET(UXGA_WIDTH) },509	{ VSIZE, VSIZE_SET(UXGA_HEIGHT) },510	{ XOFFL, XOFFL_SET(0) },511	{ YOFFL, YOFFL_SET(0) },512	{ VHYX, VHYX_HSIZE_SET(UXGA_WIDTH) | VHYX_VSIZE_SET(UXGA_HEIGHT) |513		VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},514	{ TEST, TEST_HSIZE_SET(UXGA_WIDTH) },515	ENDMARKER,516};517 518#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div)	\519	{ CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) |	\520		 CTRLI_H_DIV_SET(h_div)},		\521	{ ZMOW, ZMOW_OUTW_SET(x) },			\522	{ ZMOH, ZMOH_OUTH_SET(y) },			\523	{ ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) },	\524	{ R_DVP_SP, pclk_div },				\525	{ RESET, 0x00}526 527static const struct regval_list ov2640_qcif_regs[] = {528	PER_SIZE_REG_SEQ(QCIF_WIDTH, QCIF_HEIGHT, 3, 3, 4),529	ENDMARKER,530};531 532static const struct regval_list ov2640_qvga_regs[] = {533	PER_SIZE_REG_SEQ(QVGA_WIDTH, QVGA_HEIGHT, 2, 2, 4),534	ENDMARKER,535};536 537static const struct regval_list ov2640_cif_regs[] = {538	PER_SIZE_REG_SEQ(CIF_WIDTH, CIF_HEIGHT, 2, 2, 8),539	ENDMARKER,540};541 542static const struct regval_list ov2640_vga_regs[] = {543	PER_SIZE_REG_SEQ(VGA_WIDTH, VGA_HEIGHT, 0, 0, 2),544	ENDMARKER,545};546 547static const struct regval_list ov2640_svga_regs[] = {548	PER_SIZE_REG_SEQ(SVGA_WIDTH, SVGA_HEIGHT, 1, 1, 2),549	ENDMARKER,550};551 552static const struct regval_list ov2640_xga_regs[] = {553	PER_SIZE_REG_SEQ(XGA_WIDTH, XGA_HEIGHT, 0, 0, 2),554	{ CTRLI,    0x00},555	ENDMARKER,556};557 558static const struct regval_list ov2640_sxga_regs[] = {559	PER_SIZE_REG_SEQ(SXGA_WIDTH, SXGA_HEIGHT, 0, 0, 2),560	{ CTRLI,    0x00},561	{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },562	ENDMARKER,563};564 565static const struct regval_list ov2640_uxga_regs[] = {566	PER_SIZE_REG_SEQ(UXGA_WIDTH, UXGA_HEIGHT, 0, 0, 0),567	{ CTRLI,    0x00},568	{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },569	ENDMARKER,570};571 572#define OV2640_SIZE(n, w, h, r) \573	{.name = n, .width = w , .height = h, .regs = r }574 575static const struct ov2640_win_size ov2640_supported_win_sizes[] = {576	OV2640_SIZE("QCIF", QCIF_WIDTH, QCIF_HEIGHT, ov2640_qcif_regs),577	OV2640_SIZE("QVGA", QVGA_WIDTH, QVGA_HEIGHT, ov2640_qvga_regs),578	OV2640_SIZE("CIF", CIF_WIDTH, CIF_HEIGHT, ov2640_cif_regs),579	OV2640_SIZE("VGA", VGA_WIDTH, VGA_HEIGHT, ov2640_vga_regs),580	OV2640_SIZE("SVGA", SVGA_WIDTH, SVGA_HEIGHT, ov2640_svga_regs),581	OV2640_SIZE("XGA", XGA_WIDTH, XGA_HEIGHT, ov2640_xga_regs),582	OV2640_SIZE("SXGA", SXGA_WIDTH, SXGA_HEIGHT, ov2640_sxga_regs),583	OV2640_SIZE("UXGA", UXGA_WIDTH, UXGA_HEIGHT, ov2640_uxga_regs),584};585 586/*587 * Register settings for pixel formats588 */589static const struct regval_list ov2640_format_change_preamble_regs[] = {590	{ BANK_SEL, BANK_SEL_DSP },591	{ R_BYPASS, R_BYPASS_USE_DSP },592	ENDMARKER,593};594 595static const struct regval_list ov2640_yuyv_regs[] = {596	{ IMAGE_MODE, IMAGE_MODE_YUV422 },597	{ 0xd7, 0x03 },598	{ 0x33, 0xa0 },599	{ 0xe5, 0x1f },600	{ 0xe1, 0x67 },601	{ RESET,  0x00 },602	{ R_BYPASS, R_BYPASS_USE_DSP },603	ENDMARKER,604};605 606static const struct regval_list ov2640_uyvy_regs[] = {607	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },608	{ 0xd7, 0x01 },609	{ 0x33, 0xa0 },610	{ 0xe1, 0x67 },611	{ RESET,  0x00 },612	{ R_BYPASS, R_BYPASS_USE_DSP },613	ENDMARKER,614};615 616static const struct regval_list ov2640_rgb565_be_regs[] = {617	{ IMAGE_MODE, IMAGE_MODE_RGB565 },618	{ 0xd7, 0x03 },619	{ RESET,  0x00 },620	{ R_BYPASS, R_BYPASS_USE_DSP },621	ENDMARKER,622};623 624static const struct regval_list ov2640_rgb565_le_regs[] = {625	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },626	{ 0xd7, 0x03 },627	{ RESET,  0x00 },628	{ R_BYPASS, R_BYPASS_USE_DSP },629	ENDMARKER,630};631 632static u32 ov2640_codes[] = {633	MEDIA_BUS_FMT_YUYV8_2X8,634	MEDIA_BUS_FMT_UYVY8_2X8,635	MEDIA_BUS_FMT_YVYU8_2X8,636	MEDIA_BUS_FMT_VYUY8_2X8,637	MEDIA_BUS_FMT_RGB565_2X8_BE,638	MEDIA_BUS_FMT_RGB565_2X8_LE,639};640 641/*642 * General functions643 */644static struct ov2640_priv *to_ov2640(const struct i2c_client *client)645{646	return container_of(i2c_get_clientdata(client), struct ov2640_priv,647			    subdev);648}649 650static int ov2640_write_array(struct i2c_client *client,651			      const struct regval_list *vals)652{653	int ret;654 655	while ((vals->reg_num != 0xff) || (vals->value != 0xff)) {656		ret = i2c_smbus_write_byte_data(client,657						vals->reg_num, vals->value);658		dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x",659			 vals->reg_num, vals->value);660 661		if (ret < 0)662			return ret;663		vals++;664	}665	return 0;666}667 668static int ov2640_mask_set(struct i2c_client *client,669			   u8  reg, u8  mask, u8  set)670{671	s32 val = i2c_smbus_read_byte_data(client, reg);672	if (val < 0)673		return val;674 675	val &= ~mask;676	val |= set & mask;677 678	dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val);679 680	return i2c_smbus_write_byte_data(client, reg, val);681}682 683static int ov2640_reset(struct i2c_client *client)684{685	int ret;686	static const struct regval_list reset_seq[] = {687		{BANK_SEL, BANK_SEL_SENS},688		{COM7, COM7_SRST},689		ENDMARKER,690	};691 692	ret = ov2640_write_array(client, reset_seq);693	if (ret)694		goto err;695 696	msleep(5);697err:698	dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret);699	return ret;700}701 702static const char * const ov2640_test_pattern_menu[] = {703	"Disabled",704	"Eight Vertical Colour Bars",705};706 707/*708 * functions709 */710static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)711{712	struct v4l2_subdev *sd =713		&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;714	struct i2c_client  *client = v4l2_get_subdevdata(sd);715	struct ov2640_priv *priv = to_ov2640(client);716	u8 val;717	int ret;718 719	/* v4l2_ctrl_lock() locks our own mutex */720 721	/*722	 * If the device is not powered up by the host driver, do not apply any723	 * controls to H/W at this time. Instead the controls will be restored724	 * when the streaming is started.725	 */726	if (!priv->power_count)727		return 0;728 729	ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);730	if (ret < 0)731		return ret;732 733	switch (ctrl->id) {734	case V4L2_CID_VFLIP:735		val = ctrl->val ? REG04_VFLIP_IMG | REG04_VREF_EN : 0x00;736		return ov2640_mask_set(client, REG04,737				       REG04_VFLIP_IMG | REG04_VREF_EN, val);738		/* NOTE: REG04_VREF_EN: 1 line shift / even/odd line swap */739	case V4L2_CID_HFLIP:740		val = ctrl->val ? REG04_HFLIP_IMG : 0x00;741		return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);742	case V4L2_CID_TEST_PATTERN:743		val = ctrl->val ? COM7_COLOR_BAR_TEST : 0x00;744		return ov2640_mask_set(client, COM7, COM7_COLOR_BAR_TEST, val);745	}746 747	return -EINVAL;748}749 750#ifdef CONFIG_VIDEO_ADV_DEBUG751static int ov2640_g_register(struct v4l2_subdev *sd,752			     struct v4l2_dbg_register *reg)753{754	struct i2c_client *client = v4l2_get_subdevdata(sd);755	int ret;756 757	reg->size = 1;758	if (reg->reg > 0xff)759		return -EINVAL;760 761	ret = i2c_smbus_read_byte_data(client, reg->reg);762	if (ret < 0)763		return ret;764 765	reg->val = ret;766 767	return 0;768}769 770static int ov2640_s_register(struct v4l2_subdev *sd,771			     const struct v4l2_dbg_register *reg)772{773	struct i2c_client *client = v4l2_get_subdevdata(sd);774 775	if (reg->reg > 0xff ||776	    reg->val > 0xff)777		return -EINVAL;778 779	return i2c_smbus_write_byte_data(client, reg->reg, reg->val);780}781#endif782 783static void ov2640_set_power(struct ov2640_priv *priv, int on)784{785#ifdef CONFIG_GPIOLIB786	if (priv->pwdn_gpio)787		gpiod_direction_output(priv->pwdn_gpio, !on);788	if (on && priv->resetb_gpio) {789		/* Active the resetb pin to perform a reset pulse */790		gpiod_direction_output(priv->resetb_gpio, 1);791		usleep_range(3000, 5000);792		gpiod_set_value(priv->resetb_gpio, 0);793	}794#endif795}796 797static int ov2640_s_power(struct v4l2_subdev *sd, int on)798{799	struct i2c_client *client = v4l2_get_subdevdata(sd);800	struct ov2640_priv *priv = to_ov2640(client);801 802	mutex_lock(&priv->lock);803 804	/*805	 * If the power count is modified from 0 to != 0 or from != 0 to 0,806	 * update the power state.807	 */808	if (priv->power_count == !on)809		ov2640_set_power(priv, on);810	priv->power_count += on ? 1 : -1;811	WARN_ON(priv->power_count < 0);812	mutex_unlock(&priv->lock);813 814	return 0;815}816 817/* Select the nearest higher resolution for capture */818static const struct ov2640_win_size *ov2640_select_win(u32 width, u32 height)819{820	int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1;821 822	for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) {823		if (ov2640_supported_win_sizes[i].width  >= width &&824		    ov2640_supported_win_sizes[i].height >= height)825			return &ov2640_supported_win_sizes[i];826	}827 828	return &ov2640_supported_win_sizes[default_size];829}830 831static int ov2640_set_params(struct i2c_client *client,832			     const struct ov2640_win_size *win, u32 code)833{834	const struct regval_list *selected_cfmt_regs;835	u8 val;836	int ret;837 838	switch (code) {839	case MEDIA_BUS_FMT_RGB565_2X8_BE:840		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);841		selected_cfmt_regs = ov2640_rgb565_be_regs;842		break;843	case MEDIA_BUS_FMT_RGB565_2X8_LE:844		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);845		selected_cfmt_regs = ov2640_rgb565_le_regs;846		break;847	case MEDIA_BUS_FMT_YUYV8_2X8:848		dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);849		selected_cfmt_regs = ov2640_yuyv_regs;850		break;851	case MEDIA_BUS_FMT_UYVY8_2X8:852	default:853		dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);854		selected_cfmt_regs = ov2640_uyvy_regs;855		break;856	case MEDIA_BUS_FMT_YVYU8_2X8:857		dev_dbg(&client->dev, "%s: Selected cfmt YVYU", __func__);858		selected_cfmt_regs = ov2640_yuyv_regs;859		break;860	case MEDIA_BUS_FMT_VYUY8_2X8:861		dev_dbg(&client->dev, "%s: Selected cfmt VYUY", __func__);862		selected_cfmt_regs = ov2640_uyvy_regs;863		break;864	}865 866	/* reset hardware */867	ov2640_reset(client);868 869	/* initialize the sensor with default data */870	dev_dbg(&client->dev, "%s: Init default", __func__);871	ret = ov2640_write_array(client, ov2640_init_regs);872	if (ret < 0)873		goto err;874 875	/* select preamble */876	dev_dbg(&client->dev, "%s: Set size to %s", __func__, win->name);877	ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);878	if (ret < 0)879		goto err;880 881	/* set size win */882	ret = ov2640_write_array(client, win->regs);883	if (ret < 0)884		goto err;885 886	/* cfmt preamble */887	dev_dbg(&client->dev, "%s: Set cfmt", __func__);888	ret = ov2640_write_array(client, ov2640_format_change_preamble_regs);889	if (ret < 0)890		goto err;891 892	/* set cfmt */893	ret = ov2640_write_array(client, selected_cfmt_regs);894	if (ret < 0)895		goto err;896	val = (code == MEDIA_BUS_FMT_YVYU8_2X8)897	      || (code == MEDIA_BUS_FMT_VYUY8_2X8) ? CTRL0_VFIRST : 0x00;898	ret = ov2640_mask_set(client, CTRL0, CTRL0_VFIRST, val);899	if (ret < 0)900		goto err;901 902	return 0;903 904err:905	dev_err(&client->dev, "%s: Error %d", __func__, ret);906	ov2640_reset(client);907 908	return ret;909}910 911static int ov2640_get_fmt(struct v4l2_subdev *sd,912		struct v4l2_subdev_state *sd_state,913		struct v4l2_subdev_format *format)914{915	struct v4l2_mbus_framefmt *mf = &format->format;916	struct i2c_client  *client = v4l2_get_subdevdata(sd);917	struct ov2640_priv *priv = to_ov2640(client);918 919	if (format->pad)920		return -EINVAL;921 922	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {923		mf = v4l2_subdev_state_get_format(sd_state, 0);924		format->format = *mf;925		return 0;926	}927 928	mf->width	= priv->win->width;929	mf->height	= priv->win->height;930	mf->code	= priv->cfmt_code;931	mf->colorspace	= V4L2_COLORSPACE_SRGB;932	mf->field	= V4L2_FIELD_NONE;933	mf->ycbcr_enc	= V4L2_YCBCR_ENC_DEFAULT;934	mf->quantization = V4L2_QUANTIZATION_DEFAULT;935	mf->xfer_func	= V4L2_XFER_FUNC_DEFAULT;936 937	return 0;938}939 940static int ov2640_set_fmt(struct v4l2_subdev *sd,941		struct v4l2_subdev_state *sd_state,942		struct v4l2_subdev_format *format)943{944	struct v4l2_mbus_framefmt *mf = &format->format;945	struct i2c_client *client = v4l2_get_subdevdata(sd);946	struct ov2640_priv *priv = to_ov2640(client);947	const struct ov2640_win_size *win;948	int ret = 0;949 950	if (format->pad)951		return -EINVAL;952 953	mutex_lock(&priv->lock);954 955	/* select suitable win */956	win = ov2640_select_win(mf->width, mf->height);957	mf->width	= win->width;958	mf->height	= win->height;959 960	mf->field	= V4L2_FIELD_NONE;961	mf->colorspace	= V4L2_COLORSPACE_SRGB;962	mf->ycbcr_enc	= V4L2_YCBCR_ENC_DEFAULT;963	mf->quantization = V4L2_QUANTIZATION_DEFAULT;964	mf->xfer_func	= V4L2_XFER_FUNC_DEFAULT;965 966	switch (mf->code) {967	case MEDIA_BUS_FMT_RGB565_2X8_BE:968	case MEDIA_BUS_FMT_RGB565_2X8_LE:969	case MEDIA_BUS_FMT_YUYV8_2X8:970	case MEDIA_BUS_FMT_UYVY8_2X8:971	case MEDIA_BUS_FMT_YVYU8_2X8:972	case MEDIA_BUS_FMT_VYUY8_2X8:973		break;974	default:975		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;976		break;977	}978 979	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {980		struct ov2640_priv *priv = to_ov2640(client);981 982		if (priv->streaming) {983			ret = -EBUSY;984			goto out;985		}986		/* select win */987		priv->win = win;988		/* select format */989		priv->cfmt_code = mf->code;990	} else {991		*v4l2_subdev_state_get_format(sd_state, 0) = *mf;992	}993out:994	mutex_unlock(&priv->lock);995 996	return ret;997}998 999static int ov2640_init_state(struct v4l2_subdev *sd,1000			     struct v4l2_subdev_state *sd_state)1001{1002	struct v4l2_mbus_framefmt *try_fmt =1003		v4l2_subdev_state_get_format(sd_state, 0);1004	const struct ov2640_win_size *win =1005		ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT);1006 1007	try_fmt->width = win->width;1008	try_fmt->height = win->height;1009	try_fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;1010	try_fmt->colorspace = V4L2_COLORSPACE_SRGB;1011	try_fmt->field = V4L2_FIELD_NONE;1012	try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;1013	try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT;1014	try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;1015 1016	return 0;1017}1018 1019static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,1020		struct v4l2_subdev_state *sd_state,1021		struct v4l2_subdev_mbus_code_enum *code)1022{1023	if (code->pad || code->index >= ARRAY_SIZE(ov2640_codes))1024		return -EINVAL;1025 1026	code->code = ov2640_codes[code->index];1027	return 0;1028}1029 1030static int ov2640_get_selection(struct v4l2_subdev *sd,1031		struct v4l2_subdev_state *sd_state,1032		struct v4l2_subdev_selection *sel)1033{1034	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)1035		return -EINVAL;1036 1037	switch (sel->target) {1038	case V4L2_SEL_TGT_CROP_BOUNDS:1039	case V4L2_SEL_TGT_CROP:1040		sel->r.left = 0;1041		sel->r.top = 0;1042		sel->r.width = UXGA_WIDTH;1043		sel->r.height = UXGA_HEIGHT;1044		return 0;1045	default:1046		return -EINVAL;1047	}1048}1049 1050static int ov2640_s_stream(struct v4l2_subdev *sd, int on)1051{1052	struct i2c_client *client = v4l2_get_subdevdata(sd);1053	struct ov2640_priv *priv = to_ov2640(client);1054	int ret = 0;1055 1056	mutex_lock(&priv->lock);1057	if (priv->streaming == !on) {1058		if (on) {1059			ret = ov2640_set_params(client, priv->win,1060						priv->cfmt_code);1061			if (!ret)1062				ret = __v4l2_ctrl_handler_setup(&priv->hdl);1063		}1064	}1065	if (!ret)1066		priv->streaming = on;1067	mutex_unlock(&priv->lock);1068 1069	return ret;1070}1071 1072static int ov2640_video_probe(struct i2c_client *client)1073{1074	struct ov2640_priv *priv = to_ov2640(client);1075	u8 pid, ver, midh, midl;1076	const char *devname;1077	int ret;1078 1079	ret = ov2640_s_power(&priv->subdev, 1);1080	if (ret < 0)1081		return ret;1082 1083	/*1084	 * check and show product ID and manufacturer ID1085	 */1086	i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);1087	pid  = i2c_smbus_read_byte_data(client, PID);1088	ver  = i2c_smbus_read_byte_data(client, VER);1089	midh = i2c_smbus_read_byte_data(client, MIDH);1090	midl = i2c_smbus_read_byte_data(client, MIDL);1091 1092	switch (VERSION(pid, ver)) {1093	case PID_OV2640:1094		devname     = "ov2640";1095		break;1096	default:1097		dev_err(&client->dev,1098			"Product ID error %x:%x\n", pid, ver);1099		ret = -ENODEV;1100		goto done;1101	}1102 1103	dev_info(&client->dev,1104		 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",1105		 devname, pid, ver, midh, midl);1106 1107done:1108	ov2640_s_power(&priv->subdev, 0);1109	return ret;1110}1111 1112static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {1113	.s_ctrl = ov2640_s_ctrl,1114};1115 1116static const struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {1117	.log_status = v4l2_ctrl_subdev_log_status,1118	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,1119	.unsubscribe_event = v4l2_event_subdev_unsubscribe,1120#ifdef CONFIG_VIDEO_ADV_DEBUG1121	.g_register	= ov2640_g_register,1122	.s_register	= ov2640_s_register,1123#endif1124	.s_power	= ov2640_s_power,1125};1126 1127static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {1128	.enum_mbus_code = ov2640_enum_mbus_code,1129	.get_selection	= ov2640_get_selection,1130	.get_fmt	= ov2640_get_fmt,1131	.set_fmt	= ov2640_set_fmt,1132};1133 1134static const struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {1135	.s_stream = ov2640_s_stream,1136};1137 1138static const struct v4l2_subdev_ops ov2640_subdev_ops = {1139	.core	= &ov2640_subdev_core_ops,1140	.pad	= &ov2640_subdev_pad_ops,1141	.video	= &ov2640_subdev_video_ops,1142};1143 1144static const struct v4l2_subdev_internal_ops ov2640_internal_ops = {1145	.init_state	= ov2640_init_state,1146};1147 1148static int ov2640_probe_dt(struct i2c_client *client,1149		struct ov2640_priv *priv)1150{1151	int ret;1152 1153	/* Request the reset GPIO deasserted */1154	priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb",1155			GPIOD_OUT_LOW);1156 1157	if (!priv->resetb_gpio)1158		dev_dbg(&client->dev, "resetb gpio is not assigned!\n");1159 1160	ret = PTR_ERR_OR_ZERO(priv->resetb_gpio);1161	if (ret && ret != -ENOSYS) {1162		dev_dbg(&client->dev,1163			"Error %d while getting resetb gpio\n", ret);1164		return ret;1165	}1166 1167	/* Request the power down GPIO asserted */1168	priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn",1169			GPIOD_OUT_HIGH);1170 1171	if (!priv->pwdn_gpio)1172		dev_dbg(&client->dev, "pwdn gpio is not assigned!\n");1173 1174	ret = PTR_ERR_OR_ZERO(priv->pwdn_gpio);1175	if (ret && ret != -ENOSYS) {1176		dev_dbg(&client->dev,1177			"Error %d while getting pwdn gpio\n", ret);1178		return ret;1179	}1180 1181	return 0;1182}1183 1184/*1185 * i2c_driver functions1186 */1187static int ov2640_probe(struct i2c_client *client)1188{1189	struct ov2640_priv	*priv;1190	struct i2c_adapter	*adapter = client->adapter;1191	int			ret;1192 1193	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {1194		dev_err(&adapter->dev,1195			"OV2640: I2C-Adapter doesn't support SMBUS\n");1196		return -EIO;1197	}1198 1199	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);1200	if (!priv)1201		return -ENOMEM;1202 1203	if (client->dev.of_node) {1204		priv->clk = devm_clk_get_enabled(&client->dev, "xvclk");1205		if (IS_ERR(priv->clk))1206			return PTR_ERR(priv->clk);1207	}1208 1209	ret = ov2640_probe_dt(client, priv);1210	if (ret)1211		return ret;1212 1213	priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT);1214	priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;1215 1216	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);1217	priv->subdev.internal_ops = &ov2640_internal_ops;1218	priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |1219			      V4L2_SUBDEV_FL_HAS_EVENTS;1220	mutex_init(&priv->lock);1221	v4l2_ctrl_handler_init(&priv->hdl, 3);1222	priv->hdl.lock = &priv->lock;1223	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,1224			V4L2_CID_VFLIP, 0, 1, 1, 0);1225	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,1226			V4L2_CID_HFLIP, 0, 1, 1, 0);1227	v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov2640_ctrl_ops,1228			V4L2_CID_TEST_PATTERN,1229			ARRAY_SIZE(ov2640_test_pattern_menu) - 1, 0, 0,1230			ov2640_test_pattern_menu);1231	priv->subdev.ctrl_handler = &priv->hdl;1232	if (priv->hdl.error) {1233		ret = priv->hdl.error;1234		goto err_hdl;1235	}1236	priv->pad.flags = MEDIA_PAD_FL_SOURCE;1237	priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;1238	ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad);1239	if (ret < 0)1240		goto err_hdl;1241 1242	ret = ov2640_video_probe(client);1243	if (ret < 0)1244		goto err_videoprobe;1245 1246	ret = v4l2_async_register_subdev(&priv->subdev);1247	if (ret < 0)1248		goto err_videoprobe;1249 1250	dev_info(&adapter->dev, "OV2640 Probed\n");1251 1252	return 0;1253 1254err_videoprobe:1255	media_entity_cleanup(&priv->subdev.entity);1256err_hdl:1257	v4l2_ctrl_handler_free(&priv->hdl);1258	mutex_destroy(&priv->lock);1259	return ret;1260}1261 1262static void ov2640_remove(struct i2c_client *client)1263{1264	struct ov2640_priv       *priv = to_ov2640(client);1265 1266	v4l2_async_unregister_subdev(&priv->subdev);1267	v4l2_ctrl_handler_free(&priv->hdl);1268	mutex_destroy(&priv->lock);1269	media_entity_cleanup(&priv->subdev.entity);1270	v4l2_device_unregister_subdev(&priv->subdev);1271}1272 1273static const struct i2c_device_id ov2640_id[] = {1274	{ "ov2640" },1275	{ }1276};1277MODULE_DEVICE_TABLE(i2c, ov2640_id);1278 1279static const struct of_device_id ov2640_of_match[] = {1280	{.compatible = "ovti,ov2640", },1281	{},1282};1283MODULE_DEVICE_TABLE(of, ov2640_of_match);1284 1285static struct i2c_driver ov2640_i2c_driver = {1286	.driver = {1287		.name = "ov2640",1288		.of_match_table = ov2640_of_match,1289	},1290	.probe    = ov2640_probe,1291	.remove   = ov2640_remove,1292	.id_table = ov2640_id,1293};1294 1295module_i2c_driver(ov2640_i2c_driver);1296 1297MODULE_DESCRIPTION("Driver for Omni Vision 2640 sensor");1298MODULE_AUTHOR("Alberto Panizzo");1299MODULE_LICENSE("GPL v2");1300