/*
* ov2640 Camera Driver
*
* Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>
*
* Based on ov772x, ov9640 drivers and previous non merged implementations.
*
* Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2006, OmniVision
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/v4l2-mediabus.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-image-sizes.h>
#define VAL_SET(x, mask, rshift, lshift) \
((((x) >> rshift) & mask) << lshift)
/*
* DSP registers
* register offset for BANK_SEL == BANK_SEL_DSP
*/
#define R_BYPASS 0x05 /* Bypass DSP */
#define R_BYPASS_DSP_BYPAS 0x01 /* Bypass DSP, sensor out directly */
#define R_BYPASS_USE_DSP 0x00 /* Use the internal DSP */
#define QS 0x44 /* Quantization Scale Factor */
#define CTRLI 0x50
#define CTRLI_LP_DP 0x80
#define CTRLI_ROUND 0x40
#define CTRLI_V_DIV_SET(x) VAL_SET(x, 0x3, 0, 3)
#define CTRLI_H_DIV_SET(x) VAL_SET(x, 0x3, 0, 0)
#define HSIZE 0x51 /* H_SIZE[7:0] (real/4) */
#define HSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0)
#define VSIZE 0x52 /* V_SIZE[7:0] (real/4) */
#define VSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0)
#define XOFFL 0x53 /* OFFSET_X[7:0] */
#define XOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0)
#define YOFFL 0x54 /* OFFSET_Y[7:0] */
#define YOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0)
#define VHYX 0x55 /* Offset and size completion */
#define VHYX_VSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 7)
#define VHYX_HSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 3)
#define VHYX_YOFF_SET(x) VAL_SET(x, 0x3, 8, 4)
#define VHYX_XOFF_SET(x) VAL_SET(x, 0x3, 8, 0)
#define DPRP 0x56
#define TEST 0x57 /* Horizontal size completion */
#define TEST_HSIZE_SET(x) VAL_SET(x, 0x1, (9+2), 7)
#define ZMOW 0x5A /* Zoom: Out Width OUTW[7:0] (real/4) */
#define ZMOW_OUTW_SET(x) VAL_SET(x, 0xFF, 2, 0)
#define ZMOH 0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */
#define ZMOH_OUTH_SET(x) VAL_SET(x, 0xFF, 2, 0)
#define ZMHH 0x5C /* Zoom: Speed and H&W completion */
#define ZMHH_ZSPEED_SET(x) VAL_SET(x, 0x0F, 0, 4)
#define ZMHH_OUTH_SET(x) VAL_SET(x, 0x1, (8+2), 2)
#define ZMHH_OUTW_SET(x) VAL_SET(x, 0x3, (8+2), 0)
#define BPADDR 0x7C /* SDE Indirect Register Access: Address */
#define BPDATA 0x7D /* SDE Indirect Register Access: Data */
#define CTRL2 0x86 /* DSP Module enable 2 */
#define CTRL2_DCW_EN 0x20
#define CTRL2_SDE_EN 0x10
#define CTRL2_UV_ADJ_EN 0x08
#define CTRL2_UV_AVG_EN 0x04
#define CTRL2_CMX_EN 0x01
#define CTRL3 0x87 /* DSP Module enable 3 */
#define CTRL3_BPC_EN 0x80
#define CTRL3_WPC_EN 0x40
#define SIZEL 0x8C /* Image Size Completion */
#define SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6)
#define SIZEL_HSIZE8_SET(x) VAL_SET(x, 0x7, 0, 3)
#define SIZEL_VSIZE8_SET(x) VAL_SET(x, 0x7, 0, 0)
#define HSIZE8 0xC0 /* Image Horizontal Size HSIZE[10:3] */
#define HSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0)
#define VSIZE8 0xC1 /* Image Vertical Size VSIZE[10:3] */
#define VSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0)
#define CTRL0 0xC2 /* DSP Module enable 0 */
#define CTRL0_AEC_EN 0x80
#define CTRL0_AEC_SEL 0x40
#define CTRL0_STAT_SEL 0x20
#define CTRL0_VFIRST 0x10
#define CTRL0_YUV422 0x08
#define CTRL0_YUV_EN 0x04
#define CTRL0_RGB_EN 0x02
#define CTRL0_RAW_EN 0x01
#define CTRL1 0xC3 /* DSP Module enable 1 */
#define CTRL1_CIP 0x80
#define CTRL1_DMY 0x40
#define CTRL1_RAW_GMA 0x20
#define CTRL1_DG 0x10
#define CTRL1_AWB 0x08
#define CTRL1_AWB_GAIN 0x04
#define CTRL1_LENC 0x02
#define CTRL1_PRE 0x01
/* REG 0xC7 (unknown name): affects Auto White Balance (AWB)
* AWB_OFF 0x40
* AWB_SIMPLE 0x10
* AWB_ON 0x00 (Advanced AWB ?) */
#define R_DVP_SP 0xD3 /* DVP output speed control */
#define R_DVP_SP_AUTO_MODE 0x80
#define R_DVP_SP_DVP_MASK 0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);
* = sysclk (48)/(2*[6:0]) (RAW);*/
#define IMAGE_MODE 0xDA /* Image Output Format Select */
#define IMAGE_MODE_Y8_DVP_EN 0x40
#define IMAGE_MODE_JPEG_EN 0x10
#define IMAGE_MODE_YUV422 0x00
#define IMAGE_MODE_RAW10 0x04 /* (DVP) */
#define IMAGE_MODE_RGB565 0x08
#define IMAGE_MODE_HREF_VSYNC 0x02 /* HREF timing select in DVP JPEG output
* mode (0 for HREF is same as sensor) */
#define IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP
* 1: Low byte first UYVY (C2[4] =0)
* VYUY (C2[4] =1)
* 0: High byte first YUYV (C2[4]=0)
* YVYU (C2[4] = 1) */
#define RESET 0xE0 /* Reset */
#define RESET_MICROC 0x40
#define RESET_SCCB 0x20
#define RESET_JPEG 0x10
#define RESET_DVP 0x04
#define RESET_IPU 0x02
#define RESET_CIF 0x01
#define REGED 0xED /* Register ED */
#define REGED_CLK_OUT_DIS 0x10
#define MS_SP 0xF0 /* SCCB Master Speed */
#define SS_ID 0xF7 /* SCCB Slave ID */
#define SS_CTRL 0xF8 /* SCCB Slave Control */
#define SS_CTRL_ADD_AUTO_INC 0x20
#define SS_CTRL_EN 0x08
#define SS_CTRL_DELAY_CLK 0x04
#define SS_CTRL_ACC_EN 0x02
#define SS_CTRL_SEN_PASS_THR 0x01
#define MC_BIST 0xF9 /* Microcontroller misc register */
#define MC_BIST_RESET 0x80 /* Microcontroller Reset */
#define MC_BIST_BOOT_ROM_SEL 0x40
#define MC_BIST_12KB_SEL 0x20
#define MC_BIST_12KB_MASK 0x30
#define MC_BIST_512KB_SEL 0x08
#define MC_BIST_512KB_MASK 0x0C
#define MC_BIST_BUSY_BIT_R 0x02
#define MC_BIST_MC_RES_ONE_SH_W 0x02
#define MC_BIST_LAUNCH 0x01
#define BANK_SEL 0xFF /* Register Bank Select */
#define BANK_SEL_DSP 0x00
#define BANK_SEL_SENS 0x01
/*
* Sensor registers
* register offset for BANK_SEL == BANK_SEL_SENS
*/
#define GAIN 0x00 /* AGC - Gain control gain setting */
#define COM1 0x03 /* Common control 1 */
#define COM1_1_DUMMY_FR 0x40
#define COM1_3_DUMMY_FR 0x80
#define COM1_7_DUMMY_FR 0xC0
#define COM1_VWIN_LSB_UXGA 0x0F
#define COM1_VWIN_LSB_SVGA 0x0A
#define COM1_VWIN_LSB_CIF 0x06
#define REG04 0x04 /* Register 04 */
#define REG04_DEF 0x20 /* A