camera: add mv9335+ov56550 driver,version upated to 0.2.0x1e.
authorzyc <zyc@rock-chips.com>
Thu, 10 Jan 2013 06:25:40 +0000 (14:25 +0800)
committerzyc <zyc@rock-chips.com>
Thu, 10 Jan 2013 06:25:40 +0000 (14:25 +0800)
arch/arm/mach-rk30/board-rk30-sdk-camera.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/mv9335/Kconfig [new file with mode: 0755]
drivers/media/video/mv9335/Makefile [new file with mode: 0755]
drivers/media/video/mv9335/mv9335.c [new file with mode: 0755]
drivers/media/video/rk30_camera_oneframe.c
drivers/media/video/soc_camera.c
include/linux/videodev2.h

index 00cae90a324f5faac75bc2e44049d6a31b395559..b8caa107eee1e61e801fffef6b1cc1660eb01801 100644 (file)
 #define CONFIG_SENSOR_POWERDOWN_IOCTL_USR         0
 #define CONFIG_SENSOR_FLASH_IOCTL_USR     0
 
-static void rk_cif_power(int on)
+static void rk_cif_power(struct rk29camera_gpio_res *res,int on)
 {
     struct regulator *ldo_18,*ldo_28;
+       int camera_power = res->gpio_power;
+         int camera_ioflag = res->gpio_flag;
+         int camera_io_init = res->gpio_init;
+         
        ldo_28 = regulator_get(NULL, "ldo7");   // vcc28_cif
        ldo_18 = regulator_get(NULL, "ldo1");   // vcc18_cif
        if (ldo_28 == NULL || IS_ERR(ldo_28) || ldo_18 == NULL || IS_ERR(ldo_18)){
@@ -170,7 +174,13 @@ static void rk_cif_power(int on)
        regulator_put(ldo_28);
        regulator_disable(ldo_18);
        regulator_put(ldo_18);
-       mdelay(500);
+       mdelay(10);
+       if (camera_power != INVALID_GPIO)  {
+                 if (camera_io_init & RK29_CAM_POWERACTIVE_MASK) {
+                         gpio_set_value(camera_power, (((~camera_ioflag)&RK29_CAM_POWERACTIVE_MASK)>>RK29_CAM_POWERACTIVE_BITPOS));
+                       //  dprintk("%s..%s..PowerPin=%d ..PinLevel = %x         \n",__FUNCTION__,res->dev_name, camera_power, (((~camera_ioflag)&RK29_CAM_POWERACTIVE_MASK)>>RK29_CAM_POWERACTIVE_BITPOS));
+                       }
+               }
         }
     else{
        regulator_set_voltage(ldo_28, 2800000, 2800000);
@@ -183,14 +193,22 @@ static void rk_cif_power(int on)
        regulator_enable(ldo_18);
     // printk("%s set ldo1 vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_18));
        regulator_put(ldo_18);
-        }
+       if (camera_power != INVALID_GPIO)  {
+                 if (camera_io_init & RK29_CAM_POWERACTIVE_MASK) {
+                       gpio_set_value(camera_power, ((camera_ioflag&RK29_CAM_POWERACTIVE_MASK)>>RK29_CAM_POWERACTIVE_BITPOS));
+                       //dprintk("%s..%s..PowerPin=%d ..PinLevel = %x   \n",__FUNCTION__,res->dev_name, camera_power, ((camera_ioflag&RK29_CAM_POWERACTIVE_MASK)>>RK29_CAM_POWERACTIVE_BITPOS));
+                       mdelay(10);
+                       }
+       }
+
+    }
 }
 
 #if CONFIG_SENSOR_POWER_IOCTL_USR
 static int sensor_power_usr_cb (struct rk29camera_gpio_res *res,int on)
 {
        //#error "CONFIG_SENSOR_POWER_IOCTL_USR is 1, sensor_power_usr_cb function must be writed!!";
-    rk_cif_power(on);
+    rk_cif_power(res,on);
        return 0;
 }
 #endif
index 009e8fc41605d89e6ae616d2c03cca8fd05f5740..a7292cf75a6c0dbf594c35578e981b95da7e2e3b 100755 (executable)
@@ -1304,18 +1304,7 @@ config S5K5CA_USER_DEFINED_SERIES
        depends on SOC_CAMERA_S5K5CA
        bool "s5k5ca user defined init series"
        default n
-
-config SOC_CAMERA_MTK9335ISP
-        tristate "mtk9335isp camera support for rockchip"
-        depends on SOC_CAMERA && I2C
-        help
-          This is a mtk9335isp camera driver for rockchip
-
-config MTK9335ISP_USER_DEFINED_SERIES
-        depends on SOC_CAMERA_MTK9335ISP
-        bool "mtk9335isp user defined init series"
-        default n
-
+       
 config SOC_CAMERA_SP0838
        tristate "sp0838 camera support for rockchip"
        depends on SOC_CAMERA && I2C
@@ -1360,6 +1349,13 @@ config OV9740_USER_DEFINED_SERIES
        depends on SOC_CAMERA_OV9740
        bool "OV9740 user defined init series"
        default n
+config SOC_CAMERA_MV9335
+        tristate "MtekVision camera isp chip"
+        depends on SOC_CAMERA && I2C
+        help
+          MtekVision camera isp chip
+
+source "drivers/media/video/mv9335/Kconfig"    
 
 config MX1_VIDEO
        bool
index 10086289cb289b1ca59dcea8124832f5a7c849b5..0f739fc8289cf30d9f659fae716d901ee760df8b 100755 (executable)
@@ -118,7 +118,8 @@ obj-$(CONFIG_SOC_CAMERA_GC0329)     += gc0329.o
 obj-$(CONFIG_SOC_CAMERA_SP0838)        += sp0838.o
 obj-$(CONFIG_SOC_CAMERA_SP2518)        += sp2518.o
 obj-$(CONFIG_SOC_CAMERA_S5K5CA)        += s5k5ca.o
-obj-$(CONFIG_SOC_CAMERA_MTK9335ISP) += mtk9335isp.o
+obj-$(CONFIG_SOC_CAMERA_MV9335) += mv9335/
+
 # And now the v4l2 drivers:
 
 obj-$(CONFIG_VIDEO_BT848) += bt8xx/
diff --git a/drivers/media/video/mv9335/Kconfig b/drivers/media/video/mv9335/Kconfig
new file mode 100755 (executable)
index 0000000..5ffe46a
--- /dev/null
@@ -0,0 +1,12 @@
+#
+#  Fujitsu camera isp chip: m6moj.
+#
+choice
+       prompt "Camera Sensor attached to mv9335"
+       depends on SOC_CAMERA_MV9335
+       default n
+config MV9335_OV5650
+       tristate "mv9335 attached ov5650"
+       help
+       Choose Y here if you have this this sensor and it is attach to mv9335
+endchoice
diff --git a/drivers/media/video/mv9335/Makefile b/drivers/media/video/mv9335/Makefile
new file mode 100755 (executable)
index 0000000..cde0ceb
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for Fujitsu isp driver
+#
+mv9335_drv-objs += mv9335.o
+obj-y  += mv9335_drv.o
+
diff --git a/drivers/media/video/mv9335/mv9335.c b/drivers/media/video/mv9335/mv9335.c
new file mode 100755 (executable)
index 0000000..44acfba
--- /dev/null
@@ -0,0 +1,2794 @@
+#include <linux/videodev2.h>\r
+#include <linux/slab.h>\r
+#include <linux/i2c.h>\r
+#include <linux/log2.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/delay.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/miscdevice.h>\r
+#include <media/v4l2-common.h>\r
+#include <media/v4l2-chip-ident.h>\r
+#include <media/soc_camera.h>\r
+#include <plat/rk_camera.h>\r
+#include <linux/fs.h>\r
+#include <asm/uaccess.h>\r
+#include <linux/mm.h>\r
+#include <linux/firmware.h>\r
+\r
+static int debug = 3;\r
+module_param(debug, int, S_IRUGO|S_IWUSR);\r
+\r
+#define dprintk(level, fmt, arg...) do {                       \\r
+       if (debug >= level)                                     \\r
+       printk(KERN_WARNING fmt , ## arg); } while (0)\r
+\r
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)\r
+#define SENSOR_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)\r
+\r
+#define _CONS(a,b) a##b\r
+#define CONS(a,b) _CONS(a,b)\r
+\r
+#define __STR(x) #x\r
+#define _STR(x) __STR(x)\r
+#define STR(x) _STR(x)\r
+\r
+#define MIN(x,y)   ((x<y) ? x: y)\r
+#define MAX(x,y)    ((x>y) ? x: y)\r
+\r
+/* Sensor Driver Configuration */\r
+#define SENSOR_NAME RK29_CAM_ISP_MTK9335\r
+#define SENSOR_V4L2_IDENT V4L2_IDENT_MTK9335ISP\r
+#define SENSOR_ID 0x35\r
+#define SENSOR_MIN_WIDTH    640//176\r
+#define SENSOR_MIN_HEIGHT   480//144\r
+#define SENSOR_MAX_WIDTH    2592\r
+#define SENSOR_MAX_HEIGHT   1944\r
+#define SENSOR_INIT_WIDTH      640                     /* Sensor pixel size for sensor_init_data array */\r
+#define SENSOR_INIT_HEIGHT  480\r
+#define SENSOR_INIT_WINSEQADR sensor_vga\r
+#define SENSOR_INIT_PIXFMT V4L2_MBUS_FMT_YUYV8_2X8\r
+\r
+#define CONFIG_SENSOR_WhiteBalance     1\r
+#define CONFIG_SENSOR_Brightness       0\r
+#define CONFIG_SENSOR_Contrast      0\r
+#define CONFIG_SENSOR_Saturation    0\r
+#define CONFIG_SENSOR_Effect        1\r
+#define CONFIG_SENSOR_Scene         1\r
+#define CONFIG_SENSOR_DigitalZoom   0\r
+#define CONFIG_SENSOR_Focus         1\r
+#define CONFIG_SENSOR_Exposure      1\r
+#define CONFIG_SENSOR_Flash         0\r
+#define CONFIG_SENSOR_Mirror        0\r
+#define CONFIG_SENSOR_Flip          0\r
+#define CONFIG_SENSOR_FOCUS_ZONE   1\r
+#define CONFIG_SENSOR_FACE_DETECT   1\r
+\r
+#if CONFIG_SENSOR_Focus\r
+#define SENSOR_AF_MODE_CLOSE 0 \r
+#define SENSOR_AF_SINGLE 1\r
+#define SENSOR_AF_MACRO 2\r
+#define SENSOR_AF_CONTINUOUS 5\r
+#define SENSOR_AF_CONTINUOUS_OFF 6\r
+static int sensor_set_auto_focus(struct i2c_client *client, int value);\r
+#endif\r
+\r
+#define CONFIG_SENSOR_I2C_SPEED     400000       /* Hz */\r
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */\r
+#define CONFIG_SENSOR_I2C_NOSCHED   0\r
+#define CONFIG_SENSOR_I2C_RDWRCHK   0\r
+\r
+#define SENSOR_BUS_PARAM  (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\\r
+                          SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\\r
+                          SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8  |SOCAM_MCLK_24MHZ)\r
+\r
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))\r
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)\r
+// Using define data \r
+\r
+#define   I2C_IDLE   1 \r
+#define   I2C_STATUS_REG2  0x0D \r
+#define   DEV_ID_MV9335_I2CSLAVE_FLASH_PRO (0x40 >> 1) \r
+#define   get_lsb(x)        (char)((u16)(x)& 0xFF)\r
+#define   get_msb(x)        (char)(((u16)(x)>>8)& 0xFF)\r
+#define   FLASH_ERASE_BY_SECTOR 0\r
+#define   FLASH_ERASE_ALL 1\r
+#define   WRITE_READ_CHECK 0\r
+#define   FLASH_WRITE_CHECK 0\r
+\r
+#define    PRODUCT_ID_VALUE_REG0 0x93\r
+#define    PRODUCT_VERSION_VALUE_REG1 0x35\r
+#define    I2C_CHECKE_VALUE_REG5 0x50\r
+#define    CHECKE_VALUE_REG6 0x80\r
+\r
+#define FWVERSION (0x09)\r
+#if (FWVERSION == 0x03)\r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x03.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x03\r
+#define    CHECKE_VALUE_REG0X90 0x3c\r
+#define    CHECKE_VALUE_REG0X91 0x88\r
+#elif(FWVERSION == 0x04)\r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x04.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x04\r
+#define    CHECKE_VALUE_REG0X90 0xa4\r
+#define    CHECKE_VALUE_REG0X91 0x5e\r
+#elif(FWVERSION == 0x05) //no focus\r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x05.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x05\r
+#define    CHECKE_VALUE_REG0X90 0x51\r
+#define    CHECKE_VALUE_REG0X91 0x54\r
+#elif(FWVERSION == 0x06) \r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x06.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x06\r
+#define    CHECKE_VALUE_REG0X90 0x90\r
+#define    CHECKE_VALUE_REG0X91 0xe7\r
+#elif(FWVERSION == 0x07) \r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x07.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x07\r
+#define    CHECKE_VALUE_REG0X90 0x22\r
+#define    CHECKE_VALUE_REG0X91 0x8a\r
+#elif(FWVERSION == 0x08) \r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x08.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x08\r
+#define    CHECKE_VALUE_REG0X90 0x7a\r
+#define    CHECKE_VALUE_REG0X91 0x32\r
+#elif(FWVERSION == 0x09) \r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x09.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x09\r
+#define    CHECKE_VALUE_REG0X90 0x48\r
+#define    CHECKE_VALUE_REG0X91 0x3e\r
+\r
+#else\r
+const char fw_name[] = {"mv9335_DS1001B_RK3066_OV5653_v1_0x09.bin"};\r
+#define    FIRMWARE_MAJOR_VERSION_VALUE_REG2 0x01\r
+#define    FIRMWARE_MINOR_VERSION_VALUE_REG3 0x09\r
+#define    CHECKE_VALUE_REG0X90 0x48\r
+#define    CHECKE_VALUE_REG0X91 0x3e\r
+#endif\r
+struct reginfo\r
+{\r
+    u8 reg;\r
+    u8 val;\r
+};\r
+       \r
+/* only one fixed colorspace per pixelcode */\r
+struct sensor_datafmt {\r
+       enum v4l2_mbus_pixelcode code;\r
+       enum v4l2_colorspace colorspace;\r
+};     \r
+\r
+enum ISP_OUTPUT_RES{\r
+    OUTPUT_QCIF =0x0001, // 176*144\r
+    OUTPUT_HQVGA=0x0002,// 240*160\r
+    OUTPUT_QVGA =0x0004, // 320*240\r
+    OUTPUT_CIF  =0x0008,  // 352*288\r
+    OUTPUT_VGA  =0x0010,  // 640*480\r
+    OUTPUT_SVGA =0x0020, // 800*600\r
+    OUTPUT_720P =0x0040, // 1280*720\r
+    OUTPUT_XGA  =0x0080,  // 1024*768\r
+    OUTPUT_SXGA =0x0100, // 1280*1024\r
+    OUTPUT_UXGA =0x0200, // 1600*1200\r
+    OUTPUT_1080P=0x0400, //1920*1080\r
+    OUTPUT_QXGA =0x0800,  // 2048*1536\r
+    OUTPUT_QSXGA=0x1000, // 2592*1944\r
+};\r
+static u8 sendI2cCmd(struct i2c_client *client,u8 cmd, u8 dat); \r
+static int isp_i2c_read(struct i2c_client *client, u8 reg, u8 *val,u16 ext_addr);\r
+static int flash_read_firmware_data(struct i2c_client *client,u16 addr,u8* rd_data,int readcount);\r
+static int flash_read_data(struct i2c_client *client,u8* rd_data,int readcount);\r
+static int isp_init_check(struct i2c_client *client);\r
+static int isp_init_cmds(struct i2c_client *client);\r
+static struct soc_camera_ops sensor_ops;\r
+\r
+#if CONFIG_SENSOR_DigitalZoom\r
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value);\r
+#endif \r
+\r
+\r
+struct focus_zone_s{\r
+u8 lx;\r
+u8 ty;\r
+u8 rx;\r
+u8 dy;\r
+};\r
+\r
+//flash and focus must be considered.\r
+\r
+//soft isp or external isp used\r
+//if soft isp is defined , the value in this sturct is used in cif driver . cif driver use this value to do isp func.\r
+//value of this sturct MUST be defined(initialized) correctly. \r
+struct isp_data{\r
+\r
+       //focus\r
+       //flash\r
+         int focus;\r
+    int auto_focus;\r
+    int flash;\r
+       //awb\r
+       //ae\r
+       //scence\r
+       //effect\r
+       //brightness\r
+       //digitalzoom\r
+    int whiteBalance;\r
+    int brightness;\r
+    int contrast;\r
+    int saturation;\r
+    int effect;\r
+    int scene;\r
+    int digitalzoom;\r
+    int exposure;\r
+    int face;\r
+       //mirror or flip\r
+    unsigned char mirror;                                        /* HFLIP */\r
+    unsigned char flip;                                          /* VFLIP */\r
+       //preview or capture\r
+       int outputSize; // supported resolution\r
+       int curRes;\r
+    struct focus_zone_s focus_zone;\r
+    struct sensor_datafmt fmt;\r
+       //mutex for access the isp data\r
+       struct mutex access_data_lock;\r
+};\r
+\r
+\r
+struct isp_func_ops{\r
+       int (*isp_power_on)(void);\r
+       int (*isp_power_off)(void);\r
+       //realized by isp or external dev\r
+       int (*isp_set_focus_mode)(int value,struct isp_data* data);\r
+       int (*isp_set_flash_mode)( int value,struct isp_data* data);\r
+\r
+       //by soft isp or external isp\r
+       int (*isp_set_wb_mode)( int value,struct isp_data* data);\r
+       int (*isp_set_effect_mode)( int value,struct isp_data* data);\r
+       int (*isp_set_scence_mode)( int value,struct isp_data* data);\r
+       int (*isp_set_expose_mode)( int value,struct isp_data* data);\r
+       int (*isp_set_digitalzoom_mode)( int value,struct isp_data* data);\r
+       int (*isp_set_flip)( int value,struct isp_data* data);\r
+       int (*isp_set_mirror)( int value,struct isp_data* data);\r
+};\r
+\r
+struct isp_dev{\r
+    struct v4l2_subdev subdev;\r
+    struct i2c_client *client;\r
+       struct workqueue_struct *sensor_wq;\r
+       struct mutex wq_lock;\r
+    int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */\r
+    struct isp_func_ops* isp_ops;\r
+    struct isp_data isp_priv_info;     \r
+       };\r
+\r
+static struct isp_dev* to_sensor(const struct i2c_client *client)\r
+{\r
+    return container_of(i2c_get_clientdata(client), struct isp_dev, subdev);\r
+}\r
+\r
+/* Find a data format by a pixel code in an array */\r
+static const struct sensor_datafmt *sensor_find_datafmt(\r
+       enum v4l2_mbus_pixelcode code, const struct sensor_datafmt *fmt,\r
+       int n)\r
+{\r
+       int i;\r
+       for (i = 0; i < n; i++)\r
+               if (fmt[i].code == code)\r
+                       return fmt + i;\r
+\r
+       return NULL;\r
+}\r
+\r
+static const struct sensor_datafmt sensor_colour_fmts[] = {\r
+    {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}    \r
+};\r
+\r
+static int isp_reg_value_check(struct i2c_client *client,u8 checked_reg,u8 checked_value){\r
+    int cnt = 100;\r
+    u8 check_val = 0;\r
+       // msleep(10);\r
+     while((cnt-- > 0) && (isp_i2c_read(client,checked_reg,&check_val,0) || (check_val != checked_value))){\r
+      //  SENSOR_TR("error: %s:%d   check_val = 0x%x, exp = 0x%x\n", __func__,__LINE__, check_val,checked_value);\r
+        mdelay(30);\r
+    }\r
+     if(cnt <= 0){\r
+        SENSOR_TR("error: %s:%d  reg value checked erro,check_val = 0x%x, exp = 0x%x!\n", __func__,__LINE__,check_val,checked_value);\r
+        return -1;\r
+     }\r
+     return 0;\r
+\r
+}\r
+\r
+#if CONFIG_SENSOR_WhiteBalance\r
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    u8 set_val = 0;\r
+\r
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+    {\r
+        switch(value){\r
+            case 0: //enable auto\r
+                set_val = 0x1;\r
+                break;\r
+            case 1: //incandescent\r
+                set_val = 0x45;\r
+                break;\r
+            case 2: //fluorescent\r
+                set_val = 0x25;\r
+                break;\r
+            case 3: //daylight\r
+                set_val = 0x15;\r
+                break;\r
+            case 4: //cloudy-daylight\r
+                set_val = 0x35;\r
+                break;\r
+            default:\r
+                break;\r
+        }\r
+        //awb\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x1c, set_val);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+        return 0;\r
+    }\r
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+    return -1;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Effect\r
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    u8 set_val = 0;\r
+    printk("set effect,value = %d ......\n",value);\r
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+    {\r
+        switch(value){\r
+            case 0: //none\r
+                set_val = 0x00;\r
+                break;\r
+            case 1: //mono\r
+                set_val = 0x01;\r
+                break;\r
+            case 2: //negative\r
+                set_val = 0x02;\r
+                break;\r
+            case 3: //sepia\r
+                set_val = 0x03;\r
+                break;\r
+            case 4: //aqua\r
+                set_val = 0x04;\r
+                break;\r
+            default:\r
+                break;\r
+        }\r
+        //image effect\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x26, set_val);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+        return 0;\r
+    }\r
+       SENSOR_TR("\n%s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+    return -1;\r
+}\r
+#endif\r
+\r
+static const struct v4l2_querymenu sensor_menus[] =\r
+{\r
+       #if CONFIG_SENSOR_Effect\r
+    { .id = V4L2_CID_EFFECT,  .index = 0,  .name = "normal",  .reserved = 0, }, {  .id = V4L2_CID_EFFECT,  .index = 1, .name = "mono",  .reserved = 0,},\r
+    { .id = V4L2_CID_EFFECT,  .index = 2,  .name = "negative", .reserved = 0,}, {  .id = V4L2_CID_EFFECT, .index = 3,  .name = "sepia", .reserved = 0,},\r
+    { .id = V4L2_CID_EFFECT,  .index = 4,  .name = "aqua", .reserved = 0,},\r
+     #endif\r
+    \r
+       #if CONFIG_SENSOR_WhiteBalance\r
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 0,  .name = "auto",  .reserved = 0, }, {  .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 1, .name = "incandescent",  .reserved = 0,},\r
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 2,  .name = "fluorescent", .reserved = 0,}, {  .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3,  .name = "daylight", .reserved = 0,},\r
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 4,  .name = "cloudy-daylight", .reserved = 0,},\r
+    #endif\r
+\r
+\r
+       #if CONFIG_SENSOR_Scene\r
+    { .id = V4L2_CID_SCENE,  .index = 0, .name = "normal", .reserved = 0,} ,{ .id = V4L2_CID_SCENE,  .index = 1,  .name = "auto", .reserved = 0,},\r
+    { .id = V4L2_CID_SCENE,  .index = 2, .name = "landscape", .reserved = 0,} ,{ .id = V4L2_CID_SCENE,  .index = 3,  .name = "night", .reserved = 0,},\r
+    { .id = V4L2_CID_SCENE,  .index = 4, .name = "night_portrait", .reserved = 0,} ,{ .id = V4L2_CID_SCENE,  .index = 5,  .name = "snow", .reserved = 0,},\r
+    { .id = V4L2_CID_SCENE,  .index = 6, .name = "sports", .reserved = 0,} ,{ .id = V4L2_CID_SCENE,  .index = 7,  .name = "candlelight", .reserved = 0,},\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Flash\r
+    { .id = V4L2_CID_FLASH,  .index = 0,  .name = "off",  .reserved = 0, }, {  .id = V4L2_CID_FLASH,  .index = 1, .name = "auto",  .reserved = 0,},\r
+    { .id = V4L2_CID_FLASH,  .index = 2,  .name = "on", .reserved = 0,}, {  .id = V4L2_CID_FLASH, .index = 3,  .name = "torch", .reserved = 0,},\r
+    #endif\r
+};\r
+\r
+static  struct v4l2_queryctrl sensor_controls[] =\r
+{\r
+       #if CONFIG_SENSOR_WhiteBalance\r
+    {\r
+        .id            = V4L2_CID_DO_WHITE_BALANCE,\r
+        .type          = V4L2_CTRL_TYPE_MENU,\r
+        .name          = "White Balance Control",\r
+        .minimum       = 0,\r
+        .maximum       = 4,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Brightness\r
+       {\r
+        .id            = V4L2_CID_BRIGHTNESS,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Brightness Control",\r
+        .minimum       = -3,\r
+        .maximum       = 2,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Effect\r
+       {\r
+        .id            = V4L2_CID_EFFECT,\r
+        .type          = V4L2_CTRL_TYPE_MENU,\r
+        .name          = "Effect Control",\r
+        .minimum       = 0,\r
+        .maximum       = 4,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+       #endif\r
+\r
+       #if CONFIG_SENSOR_Exposure\r
+       {\r
+        .id            = V4L2_CID_EXPOSURE,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Exposure Control",\r
+        .minimum       = 0,\r
+        .maximum       = 5,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+       #endif\r
+\r
+       #if CONFIG_SENSOR_Saturation\r
+       {\r
+        .id            = V4L2_CID_SATURATION,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Saturation Control",\r
+        .minimum       = 0,\r
+        .maximum       = 2,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Contrast\r
+       {\r
+        .id            = V4L2_CID_CONTRAST,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Contrast Control",\r
+        .minimum       = -3,\r
+        .maximum       = 3,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+       #endif\r
+\r
+       #if CONFIG_SENSOR_Mirror\r
+       {\r
+        .id            = V4L2_CID_HFLIP,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Mirror Control",\r
+        .minimum       = 0,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 1,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Flip\r
+       {\r
+        .id            = V4L2_CID_VFLIP,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Flip Control",\r
+        .minimum       = 0,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 1,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Scene\r
+    {\r
+        .id            = V4L2_CID_SCENE,\r
+        .type          = V4L2_CTRL_TYPE_MENU,\r
+        .name          = "Scene Control",\r
+        .minimum       = 0,\r
+        .maximum       = 7,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_DigitalZoom\r
+    {\r
+        .id            = V4L2_CID_ZOOM_ABSOLUTE,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "DigitalZoom Control",\r
+        .minimum       = 100,\r
+        .maximum       = 275, // app pass 275-25 maximum\r
+        .step          = 25,\r
+        .default_value = 100,\r
+    }, \r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Focus\r
+       /*{\r
+        .id            = V4L2_CID_FOCUS_RELATIVE,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Focus Control",\r
+        .minimum       = -1,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    }, */\r
+    {\r
+        .id            = V4L2_CID_FOCUS_ABSOLUTE,\r
+        .type          = V4L2_CTRL_TYPE_INTEGER,\r
+        .name          = "Focus Control",\r
+        .minimum       = 0,\r
+        .maximum       = 2,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+       {\r
+        .id            = V4L2_CID_FOCUS_AUTO,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Focus Control",\r
+        .minimum       = 0,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },{\r
+        .id            = V4L2_CID_FOCUS_CONTINUOUS,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Focus Control",\r
+        .minimum       = 0,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+    #endif\r
+\r
+       #if CONFIG_SENSOR_Flash\r
+       {\r
+        .id            = V4L2_CID_FLASH,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Flash Control Focus",\r
+        .minimum       = 0,\r
+        .maximum       = 3,\r
+        .step          = 1,\r
+        .default_value = 0,\r
+    },\r
+       #endif\r
+    #if CONFIG_SENSOR_FOCUS_ZONE\r
+       {\r
+        .id            = V4L2_CID_FOCUSZONE,\r
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,\r
+        .name          = "Focus Zone support",\r
+        .minimum       = 0,\r
+        .maximum       = 1,\r
+        .step          = 1,\r
+        .default_value = 1,\r
+    },\r
+       #endif\r
+       #if     CONFIG_SENSOR_FACE_DETECT\r
+       {\r
+       .id     = V4L2_CID_FACEDETECT,\r
+       .type           = V4L2_CTRL_TYPE_BOOLEAN,\r
+       .name           = "face dectect support",\r
+       .minimum        = 0,\r
+       .maximum        = 1,\r
+       .step           = 1,\r
+       .default_value = 1,\r
+       },\r
+       #endif\r
+\r
+};\r
+\r
+\r
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    const struct v4l2_queryctrl *qctrl;\r
+\r
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);\r
+\r
+    if (!qctrl)\r
+    {\r
+        SENSOR_TR("\n %s ioctrl id = 0x%x  is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);\r
+        return -EINVAL;\r
+    }\r
+\r
+    switch (ctrl->id)\r
+    {\r
+        case V4L2_CID_BRIGHTNESS:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.brightness;\r
+                break;\r
+            }\r
+        case V4L2_CID_SATURATION:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.saturation;\r
+                break;\r
+            }\r
+        case V4L2_CID_CONTRAST:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.contrast;\r
+                break;\r
+            }\r
+        case V4L2_CID_DO_WHITE_BALANCE:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.whiteBalance;\r
+                break;\r
+            }\r
+        case V4L2_CID_EXPOSURE:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.exposure;\r
+                break;\r
+            }\r
+        case V4L2_CID_HFLIP:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.mirror;\r
+                break;\r
+            }\r
+        case V4L2_CID_VFLIP:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.flip;\r
+                break;\r
+            }\r
+        case V4L2_CID_ZOOM_ABSOLUTE:\r
+            {\r
+                ctrl->value = sensor->isp_priv_info.digitalzoom;\r
+                break;\r
+            }\r
+        default :\r
+                break;\r
+    }\r
+    return 0;\r
+}\r
+static int sensor_set_face_detect(struct i2c_client *client, int value);\r
+#if CONFIG_SENSOR_Exposure\r
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    u8 set_val = 0x0 ,ac_val = 0x01;\r
+    printk("set iso ,value = %d......\n", value);\r
+\r
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+    {\r
+        switch(value){\r
+            case 0: //iso auto\r
+                set_val = 0x0;\r
+                break;\r
+            case 1: //iso 100\r
+                set_val = 0x1;\r
+                break;\r
+            case 2: //iso 200\r
+                set_val = 0x2;\r
+                break;\r
+            case 3: //iso 400\r
+                set_val = 0x3;\r
+                break;\r
+            case 4: //iso 800\r
+                set_val = 0x4;\r
+                break;\r
+            case 5: //iso 1600\r
+                set_val = 0x5;\r
+                break;\r
+            default:\r
+                break;\r
+        }\r
+        \r
+        //iso\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x17, set_val);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+        //AC freq :50Hz\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x16, 0x01);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+        return 0;\r
+    }\r
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+    return -EINVAL;\r
+}\r
+#endif\r
+\r
+\r
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    const struct v4l2_queryctrl *qctrl;\r
+\r
+\r
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);\r
+\r
+    if (!qctrl)\r
+    {\r
+        SENSOR_TR("\n %s ioctrl id = 0x%x  is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);\r
+        return -EINVAL;\r
+    }\r
+\r
+    switch (ctrl->id)\r
+    {\r
+#if CONFIG_SENSOR_Brightness\r
+        case V4L2_CID_BRIGHTNESS:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.brightness)\r
+                {\r
+                    if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)\r
+                    {\r
+                        return -EINVAL;\r
+                    }\r
+                    sensor->isp_priv_info.brightness = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Exposure\r
+        case V4L2_CID_EXPOSURE:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.exposure)\r
+                {\r
+                    if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)\r
+                    {\r
+                        return -EINVAL;\r
+                    }\r
+                    sensor->isp_priv_info.exposure = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Saturation\r
+        case V4L2_CID_SATURATION:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.saturation)\r
+                {\r
+                    if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)\r
+                    {\r
+                        return -EINVAL;\r
+                    }\r
+                    sensor->isp_priv_info.saturation = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Contrast\r
+        case V4L2_CID_CONTRAST:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.contrast)\r
+                {\r
+                    if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)\r
+                    {\r
+                        return -EINVAL;\r
+                    }\r
+                    sensor->isp_priv_info.contrast = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_WhiteBalance\r
+        case V4L2_CID_DO_WHITE_BALANCE:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.whiteBalance)\r
+                {\r
+                    if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)\r
+                    {\r
+                        return -EINVAL;\r
+                    }\r
+                    sensor->isp_priv_info.whiteBalance = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Mirror\r
+        case V4L2_CID_HFLIP:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.mirror)\r
+                {\r
+                    if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.mirror = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Flip\r
+        case V4L2_CID_VFLIP:\r
+            {\r
+                if (ctrl->value != sensor->isp_priv_info.flip)\r
+                {\r
+                    if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.flip = ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_DigitalZoom\r
+        case V4L2_CID_ZOOM_ABSOLUTE:\r
+            {\r
+                int val_offset = 0;\r
+                printk("V4L2_CID_ZOOM_ABSOLUTE ...... ctrl->value = %d\n",ctrl->value);\r
+                if ((ctrl->value < qctrl->minimum) || (ctrl->value > qctrl->maximum)){\r
+                    return -EINVAL;\r
+                    }\r
+\r
+                if (ctrl->value != sensor->isp_priv_info.digitalzoom)\r
+                {\r
+                    val_offset = ctrl->value -sensor->isp_priv_info.digitalzoom;\r
+\r
+                    if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.digitalzoom += val_offset;\r
+\r
+                    SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(),  sensor->isp_priv_info.digitalzoom);\r
+                }\r
+\r
+                break;\r
+            }\r
+        case V4L2_CID_ZOOM_RELATIVE:\r
+            {\r
+                if (ctrl->value)\r
+                {\r
+                    if (sensor_set_digitalzoom(icd, qctrl,&ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.digitalzoom += ctrl->value;\r
+\r
+                    SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->isp_priv_info.digitalzoom);\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+        default:\r
+            break;\r
+    }\r
+\r
+    return 0;\r
+}\r
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)\r
+{\r
+    const struct v4l2_queryctrl *qctrl;\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    struct isp_dev *sensor = to_sensor(client);\r
+\r
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);\r
+\r
+    if (!qctrl)\r
+    {\r
+        SENSOR_TR("\n %s ioctrl id = 0x%x  is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);\r
+        return -EINVAL;\r
+    }\r
+\r
+    switch (ext_ctrl->id)\r
+    {\r
+        case V4L2_CID_SCENE:\r
+            {\r
+                ext_ctrl->value = sensor->isp_priv_info.scene;\r
+                break;\r
+            }\r
+        case V4L2_CID_EFFECT:\r
+            {\r
+                ext_ctrl->value = sensor->isp_priv_info.effect;\r
+                break;\r
+            }\r
+        case V4L2_CID_ZOOM_ABSOLUTE:\r
+            {\r
+                ext_ctrl->value = sensor->isp_priv_info.digitalzoom;\r
+                break;\r
+            }\r
+        case V4L2_CID_ZOOM_RELATIVE:\r
+            {\r
+                return -EINVAL;\r
+            }\r
+        case V4L2_CID_FOCUS_ABSOLUTE:\r
+            {\r
+                return -EINVAL;\r
+            }\r
+        case V4L2_CID_FOCUS_RELATIVE:\r
+            {\r
+                return -EINVAL;\r
+            }\r
+        case V4L2_CID_FLASH:\r
+            {\r
+                ext_ctrl->value = sensor->isp_priv_info.flash;\r
+                break;\r
+            }\r
+        case V4L2_CID_FACEDETECT:\r
+               {\r
+               ext_ctrl->value =sensor->isp_priv_info.face ;\r
+               break;\r
+               }\r
+        default :\r
+            break;\r
+    }\r
+    return 0;\r
+}\r
+#if CONFIG_SENSOR_Focus\r
+static int sensor_set_auto_focus(struct i2c_client *client, int value)\r
+{\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    u8 zone_x = 0x0,zone_y = 0x0; // 0->0x0f\r
+    int ret = 0;\r
+//     return 0;\r
+    //set the zone\r
+ //   printk("lx = %x,rx = %x,ty = %x,dy = %x\n",sensor->isp_priv_info.focus_zone.lx,sensor->isp_priv_info.focus_zone.rx,sensor->isp_priv_info.focus_zone.ty,sensor->isp_priv_info.focus_zone.dy);\r
+    zone_x = (sensor->isp_priv_info.focus_zone.lx << 4) | (sensor->isp_priv_info.focus_zone.rx & 0x0f);\r
+    zone_y = (sensor->isp_priv_info.focus_zone.ty << 4) | (sensor->isp_priv_info.focus_zone.dy & 0x0f);\r
+    //auto focus\r
+    sendI2cCmd(client, 0x0E, 0x00);\r
+    if((zone_x != 0) && (zone_y !=0)){\r
+        sendI2cCmd(client, 0x21, zone_x);\r
+        sendI2cCmd(client, 0x22, zone_y);\r
+        }else{\r
+        sendI2cCmd(client, 0x21, 0x6a);\r
+        sendI2cCmd(client, 0x22, 0x6a);\r
+        }\r
+    printk("%s:auto focus, val = %d,zone_x = %x, zone_y = %x\n",__func__,value,zone_x,zone_y);\r
+    sendI2cCmd(client, 0x23, value);\r
+    ret = isp_reg_value_check(client,0x0E,0xBB);\r
+    if(ret == 0xCC){\r
+        printk("%s:%d,auto focus failed!\n",__func__,__LINE__);\r
+        }\r
+  //  printk("%s:auto focus done\n",__func__);\r
+    return 0;\r
+}\r
+\r
+enum sensor_work_state\r
+{\r
+       sensor_work_ready = 0,\r
+       sensor_working,\r
+};\r
+enum sensor_wq_result\r
+{\r
+    WqRet_success = 0,\r
+    WqRet_fail = -1,\r
+    WqRet_inval = -2\r
+};\r
+enum sensor_wq_cmd\r
+{\r
+    WqCmd_af_init,\r
+    WqCmd_af_single,\r
+    WqCmd_af_special_pos,\r
+    WqCmd_af_far_pos,\r
+    WqCmd_af_near_pos,\r
+    WqCmd_af_continues,\r
+    WqCmd_af_return_idle,\r
+};\r
+struct sensor_work\r
+{\r
+       struct i2c_client *client;\r
+       struct delayed_work dwork;\r
+       enum sensor_wq_cmd cmd;\r
+    wait_queue_head_t done;\r
+    enum sensor_wq_result result;\r
+    bool wait;\r
+    int var;    \r
+};\r
+\r
+static void sensor_af_workqueue(struct work_struct *work)\r
+{\r
+       struct sensor_work *sensor_work = container_of(work, struct sensor_work, dwork.work);\r
+       struct i2c_client *client = sensor_work->client;\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    \r
+    SENSOR_DG("%s %s Enter, cmd:0x%x \n",SENSOR_NAME_STRING(), __FUNCTION__,sensor_work->cmd);\r
+    \r
+    mutex_lock(&sensor->wq_lock);\r
+    \r
+//    printk("%s:auto focus, val = %d\n",__func__,sensor_work->var);\r
+    //auto focus\r
+    if(sensor_set_auto_focus(client,sensor_work->var) == 0){\r
+        sensor_work->result = WqRet_success;\r
+        }else{\r
+        printk("%s:auto focus failed\n",__func__);\r
+        }\r
+//    printk("%s:auto focus done\n",__func__);\r
+    \r
+//set_end:\r
+    if (sensor_work->wait == false) {\r
+        kfree((void*)sensor_work);\r
+    } else {\r
+        wake_up(&sensor_work->done); \r
+    }\r
+    mutex_unlock(&sensor->wq_lock); \r
+    return;\r
+}\r
+\r
+static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+       struct isp_dev *sensor = to_sensor(client); \r
+    struct sensor_work *wk;\r
+    int ret=0;\r
+\r
+    if (sensor->sensor_wq == NULL) { \r
+        ret = -EINVAL;\r
+        goto sensor_af_workqueue_set_end;\r
+    }\r
+\r
+    wk = kzalloc(sizeof(struct sensor_work), GFP_KERNEL);\r
+    if (wk) {\r
+           wk->client = client;\r
+           INIT_WORK(&(wk->dwork.work), sensor_af_workqueue);\r
+        wk->cmd = cmd;\r
+        wk->result = WqRet_inval;\r
+        wk->wait = wait;\r
+        wk->var = var;\r
+        init_waitqueue_head(&wk->done);\r
+        \r
+           queue_delayed_work(sensor->sensor_wq,&(wk->dwork),0);\r
+        \r
+        /* ddl@rock-chips.com: \r
+        * video_lock is been locked in v4l2_ioctl function, but auto focus may slow,\r
+        * As a result any other ioctl calls will proceed very, very slowly since each call\r
+        * will have to wait for the AF to finish. Camera preview is pause,because VIDIOC_QBUF \r
+        * and VIDIOC_DQBUF is sched. so unlock video_lock here.\r
+        */\r
+        if (wait == true) {\r
+            mutex_unlock(&icd->video_lock);\r
+            if (wait_event_timeout(wk->done, (wk->result != WqRet_inval), msecs_to_jiffies(5000)) == 0) {  //hhb\r
+                SENSOR_TR("%s %s cmd(%d) is timeout!\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+            }\r
+            ret = wk->result;\r
+            kfree((void*)wk);\r
+            mutex_lock(&icd->video_lock);  \r
+        }\r
+        \r
+    } else {\r
+        SENSOR_TR("%s %s cmd(%d) ingore,because struct sensor_work malloc failed!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+        ret = -1;\r
+    }\r
+sensor_af_workqueue_set_end:\r
+    return ret;\r
+}\r
+#endif\r
+\r
+\r
+#if CONFIG_SENSOR_Scene\r
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+//when scene mod is working , face deteciton and awb and iso are not recomemnded.\r
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+    {\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+        //    sendI2cCmd(client, 0x13, value);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+            return 0;\r
+    }\r
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+    return -EINVAL;\r
+}\r
+#endif\r
+static int sensor_set_face_detect(struct i2c_client *client, int value)\r
+{\r
+       u8 orien, window;\r
+       window = (value & 0x100)>>8;\r
+    //face detect\r
+    switch (value & 0x1f){\r
+       case 0:\r
+               orien = 0x02; //off\r
+               break;\r
+       case 1:\r
+               orien = 0x80; //default on\r
+               break;\r
+       case 2:\r
+               orien = 0x90; //90 degree\r
+               break;\r
+       case 3:\r
+               orien = 0xb0; //180 degree\r
+               break;\r
+       case 4:\r
+               orien = 0xa0; //270 degree\r
+               break;\r
+       default:\r
+               orien = 0x02; //off\r
+\r
+       }\r
+       printk("orien = %x,window = %d \n",orien,window);\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x2a, orien);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+        sendI2cCmd(client, 0x0E, 0x00);\r
+        sendI2cCmd(client, 0x29, window);\r
+        isp_reg_value_check(client,0x0E,0xBB);\r
+    \r
+    SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+    return 0;\r
+}\r
+#if CONFIG_SENSOR_Flip\r
+//off 0x00;mirror 0x01,flip 0x10;\r
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)\r
+{\r
+       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+       sendI2cCmd(client, 0x0E, 0x00);\r
+       sendI2cCmd(client, 0x28, 0x10);\r
+       isp_reg_value_check(client,0x0E,0xBB);\r
+       return 0;\r
+\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Mirror\r
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)\r
+{\r
+       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+       sendI2cCmd(client, 0x0E, 0x00);\r
+       sendI2cCmd(client, 0x28, 0x01);\r
+       isp_reg_value_check(client,0x0E,0xBB);\r
+       return 0;\r
+}\r
+#endif\r
+\r
+#if CONFIG_SENSOR_DigitalZoom\r
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)\r
+{\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    struct isp_dev *sensor = to_sensor(client);\r
+       const struct v4l2_queryctrl *qctrl_info;\r
+    int digitalzoom_cur, digitalzoom_total;\r
+    u8 zoom_val = 0;\r
+\r
+       qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);\r
+       if (!qctrl_info){\r
+               return -EINVAL;\r
+           }\r
+\r
+    digitalzoom_cur = sensor->isp_priv_info.digitalzoom;\r
+    digitalzoom_total = qctrl_info->maximum;\r
+\r
+    if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))\r
+    {\r
+        SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);\r
+        return -EINVAL;\r
+    }\r
+\r
+    if  ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))\r
+    {\r
+        SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);\r
+        return -EINVAL;\r
+    }\r
+\r
+    if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))\r
+    {\r
+        *value = digitalzoom_total - digitalzoom_cur;\r
+    }\r
+\r
+    if ((*value < 0) && ((digitalzoom_cur + *value) < 0))\r
+    {\r
+        *value = 0 - digitalzoom_cur;\r
+    }\r
+\r
+    digitalzoom_cur += *value;\r
+    printk("digitalzoom_cur = %d =====\n",digitalzoom_cur);\r
+    switch(digitalzoom_cur){\r
+    case 100 :\r
+        zoom_val = 0;\r
+        break;\r
+    case 125 :\r
+        zoom_val = 1;\r
+        break;\r
+    case 150 :\r
+        zoom_val = 2;\r
+        break;\r
+    case 175 :\r
+        zoom_val = 3;\r
+        break;\r
+    case 200 :\r
+        zoom_val = 4;\r
+        break;\r
+    case 225 :\r
+        zoom_val = 5;\r
+        break;\r
+    case 250 :\r
+        zoom_val = 6;\r
+        break;\r
+    case 275 :\r
+        zoom_val = 7;\r
+        break;\r
+    case 300 :\r
+        zoom_val = 8;\r
+        break;\r
+    }\r
+    \r
+    sendI2cCmd(client, 0x0E, 0x00);\r
+    sendI2cCmd(client, 0x2b, zoom_val);\r
+    isp_reg_value_check(client,0x0E,0xBB);\r
+    mdelay(5);\r
+    return 0;\r
+}\r
+#endif\r
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)\r
+{\r
+    const struct v4l2_queryctrl *qctrl;\r
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    int val_offset;\r
+\r
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);\r
+\r
+    if (!qctrl)\r
+    {\r
+        SENSOR_TR("\n %s ioctrl id = 0x%x  is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);\r
+        return -EINVAL;\r
+    }\r
+\r
+       val_offset = 0;\r
+    switch (ext_ctrl->id)\r
+    {\r
+#if CONFIG_SENSOR_Scene\r
+        case V4L2_CID_SCENE:\r
+            {\r
+                if (ext_ctrl->value != sensor->isp_priv_info.scene)\r
+                {\r
+                    if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.scene = ext_ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Effect\r
+        case V4L2_CID_EFFECT:\r
+            {   \r
+                if (ext_ctrl->value != sensor->isp_priv_info.effect)\r
+                {                    \r
+                    if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.effect= ext_ctrl->value;\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_DigitalZoom\r
+        case V4L2_CID_ZOOM_ABSOLUTE:\r
+            {\r
+                printk("V4L2_CID_ZOOM_ABSOLUTE ...... ext_ctrl->value = %d\n",ext_ctrl->value);\r
+                if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum)){\r
+                    return -EINVAL;\r
+                    }\r
+\r
+                if (ext_ctrl->value != sensor->isp_priv_info.digitalzoom)\r
+                {\r
+                    val_offset = ext_ctrl->value -sensor->isp_priv_info.digitalzoom;\r
+\r
+                    if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.digitalzoom += val_offset;\r
+\r
+                    SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(),  sensor->isp_priv_info.digitalzoom);\r
+                }\r
+\r
+                break;\r
+            }\r
+        case V4L2_CID_ZOOM_RELATIVE:\r
+            {\r
+                if (ext_ctrl->value)\r
+                {\r
+                    if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)\r
+                        return -EINVAL;\r
+                    sensor->isp_priv_info.digitalzoom += ext_ctrl->value;\r
+\r
+                    SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->isp_priv_info.digitalzoom);\r
+                }\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_Focus\r
+        case V4L2_CID_FOCUS_ABSOLUTE:\r
+            {\r
+               //DO MACRO\r
+                if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))\r
+                    return -EINVAL;\r
+               \r
+               if (SENSOR_AF_CONTINUOUS == sensor->isp_priv_info.auto_focus) {\r
+                       sensor_af_workqueue_set(icd,0,SENSOR_AF_CONTINUOUS_OFF,true);\r
+                       }\r
+               if (ext_ctrl->value == 1) {\r
+                       sensor_af_workqueue_set(icd,0,SENSOR_AF_MACRO,true);\r
+                       sensor->isp_priv_info.auto_focus = SENSOR_AF_MACRO;\r
+               } else if(ext_ctrl->value == 0){\r
+                        sensor_af_workqueue_set(icd,0,SENSOR_AF_MODE_CLOSE,true);\r
+                       sensor->isp_priv_info.auto_focus = SENSOR_AF_MODE_CLOSE;\r
+               }\r
+                break;\r
+            }\r
+        case V4L2_CID_FOCUS_RELATIVE:\r
+            {\r
+          //      if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))\r
+        //            return -EINVAL;\r
+\r
+         //       sensor_set_focus_relative(icd, qctrl,ext_ctrl->value);\r
+                break;\r
+            }\r
+               \r
+       case V4L2_CID_FOCUS_AUTO:\r
+                       {\r
+                               \r
+                               if (SENSOR_AF_CONTINUOUS == sensor->isp_priv_info.auto_focus) {\r
+                                       sensor_af_workqueue_set(icd,0,SENSOR_AF_CONTINUOUS_OFF,true);\r
+                               }\r
+                               if (ext_ctrl->value == 1) {\r
+                                   sensor_af_workqueue_set(icd,0,SENSOR_AF_SINGLE,true);\r
+                                       sensor->isp_priv_info.auto_focus = SENSOR_AF_SINGLE;\r
+                               } else if(ext_ctrl->value == 0){\r
+                                    sensor_af_workqueue_set(icd,0,SENSOR_AF_MODE_CLOSE,true);\r
+                                       sensor->isp_priv_info.auto_focus = SENSOR_AF_MODE_CLOSE;\r
+                               }\r
+                               break;\r
+                       }\r
+               case V4L2_CID_FOCUS_CONTINUOUS:\r
+                       {\r
+                               if ((ext_ctrl->value == 1) && (SENSOR_AF_CONTINUOUS != sensor->isp_priv_info.auto_focus)) {\r
+                                       sensor_af_workqueue_set(icd,0,SENSOR_AF_MODE_CLOSE,true);\r
+                                        sensor_af_workqueue_set(icd,0,SENSOR_AF_CONTINUOUS,true);\r
+                                       sensor->isp_priv_info.auto_focus = SENSOR_AF_CONTINUOUS;\r
+                               }else if(ext_ctrl->value == 0){\r
+                                               sensor_af_workqueue_set(icd,0,SENSOR_AF_CONTINUOUS_OFF,true);\r
+                                               sensor->isp_priv_info.auto_focus = SENSOR_AF_CONTINUOUS_OFF;\r
+                               }\r
+                               break;\r
+                       }\r
+#endif\r
+#if CONFIG_SENSOR_Flash\r
+        case V4L2_CID_FLASH:\r
+            {\r
+                if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)\r
+                    return -EINVAL;\r
+                sensor->info_priv.flash = ext_ctrl->value;\r
+\r
+                SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->isp_priv_info.flash);\r
+                break;\r
+            }\r
+#endif\r
+#if CONFIG_SENSOR_FACE_DETECT\r
+       case V4L2_CID_FACEDETECT:\r
+               {\r
+                       if(sensor->isp_priv_info.face != ext_ctrl->value){\r
+                               if (sensor_set_face_detect(client, ext_ctrl->value) != 0)\r
+                                       return -EINVAL;\r
+                               sensor->isp_priv_info.face = ext_ctrl->value;\r
+                               SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->isp_priv_info.face);\r
+                               }\r
+                       break;\r
+               }\r
+#endif\r
+        default:\r
+            break;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    int i, error_cnt=0, error_idx=-1;\r
+\r
+    for (i=0; i<ext_ctrl->count; i++) {\r
+        if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {\r
+            error_cnt++;\r
+            error_idx = i;\r
+        }\r
+    }\r
+\r
+    if (error_cnt > 1)\r
+        error_idx = ext_ctrl->count;\r
+\r
+    if (error_idx != -1) {\r
+        ext_ctrl->error_idx = error_idx;\r
+        return -EINVAL;\r
+    } else {\r
+        return 0;\r
+    }\r
+}\r
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    struct isp_dev *sensor = to_sensor(client);\r
+\r
+    int i, error_cnt=0, error_idx=-1;\r
+    for (i=0; i<ext_ctrl->count; i++) {\r
+        if(ext_ctrl->controls[i].id == V4L2_CID_FOCUS_AUTO){\r
+            int lx,ty,rx,dy;\r
+               /*\r
+            lx = (s16)((int)(ext_ctrl->reserved[0])>>16);\r
+            ty = (s16)(ext_ctrl->reserved[0]);\r
+            rx = (s16)((int)(ext_ctrl->reserved[1])>>16);\r
+            dy = (s16)(ext_ctrl->reserved[1]);\r
+            */\r
+            //\r
+            lx = ext_ctrl->controls[i].rect[0];\r
+            ty = ext_ctrl->controls[i].rect[1];\r
+            rx = ext_ctrl->controls[i].rect[2];\r
+            dy = ext_ctrl->controls[i].rect[3];\r
+            printk("lx = %d,ty = %d,rx = %d,dy = %d\n",lx,ty,rx,dy);\r
+            sensor->isp_priv_info.focus_zone.lx = (lx+1000)*16/2000;\r
+            sensor->isp_priv_info.focus_zone.ty = (ty+1000)*16/2000;\r
+            sensor->isp_priv_info.focus_zone.rx = (rx+1000)*16/2000;\r
+            sensor->isp_priv_info.focus_zone.dy = (dy+1000)*16/2000;\r
+        //    printk("lx = %x,ty = %x,rx = %x,dy = %x\n",sensor->isp_priv_info.focus_zone.lx,sensor->isp_priv_info.focus_zone.ty,sensor->isp_priv_info.focus_zone.rx,sensor->isp_priv_info.focus_zone.dy);\r
+            if((lx == 0)&&(ty == 0)&&(rx==0)&&(dy==0)){\r
+                sensor->isp_priv_info.focus_zone.lx = 0;\r
+                sensor->isp_priv_info.focus_zone.ty = 0;\r
+                sensor->isp_priv_info.focus_zone.rx = 0;\r
+                sensor->isp_priv_info.focus_zone.dy = 0;\r
+                }\r
+            if(sensor->isp_priv_info.focus_zone.lx > 0xf){\r
+                sensor->isp_priv_info.focus_zone.lx = 0xf;\r
+            } \r
+            if(sensor->isp_priv_info.focus_zone.ty > 0xf){\r
+                sensor->isp_priv_info.focus_zone.ty = 0xf;\r
+            }\r
+            if(sensor->isp_priv_info.focus_zone.rx > 0xf){\r
+                sensor->isp_priv_info.focus_zone.rx = 0xf;\r
+            } \r
+            if(sensor->isp_priv_info.focus_zone.dy > 0xf){\r
+                sensor->isp_priv_info.focus_zone.dy = 0xf;\r
+            }                \r
+         }\r
+        if(ext_ctrl->controls[i].id == V4L2_CID_ZOOM_ABSOLUTE){\r
+            printk("%s: digtal zoom \n",__func__);\r
+        }\r
+\r
+        if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {\r
+            error_cnt++;\r
+            error_idx = i;\r
+        }\r
+    }\r
+\r
+    if (error_cnt > 1)\r
+        error_idx = ext_ctrl->count;\r
+\r
+    if (error_idx != -1) {\r
+        ext_ctrl->error_idx = error_idx;\r
+        return -EINVAL;\r
+    } else {\r
+        return 0;\r
+    }\r
+}\r
+\r
+//640*480 default\r
+static int sensor_set_isp_output_res(struct i2c_client *client,enum ISP_OUTPUT_RES outputSize){\r
+    u8 check_val = 0;\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    switch(outputSize)\r
+        {\r
+        case OUTPUT_QCIF:\r
+            {\r
+             SENSOR_TR(" SET qcif!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 176*144\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_HQVGA:\r
+            {\r
+             SENSOR_TR(" SET hqvga !\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 240*160\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+               break;\r
+            }\r
+        case OUTPUT_QVGA:\r
+            {\r
+             SENSOR_TR(" SET qvga RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 320*240\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x02);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_CIF:\r
+            {\r
+             SENSOR_TR(" SET cif RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 352*288\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x04);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+\r
+            break;\r
+        case OUTPUT_VGA:\r
+            {\r
+             SENSOR_TR(" SET VGA RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 640x480\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x03);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_SVGA:\r
+            {\r
+             SENSOR_TR(" SET SVGA RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x05);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            //isp output 800*600\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x06);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_720P:\r
+            {\r
+             SENSOR_TR(" SET 720P RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x0c);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 1280*720\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x0c);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+           \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x00);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            }\r
+            break;\r
+        case OUTPUT_XGA:\r
+            {\r
+             SENSOR_TR(" SET XGA RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x0E);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 1024*768\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x07);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_SXGA:\r
+            break;\r
+        case OUTPUT_UXGA:\r
+            {\r
+             SENSOR_TR(" SET UXGA RES!\n");\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x0E);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 1600*1200\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x09);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_1080P:\r
+            break;\r
+        case OUTPUT_QXGA:\r
+            {\r
+             SENSOR_TR(" SET QXGA RES!\n");\r
+            //sensor output 2592*1944\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x0E);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 2592*1944\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x0D);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        case OUTPUT_QSXGA:\r
+            {\r
+             SENSOR_TR(" SET QSXGA RES!\n");\r
+            //sensor output 2592*1944\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x08, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x10, 0x0E);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            //isp output 2592*1944\r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x11, 0x0E);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            \r
+            sendI2cCmd(client, 0x0E, 0x00);\r
+            sendI2cCmd(client, 0x07, 0x01);\r
+            isp_reg_value_check(client,0x0E,0xBB);\r
+            }\r
+            break;\r
+        default:\r
+            SENSOR_TR("%s %s  isp not support this resolution!\n",SENSOR_NAME_STRING(),__FUNCTION__);\r
+            \r
+        }\r
+\r
+    //AC freq :50Hz\r
+    sendI2cCmd(client, 0x0E, 0x00);\r
+    sendI2cCmd(client, 0x16, 0x01);\r
+    isp_reg_value_check(client,0x0E,0xBB);\r
+    \r
+    return 0;\r
+\r
+}\r
+static int sensor_init(struct v4l2_subdev *sd, u32 val)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+    struct isp_dev *sensor = to_sensor(client);\r
+       const struct v4l2_queryctrl *qctrl;\r
+    //define the outputsize , qcif - cif is down-scaling from vga , or jaggies is very serious\r
+    sensor->isp_priv_info.outputSize = /*OUTPUT_QCIF|OUTPUT_HQVGA|OUTPUT_QVGA |OUTPUT_CIF |*/OUTPUT_VGA | OUTPUT_SVGA|OUTPUT_720P|OUTPUT_XGA|OUTPUT_QXGA|OUTPUT_UXGA|OUTPUT_QSXGA;\r
+    sensor->isp_priv_info.curRes = -1;\r
+    #if 1\r
+        //reset , reset pin low ,then high\r
+       if (icl->reset)\r
+               icl->reset(icd->pdev);\r
+    #endif\r
+    isp_init_cmds(client);\r
+    #if 1\r
+    isp_reg_value_check(client,0x01,PRODUCT_VERSION_VALUE_REG1);\r
+    printk("init default size :VGA\n");\r
+    sensor->isp_priv_info.curRes = OUTPUT_VGA;\r
+    sensor_set_isp_output_res(client,OUTPUT_VGA);\r
+    #endif\r
+        /* sensor sensor information for initialization  */\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);\r
+       if (qctrl)\r
+       sensor->isp_priv_info.whiteBalance = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);\r
+       if (qctrl)\r
+       sensor->isp_priv_info.brightness = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);\r
+       if (qctrl)\r
+       sensor->isp_priv_info.effect = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);\r
+       if (qctrl){\r
+        sensor->isp_priv_info.exposure = qctrl->default_value;\r
+        //set expose auto \r
+        sensor_set_exposure(icd,qctrl,qctrl->default_value);\r
+           }\r
+\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);\r
+       if (qctrl)\r
+        sensor->isp_priv_info.saturation = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);\r
+       if (qctrl)\r
+        sensor->isp_priv_info.contrast = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);\r
+       if (qctrl)\r
+        sensor->isp_priv_info.mirror = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);\r
+       if (qctrl)\r
+        sensor->isp_priv_info.flip = qctrl->default_value;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);\r
+       if (qctrl){\r
+        sensor->isp_priv_info.scene = qctrl->default_value;\r
+        sensor_set_scene(icd,qctrl,qctrl->default_value);\r
+           }\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);\r
+       if (qctrl)\r
+        sensor->isp_priv_info.digitalzoom = qctrl->default_value;\r
+    /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code  */\r
+       //qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_AUTO);\r
+       //if (qctrl)\r
+               sensor->isp_priv_info.auto_focus = SENSOR_AF_CONTINUOUS_OFF;\r
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FACEDETECT);\r
+       if (qctrl)\r
+               sensor->isp_priv_info.face = qctrl->default_value;\r
+    return 0;\r
+}\r
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)\r
+{\r
+    return 0;\r
+}\r
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)\r
+{\r
+#if 0\r
+       struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+       int ret = 0;\r
+\r
+    SENSOR_DG("%s %s  cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);\r
+       switch (cmd)\r
+       {\r
+               case Sensor_PowerDown:\r
+               {\r
+                       if (icl->powerdown) {\r
+                               ret = icl->powerdown(icd->pdev, on);\r
+                               if (ret == RK29_CAM_IO_SUCCESS) {\r
+                                       if (on == 0) {\r
+                                               mdelay(2);\r
+                                               if (icl->reset)\r
+                                                       icl->reset(icd->pdev);\r
+                                       }\r
+                               } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {\r
+                                       ret = -ENODEV;\r
+                                       goto sensor_power_end;\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+               case Sensor_Flash:\r
+               {\r
+                       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+               struct sensor *sensor = to_sensor(client);\r
+\r
+                       if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {\r
+                               sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);\r
+                if(on){\r
+                    //flash off after 2 secs\r
+                       hrtimer_cancel(&(flash_off_timer.timer));\r
+                       hrtimer_start(&(flash_off_timer.timer),ktime_set(0, 800*1000*1000),HRTIMER_MODE_REL);\r
+                    }\r
+                       }\r
+            break;\r
+               }\r
+               default:\r
+               {\r
+                       SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+                       break;\r
+               }\r
+       }\r
+sensor_power_end:\r
+       return ret;\r
+#endif\r
+return 0;\r
+}\r
+#if 0\r
+static enum hrtimer_restart flash_off_func(struct hrtimer *timer){\r
+       struct flash_timer *fps_timer = container_of(timer, struct flash_timer, timer);\r
+    sensor_ioctrl(fps_timer->icd,Sensor_Flash,0);\r
+       SENSOR_DG("%s %s !!!!!!",SENSOR_NAME_STRING(),__FUNCTION__);\r
+    return 0;\r
+    \r
+}\r
+#endif\r
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    struct isp_dev *sensor = to_sensor(client);\r
+\r
+    mf->width  = icd->user_width;\r
+       mf->height      = icd->user_height;\r
+       mf->code        = sensor->isp_priv_info.fmt.code;\r
+       mf->colorspace  = sensor->isp_priv_info.fmt.colorspace;\r
+       mf->field       = V4L2_FIELD_NONE;\r
+    return 0;\r
+}\r
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    const struct sensor_datafmt *fmt;\r
+    struct isp_dev *sensor = to_sensor(client);\r
+       //const struct v4l2_queryctrl *qctrl;\r
+       //struct soc_camera_device *icd = client->dev.platform_data;\r
+    int ret=0;\r
+    int set_w,set_h;\r
+    int supported_size = sensor->isp_priv_info.outputSize;\r
+    int res_set = 0;\r
+       fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,\r
+                                  ARRAY_SIZE(sensor_colour_fmts));\r
+       if (!fmt) {\r
+        ret = -EINVAL;\r
+        goto sensor_s_fmt_end;\r
+    }\r
+    set_w = mf->width;\r
+    set_h = mf->height;\r
+       if (((set_w <= 176) && (set_h <= 144)) && (supported_size & OUTPUT_QCIF))\r
+       {\r
+        set_w = 176;\r
+        set_h = 144;\r
+        res_set = OUTPUT_QCIF;\r
+       }\r
+       else if (((set_w <= 320) && (set_h <= 240)) && (supported_size & OUTPUT_QVGA))\r
+    {\r
+        set_w = 320;\r
+        set_h = 240;\r
+        res_set = OUTPUT_QVGA;\r
+\r
+    }\r
+    else if (((set_w <= 352) && (set_h<= 288)) && (supported_size & OUTPUT_CIF))\r
+    {\r
+        set_w = 352;\r
+        set_h = 288;\r
+        res_set = OUTPUT_CIF;\r
+        \r
+    }\r
+    else if (((set_w <= 640) && (set_h <= 480)) && (supported_size & OUTPUT_VGA))\r
+    {\r
+        set_w = 640;\r
+        set_h = 480;\r
+        res_set = OUTPUT_VGA;\r
+        \r
+    }\r
+    else if (((set_w <= 800) && (set_h <= 600)) && (supported_size & OUTPUT_SVGA))\r
+    {\r
+        set_w = 800;\r
+        set_h = 600;\r
+        res_set = OUTPUT_SVGA;\r
+        \r
+    }\r
+       else if (((set_w <= 1024) && (set_h <= 768)) && (supported_size & OUTPUT_XGA))\r
+    {\r
+        set_w = 1024;\r
+        set_h = 768;\r
+        res_set = OUTPUT_XGA;\r
+        \r
+    }\r
+       else if (((set_w <= 1280) && (set_h <= 720)) && (supported_size & OUTPUT_720P))\r
+    {\r
+        set_w = 1280;\r
+        set_h = 720;\r
+        res_set = OUTPUT_720P;\r
+    }\r
+    else if (((set_w <= 1280) && (set_h <= 1024)) && (supported_size & OUTPUT_XGA))\r
+    {\r
+        set_w = 1280;\r
+        set_h = 1024;\r
+        res_set = OUTPUT_XGA;\r
+    }\r
+    else if (((set_w <= 1600) && (set_h <= 1200)) && (supported_size & OUTPUT_UXGA))\r
+    {\r
+        set_w = 1600;\r
+        set_h = 1200;\r
+        res_set = OUTPUT_UXGA;\r
+    }\r
+    else if (((set_w <= 1920) && (set_h <= 1080)) && (supported_size & OUTPUT_1080P))\r
+    {\r
+        set_w = 1920;\r
+        set_h = 1080;\r
+        res_set = OUTPUT_1080P;\r
+    }\r
+       else if (((set_w <= 2048) && (set_h <= 1536)) && (supported_size & OUTPUT_QXGA))\r
+    {\r
+        set_w = 2048;\r
+        set_h = 1536;\r
+        res_set = OUTPUT_QXGA;\r
+    }\r
+       else if (((set_w <= 2592) && (set_h <= 1944)) && (supported_size & OUTPUT_QSXGA))\r
+    {\r
+        set_w = 2592;\r
+        set_h = 1944;\r
+        res_set = OUTPUT_QSXGA;\r
+    }\r
+    else\r
+    {\r
+        set_w = SENSOR_INIT_WIDTH;\r
+        set_h = SENSOR_INIT_HEIGHT;\r
+        res_set = OUTPUT_VGA;\r
+    }\r
+    if(res_set != sensor->isp_priv_info.curRes)\r
+        sensor_set_isp_output_res(client,res_set);\r
+    sensor->isp_priv_info.curRes = res_set;\r
+       mf->width = set_w;\r
+    mf->height = set_h;\r
+\r
+sensor_s_fmt_end:\r
+    return ret;\r
+}\r
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)\r
+{\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    const struct sensor_datafmt *fmt;\r
+    int ret = 0,set_w,set_h;\r
+    int supported_size = sensor->isp_priv_info.outputSize;\r
+   \r
+       fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,\r
+                                  ARRAY_SIZE(sensor_colour_fmts));\r
+       if (fmt == NULL) {\r
+               fmt = &sensor->isp_priv_info.fmt;\r
+        mf->code = fmt->code;\r
+       } \r
+    if (mf->height > SENSOR_MAX_HEIGHT)\r
+        mf->height = SENSOR_MAX_HEIGHT;\r
+    else if (mf->height < SENSOR_MIN_HEIGHT)\r
+        mf->height = SENSOR_MIN_HEIGHT;\r
+\r
+    if (mf->width > SENSOR_MAX_WIDTH)\r
+        mf->width = SENSOR_MAX_WIDTH;\r
+    else if (mf->width < SENSOR_MIN_WIDTH)\r
+        mf->width = SENSOR_MIN_WIDTH;\r
+\r
+    set_w = mf->width;\r
+    set_h = mf->height;\r
+\r
+       if (((set_w <= 176) && (set_h <= 144)) && (supported_size & OUTPUT_QCIF))\r
+       {\r
+        set_w = 176;\r
+        set_h = 144;\r
+       }\r
+       else if (((set_w <= 320) && (set_h <= 240)) && (supported_size & OUTPUT_QVGA))\r
+    {\r
+        set_w = 320;\r
+        set_h = 240;\r
+    }\r
+    else if (((set_w <= 352) && (set_h<= 288)) && (supported_size & OUTPUT_CIF))\r
+    {\r
+        set_w = 352;\r
+        set_h = 288;\r
+    }\r
+    else if (((set_w <= 640) && (set_h <= 480)) && (supported_size & OUTPUT_VGA))\r
+    {\r
+        set_w = 640;\r
+        set_h = 480;\r
+    }\r
+    else if (((set_w <= 800) && (set_h <= 600)) && (supported_size & OUTPUT_SVGA))\r
+    {\r
+        set_w = 800;\r
+        set_h = 600;\r
+    }\r
+       else if (((set_w <= 1024) && (set_h <= 768)) && (supported_size & OUTPUT_XGA))\r
+    {\r
+        set_w = 1024;\r
+        set_h = 768;\r
+    }\r
+       else if (((set_w <= 1280) && (set_h <= 720)) && (supported_size & OUTPUT_720P))\r
+    {\r
+        set_w = 1280;\r
+        set_h = 720;\r
+    }\r
+    else if (((set_w <= 1280) && (set_h <= 1024)) && (supported_size & OUTPUT_XGA))\r
+    {\r
+        set_w = 1280;\r
+        set_h = 1024;\r
+    }\r
+    else if (((set_w <= 1600) && (set_h <= 1200)) && (supported_size & OUTPUT_UXGA))\r
+    {\r
+        set_w = 1600;\r
+        set_h = 1200;\r
+    }\r
+    else if (((set_w <= 1920) && (set_h <= 1080)) && (supported_size & OUTPUT_1080P))\r
+    {\r
+        set_w = 1920;\r
+        set_h = 1080;\r
+    }\r
+       else if (((set_w <= 2048) && (set_h <= 1536)) && (supported_size & OUTPUT_QXGA))\r
+    {\r
+        set_w = 2048;\r
+        set_h = 1536;\r
+    }\r
+       else if (((set_w <= 2592) && (set_h <= 1944)) && (supported_size & OUTPUT_QSXGA))\r
+    {\r
+        set_w = 2592;\r
+        set_h = 1944;\r
+    }\r
+    else\r
+    {\r
+        set_w = SENSOR_INIT_WIDTH;\r
+        set_h = SENSOR_INIT_HEIGHT;\r
+    }\r
+\r
+\r
+    mf->width = set_w;\r
+    mf->height = set_h;\r
+    mf->colorspace = fmt->colorspace;\r
+    \r
+    return ret;\r
+\r
+}\r
+\r
+static int sensor_enum_fmt(struct v4l2_subdev *sd, unsigned int index,\r
+                           enum v4l2_mbus_pixelcode *code)\r
+{\r
+       if (index >= ARRAY_SIZE(sensor_colour_fmts))\r
+               return -EINVAL;\r
+\r
+       *code = sensor_colour_fmts[index].code;\r
+       return 0;\r
+\r
+}\r
+static int sensor_s_stream(struct v4l2_subdev *sd, int enable){\r
+       struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+       struct soc_camera_device *icd = client->dev.platform_data;\r
+    if(enable == 0){\r
+     //   sensor_set_face_detect(client,0);\r
+      //  sensor_af_workqueue_set(icd,0,0,true);\r
+        }else{\r
+        //sensor_set_face_detect(client,1);\r
+     }\r
+    return 0;\r
+}\r
+static int sensor_g_face_area(struct v4l2_subdev *sd, void* face_data){\r
+    struct i2c_client *client = v4l2_get_subdevdata(sd);\r
+     u8 lx_rx = 0,tx_dy = 0;\r
+     isp_i2c_read(client,0x2c,&lx_rx,0);\r
+     isp_i2c_read(client,0x2d,&tx_dy,0);\r
+    // printk("lx_rx = %x, ty_dy = %x\n",lx_rx,tx_dy);\r
+      *(u16 *)face_data = ((u16)lx_rx << 8 ) | tx_dy;\r
+\r
+}\r
+static struct v4l2_subdev_core_ops isp_subdev_core_ops = {\r
+       .init           = sensor_init,\r
+       .g_ctrl         = sensor_g_control,\r
+       .s_ctrl         = sensor_s_control,\r
+       .g_ext_ctrls          = sensor_g_ext_controls,\r
+       .s_ext_ctrls          = sensor_s_ext_controls,\r
+//     .g_chip_ident   = sensor_g_chip_ident,\r
+       .ioctl = sensor_ioctl,\r
+};\r
+static struct v4l2_subdev_video_ops isp_subdev_video_ops = {\r
+       .s_mbus_fmt     = sensor_s_fmt,\r
+       .g_mbus_fmt     = sensor_g_fmt,\r
+       .try_mbus_fmt   = sensor_try_fmt,\r
+       .enum_mbus_fmt  = sensor_enum_fmt,\r
+       .s_stream   = sensor_s_stream,\r
+       //.g_face_area = sensor_g_face_area,\r
+};\r
+\r
+static struct v4l2_subdev_ops sensor_subdev_ops = {\r
+       .core   = &isp_subdev_core_ops,\r
+       .video = &isp_subdev_video_ops,\r
+};\r
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)\r
+{\r
+    return 0;\r
+}\r
+static int sensor_resume(struct soc_camera_device *icd)\r
+{\r
+    return 0;\r
+\r
+}\r
+static int sensor_set_bus_param(struct soc_camera_device *icd,\r
+                                unsigned long flags)\r
+{\r
+\r
+    return 0;\r
+}\r
+\r
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)\r
+{\r
+    struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+    unsigned long flags = SENSOR_BUS_PARAM;\r
+\r
+    return soc_camera_apply_sensor_flags(icl, flags);\r
+}\r
+static struct soc_camera_ops sensor_ops =\r
+{\r
+    .suspend                     = sensor_suspend,\r
+    .resume                       = sensor_resume,\r
+    .set_bus_param             = sensor_set_bus_param,\r
+    .query_bus_param   = sensor_query_bus_param,\r
+    .controls          = sensor_controls,\r
+    .menus                         = sensor_menus,\r
+    .num_controls              = ARRAY_SIZE(sensor_controls),\r
+    .num_menus         = ARRAY_SIZE(sensor_menus),\r
+};\r
+       \r
+\r
+/* sensor register read */\r
+static int isp_i2c_read(struct i2c_client *client, u8 reg, u8 *val,u16 ext_addr)\r
+{\r
+    int err = 0,cnt;\r
+    u8 buf[1];\r
+    struct i2c_msg msg[2];\r
+\r
+    buf[0] = reg;\r
+\r
+    msg[0].addr = (ext_addr == 0)? client->addr:ext_addr;\r
+    msg[0].flags = client->flags;\r
+    msg[0].buf = buf;\r
+    msg[0].len = sizeof(buf);\r
+    msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED;       /* ddl@rock-chips.com : 100kHz */\r
+    msg[0].read_type = 0;   /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */\r
+\r
+    cnt = 50;\r
+    err = -EAGAIN;\r
+    while ((cnt-- > 0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */\r
+        err = i2c_transfer(client->adapter, &msg[0], 1);\r
+\r
+        if (err >= 0) {\r
+          break;\r
+        } else {\r
+                //SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);\r
+            udelay(10);\r
+        }\r
+    }\r
+    if(cnt <=0 ){\r
+       SENSOR_TR("write i2c addr erro!\n");\r
+       return err;\r
+       }\r
+\r
+    msg[1].addr = (ext_addr == 0)? client->addr:ext_addr;\r
+    msg[1].flags = client->flags|I2C_M_RD;\r
+    msg[1].buf = buf;\r
+    msg[1].len = 1;\r
+    msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED;                       /* ddl@rock-chips.com : 100kHz */\r
+    msg[1].read_type = 2;                             /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */\r
+\r
+    cnt = 50;\r
+    err = -EAGAIN;\r
+    while ((cnt-- > 0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */\r
+        err = i2c_transfer(client->adapter, &msg[1], 1);\r
+\r
+        if (err >= 0) {\r
+            *val = buf[0];\r
+            return 0;\r
+        } else {\r
+               SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);\r
+            udelay(10);\r
+        }\r
+    }\r
+\r
+    return err;\r
+}\r
+\r
+u8  i2cWaitIdle(struct i2c_client *client,u8 timeOut) \r
+{ \r
+  u8  ret; \r
+  u8 dat = 0; \r
+  /* read I2C_IDLE_IDX register until the value I2C_IDLE */ \r
+  while(timeOut) \r
+  {   \r
+    ret = isp_i2c_read(client, I2C_STATUS_REG2, &dat,0); \r
+    if ((ret >= 0) && ((dat&0x01) == I2C_IDLE)) \r
+       break; \r
+    udelay(100); \r
+    timeOut--; \r
+  } \r
+  if(!timeOut){ \r
+   //SENSOR_TR("wait i2c idle erro!!\n");  \r
+   return -1;\r
+  } \r
+ return 0; \r
+} \r
+\r
+static int isp_write_regs(struct i2c_client *client,  u8 *reg_info, u16 num,u16 ext_addr,int seq)\r
+{\r
+       int err=0,cnt;\r
+       struct i2c_msg msg;\r
+    u16 windex = 0;\r
+    \r
+    switch(seq){\r
+    case 0 :\r
+            {\r
+                msg.len = num; \r
+               msg.addr = (ext_addr == 0)? client->addr:ext_addr;      \r
+               msg.flags = client->flags;      \r
+               msg.buf = reg_info;     \r
+               msg.scl_rate = CONFIG_SENSOR_I2C_SPEED;         /* ddl@rock-chips.com : 100kHz */       \r
+               msg.read_type = 0;               /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */    \r
+\r
+               \r
+               cnt= 10;        \r
+               err = -EAGAIN;\r
+               \r
+               while ((cnt-- > 0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */             \r
+                       err = i2c_transfer(client->adapter, &msg, 1);           \r
+                       if (err >= 0) {                     \r
+                               return 0;               \r
+                       } else {                            \r
+                               SENSOR_TR("\n %s write reg failed, try to write again!\n",      SENSOR_NAME_STRING());                      \r
+                               mdelay(5);      \r
+                       }       \r
+               }\r
+                break;\r
+            }\r
+    case 1 :\r
+            {\r
+                #define TRPERTIME (2)\r
+                int remain = 0;\r
+               msg.len = TRPERTIME;    \r
+               msg.addr = (ext_addr == 0)? client->addr:ext_addr;      \r
+               msg.flags = client->flags;      \r
+               msg.scl_rate = CONFIG_SENSOR_I2C_SPEED;         /* ddl@rock-chips.com : 100kHz */       \r
+               msg.read_type = 0;               /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */    \r
+               \r
+               err = -EAGAIN;\r
+                remain = num % TRPERTIME;\r
+                while(windex < num){\r
+                       cnt= 10;        \r
+                    msg.buf = reg_info+windex;\r
+                       err = -EAGAIN;\r
+                       while ((cnt-- > 0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */             \r
+                               err = i2c_transfer(client->adapter, &msg, 1);           \r
+                               if (err >= 0) {                     \r
+                                       break;          \r
+                               } else {                            \r
+                                       SENSOR_TR("\n %s write reg failed, try to write again ,index = %d!\n",  SENSOR_NAME_STRING(),windex);                       \r
+                                       udelay(10);     \r
+                               }       \r
+                       }\r
+                    if(cnt <= 0){\r
+                               SENSOR_TR("\n %s write reg failed ,index = %d!\n",      SENSOR_NAME_STRING(),windex);\r
+                        break;\r
+                    }\r
+                    windex+= TRPERTIME;\r
+                    if((windex >= num) && (remain != 0)){\r
+                        windex = num - remain;\r
+                        remain = 0;\r
+                        }\r
+                }\r
+                if(err >= 0){\r
+                    err = 0;\r
+                    if(num % TRPERTIME){\r
+                       SENSOR_TR("\n %s isp_write_regs sucess ,index = %d, val = %x!!\n",SENSOR_NAME_STRING(),(windex  - (TRPERTIME - num % TRPERTIME) -1),*((u8*)(reg_info+(windex  - (TRPERTIME - num % TRPERTIME) -1))));\r
+                        }\r
+                    else{\r
+                       SENSOR_TR("\n %s isp_write_regs sucess ,index = %d, val = %x!!\n",SENSOR_NAME_STRING(),windex - 1,*((u8*)(reg_info+windex - 1)));\r
+                        }\r
+                    }\r
+                \r
+                break;\r
+            }\r
+    default:\r
+       SENSOR_TR("\n %s isp_write_regs erro\n",SENSOR_NAME_STRING());\r
+    }\r
+       \r
+       return err;\r
+\r
+}\r
+\r
+static u8 sendI2cCmd(struct i2c_client *client,u8 cmd, u8 dat) \r
+{ \r
+    u8 buf[2];\r
+    buf[0] = cmd & 0xFF;\r
+    buf[1] = dat;\r
+  if (i2cWaitIdle(client,100) < 0){ \r
+       SENSOR_TR("%s:%d,send i2c command erro!",__func__,__LINE__);\r
+       return -1;\r
+       }\r
+  if (isp_write_regs(client,buf,2,0,0)<0) \r
+      { \r
+        SENSOR_TR("%s:%d,send i2c command erro!",__func__,__LINE__);\r
+        return -1; \r
+      } \r
+ //check the write\r
+ #if WRITE_READ_CHECK\r
+  if(cmd != 0xE){// no need to check if 0x0e\r
+      buf[1] = 0xff;\r
+      isp_i2c_read(client,cmd,&buf[1],0);\r
+      if(buf[1]!=dat){\r
+        SENSOR_TR("%s:%d,send i2c command check erro,reg %x:(%x:%x)\n!",__func__,__LINE__,cmd,buf[1],dat);\r
+      }\r
+    }\r
+ #endif\r
+  return 0; \r
+} \r
+\r
+static int flash_program_mode(struct i2c_client *client,bool enable){\r
+    u8 ss_array[2] = {0x5b,enable};\r
+    u8 mem_choose[2] = {0x80,0x2}; // 0x2 ,flash ;0x0 sdram\r
+    if(enable == true){\r
+        //select flash mem\r
+        if(isp_write_regs(client,(u8*)mem_choose,sizeof(mem_choose),0,0)){\r
+            SENSOR_TR("%s:%d,enter_program_mode %d erro!",__func__,__LINE__,enable);\r
+            return -1;\r
+        }\r
+        //enter pro mode\r
+        if(isp_write_regs(client,(u8*)ss_array,sizeof(ss_array),0,0)){\r
+            SENSOR_TR("%s:%d,enter_program_mode %d erro!",__func__,__LINE__,enable);\r
+            return -1;\r
+        }\r
+        mdelay(10);\r
+    }else{\r
+        //exit promode\r
+        mem_choose[1] = 0x0; \r
+        if(isp_write_regs(client,(u8*)ss_array,sizeof(ss_array),0,0)){\r
+            SENSOR_TR("%s:%d,enter_program_mode %d erro!",__func__,__LINE__,enable);\r
+            return -1;\r
+        }\r
+        //select sdram mem\r
+        mdelay(10);\r
+        if(isp_write_regs(client,(u8*)mem_choose,sizeof(mem_choose),0,0)){\r
+            SENSOR_TR("%s:%d,enter_program_mode %d erro!",__func__,__LINE__,enable);\r
+            return -1;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+static int flash_mem_erase(struct i2c_client *client,u8 sector){\r
+    //default is chip erase.\r
+    u8 ss_array[3] = {0x00,sector,0x02};\r
+\r
+    if(sector == 0xFF){\r
+        if(isp_write_regs(client,(u8*)ss_array,sizeof(ss_array),DEV_ID_MV9335_I2CSLAVE_FLASH_PRO,0)){\r
+            SENSOR_TR("%s:%d,chip_erase  erro!",__func__,__LINE__);\r
+            return -1;\r
+        }\r
+        //delay 120ms\r
+        mdelay(120);\r
+    }else{\r
+        ss_array[2] = 0x05;\r
+        if(isp_write_regs(client,(u8*)ss_array,sizeof(ss_array),DEV_ID_MV9335_I2CSLAVE_FLASH_PRO,0)){\r
+            SENSOR_TR("%s:%d,sector_erase  erro\n!",__func__,__LINE__);\r
+            return -1;\r
+        }\r
+        mdelay(120);\r
+    }\r
+    \r
+    return 0;\r
+}\r
+static int flash_write_read_addr(struct i2c_client *client,u16 addr,u8 commd){\r
+    //commd :0x50 write, 0x00 read\r
+    u8 lsb = get_lsb(addr);\r
+    u8 msb = get_msb(addr);\r
+    u8 ss_array[3] = {lsb,msb,commd};\r
+    if(isp_write_regs(client,(u8*)ss_array,sizeof(ss_array),DEV_ID_MV9335_I2CSLAVE_FLASH_PRO,0)){\r
+        SENSOR_TR("%s:%d,flash_write_addr  erro!",__func__,__LINE__);\r
+        return -1;\r
+    }\r
+    return 0;\r
+}\r
+static int flash_write_data(struct i2c_client *client){\r
+    int ret = 0;\r
+       const struct firmware *fw = NULL;\r
+       ret = request_firmware(&fw, fw_name, &client->dev);\r
+    if(ret){\r
+        SENSOR_TR("%s:%d,request_firmware  erro+++++++++++++!\n",__func__,__LINE__);\r
+        ret = -1;\r
+        goto free_fw_buffer;\r
+    }\r
+        SENSOR_TR("%s:%d,request_firmware sucess,val = %x!\n",__func__,__LINE__,*((u8*)fw->data+fw->size-1));\r
+    if(isp_write_regs(client,(u8*)fw->data,fw->size,DEV_ID_MV9335_I2CSLAVE_FLASH_PRO,1)){\r
+        SENSOR_TR("%s:%d,flash_write_data  erro,size = %d!\n",__func__,__LINE__,fw->size);\r
+        ret = -1;\r
+        goto free_fw_buffer;\r
+    }\r
+    #if FLASH_WRITE_CHECK // read all datas back to check\r
+        {\r
+        flash_write_read_addr(client,0x00,0x00);\r
+        u8 rd_data = 0;\r
+        u32 i = 0;\r
+        for(;i<fw->size;i++){\r
+            flash_read_data(client,&rd_data,1);\r
+            if(rd_data!= *((u8*)(fw->data+i)))\r
+                {\r
+                printk("0x%x, ori = 0x%x, rb = 0x%x\n",i,*((u8*)(fw->data+i)),rd_data);\r
+                break;\r
+                }\r
+            rd_data = 0;\r
+            udelay(200);\r
+            }\r
+        }\r
+    #endif\r
+\r
+free_fw_buffer:\r
+    if(fw)\r
+       release_firmware(fw);\r
+    return ret;\r
+}\r
+static int flash_read_data(struct i2c_client *client,u8* rd_data,int readcount){\r
+    int err = 0,cnt,i = 0;\r
+    //u8 buf[2];\r
+    u8 buf;\r
+    struct i2c_msg msg;\r
+\r
+    msg.addr = DEV_ID_MV9335_I2CSLAVE_FLASH_PRO;\r
+    msg.flags = client->flags|I2C_M_RD;\r
+    msg.buf = &buf;\r
+    msg.len = 1;\r
+    msg.scl_rate = CONFIG_SENSOR_I2C_SPEED;       /* ddl@rock-chips.com : 100kHz */\r
+    msg.read_type = 2;   /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */\r
+    for(i = 0;i < readcount;i++){\r
+            cnt = 3;\r
+            err = -EAGAIN;\r
+            while ((cnt-- > 0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */\r
+                err = i2c_transfer(client->adapter, &msg, 1);\r
+\r
+                if (err >= 0) {\r
+                    rd_data[i] = buf;\r
+                  break;\r
+                } else {\r
+                    //SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);\r
+                    udelay(10);\r
+                }\r
+            }\r
+            if(cnt <=0 ){\r
+               SENSOR_TR("flash read  erro,i = %d ,readcount = %d!\n",i,readcount);\r
+               return err;\r
+               }\r
+        }\r
+    return 0;\r
+}\r
+static int isp_load_fw_prepare(struct i2c_client *client){\r
+       //pll start cmd\r
+       sendI2cCmd(client, 0x80, 0x0);\r
+//     msleep(5);\r
+       //flash memory devider\r
+       sendI2cCmd(client, 0xD0, 0x30); \r
+//     msleep(5);\r
+       //pll 1 Conf.command(24MHZ->192MHZ)\r
+       sendI2cCmd(client, 0x40, 0x01); \r
+       sendI2cCmd(client, 0x41, 0x40); \r
+       sendI2cCmd(client, 0x42, 0x05); \r
+       sendI2cCmd(client, 0x49, 0x03); \r
+       sendI2cCmd(client, 0x80, 0x02); \r
+//     sendI2cCmd(client, 0x4A, 0x01); \r
+    return 0;\r
+}\r
+static int isp_init_cmds(struct i2c_client *client){\r
+       //pll start cmd\r
+       sendI2cCmd(client, 0x80, 0x0);\r
+//     msleep(5);\r
+       //flash memory devider\r
+       sendI2cCmd(client, 0xD0, 0x30); \r
+//     msleep(5);\r
+       //pll 1 Conf.command(24MHZ->192MHZ)\r
+       sendI2cCmd(client, 0x40, 0x01); \r
+       sendI2cCmd(client, 0x41, 0x40); \r
+       sendI2cCmd(client, 0x42, 0x05); \r
+       sendI2cCmd(client, 0x49, 0x03);\r
+    isp_reg_value_check(client,0x36,0x03);\r
+       sendI2cCmd(client, 0x80, 0x03); \r
+//     sendI2cCmd(client, 0x4A, 0x01); \r
+  //  msleep(100);\r
+    return 0;\r
+}\r
+static int isp_init_check(struct i2c_client *client){\r
+    if(!isp_reg_value_check(client,0x00,PRODUCT_ID_VALUE_REG0)){\r
+               SENSOR_TR("%s:%d,check erro!\n", __func__,__LINE__);\r
+               return -1;\r
+       }\r
+    if(!isp_reg_value_check(client,0x01,PRODUCT_VERSION_VALUE_REG1)){\r
+               SENSOR_TR("%s:%d,check erro!\n", __func__,__LINE__);\r
+               return -1;\r
+       }\r
+\r
+    isp_reg_value_check(client,0x02,FIRMWARE_MAJOR_VERSION_VALUE_REG2);\r
+    isp_reg_value_check(client,0x03,FIRMWARE_MINOR_VERSION_VALUE_REG3);\r
+    isp_reg_value_check(client,0x05,I2C_CHECKE_VALUE_REG5);\r
+  //  isp_reg_value_check(client,0x06,CHECKE_VALUE_REG6);\r
+    //now do not check the two reg.\r
+       sendI2cCmd(client, 0x1F, 0x01); \r
+    isp_reg_value_check(client,0x90,CHECKE_VALUE_REG0X90);\r
+    isp_reg_value_check(client,0x91,CHECKE_VALUE_REG0X91);\r
+    SENSOR_TR("%s:%d,check succsess!\n", __func__,__LINE__);\r
+       //while(1);\r
+    return 0;\r
+}\r
+static int flash_down_load_firmware(struct i2c_client *client,u16 addr){\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+       isp_load_fw_prepare(client);\r
+    // 1.enter pro mode\r
+    if(flash_program_mode(client,true)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit;\r
+        }\r
+    // 2. flash erase , chip erase or sector erase\r
+    #if FLASH_ERASE_BY_SECTOR\r
+    //for test\r
+    {\r
+    int sect,sectCnt,i;\r
+\r
+    sect = 0;\r
+    sectCnt = 15;\r
+    for(i = 0;i < sectCnt;i++)\r
+        {\r
+        sect = (i << 4) & 0xF0;\r
+        if(flash_mem_erase(client,sect/*+i*/))\r
+            {\r
+            printk("%s:%d erro \n",__func__,__LINE__);\r
+            goto erro_quit_promode;  \r
+            }\r
+        }\r
+    }\r
+    #elif FLASH_ERASE_ALL\r
+    if(flash_mem_erase(client,0xFF))\r
+        {\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit_promode;\r
+        }\r
+    #endif\r
+\r
+    // 3. write addr\r
+    if(flash_write_read_addr(client,addr,0x50)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit_promode;\r
+       }\r
+\r
+    // 4. write data ,sequence write\r
+    if(flash_write_data(client)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit_promode;\r
+        }\r
+    // 5. quit pro mode\r
+    if(flash_program_mode(client,false)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit;\r
+        }\r
+    //reset , reset pin low ,then high\r
+       if (icl->reset)\r
+               icl->reset(icd->pdev);\r
+        mdelay(10);\r
+    isp_init_cmds(client);\r
+    isp_init_check(client);\r
+    return 0;\r
+    erro_quit_promode:\r
+        flash_program_mode(client,false);\r
+    erro_quit:\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        return -1;\r
+}\r
+static int flash_read_firmware_data(struct i2c_client *client,u16 addr,u8* rd_data,int readcount){\r
+    // 1.enter pro mode\r
+    if(flash_program_mode(client,true)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit;\r
+        }\r
+    // 2. write addr\r
+    if(flash_write_read_addr(client,addr,0x00)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit_promode;\r
+        }\r
+    // 3. read data\r
+    if(flash_read_data(client,rd_data,readcount)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit_promode;\r
+        }\r
+    // 4. quit pro mode\r
+    if(flash_program_mode(client,false)){\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        goto erro_quit;\r
+        }\r
+    return 0;\r
+    erro_quit_promode:\r
+        flash_program_mode(client,false);\r
+    erro_quit:\r
+        printk("%s:%d erro \n",__func__,__LINE__);\r
+        return -1;\r
+}\r
+//power control\r
+//power_up sequence : reset low,no mclk; power up ; supply mclk ; reset high\r
+//power_off sequence: reset low ,mclk off , power off\r
+//power down sequence :as the power up ,then cut off mclk;\r
+//wake up from power down: supply mclk ;reset asserted twice(low - high -low -high)\r
+//soc camera has done the power control\r
+/* Interface active, can use i2c. If it fails, it can indeed mean, that\r
+ * this wasn't our capture interface, so, we wait for the right one */\r
+static int sensor_video_probe(struct soc_camera_device *icd,\r
+                              struct i2c_client *client)\r
+{\r
+\r
+    /* We must have a parent by now. And it cannot be a wrong one.\r
+     * So this entire test is completely redundant. */\r
+    if (!icd->dev.parent ||\r
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)\r
+               return -ENODEV;\r
+       //get the pid of sensor\r
+       //pll start cmd\r
+\r
+       //ISP initialization check\r
+#if 1\r
+    flash_down_load_firmware(client,0x00);\r
+    isp_init_cmds(client);\r
+    if(!isp_init_check(client)){\r
+               SENSOR_TR("%s:%d,check erro!\n", __func__,__LINE__);\r
+               return -1;\r
+       }\r
+\r
+#endif\r
+    return 0;\r
+\r
+//sensor_video_probe_err:\r
+ //   return ret;\r
+}\r
+static int sensor_probe(struct i2c_client *client,\r
+                        const struct i2c_device_id *did)\r
+{\r
+           struct isp_dev *sensor;\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);\r
+    struct soc_camera_link *icl;\r
+    int ret;\r
+\r
+    SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);\r
+    if (!icd) {\r
+        dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());\r
+        return -EINVAL;\r
+    }\r
+\r
+    icl = to_soc_camera_link(icd);\r
+    if (!icl) {\r
+        dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());\r
+        return -EINVAL;\r
+    }\r
+\r
+    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {\r
+        dev_warn(&adapter->dev,\r
+                "I2C-Adapter doesn't support I2C_FUNC_I2C\n");\r
+        return -EIO;\r
+    }\r
+\r
+    sensor = kzalloc(sizeof(struct isp_dev), GFP_KERNEL);\r
+    if (!sensor)\r
+        return -ENOMEM;\r
+\r
+    v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);\r
+\r
+    /* Second stage probe - when a capture adapter is there */\r
+    icd->ops           = &sensor_ops;\r
+    sensor->isp_priv_info.fmt = sensor_colour_fmts[0];\r
+\r
+\r
+    ret = sensor_video_probe(icd, client);\r
+    if (ret < 0) {\r
+        icd->ops = NULL;\r
+        i2c_set_clientdata(client, NULL);\r
+        kfree(sensor);\r
+               sensor = NULL;\r
+    } else {\r
+               #if CONFIG_SENSOR_Focus\r
+               sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING(_af_workqueue));\r
+               if (sensor->sensor_wq == NULL)\r
+                       SENSOR_TR("%s create fail!", SENSOR_NAME_STRING(_af_workqueue));\r
+               mutex_init(&sensor->wq_lock);\r
+               #endif\r
+               mutex_init(&sensor->isp_priv_info.access_data_lock);\r
+\r
+    }\r
+\r
+    SENSOR_DG("\n%s..%s..%d  ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);\r
+    return ret;\r
+}\r
+static int sensor_remove(struct i2c_client *client)\r
+{\r
+    struct isp_dev *sensor = to_sensor(client);\r
+    struct soc_camera_device *icd = client->dev.platform_data;\r
+\r
+    icd->ops = NULL;\r
+    i2c_set_clientdata(client, NULL);\r
+    client->driver = NULL;\r
+    kfree(sensor);\r
+       sensor = NULL;\r
+\r
+    return 0;\r
+}\r
+static const struct i2c_device_id sensor_id[] = {\r
+       {SENSOR_NAME_STRING(), 0 },\r
+       { }\r
+};\r
+MODULE_DEVICE_TABLE(i2c, sensor_id);\r
+\r
+static struct i2c_driver sensor_i2c_driver = {\r
+       .driver = {\r
+               .name = SENSOR_NAME_STRING(),\r
+       },\r
+       .probe          = sensor_probe,\r
+       .remove         = sensor_remove,\r
+       .id_table       = sensor_id,\r
+};\r
+\r
+static int __init sensor_mod_init(void)\r
+{\r
+    SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());\r
+    return i2c_add_driver(&sensor_i2c_driver);\r
+}\r
+\r
+static void __exit sensor_mod_exit(void)\r
+{\r
+    i2c_del_driver(&sensor_i2c_driver);\r
+}\r
+\r
+device_initcall_sync(sensor_mod_init);\r
+module_exit(sensor_mod_exit);\r
+\r
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));\r
+MODULE_AUTHOR("ddl <kernel@rock-chips>");\r
+MODULE_LICENSE("GPL");\r
index a849b69172ae79846df169182847eaa0ccdcccff..de2385d279cb735e61d60903f75a867b21efc525 100755 (executable)
@@ -280,8 +280,9 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 
 *v0.x.1c:
 *         1. fix query resolution error;
+*v0.x.1e: 1. add mv9335+ov5650 driver
 */
-#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x1c)
+#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x1e)
 
 /* limit to rk29 hardware capabilities */
 #define RK_CAM_BUS_PARAM   (SOCAM_MASTER |\
index 3f066f713a263599623765b2b2699cab15e9b885..bc0b686336c66fd4f68a0772da25f00b3aff842a 100755 (executable)
@@ -64,8 +64,10 @@ static int soc_camera_power_set(struct soc_camera_device *icd,
                        return ret;
                }
 
-               if (icl->power)
+               if (icl->power){
+                       icl->power(icd->pdev, 0); // ensure power and reset pin are not active.
                        ret = icl->power(icd->pdev, power_on);
+                       }
                if (ret < 0) {
                        dev_err(&icd->dev,
                                "Platform failed to power-on the camera.\n");
@@ -491,9 +493,6 @@ static int soc_camera_open(struct file *file)
                if (ret < 0)
                        goto epower;
 
-               /* The camera could have been already on, try to reset */
-               if (icl->reset)
-                       icl->reset(icd->pdev);
         }
 
                ret = ici->ops->add(icd);
@@ -501,7 +500,14 @@ static int soc_camera_open(struct file *file)
                        dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
                        goto eiciadd;
                }
-
+        /* ddl@rock-chips.com : accelerate device open  */
+        //reset MUST be done after mclk supply(for mt9335 isp)
+        
+        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+               /* The camera could have been already on, try to reset */
+               if (icl->reset)
+                       icl->reset(icd->pdev);
+            }
                pm_runtime_enable(&icd->vdev->dev);
                ret = pm_runtime_resume(&icd->vdev->dev);
                if (ret < 0 && ret != -ENOSYS)
@@ -836,18 +842,19 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
        if (!qc->id)
                return -EINVAL;
 
-       /* First check host controls */
-       for (i = 0; i < ici->ops->num_controls; i++)
-               if (qc->id == ici->ops->controls[i].id) {
-                       memcpy(qc, &(ici->ops->controls[i]),
+       /* first device controls */
+       //if device support digital zoom ,first use it to do zoom,zyc
+       for (i = 0; i < icd->ops->num_controls; i++)
+               if (qc->id == icd->ops->controls[i].id) {
+                       memcpy(qc, &(icd->ops->controls[i]),
                                sizeof(*qc));
                        return 0;
                }
 
-       /* Then device controls */
-       for (i = 0; i < icd->ops->num_controls; i++)
-               if (qc->id == icd->ops->controls[i].id) {
-                       memcpy(qc, &(icd->ops->controls[i]),
+       /* then check host controls */
+       for (i = 0; i < ici->ops->num_controls; i++)
+               if (qc->id == ici->ops->controls[i].id) {
+                       memcpy(qc, &(ici->ops->controls[i]),
                                sizeof(*qc));
                        return 0;
                }
@@ -1194,13 +1201,14 @@ static int soc_camera_probe(struct device *dev)
        if (ret < 0)
                goto epower;
 
-       /* The camera could have been already on, try to reset */
-       if (icl->reset)
-               icl->reset(icd->pdev);
-
        ret = ici->ops->add(icd);
        if (ret < 0)
                goto eadd;
+    
+    /* The camera could have been already on, try to reset */
+    //reset MUST be done after mclk supply(for mt9335 isp)
+    if (icl->reset)
+            icl->reset(icd->pdev);
 
        /* Must have icd->vdev before registering the device */
        ret = video_dev_create(icd);
index f8b5600bb88f6684c1c3ad4ef08e95546dc1b6b3..f1ba530824d29ba7ffdae415bb22d0bf3a350843 100644 (file)
@@ -1403,6 +1403,7 @@ enum  v4l2_exposure_auto_type {
 #define V4L2_CID_FLASH                         (V4L2_CID_CAMERA_CLASS_BASE_ROCK+3)
 #define V4L2_CID_FOCUS_CONTINUOUS              (V4L2_CID_CAMERA_CLASS_BASE_ROCK+4)
 #define V4L2_CID_FOCUSZONE       (V4L2_CID_CAMERA_CLASS_BASE_ROCK+5)
+#define V4L2_CID_FACEDETECT (V4L2_CID_CAMERA_CLASS_BASE_ROCK+6)
 
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE              (V4L2_CTRL_CLASS_FM_TX | 0x900)