camsys_drv : v0.9.0
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk30_camera_pingpong.c
index 36bb8c05d0be409b5ab1862ea74d78869d464317..d24a0b7b0fa76934f53b59361659ad1db3339f59 100755 (executable)
@@ -9,7 +9,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK30)
+#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK30) ||defined(CONFIG_ARCH_RK3188)
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -40,7 +40,7 @@
 #include <plat/ipp.h>
 #include <plat/vpu_service.h>
 #include "../../video/rockchip/rga/rga.h"
-#if defined(CONFIG_ARCH_RK30)
+#if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK3188)
 #include <mach/rk30_camera.h>
 #include <mach/cru.h>
 #include <mach/pmu.h>
 
 #if defined(CONFIG_ARCH_RK2928)
 #include <mach/rk2928_camera.h>
+#include <mach/cru.h>
+#include <mach/pmu.h>
+#define SOFT_RST_CIF1 (SOFT_RST_MAX+1)
 #endif
 #include <asm/cacheflush.h>
-static int debug;
+static int debug = 0;
 module_param(debug, int, S_IRUGO|S_IWUSR);
 
+#if defined(CONFIG_TRACE_LOG_PRINTK)
+ #define RK30_CAM_DEBUG_TRACE(format, ...) printk(KERN_ERR"rk30_camera: " format, ## __VA_ARGS__)
+#else
+ #define RK30_CAM_DEBUG_TRACE(format, ...)
+#endif
+#define RK30_CAM_LOG_TRACE(format, ...) printk(KERN_WARNING"rk30_camera: " format, ## __VA_ARGS__)
+
 #define dprintk(level, fmt, arg...) do {                       \
        if (debug >= level)                                     \
        printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
@@ -153,14 +163,15 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 
 #define MIN(x,y)   ((x<y) ? x: y)
 #define MAX(x,y)    ((x>y) ? x: y)
+#define RK_SENSOR_12MHZ      12*1000*1000 
 #define RK_SENSOR_24MHZ      24*1000*1000          /* MHz */
-#define RK_SENSOR_48MHZ      48
+#define RK_SENSOR_48MHZ      48*1000*1000
 
 #define write_cif_reg(base,addr, val)  __raw_writel(val, addr+(base))
 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
 #define mask_cif_reg(addr, msk, val)    write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
 
-#if defined(CONFIG_ARCH_RK30)
+#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
 //CRU,PIXCLOCK
 #define CRU_PCLK_REG30                     0xbc
 #define ENANABLE_INVERT_PCLK_CIF0          ((0x1<<24)|(0x1<<8))
@@ -179,7 +190,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define mask_cru_reg(addr, msk, val)   write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
 #endif
 
-#if defined(CONFIG_ARCH_RK3066B)
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
 //GRF_IO_CON3                        0x100
 #define CIF_DRIVER_STRENGTH_2MA            (0x00 << 12)
 #define CIF_DRIVER_STRENGTH_4MA            (0x01 << 12)
@@ -276,8 +287,24 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 *         1. support rk3066b;
 *v0.4.15:
 *         1. cif work on pingping mode;
+*v0.x.17: 
+*         1. support 8Mega picture;
+*v0.x.19:
+*         1. invalidate the limit which scale is invalidat when scale ratio > 2;
+*v0.x.1b: 1. fix oops bug  when using arm to do scale_crop if preview buffer is not allocated correctly 
+          2. rk_camera_set_fmt will called twice, optimize the procedure. at the first time call ,just to do the sensor init.
+
+*v0.x.1c:
+*         1. fix query resolution error;
+*v0.x.1d: 
+*         1. add mv9335+ov5650 driver;
+*         2. fix 2928 digitzoom erro(arm crop scale) of selected zone;
+*v0.x.1f:
+*         1. support rk3188
+*v0.x.21:
+                 1. cif change mode to free run.support icatch 7002.
 */
-#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0x15)
+#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0x21)
 
 /* limit to rk29 hardware capabilities */
 #define RK_CAM_BUS_PARAM   (SOCAM_MASTER |\
@@ -296,8 +323,8 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define RK_CAM_H_MIN        32
 #define RK_CAM_W_MAX        3856            /* ddl@rock-chips.com : 10M Pixel */
 #define RK_CAM_H_MAX        2764
-#define RK_CAM_FRAME_INVAL_INIT 3
-#define RK_CAM_FRAME_INVAL_DC 3          /* ddl@rock-chips.com :  */
+#define RK_CAM_FRAME_INVAL_INIT 0
+#define RK_CAM_FRAME_INVAL_DC 0          /* ddl@rock-chips.com :  */
 #define RK30_CAM_FRAME_MEASURE  5
 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
@@ -310,6 +337,7 @@ struct rk_camera_buffer
     enum v4l2_mbus_pixelcode   code;
     int                        inwork;
 };
+
 enum rk_camera_reg_state
 {
        Reg_Invalidate,
@@ -334,18 +362,22 @@ struct rk_camera_work
        struct rk_camera_dev *pcdev;
        struct work_struct work;
     struct list_head queue;
-    unsigned int index;    
+    unsigned int index; 
+    unsigned int ts;
 };
+
 struct rk_camera_frmivalenum
 {
     struct v4l2_frmivalenum fival;
     struct rk_camera_frmivalenum *nxt;
 };
+
 struct rk_camera_frmivalinfo
 {
     struct soc_camera_device *icd;
     struct rk_camera_frmivalenum *fival_list;
 };
+
 struct rk_camera_zoominfo
 {
     struct semaphore sem;
@@ -354,6 +386,7 @@ struct rk_camera_zoominfo
    int vir_height;
     int zoom_rate;
 };
+
 #if CAMERA_VIDEOBUF_ARM_ACCESS
 struct rk29_camera_vbinfo
 {
@@ -362,11 +395,46 @@ struct rk29_camera_vbinfo
     unsigned int size;
 };
 #endif
+
 struct rk_camera_timer{
        struct rk_camera_dev *pcdev;
        struct hrtimer timer;
     bool istarted;
-       };
+};
+struct rk_cif_clk
+{
+    //************must modify start************/
+    struct clk *pd_cif;
+    struct clk *aclk_cif;
+    struct clk *hclk_cif;
+    struct clk *cif_clk_in;
+    struct clk *cif_clk_out;
+    //************must modify end************/
+
+    spinlock_t lock;
+    bool on;
+};
+static struct rk_cif_clk  cif_clk[2];
+struct hdr_exposure
+{
+    unsigned int set_ts;
+    unsigned int get_ts;
+    unsigned int code;
+};
+struct rk_hdr_info_s
+{
+    bool en;
+    struct hdr_exposure frame[3];
+};
+struct rk_cif_crop
+{
+    spinlock_t lock;
+    struct v4l2_rect c;
+    struct v4l2_rect bounds;
+};
+
+#define CONFIG_CIF_STOP_SYNC 1
+
 struct rk_camera_dev
 {
        struct soc_camera_host  soc_host;
@@ -397,8 +465,9 @@ struct rk_camera_dev
        unsigned int vipmem_bsize;
 #if CAMERA_VIDEOBUF_ARM_ACCESS    
     struct rk29_camera_vbinfo *vbinfo;
-    unsigned int vbinfo_count;
-#endif    
+#endif  
+       unsigned int vbinfo_count;
+
        int host_width;
        int host_height;
        int host_left;  //sensor output size ?
@@ -406,6 +475,7 @@ struct rk_camera_dev
        int hostid;
     int icd_width;
     int icd_height;
+    struct rk_cif_crop cropinfo;
 
        struct rk29camera_platform_data *pdata;
        struct resource         *res;
@@ -430,8 +500,15 @@ struct rk_camera_dev
     bool timer_get_fps;
     unsigned int reinit_times; 
     struct videobuf_queue *video_vq;
-    bool stop_cif;
+    volatile bool stop_cif;
+#if CONFIG_CIF_STOP_SYNC
+       wait_queue_head_t cif_stop_done;
+       volatile  bool cif_stopped;
+#endif
     struct timeval first_tv;
+
+    struct rk_hdr_info_s  hdr_info;
+//     spinlock_t              irq_lock;
 };
 
 static const struct v4l2_queryctrl rk_camera_controls[] =
@@ -447,6 +524,18 @@ static const struct v4l2_queryctrl rk_camera_controls[] =
         .default_value = 100,
     },
     #endif
+
+    {
+        .id            = V4L2_CID_HDR,
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,
+        .name          = "HDR",
+        .minimum       = 0,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 0,
+    }
+
+    
 };
 
 static DEFINE_MUTEX(camera_lock);
@@ -455,6 +544,7 @@ static const char *rk_cam_driver_description = "RK_Camera";
 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
 static void rk_camera_capture_process(struct work_struct *work);
 
+// #define OPTIMIZE_MEMORY_USE
 
 /*
  *  Videobuf operations
@@ -497,9 +587,11 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
         #endif
         {
             BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
+        #ifndef OPTIMIZE_MEMORY_USE
                if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) {    /* Buffers must be limited, when this resolution is genered by IPP */
                        *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
                }
+               #endif
         }
                if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
                        kfree(pcdev->camera_work);
@@ -510,7 +602,7 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
                if (pcdev->camera_work == NULL) {
                        pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
                        if (pcdev->camera_work == NULL) {
-                               RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
+                               RK30_CAM_DEBUG_TRACE("\n %s kmalloc fail\n", __FUNCTION__);
                                BUG();
                        }
             INIT_LIST_HEAD(&pcdev->camera_work_queue);
@@ -532,15 +624,18 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
         if (pcdev->vbinfo == NULL) {
             pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
             if (pcdev->vbinfo == NULL) {
-                               RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
+                               RK30_CAM_DEBUG_TRACE("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
                                BUG();
                        }
+            memset(pcdev->vbinfo,0,sizeof(struct rk29_camera_vbinfo)*(*count));
                        pcdev->vbinfo_count = *count;
         }
 #endif        
        }
+       
+       pcdev->vbinfo_count = *count;
     pcdev->video_vq = vq;
-    RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
+    RK30_CAM_DEBUG_TRACE("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
 
     return 0;
 }
@@ -574,8 +669,8 @@ static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer
     int ret;
     int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                                                icd->current_fmt->host_fmt);
-       if (bytes_per_line < 0)
-               return bytes_per_line;
+       if ((bytes_per_line < 0) || (vb->boff == 0))
+               return -EINVAL;
 
     buf = container_of(vb, struct rk_camera_buffer, vb);
 
@@ -588,9 +683,9 @@ static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer
     BUG_ON(NULL == icd->current_fmt);
 
     if (buf->code    != icd->current_fmt->code ||
-            vb->width   != icd->user_width ||
-            vb->height  != icd->user_height ||
-             vb->field   != field) {
+        vb->width   != icd->user_width ||
+        vb->height  != icd->user_height ||
+        vb->field   != field) {
         buf->code    = icd->current_fmt->code;
         vb->width   = icd->user_width;
         vb->height  = icd->user_height;
@@ -619,6 +714,38 @@ out:
     return ret;
 }
 
+#if 0
+static void rk_camera_store_register(struct rk_camera_dev *pcdev)
+{
+#if defined(CONFIG_ARCH_RK3188)
+       pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+       pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
+       pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
+       pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
+       pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
+       pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
+       pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
+       
+       cru_set_soft_reset(SOFT_RST_CIF0, true);
+       udelay(3);
+       cru_set_soft_reset(SOFT_RST_CIF0, false);
+       
+#endif
+}
+static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
+{
+#if defined(CONFIG_ARCH_RK3188)
+       write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
+       write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
+       write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
+       write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
+       write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
+       write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
+       write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
+#endif
+}
+#endif
+
 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev, int fmt_ready)
 {
        unsigned int y_addr,uv_addr;
@@ -626,13 +753,18 @@ static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_came
 
     if (vb) {
                if (CAM_WORKQUEUE_IS_EN()) {
+                   #ifdef OPTIMIZE_MEMORY_USE
+                       y_addr = vb->boff;
+                       uv_addr = y_addr + vb->width * vb->height;
+                   #else
                        y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
                        uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
                        if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
-                               RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
+                               RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
                                                  pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
                                BUG();
                        }
+                       #endif
                } else {
                        y_addr = vb->boff;
                        uv_addr = y_addr + vb->width * vb->height;
@@ -649,7 +781,7 @@ static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_came
                        write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
                                break;
                        default:
-                               RKCAMERA_TR("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready);
+                               RK30_CAM_DEBUG_TRACE("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready);
                                break;
                }
       
@@ -668,6 +800,7 @@ static void rk_videobuf_queue(struct videobuf_queue *vq,
 
     dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
             vb, vb->baddr, vb->bsize);
+   // spin_lock_irqsave(&pcdev->irq_lock, flags);
 
     vb->state = VIDEOBUF_QUEUED;
        if (list_empty(&pcdev->capture)) {
@@ -698,20 +831,23 @@ static void rk_videobuf_queue(struct videobuf_queue *vq,
                 vb_info->size = vb->bsize;
                 vb_info->phy_addr = vb->boff;
             } else {
-                RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
+                RK30_CAM_DEBUG_TRACE("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
             }
         }
     }
-#endif    
-    if (!pcdev->active0) {
-        pcdev->active0 = vb;
-        rk_videobuf_capture(vb,pcdev,0);
-               list_del_init(&(vb->queue));
-    } else if (!pcdev->active1) {
-        pcdev->active1 = vb;
-        rk_videobuf_capture(vb,pcdev,1);
-               list_del_init(&(vb->queue));
+#endif
+    if((((read_cif_reg(pcdev->base,CIF_CIF_CTRL)) & ENABLE_CAPTURE) == 0)){
+        if (!pcdev->active0) {
+            pcdev->active0 = vb;
+            rk_videobuf_capture(vb,pcdev,0);
+               list_del_init(&(vb->queue));
+        } else if (!pcdev->active1) {
+            pcdev->active1 = vb;
+            rk_videobuf_capture(vb,pcdev,1);
+               list_del_init(&(vb->queue));
+        }
     }
+       //spin_unlock_irqrestore(&pcdev->irq_lock, flags);
 }
 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
 {
@@ -738,6 +874,7 @@ rk_pixfmt2ippfmt_err:
        return -1;
 }
 
+#if 0
 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
 {
        switch (pixfmt)
@@ -774,6 +911,8 @@ static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
 rk_pixfmt2rgafmt_err:
        return -1;
 }
+#endif
+
 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
 static int rk_camera_scale_crop_pp(struct work_struct *work){
        struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
@@ -834,7 +973,7 @@ static int rk_camera_scale_crop_rga(struct work_struct *work){
        vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
        if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
                && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
-               RKCAMERA_TR("RGA not support this format !\n");
+               RK30_CAM_DEBUG_TRACE("RGA not support this format !\n");
                goto do_ipp_err;
                }
        if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
@@ -899,13 +1038,13 @@ static int rk_camera_scale_crop_rga(struct work_struct *work){
                        req.dst.x_offset =  pcdev->icd->user_width*w/scale_times;
                        req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
                        req.dst.yrgb_addr = vb->boff ;
-               //      RKCAMERA_TR("src.act_w = %d , src.act_h  = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset);
-               //      RKCAMERA_TR("dst.act_w = %d , dst.act_h  = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset);
-               //      RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
+               //      RK30_CAM_DEBUG_TRACE("src.act_w = %d , src.act_h  = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset);
+               //      RK30_CAM_DEBUG_TRACE("dst.act_w = %d , dst.act_h  = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset);
+               //      RK30_CAM_DEBUG_TRACE("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
 
                        while(rga_times-- > 0) {
                                if (rga_blit_sync(&session, &req)){
-                                       RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times);
+                                       RK30_CAM_DEBUG_TRACE("rga do erro,do again,rga_times = %d!\n",rga_times);
                                 } else {
                                        break;
                                 }
@@ -936,7 +1075,7 @@ static int rk_camera_scale_crop_rga(struct work_struct *work){
 }
 
 #endif
-#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
+#if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
 
 static int rk_camera_scale_crop_ipp(struct work_struct *work)
 {
@@ -949,7 +1088,7 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work)
        struct rk29_ipp_req ipp_req;
        int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
        int scale_times,w,h;
-        int ret = 0;
+       int ret = 0;
     /*
     *ddl@rock-chips.com: 
     * IPP Dest image resolution is 2047x1088, so scale operation break up some times
@@ -961,7 +1100,49 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work)
         scale_times = 1;
     }
     memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
-
+#ifdef OPTIMIZE_MEMORY_USE
+    //need copy to ipp buffer?
+    if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width)
+        ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){
+            if((pcdev->zoominfo.vir_width != pcdev->icd->user_width) || (pcdev->zoominfo.vir_height != pcdev->icd->user_height)){
+                printk("OPTIMIZE_MEMORY_USE erro: src size not equal to dst size\n");
+                goto do_ipp_err;
+            }
+            ipp_req.timeout = 3000;
+            ipp_req.flag = IPP_ROT_0; 
+            ipp_req.store_clip_mode =1;
+            ipp_req.src0.w = pcdev->zoominfo.vir_width/scale_times;
+            ipp_req.src0.h = pcdev->zoominfo.vir_height/scale_times;
+            ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
+            ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
+            ipp_req.src_vir_w =  pcdev->zoominfo.vir_width; 
+            ipp_req.dst_vir_w = pcdev->icd->user_width; 
+            rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
+            rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
+            vipdata_base = pcdev->vipmem_phybase;
+            src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;  //vipmem
+            dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
+            for (h=0; h<scale_times; h++) {
+                for (w=0; w<scale_times; w++) {
+                    src_y_offset = (h*pcdev->zoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width 
+                                +  w*pcdev->zoominfo.vir_width/scale_times;
+                           src_uv_offset = (h*pcdev->zoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width/2
+                                + w*pcdev->zoominfo.vir_width/scale_times;
+
+                    dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
+                    dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
+                       ipp_req.src0.YrgbMst = vb->boff + src_y_offset;
+                       ipp_req.src0.CbrMst = vb->boff + src_y_size + src_uv_offset;
+                       ipp_req.dst0.YrgbMst = vipdata_base + dst_y_offset;
+                       ipp_req.dst0.CbrMst = vipdata_base + dst_y_size + dst_uv_offset;
+                    if (ipp_blit_sync(&ipp_req)){
+                        RK30_CAM_DEBUG_TRACE("ipp do erro\n");
+                     }
+                 }
+             }
+            memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
+        }
+#endif
 
     ipp_req.timeout = 3000;
     ipp_req.flag = IPP_ROT_0; 
@@ -974,7 +1155,16 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work)
     ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
     ipp_req.dst_vir_w = pcdev->icd->user_width;        
     rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
+#ifdef OPTIMIZE_MEMORY_USE
+    if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width)
+        ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){
+        vipdata_base = pcdev->vipmem_phybase;
+    }else
+        vipdata_base = vb->boff;
+
+#else
     vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
+#endif
     src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;  //vipmem
     dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
     for (h=0; h<scale_times; h++) {
@@ -994,7 +1184,7 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work)
                ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
                while(ipp_times-- > 0) {
                 if (ipp_blit_sync(&ipp_req)){
-                    RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
+                    RK30_CAM_DEBUG_TRACE("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
                  } else {
                     break;
                  }
@@ -1004,17 +1194,17 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work)
                        spin_lock_irqsave(&pcdev->lock, flags);
                        vb->state = VIDEOBUF_NEEDS_INIT;
                        spin_unlock_irqrestore(&pcdev->lock, flags);
-                       RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
-                       RKCAMERA_TR("widx:%d hidx:%d ",w,h);
-                       RKCAMERA_TR("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height);
-                       RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
-                       RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
-                       RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
-                       RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
-                       RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
-                       RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
-                       RKCAMERA_TR("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w);
-                       RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
+                       RK30_CAM_DEBUG_TRACE("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
+                       RK30_CAM_DEBUG_TRACE("widx:%d hidx:%d ",w,h);
+                       RK30_CAM_DEBUG_TRACE("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w);
+                       RK30_CAM_DEBUG_TRACE("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
                 
                        goto do_ipp_err;
                }
@@ -1052,8 +1242,8 @@ static int rk_camera_scale_crop_arm(struct work_struct *work)
     cropW = pcdev->zoominfo.a.c.width;
     cropH = pcdev->zoominfo.a.c.height;
        
-    psY = psY + (srcW-cropW);
-    psUV = psUV + (srcW-cropW)
+    psY = psY + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width+pcdev->zoominfo.a.c.left;
+    psUV = psUV + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width/2+pcdev->zoominfo.a.c.left
     
     vb_info = pcdev->vbinfo+vb->i; 
     dst_phy = vb_info->phy_addr;
@@ -1062,9 +1252,8 @@ static int rk_camera_scale_crop_arm(struct work_struct *work)
     dstW = pcdev->icd->user_width;
     dstH = pcdev->icd->user_height;
 
-    zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1;
-    zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1;
+    zoomindstxIntInv = ((unsigned long)(cropW)<<16)/dstW + 1;
+    zoomindstyIntInv = ((unsigned long)(cropH)<<16)/dstH + 1;
     //y
     //for(y = 0; y<dstH - 1 ; y++ ) {   
     for(y = 0; y<dstH; y++ ) {   
@@ -1146,17 +1335,48 @@ rk_camera_scale_crop_arm_end:
        return ret;    
 }
 #endif
+
 static void rk_camera_capture_process(struct work_struct *work)
 {
     struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);    
     struct videobuf_buffer *vb = camera_work->vb;    
     struct rk_camera_dev *pcdev = camera_work->pcdev;    
     //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;    
+    struct device *control = to_soc_camera_control(pcdev->icd);
+    struct v4l2_subdev *sd=dev_get_drvdata(control);
     unsigned long flags = 0;    
-    int err = 0;    
+    int err = 0,i;    
 
     if (!CAM_WORKQUEUE_IS_EN())        
         goto rk_camera_capture_process_end; 
+
+    camera_work->vb->rk_code = 0x00;
+    if (pcdev->hdr_info.en) {
+               printk("rk_camera_capture_process hdr %d fps\n",camera_work->ts);
+        if (pcdev->hdr_info.frame[0].set_ts == 0) {
+            v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)pcdev->hdr_info.frame[0].code);
+            pcdev->hdr_info.frame[0].set_ts = pcdev->fps;
+            printk("set hdr %d @ %d fps\n",0,pcdev->fps);
+        } else {
+            if ((camera_work->ts - pcdev->hdr_info.frame[0].set_ts) > 1) {
+                for (i=0; i<3; i++) {
+                    if (pcdev->hdr_info.frame[i].get_ts == 0) {
+                                               printk("get hdr %d @ %d fps %dx%d\n",i,camera_work->ts,camera_work->vb->width,camera_work->vb->height);
+                        pcdev->hdr_info.frame[i].get_ts = camera_work->ts;
+                        RK_VIDEOBUF_CODE_SET(camera_work->vb->rk_code,pcdev->hdr_info.frame[i].code);
+                        break;
+                    }
+                }
+
+                if (i==2) {
+                    v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)RK_VIDEOBUF_HDR_EXPOSURE_FINISH);
+                    pcdev->hdr_info.en = false;
+                    printk("hdr off\n");
+                }
+            }
+        }
+    }
+    
     
     down(&pcdev->zoominfo.sem);
     if (pcdev->icd_cb.scale_crop_cb){
@@ -1175,13 +1395,41 @@ rk_camera_capture_process_end:
                vb->state = VIDEOBUF_DONE;
                vb->field_count++;
                }
-    }    
-    wake_up(&(camera_work->vb->done));     
+    }       
     spin_lock_irqsave(&pcdev->camera_work_lock, flags);    
-    list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);    
-    spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);    
+    list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
+    spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); 
+    wake_up(&(camera_work->vb->done));  
     return;
 }
+#if defined(CONFIG_ARCH_RK3188)
+static void rk_camera_store_resore_register(struct rk_camera_dev *pcdev)
+{
+
+       pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+       pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
+       pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
+       pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
+       pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
+       pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
+       pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
+       
+       cru_set_soft_reset(SOFT_RST_CIF0, true);
+       udelay(5);
+       cru_set_soft_reset(SOFT_RST_CIF0, false);
+       
+    if (pcdev->reginfo_suspend.cifCtrl&ENABLE_CAPTURE)
+        write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
+       write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
+       write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
+       write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
+       write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
+       write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
+       write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
+       
+}
+#endif
+
 static irqreturn_t rk_camera_irq(int irq, void *data)
 {
     struct rk_camera_dev *pcdev = data;
@@ -1191,33 +1439,88 @@ static irqreturn_t rk_camera_irq(int irq, void *data)
     unsigned long tmp_intstat;
     unsigned long tmp_cifctrl; 
        unsigned long tmp_cif_frmst; 
-       struct videobuf_buffer **active;
+       struct videobuf_buffer **active = 0;
        int flag = 0;
+        unsigned int invalid_y_addr ,invalid_uv_addr;
+#ifdef OPTIMIZE_MEMORY_USE
+       invalid_y_addr = 0/*pcdev->vipmem_phybase + pcdev->vipmem_bsize*/;
+       invalid_uv_addr = 0/*invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height*/;
+#else
+       invalid_y_addr = pcdev->vipmem_phybase + pcdev->vbinfo_count *pcdev->vipmem_bsize;
+       invalid_uv_addr = invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
+#endif 
     tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
     tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
        tmp_cif_frmst = read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS);
 
-    
+#if (CONFIG_CIF_STOP_SYNC == 0)
     if(pcdev->stop_cif == true) {
-        RKCAMERA_TR("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__);
-       write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);  /* clear vip interrupte single  */
-        return IRQ_HANDLED;
-    }
-    
+               //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__);
+               write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);  /* clear vip interrupte single  */
+               return IRQ_HANDLED;
+       }
+#endif
+
     if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/) {//bit9 =1 ,bit0 = 0
        write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200);  /* clear vip interrupte single  */
-        if(tmp_cifctrl & ENABLE_CAPTURE)
-            write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
//       if(tmp_cifctrl & ENABLE_CAPTURE)
//           write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
          return IRQ_HANDLED;
     }
     
     /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
     if (tmp_cif_frmst & (CIF_F0_READY | CIF_F1_READY)) {
        write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01);  /* clear vip interrupte single  */
+#if CONFIG_CIF_STOP_SYNC 
+                       if(pcdev->stop_cif == true) {
+                               //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__);
+                               write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);  /* clear vip interrupte single  */
+                               
+#if 1
+                               //              write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0);     //capture complete interrupt enable
+                                               {
+#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
+                                       mdelay(100);
+                                       if(IS_CIF0()){
+                                               cru_set_soft_reset(SOFT_RST_CIF0, true);
+                                               udelay(5);
+                                               cru_set_soft_reset(SOFT_RST_CIF0, false);
+                       
+                                       }else{
+                                               cru_set_soft_reset(SOFT_RST_CIF1, true);
+                                               udelay(5);
+                                               cru_set_soft_reset(SOFT_RST_CIF1, false);
+                                       }
+#elif defined(CONFIG_ARCH_RK3188)
+                                       cru_set_soft_reset(SOFT_RST_CIF0, true);
+                                       udelay(5);
+                                       cru_set_soft_reset(SOFT_RST_CIF0, false);
+#endif
+                               }
+#endif
+                           spin_lock(&pcdev->lock);
+                               pcdev->cif_stopped = true;
+                               wake_up(&pcdev->cif_stop_done);
+                               spin_unlock(&pcdev->lock);
+                               return IRQ_HANDLED;
+                       }
+#endif
         if (!pcdev->fps) {
             do_gettimeofday(&pcdev->first_tv);            
         }
+process_another_frame: 
+        if((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){
+                   printk(KERN_DEBUG"%s:f0 && f1 ready ,need to resart cif!!!!!\n",__func__);
+           spin_lock(&pcdev->lock);
+
+            rk_camera_store_resore_register(pcdev);
+                       rk_videobuf_capture(pcdev->active0,pcdev,0);
+                       rk_videobuf_capture(pcdev->active1,pcdev,1);
+                       tmp_cifctrl &=~ENABLE_CAPTURE;
+                   spin_unlock(&pcdev->lock);
+
+                       goto RK_CAMERA_IRQ_END;
+        }
                pcdev->fps++;
         
                if (tmp_cif_frmst & CIF_F0_READY){
@@ -1226,70 +1529,103 @@ static irqreturn_t rk_camera_irq(int irq, void *data)
                } else if (tmp_cif_frmst & CIF_F1_READY){
                        active = &pcdev->active1;
                        flag = 1;
+               } else {
+                       printk("irq frame status erro \n");
+                       goto RK_CAMERA_IRQ_END;
                }
-               
+#if 0  
                if (!(*active)){
                        goto RK_CAMERA_IRQ_END;
                }
+#endif
+               if (pcdev->frame_inval>0) {
+                       pcdev->frame_inval--;
+                       rk_videobuf_capture(*active,pcdev,flag);
+                       goto first_frame_done;
+               } else if (pcdev->frame_inval) {
+                       RK30_CAM_DEBUG_TRACE("frame_inval : %0x",pcdev->frame_inval);
+                       pcdev->frame_inval = 0;
+               }
         
-        if (pcdev->frame_inval>0) {
-            pcdev->frame_inval--;
-            rk_videobuf_capture(*active,pcdev,flag);
-            goto RK_CAMERA_IRQ_END;
-        } else if (pcdev->frame_inval) {
-               RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
-            pcdev->frame_inval = 0;
-        }
-        
-        if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
-            do_gettimeofday(&tv);            
-            pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
-                                    /(RK30_CAM_FRAME_MEASURE-1);
+               if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
+                       do_gettimeofday(&tv);            
+                       pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
+                                                                       /(RK30_CAM_FRAME_MEASURE-1);
         }
                
-        vb = *active;
-        if(!vb){
-            RKCAMERA_TR("no acticve buffer!!!\n");
-            goto RK_CAMERA_IRQ_END;
-        }
+               vb = *active;
+               
+#if 0
+               if(!vb){
+                       RK30_CAM_DEBUG_TRACE("no acticve buffer!!!\n");
+                       goto RK_CAMERA_IRQ_END;
+               }
 
                if (vb->stream.prev != &(pcdev->video_vq->stream)) {
-                       RKCAMERA_DG("vb(%d) isn't first node in stream list\n", vb->i);
+                       RK30_CAM_DEBUG_TRACE("vb(%d) isn't first node in stream list\n", vb->i);
                        goto RK_CAMERA_IRQ_END;
                }
-
+#endif
                *active = NULL;
-        if (!list_empty(&pcdev->capture)) {
-            *active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
+           spin_lock(&pcdev->lock);
+               if (!list_empty(&pcdev->capture)) {
+                       *active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
                        if (*active) {
-                WARN_ON((*active)->state != VIDEOBUF_QUEUED);                     
+                               WARN_ON((*active)->state != VIDEOBUF_QUEUED); 
+                               if (tmp_cif_frmst & CIF_F0_READY){
+                               pcdev->active0 = *active;
+                       } else if (tmp_cif_frmst & CIF_F1_READY){
+                               pcdev->active1 = *active;
+                       }else{
+                    printk("irq frame status erro !\n");
+                       }
                                rk_videobuf_capture((*active),pcdev,flag);
                                list_del_init(&((*active)->queue));
                        }
-        }
-        if ((*active) == NULL) {
-                       RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
                }
-
-        do_gettimeofday(&vb->ts);
+           spin_unlock(&pcdev->lock);
+               if ((*active) == NULL) {
+               //      RK30_CAM_DEBUG_TRACE("%s video_buf queue is empty!\n",__FUNCTION__);
+                       if(flag == 0){                  
+                           pcdev->active0 = NULL;
+                               write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, invalid_y_addr);
+                               write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, invalid_uv_addr);
+                               }else{
+                           pcdev->active1 = NULL;
+                               write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, invalid_y_addr);
+                               write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, invalid_uv_addr);
+                               }
+               }
+               if(vb)
+                       do_gettimeofday(&vb->ts);
                if (CAM_WORKQUEUE_IS_EN()) {
-            if (!list_empty(&pcdev->camera_work_queue)) {
-                wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
-                list_del_init(&wk->queue);
-                INIT_WORK(&(wk->work), rk_camera_capture_process);
-                       wk->vb = vb;
-                       wk->pcdev = pcdev;
-                       queue_work(pcdev->camera_wq, &(wk->work));
-            }                                  
+                       if(vb){
+                                       if (!list_empty(&pcdev->camera_work_queue)) {
+                                               wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
+                                               list_del_init(&wk->queue);
+                                               INIT_WORK(&(wk->work), rk_camera_capture_process);
+                                               wk->vb = vb;
+                                               wk->pcdev = pcdev;
+                                       wk->ts = pcdev->fps;
+                                               queue_work(pcdev->camera_wq, &(wk->work));
+                                       }else{
+                                               printk("work queue is empty \n!!!!!!!!");
+                                       }
+                               }
                } else {
-                   if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
-               vb->state = VIDEOBUF_DONE;              
-               vb->field_count++;
-               }
+                       if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
+                               vb->state = VIDEOBUF_DONE;              
+                               vb->field_count++;
+                       }
                        wake_up(&vb->done);
                }
-               
     }
+first_frame_done:
+       if ((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){
+                   printk(KERN_DEBUG"%s:f0 && f1 ready ,need to process f1 too!!!!!\n",__func__);
+            tmp_cif_frmst &=~CIF_F0_READY;
+            goto process_another_frame;
+       }
 
 RK_CAMERA_IRQ_END:
     if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
@@ -1329,26 +1665,27 @@ static void rk_videobuf_release(struct videobuf_queue *vq,
             break;
     }
 #endif
+
+       #if 0   /* ddl@rock-chips.com: this wait operation is not nessary, invalidate in v0.x.1f */
        if (vb == pcdev->active0 || vb == pcdev->active1) {
-               RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
+               RK30_CAM_DEBUG_TRACE("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
                interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
-               RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
+               RK30_CAM_DEBUG_TRACE("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
        }
-
-    flush_workqueue(pcdev->camera_wq); 
+       #endif
+       flush_workqueue(pcdev->camera_wq); 
 #if CAMERA_VIDEOBUF_ARM_ACCESS
-    if (pcdev->vbinfo) {
-        vb_info = pcdev->vbinfo + vb->i;
+       if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
+               vb_info = pcdev->vbinfo + vb->i;
         
-        if (vb_info->vir_addr) {
-            iounmap(vb_info->vir_addr);
-            release_mem_region(vb_info->phy_addr, vb_info->size);
-            memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
-        }       
-               
+               if (vb_info->vir_addr) {
+                       iounmap(vb_info->vir_addr);
+                       release_mem_region(vb_info->phy_addr, vb_info->size);
+                       memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
+               }
        }
 #endif    
-    rk_videobuf_free(vq, buf);
+       rk_videobuf_free(vq, buf);
 }
 
 static struct videobuf_queue_ops rk_videobuf_ops =
@@ -1375,68 +1712,74 @@ static void rk_camera_init_videobuf(struct videobuf_queue *q,
                                    sizeof(struct rk_camera_buffer),
                                    icd,&icd->video_lock);
 }
-static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
-{
-    int err = 0;
-    
-    if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){
-        RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
-        err = -ENOENT;
-        goto RK_CAMERA_ACTIVE_ERR;
-        }
 
-       clk_enable(pcdev->pd_cif);
-       clk_enable(pcdev->aclk_cif);
+static int rk_camera_mclk_ctrl(int cif_idx, int on, int clk_rate){
+    int err = 0,cif;
+    struct rk_cif_clk *clk;
+    struct clk *cif_clk_out_div;
 
-       clk_enable(pcdev->hclk_cif);
-       clk_enable(pcdev->cif_clk_in);
+    cif = cif_idx - RK29_CAM_PLATFORM_DEV_ID;
+    if ((cif<0)||(cif>1)) {
+        RKCAMERA_TR(KERN_ERR "cif index(%d) is invalidate\n",cif_idx);
+        err = -1;
+        goto rk_camera_clk_ctrl_end;
+    }
 
-    //if (icd->ops->query_bus_param)                                                  /* ddl@rock-chips.com : Query Sensor's xclk */
-        //sensor_bus_flags = icd->ops->query_bus_param(icd);
-       clk_enable(pcdev->cif_clk_out);
-    clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ);
+    clk = &cif_clk[cif];
 
-       ndelay(10);
-    //soft reset  the registers
-    #if 0 //has somthing wrong when suspend and resume now
-    if(IS_CIF0()){
-        printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30));
-               //dump regs
-       {
-               printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
-               printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
-               printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
-               printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
-               printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
-               printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
-               printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
-               printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
-               printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
-               
-               printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
-               printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
-       printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
-       printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
-       printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
-       printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
-       }
+    if(!clk->aclk_cif || !clk->hclk_cif || !clk->cif_clk_in || !clk->cif_clk_out) {
+        RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
+        err = -ENOENT;
+        goto rk_camera_clk_ctrl_end;
+    }
+    spin_lock(&clk->lock);
+    if (on && !clk->on) {
+        clk_enable(clk->pd_cif);
+        clk_enable(clk->aclk_cif);
+        clk_enable(clk->hclk_cif);
+        clk_enable(clk->cif_clk_in);
+        clk_enable(clk->cif_clk_out);
+        clk_set_rate(clk->cif_clk_out,clk_rate);
+        mdelay(10);
+        clk->on = true;
+        
+    } else if (!on && clk->on) {
+        clk_disable(clk->aclk_cif);
+        clk_disable(clk->hclk_cif);
+        clk_disable(clk->cif_clk_in);
+
+        clk_disable(clk->cif_clk_out);
+        clk_disable(clk->pd_cif);
+        clk->on = false;
+        if(cif){
+            cif_clk_out_div =  clk_get(NULL, "cif1_out_div");
+        }else{
+            cif_clk_out_div =  clk_get(NULL, "cif0_out_div");
+            if(IS_ERR_OR_NULL(cif_clk_out_div)) {
+                cif_clk_out_div =  clk_get(NULL, "cif_out_div");
+            }
+        }
 
-       mdelay(100);
-        write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 ));
-        printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
-        write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
-       mdelay(1000);
-        printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
-    }else{
-        write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
-        write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
+        if(IS_ERR_OR_NULL(cif_clk_out_div)) {
+            err = clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
+            clk_put(cif_clk_out_div);
+        } else {
+            err = -1;
+        }
+
+        if(err)
+           RKCAMERA_TR("WARNING %s_%s_%d: camera sensor mclk maybe not close, please check!!!\n", __FILE__, __FUNCTION__, __LINE__);
     }
-    #endif
+    spin_unlock(&clk->lock);
+rk_camera_clk_ctrl_end:
+    return err;
+}
+static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
+{
     write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE);   /* ddl@rock-chips.com : vip ahb burst 16 */
 
-    write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE);   /* ddl@rock-chips.com : vip ahb burst 16 */
     write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01);    //capture complete interrupt enable
-    RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
+    RK30_CAM_DEBUG_TRACE("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
     return 0;
 RK_CAMERA_ACTIVE_ERR:
     return -ENODEV;
@@ -1444,18 +1787,6 @@ RK_CAMERA_ACTIVE_ERR:
 
 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
 {
-       clk_disable(pcdev->aclk_cif);
-
-       clk_disable(pcdev->hclk_cif);
-       clk_disable(pcdev->cif_clk_in);
-       
-       clk_disable(pcdev->cif_clk_out);
-       clk_enable(pcdev->cif_clk_out);
-    clk_set_rate(pcdev->cif_clk_out,48*1000*1000);
-       clk_disable(pcdev->cif_clk_out);
-    
-       clk_disable(pcdev->pd_cif);
     return;
 }
 
@@ -1469,6 +1800,9 @@ static int rk_camera_add_device(struct soc_camera_device *icd)
     struct v4l2_subdev *sd;
     int ret,i,icd_catch;
     struct rk_camera_frmivalenum *fival_list,*fival_nxt;
+    struct v4l2_cropcap cropcap;
+    struct v4l2_mbus_framefmt mf;
+    const struct soc_camera_format_xlate *xlate = NULL;
     
     mutex_lock(&camera_lock);
 
@@ -1477,7 +1811,7 @@ static int rk_camera_add_device(struct soc_camera_device *icd)
         goto ebusy;
     }
 
-    RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
+    RK30_CAM_DEBUG_TRACE("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
 
        pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
     pcdev->active0 = NULL;
@@ -1505,6 +1839,23 @@ static int rk_camera_add_device(struct soc_camera_device *icd)
             goto ebusy;
         #endif
         v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
+
+        if (v4l2_subdev_call(sd, video, cropcap, &cropcap) == 0) {
+            memcpy(&pcdev->cropinfo.bounds ,&cropcap.bounds,sizeof(struct v4l2_rect));
+        } else {
+            xlate = soc_camera_xlate_by_fourcc(icd, V4L2_PIX_FMT_NV12);
+            mf.width = 10000;
+            mf.height = 10000;
+            mf.field = V4L2_FIELD_NONE;
+            mf.code = xlate->code;
+            mf.reserved[6] = 0xfefe5a5a;
+            v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+
+            pcdev->cropinfo.bounds.left = 0;
+            pcdev->cropinfo.bounds.top = 0;
+            pcdev->cropinfo.bounds.width = mf.width;
+            pcdev->cropinfo.bounds.height = mf.height;
+        }
     }
     pcdev->icd = icd;
     pcdev->icd_init = 0;
@@ -1547,7 +1898,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd)
        mutex_lock(&camera_lock);
     BUG_ON(icd != pcdev->icd);
 
-    RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
+    RK30_CAM_DEBUG_TRACE("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
 
        /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
           stream may be turn on again before close device, if suspend and resume happened. */
@@ -1608,7 +1959,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd)
     INIT_LIST_HEAD(&pcdev->capture);
 
        mutex_unlock(&camera_lock);
-       RKCAMERA_DG("%s exit\n",__FUNCTION__);
+       RK30_CAM_DEBUG_TRACE("%s exit\n",__FUNCTION__);
 
        return;
 }
@@ -1620,7 +1971,7 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        int ret = 0;
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct rk_camera_dev *pcdev = ici->priv;
-    RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
+    RK30_CAM_DEBUG_TRACE("%s..%d..\n",__FUNCTION__,__LINE__);
 
        fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
        if (!fmt)
@@ -1661,22 +2012,22 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
         goto RK_CAMERA_SET_BUS_PARAM_END;
 
     cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
-       RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
+       RK30_CAM_DEBUG_TRACE("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
     if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
                if(IS_CIF0()) {
                write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
-            RKCAMERA_DG("enable cif0 pclk invert\n");
+            RK30_CAM_DEBUG_TRACE("enable cif0 pclk invert\n");
         } else {
                write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
-            RKCAMERA_DG("enable cif1 pclk invert\n");
+            RK30_CAM_DEBUG_TRACE("enable cif1 pclk invert\n");
         }
     } else {
                if(IS_CIF0()){
                        write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
-            RKCAMERA_DG("diable cif0 pclk invert\n");
+            RK30_CAM_DEBUG_TRACE("diable cif0 pclk invert\n");
         } else {
                        write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
-            RKCAMERA_DG("diable cif1 pclk invert\n");
+            RK30_CAM_DEBUG_TRACE("diable cif1 pclk invert\n");
         }
     }
     if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
@@ -1693,11 +2044,11 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
     /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
     //vip_ctrl_val |= ENABLE_CAPTURE;
     write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
-    RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x  \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
+    RK30_CAM_DEBUG_TRACE("%s..ctrl:0x%x CIF_CIF_FOR=%x  \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
 
 RK_CAMERA_SET_BUS_PARAM_END:
        if (ret)
-       RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
+       RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
     return ret;
 }
 
@@ -1714,10 +2065,19 @@ static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        }
     ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
 
-    if (ret < 0)
-        dev_warn(icd->dev.parent,
-                        "Flags incompatible: camera %lx, host %lx\n",
-                        camera_flags, bus_flags);
+       /* rockchip BUGBUG
+               if (ret < 0)
+                       dev_warn(icd->dev.parent,
+                                "Flags incompatible: camera %lx, host %lx\n",
+                                camera_flags, bus_flags);
+       */
+       if(!ret){
+               dev_warn(icd->dev.parent, "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags);
+               ret = -EINVAL;
+       }
+       else{
+               ret = 0;
+       }
     return ret;
 }
 
@@ -1829,7 +2189,7 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix
     }
 #if 1
         {
-#ifdef CONFIG_ARCH_RK30
+#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
            mdelay(100);
             if(IS_CIF0()){
         //             pmu_set_idle_request(IDLE_REQ_VIO, true);
@@ -1845,6 +2205,13 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix
                        cru_set_soft_reset(SOFT_RST_CIF1, false);
         //             pmu_set_idle_request(IDLE_REQ_VIO, false);  
             }
+#elif defined(CONFIG_ARCH_RK3188)
+//             pmu_set_idle_request(IDLE_REQ_VIO, true);
+               cru_set_soft_reset(SOFT_RST_CIF0, true);
+               udelay(5);
+               cru_set_soft_reset(SOFT_RST_CIF0, false);
+//             pmu_set_idle_request(IDLE_REQ_VIO, false);
+
 #endif
         }
     write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE);   /* ddl@rock-chips.com : vip ahb burst 16 */
@@ -1853,12 +2220,15 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix
     write_cif_reg(pcdev->base,CIF_CIF_FOR,cif_fmt_val);         /* ddl@rock-chips.com: VIP capture mode and capture format must be set before FS register set */
 
    // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);                /* clear vip interrupte single  */
-    write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); 
-    
-       cif_crop = (rect->left+ (rect->top<<16));
-       cif_fs  = ((rect->width ) + (rect->height<<16));
-    
-       RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
+    write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
+       /* 
+    if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
+               ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
+           BUG();      
+    } else*/{ // this is one frame mode
+           cif_crop = (rect->left+ (rect->top<<16));
+           cif_fs      = ((rect->width ) + (rect->height<<16));
+       }
 
        write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
        write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
@@ -1867,7 +2237,7 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix
 
     //MUST bypass scale 
        write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
-    RKCAMERA_DG("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
+    RK30_CAM_DEBUG_TRACE("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
        return;
 }
 
@@ -1967,7 +2337,17 @@ static void rk_camera_put_formats(struct soc_camera_device *icd)
 {
        return;
 }
+static int rk_camera_get_crop(struct soc_camera_device *icd,struct v4l2_crop *crop)
+{
+    struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
+    struct rk_camera_dev *pcdev = ici->priv;
 
+    spin_lock(&pcdev->cropinfo.lock);
+    memcpy(&crop->c,&pcdev->cropinfo.c,sizeof(struct v4l2_rect));
+    spin_unlock(&pcdev->cropinfo.lock);
+    
+    return 0;
+}
 static int rk_camera_set_crop(struct soc_camera_device *icd,
                               struct v4l2_crop *a)
 {
@@ -2013,12 +2393,14 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd,
     struct v4l2_pix_format *pix = &f->fmt.pix;
     struct v4l2_mbus_framefmt mf;
     struct v4l2_rect rect;
-    int ret,usr_w,usr_h;
+    int ret,usr_w,usr_h,sensor_w,sensor_h;
     int stream_on = 0;
-
+    int ratio, bounds_aspect;
+    
        usr_w = pix->width;
        usr_h = pix->height;
-    RKCAMERA_TR("%s enter width:%d  height:%d\n",__FUNCTION__,usr_w,usr_h);
+    
+    RK30_CAM_DEBUG_TRACE("enter width:%d  height:%d\n",usr_w,usr_h);
     xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
     if (!xlate) {
         dev_err(dev, "Format %x not found\n", pix->pixelformat);
@@ -2030,109 +2412,163 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd,
     if (pcdev->icd_init == 0) {
         v4l2_subdev_call(sd,core, init, 0); 
         pcdev->icd_init = 1;
+        return 0;
     }
     stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
     if (stream_on & ENABLE_CAPTURE)
         write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
-    
-       mf.width        = pix->width;
-       mf.height       = pix->height;
-       mf.field        = pix->field;
-       mf.colorspace   = pix->colorspace;
-       mf.code         = xlate->code;
-       ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
-       if (mf.code != xlate->code)
-               return -EINVAL;
-       #ifdef CONFIG_VIDEO_RK29_WORK_IPP
+
+    mf.width   = pix->width;
+    mf.height  = pix->height;
+    mf.field   = pix->field;
+    mf.colorspace      = pix->colorspace;
+    mf.code            = xlate->code;
+    mf.reserved[0] = pix->priv;              /* ddl@rock-chips.com : v0.3.3 */
+    mf.reserved[1] = 0;
+
+    ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+    if (mf.code != xlate->code)
+               return -EINVAL;                 
+
+    if ((pcdev->cropinfo.c.width == pcdev->cropinfo.bounds.width) && 
+        (pcdev->cropinfo.c.height == pcdev->cropinfo.bounds.height)) {
+        bounds_aspect = (pcdev->cropinfo.bounds.width*10/pcdev->cropinfo.bounds.height);
+        if ((mf.width*10/mf.height) != bounds_aspect) {
+            RK30_CAM_DEBUG_TRACE("User request fov unchanged in %dx%d, But sensor %dx%d is croped, so switch to full resolution %dx%d\n",
+                        usr_w,usr_h,mf.width, mf.height,pcdev->cropinfo.bounds.width,pcdev->cropinfo.bounds.height);
+            
+            mf.width   = pcdev->cropinfo.bounds.width/4;
+            mf.height  = pcdev->cropinfo.bounds.height/4;
+
+            mf.field   = pix->field;
+            mf.colorspace      = pix->colorspace;
+            mf.code            = xlate->code;
+            mf.reserved[0] = pix->priv; 
+            mf.reserved[1] = 0;
+
+            ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+            if (mf.code != xlate->code)
+               return -EINVAL; 
+        }
+    }
+
+    sensor_w = mf.width;
+    sensor_h = mf.height;
+
+    ratio = ((mf.width*mf.reserved[1])/100)&(~0x03);      // 4 align
+    mf.width -= ratio;
+
+    ratio = ((ratio*mf.height/mf.width)+1)&(~0x01);       // 2 align
+    mf.height -= ratio;
+
        if ((mf.width != usr_w) || (mf.height != usr_h)) {
-         int ratio;
+        
         if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
                RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
                ret = -EINVAL;
                goto RK_CAMERA_SET_FMT_END;
-       }       
+        }      
        if (unlikely((usr_w <16)||(usr_h < 16))) {
                RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
                ret = -EINVAL;
             goto RK_CAMERA_SET_FMT_END;
-       }
-               //need crop ?
-               if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
-                       ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
-                       pcdev->host_width = ratio*usr_w/10;
-                       pcdev->host_height = ratio*usr_h/10;
-            //for ipp ,need 4 bit alligned.
-               pcdev->host_width &= ~CROP_ALIGN_BYTES;
-               pcdev->host_height &= ~CROP_ALIGN_BYTES;
-                       RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
-                       }
-               else{ // needn't crop ,just scaled by ipp
-                       pcdev->host_width = mf.width;
-                       pcdev->host_height = mf.height;
-                       }
-       }
-       else{
-               pcdev->host_width = usr_w;
-               pcdev->host_height = usr_h;
-               }
-       #else
-       //according to crop and scale capability to change , here just cropt to user needed
-        if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
-               RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height);
-               ret = -EINVAL;
-               goto RK_CAMERA_SET_FMT_END;
-       }       
-       if (unlikely((usr_w <16)||(usr_h < 16))) {
-               RKCAMERA_TR("Senor  invalid destination resolution(%dx%d)\n",usr_w,usr_h);
-               ret = -EINVAL;
-            goto RK_CAMERA_SET_FMT_END;
-       }
-       pcdev->host_width = usr_w;
-       pcdev->host_height = usr_h;
-       #endif
+        }
+        
+               spin_lock(&pcdev->cropinfo.lock);
+               if (((mf.width*10/mf.height) != (usr_w*10/usr_h))) {  
+            if ((pcdev->cropinfo.c.width == 0)&&(pcdev->cropinfo.c.height == 0)) {        
+                //Scale + Crop center is for keep aspect ratio unchange
+                ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
+                pcdev->host_width = ratio*usr_w/10;
+                pcdev->host_height = ratio*usr_h/10;
+                pcdev->host_width &= ~CROP_ALIGN_BYTES;
+                pcdev->host_height &= ~CROP_ALIGN_BYTES;
+
+                pcdev->host_left = ((sensor_w-pcdev->host_width )>>1);
+                pcdev->host_top = ((sensor_h-pcdev->host_height)>>1);
+            } else {    
+                //Scale + crop(user define)
+                pcdev->host_width = pcdev->cropinfo.c.width*mf.width/pcdev->cropinfo.bounds.width;
+                pcdev->host_height = pcdev->cropinfo.c.height*mf.height/pcdev->cropinfo.bounds.height;
+                pcdev->host_left = (pcdev->cropinfo.c.left*mf.width/pcdev->cropinfo.bounds.width);
+                pcdev->host_top = (pcdev->cropinfo.c.top*mf.height/pcdev->cropinfo.bounds.height);
+            }
+
+            pcdev->host_left &= (~0x01);
+            pcdev->host_top &= (~0x01);
+        } else { 
+            if ((pcdev->cropinfo.c.width == 0)&&(pcdev->cropinfo.c.height == 0)) {
+                //Crop Center for cif can work , then scale
+                pcdev->host_width = mf.width;
+                pcdev->host_height = mf.height;
+                pcdev->host_left = ((sensor_w - mf.width)>>1)&(~0x01);
+                pcdev->host_top = ((sensor_h - mf.height)>>1)&(~0x01);
+            } else {
+                //Crop center for cif can work + crop(user define), then scale 
+                pcdev->host_width = pcdev->cropinfo.c.width*mf.width/pcdev->cropinfo.bounds.width;
+                pcdev->host_height = pcdev->cropinfo.c.height*mf.height/pcdev->cropinfo.bounds.height;
+                pcdev->host_left = (pcdev->cropinfo.c.left*mf.width/pcdev->cropinfo.bounds.width)+((sensor_w - mf.width)>>1);
+                pcdev->host_top = (pcdev->cropinfo.c.top*mf.height/pcdev->cropinfo.bounds.height)+((sensor_h - mf.height)>>1);
+            }
+
+            pcdev->host_left &= (~0x01);
+            pcdev->host_top &= (~0x01);
+        }
+        spin_unlock(&pcdev->cropinfo.lock);
+    } else {
+        spin_lock(&pcdev->cropinfo.lock);
+        if ((pcdev->cropinfo.c.width == 0)&&(pcdev->cropinfo.c.height == 0)) {
+            pcdev->host_width = mf.width;
+            pcdev->host_height = mf.height;
+            pcdev->host_left = 0;
+            pcdev->host_top = 0;
+        } else {
+            pcdev->host_width = pcdev->cropinfo.c.width*mf.width/pcdev->cropinfo.bounds.width;
+            pcdev->host_height = pcdev->cropinfo.c.height*mf.height/pcdev->cropinfo.bounds.height;
+            pcdev->host_left = (pcdev->cropinfo.c.left*mf.width/pcdev->cropinfo.bounds.width);
+            pcdev->host_top = (pcdev->cropinfo.c.top*mf.height/pcdev->cropinfo.bounds.height);
+        }
+        spin_unlock(&pcdev->cropinfo.lock);
+    }
+    
     icd->sense = NULL;
     if (!ret) {
-        RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__,
-               pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
         rect.width = pcdev->host_width;
         rect.height = pcdev->host_height;
-       rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
-       rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
-       pcdev->host_left = rect.left;
-       pcdev->host_top = rect.top;
+       rect.left = pcdev->host_left;
+       rect.top = pcdev->host_top;
         
         down(&pcdev->zoominfo.sem);
-       #if CIF_DO_CROP
-       pcdev->zoominfo.a.c.left = 0;
-       pcdev->zoominfo.a.c.top = 0;
-       pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
-       pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
-       pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
-       pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
-       pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
-       pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
-       //recalculate the CIF width & height
-       rect.width = pcdev->zoominfo.a.c.width ;
-       rect.height = pcdev->zoominfo.a.c.height;
-       rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
-       rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
-       #else
-       pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
-       pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
-       pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
-       pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
-       //now digital zoom use ipp to do crop and scale
-       if(pcdev->zoominfo.zoom_rate != 100){
-               pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
-               pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
-               }
-       else{
-               pcdev->zoominfo.a.c.left = 0;
-               pcdev->zoominfo.a.c.top = 0;
-               }
-       pcdev->zoominfo.vir_width = pcdev->host_width;
-       pcdev->zoominfo.vir_height = pcdev->host_height;
-       #endif
+#if CIF_DO_CROP   // this crop is only for digital zoom
+        pcdev->zoominfo.a.c.left = 0;
+        pcdev->zoominfo.a.c.top = 0;
+        pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
+        pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
+        pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
+        pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
+        pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
+        pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
+        //recalculate the CIF width & height
+        rect.width = pcdev->zoominfo.a.c.width ;
+        rect.height = pcdev->zoominfo.a.c.height;
+        rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
+        rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
+#else
+        pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
+        pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
+        pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
+        pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
+        //now digital zoom use ipp to do crop and scale
+        if(pcdev->zoominfo.zoom_rate != 100){
+            pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
+            pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
+        } else {
+            pcdev->zoominfo.a.c.left = 0;
+            pcdev->zoominfo.a.c.top = 0;
+        }
+        pcdev->zoominfo.vir_width = pcdev->host_width;
+        pcdev->zoominfo.vir_height = pcdev->host_height;
+#endif
         up(&pcdev->zoominfo.sem);
 
         /* ddl@rock-chips.com: IPP work limit check */
@@ -2151,8 +2587,13 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd,
                 }
             }
         }
-        RKCAMERA_DG("%s..%s icd width:%d  user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
-                                  rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
+        
+        RK30_CAM_DEBUG_TRACE("%s CIF Host:%dx%d@(%d,%d) Sensor:%dx%d->%dx%d User crop:(%d,%d,%d,%d)in(%d,%d) (zoom: %dx%d@(%d,%d)->%dx%d)\n",xlate->host_fmt->name,
+                                  pcdev->host_width,pcdev->host_height,pcdev->host_left,pcdev->host_top,
+                                  sensor_w,sensor_h,mf.width,mf.height,
+                                  pcdev->cropinfo.c.left,pcdev->cropinfo.c.top,pcdev->cropinfo.c.width,pcdev->cropinfo.c.height,
+                                  pcdev->cropinfo.bounds.width,pcdev->cropinfo.bounds.height,
+                                  pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
                                   pix->width, pix->height);
         rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect); 
         
@@ -2189,10 +2630,12 @@ static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
                ret = true;
        } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
                ret = true;
+       } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
+               ret = true;
        }
 
        if (ret == true)
-               RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+               RK30_CAM_DEBUG_TRACE("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
        return ret;
 }
 static int rk_camera_try_fmt(struct soc_camera_device *icd,
@@ -2212,17 +2655,16 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd,
     
        usr_w = pix->width;
        usr_h = pix->height;
-       RKCAMERA_DG("%s enter width:%d  height:%d\n",__FUNCTION__,usr_w,usr_h);
-
+    
     xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
     if (!xlate) {
         dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
                        (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
         ret = -EINVAL;
-        RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
+        RK30_CAM_DEBUG_TRACE("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
             (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
         for (i = 0; i < icd->num_user_formats; i++)
-                   RKCAMERA_TR("(%c%c%c%c)-%s\n",
+                   RK30_CAM_DEBUG_TRACE("(%c%c%c%c)-%s\n",
                    icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
                        (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
                        icd->user_formats[i].host_fmt->name);
@@ -2239,41 +2681,62 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd,
                return pix->bytesperline;
 
     /* limit to sensor capabilities */
+    memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
        mf.width        = pix->width;
        mf.height       = pix->height;
        mf.field        = pix->field;
        mf.colorspace   = pix->colorspace;
        mf.code         = xlate->code;
+    /* ddl@rock-chips.com : It is query max resolution only. */
+    if ((usr_w == 10000) && (usr_h == 10000)) {
+        mf.reserved[6] = 0xfefe5a5a;
+    }
 
        ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
        if (ret < 0)
                goto RK_CAMERA_TRY_FMT_END;
-    RKCAMERA_DG("%s mf.width:%d  mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
+    
+       //query resolution.
+       if((usr_w == 10000) && (usr_h == 10000)) {
+               pix->width = mf.width;
+        pix->height = mf.height;
+        RK30_CAM_DEBUG_TRACE("%s: Sensor resolution : %dx%d\n",__FUNCTION__,mf.width,mf.height);
+               goto RK_CAMERA_TRY_FMT_END;
+       } else {
+        RK30_CAM_DEBUG_TRACE("%s: user demand: %dx%d  sensor output: %dx%d \n",__FUNCTION__,usr_w,usr_h,mf.width,mf.height);
+       }
+    
        #ifdef CONFIG_VIDEO_RK29_WORK_IPP       
        if ((mf.width != usr_w) || (mf.height != usr_h)) {
         bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt); 
+        #ifndef OPTIMIZE_MEMORY_USE
                if (is_capture) {
                        vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
                } else {
                        /* Assume preview buffer minimum is 4 */
                        vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
-               }        
+               }
+               #else
+                   vipmem_is_overflow =false;
+               #endif
                if (vipmem_is_overflow == false) {
                        pix->width = usr_w;
                        pix->height = usr_h;
                } else {
-                       RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
+                       RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
             pix->width = mf.width;
             pix->height = mf.height;            
                }
-        
+        /* ddl@rock-chips.com: Invalidate these code, because sensor need interpolate */
+        #if 0     
         if ((mf.width < usr_w) || (mf.height < usr_h)) {
             if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
-                RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
+                RK30_CAM_DEBUG_TRACE("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
                 pix->width = mf.width;
                 pix->height = mf.height;
             }
-        }        
+        }    
+        #endif
        }
        #else
        //need to change according to crop and scale capablicity
@@ -2281,7 +2744,7 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd,
                        pix->width = usr_w;
                        pix->height = usr_h;
            } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
-                       RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
+                       RK30_CAM_DEBUG_TRACE("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
             pix->width = mf.width;
                pix->height     = mf.height;    
         }
@@ -2302,7 +2765,7 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd,
 
 RK_CAMERA_TRY_FMT_END:
        if (ret)
-       RKCAMERA_TR("\n%s..%d.. ret = %d  \n",__FUNCTION__,__LINE__, ret);
+       RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d  \n",__FUNCTION__,__LINE__, ret);
     return ret;
 }
 
@@ -2346,51 +2809,46 @@ static int rk_camera_querycap(struct soc_camera_host *ici,
                                 struct v4l2_capability *cap)
 {
     struct rk_camera_dev *pcdev = ici->priv;
+    struct rkcamera_platform_data *new_camera;
     char orientation[5];
+    char fov[9];
     int i;
 
-    strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));    
+    strlcpy(cap->card, dev_name(pcdev->icd->pdev), 20);
     memset(orientation,0x00,sizeof(orientation));
     for (i=0; i<RK_CAM_NUM;i++) {
         if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
             sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
+            sprintf(fov,"_50_50");
         }
     }
-    
+
+    i=0;
+    new_camera = pcdev->pdata->register_dev_new;
+    while (strstr(new_camera->dev_name,"end")==NULL) {
+        if (strcmp(dev_name(pcdev->icd->pdev), new_camera->dev_name) == 0) {
+            sprintf(orientation,"-%d",new_camera->orientation);
+            sprintf(fov,"_%d_%d",new_camera->fov_h,new_camera->fov_v);
+        }
+        new_camera++;
+    }
+
     if (orientation[0] != '-') {
         RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
-        if (strstr(dev_name(pcdev->icd->pdev),"front")) 
+        if (strstr(dev_name(pcdev->icd->pdev),"front"))
             strcat(cap->card,"-270");
-        else 
+        else
             strcat(cap->card,"-90");
     } else {
-        strcat(cap->card,orientation); 
+        strcat(cap->card,orientation);
     }
+
+    strcat(cap->card,fov);                          /* ddl@rock-chips.com: v0.3.f */
     cap->version = RK_CAM_VERSION_CODE;
     cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
     return 0;
 }
-static void rk_camera_store_register(struct rk_camera_dev *pcdev)
-{
-       pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
-       pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
-       pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
-       pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
-       pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
-       pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
-       pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
-}
-static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
-{
-       write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
-       write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
-       write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
-       write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
-       write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
-       write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
-       write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
-}
 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
 {
     struct soc_camera_host *ici =
@@ -2417,9 +2875,9 @@ static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
                pcdev->reginfo_suspend.Inval = Reg_Validate;
                rk_camera_deactivate(pcdev);
 
-               RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
+               RK30_CAM_DEBUG_TRACE("%s Enter Success...\n", __FUNCTION__);
        } else {
-               RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
+               RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
        }
        mutex_unlock(&camera_lock);
     return ret;
@@ -2449,7 +2907,7 @@ static int rk_camera_resume(struct soc_camera_device *icd)
                        rk_camera_s_stream(icd, 1);
                        pcdev->reginfo_suspend.Inval = Reg_Invalidate;
                } else {
-                       RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
+                       RK30_CAM_DEBUG_TRACE("Resume fail, vip register recored is invalidate!!\n");
                        goto rk_camera_resume_end;
                }
 
@@ -2457,9 +2915,9 @@ static int rk_camera_resume(struct soc_camera_device *icd)
                sd = soc_camera_to_subdev(icd);
                v4l2_subdev_call(sd, video, s_stream, 1);
 
-               RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
+               RK30_CAM_DEBUG_TRACE("%s Enter success\n",__FUNCTION__);
        } else {
-               RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
+               RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
        }
 
 rk_camera_resume_end:
@@ -2481,27 +2939,27 @@ static void rk_camera_reinit_work(struct work_struct *work)
     tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
        //dump regs
        {
-               RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
-               RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
-               RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
-               RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
-               RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
-               RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
-               RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
-               RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
-               RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
+               RK30_CAM_DEBUG_TRACE("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
                
-               RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
-               RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
-       RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
-       RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
-       RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
-       RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
+               RK30_CAM_DEBUG_TRACE("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
+       RK30_CAM_DEBUG_TRACE("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
+       RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
+       RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
+       RK30_CAM_DEBUG_TRACE("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
        }
-    
+    return;
     pcdev->stop_cif = true;
        write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
-       RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
+       RK30_CAM_DEBUG_TRACE("the reinit times = %d\n",pcdev->reinit_times);
    if(pcdev->video_vq && pcdev->video_vq->irqlock){
        spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
        for (index = 0; index < VIDEO_MAX_FRAME; index++) {
@@ -2518,10 +2976,10 @@ static void rk_camera_reinit_work(struct work_struct *work)
        }
        spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags); 
     }else{
-    RKCAMERA_TR("video queue has somthing wrong !!\n");
+    RK30_CAM_DEBUG_TRACE("video queue has somthing wrong !!\n");
     }
 
-       RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
+       RK30_CAM_DEBUG_TRACE("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
 }
 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
 {
@@ -2533,9 +2991,9 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
     struct soc_camera_link *tmp_soc_cam_link;
     tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
 
-       RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
+       RK30_CAM_DEBUG_TRACE("rk_camera_fps_func fps:%d\n",(pcdev->fps - pcdev->last_fps)/3);
        if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
-               RKCAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps);
+               RK30_CAM_DEBUG_TRACE("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps);
                pcdev->camera_reinit_work.pcdev = pcdev;
                //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
         pcdev->reinit_times++;
@@ -2552,7 +3010,7 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
         fival_pre = fival_nxt;
         while (fival_nxt != NULL) {
 
-            RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev), 
+            RK30_CAM_DEBUG_TRACE("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
                 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
                            (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
                            fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
@@ -2611,8 +3069,8 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-    struct rk_camera_dev *pcdev = ici->priv;
-    int cif_ctrl_val;
+       struct rk_camera_dev *pcdev = ici->priv;
+       int cif_ctrl_val;
        int ret;
        unsigned long flags;
 
@@ -2621,39 +3079,45 @@ static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
        cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
        if (enable) {
                pcdev->fps = 0;
-        pcdev->last_fps = 0;
-        pcdev->frame_interval = 0;
+               pcdev->last_fps = 0;
+               pcdev->frame_interval = 0;
                hrtimer_cancel(&(pcdev->fps_timer.timer));
                pcdev->fps_timer.pcdev = pcdev;
-        pcdev->timer_get_fps = false;
-        pcdev->reinit_times  = 0;
-        pcdev->stop_cif = false;
-//             hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
+               pcdev->timer_get_fps = false;
+               pcdev->reinit_times  = 0;
+               pcdev->stop_cif = false;
+               pcdev->cif_stopped = false;
+               //      hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
                cif_ctrl_val |= ENABLE_CAPTURE;
-               write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+               write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
                hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
-        pcdev->fps_timer.istarted = true;
+               pcdev->fps_timer.istarted = true;
        } else {
            //cancel timer before stop cif
                ret = hrtimer_cancel(&pcdev->fps_timer.timer);
         pcdev->fps_timer.istarted = false;
         flush_work(&(pcdev->camera_reinit_work.work));
-        
         cif_ctrl_val &= ~ENABLE_CAPTURE;
                spin_lock_irqsave(&pcdev->lock, flags);
-       write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+               //      write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
         pcdev->stop_cif = true;
        spin_unlock_irqrestore(&pcdev->lock, flags);
+#if CONFIG_CIF_STOP_SYNC
+                               init_waitqueue_head(&pcdev->cif_stop_done);
+                               if (wait_event_timeout(pcdev->cif_stop_done, pcdev->cif_stopped, msecs_to_jiffies(1000)) == 0) {
+                                       RKCAMERA_DG("%s:%d, wait cif stop timeout!",__func__,__LINE__);
+                               }
+#endif
+               //mdelay(35);
                flush_workqueue((pcdev->camera_wq));
-               RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
+               RK30_CAM_DEBUG_TRACE("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
        }
     //must be reinit,or will be somthing wrong in irq process.
-    if(enable == false){
+    if(enable == false) {
         pcdev->active0 = NULL;
                pcdev->active1 = NULL;
         INIT_LIST_HEAD(&pcdev->capture);
-        }
-       RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
+       }
        return 0;
 }
 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
@@ -2691,7 +3155,7 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm
                 ret = -EINVAL;
             }
         } else {
-            RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
+            RK30_CAM_DEBUG_TRACE("%s: fival_list is NULL\n",__FUNCTION__);
             ret = -EINVAL;
         }
     }  else {  
@@ -2703,7 +3167,7 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm
         }
         
         if (fival_head == NULL) {
-            RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
+            RK30_CAM_DEBUG_TRACE("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
             ret = -EINVAL;
             goto rk_camera_enum_frameintervals_end;
         }
@@ -2723,20 +3187,20 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm
 
         if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
             memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
-            RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
+            RK30_CAM_DEBUG_TRACE("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
                 fival->width, fival->height,
                 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
                            (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
                             fival->discrete.denominator,fival->discrete.numerator);                        
         } else {
             if (index == 0)
-                RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
+                RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
                     fival->width,fival->height, 
                     fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
                            (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
                            index);
             else
-                RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
+                RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
                     fival->width,fival->height, 
                     fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
                            (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
@@ -2796,7 +3260,7 @@ static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
        up(&pcdev->zoominfo.sem);
        pcdev->stop_cif = false;
        hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
-       RKCAMERA_DG("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
+       RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
 #else
        a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a.c.width = pcdev->host_width*100/zoom_rate;
@@ -2813,7 +3277,7 @@ static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
        pcdev->zoominfo.vir_width = pcdev->host_width;
        pcdev->zoominfo.vir_height= pcdev->host_height;
        up(&pcdev->zoominfo.sem);
-       RKCAMERA_DG("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
+       RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
 #endif 
 
        return 0;
@@ -2848,16 +3312,18 @@ static int rk_camera_set_ctrl(struct soc_camera_device *icd,
                ret = -ENOIOCTLCMD;
         goto rk_camera_set_ctrl_end;
        }
-
+       
+    if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
+               ret = -EINVAL;
+        goto rk_camera_set_ctrl_end;
+       }
+       
        switch (sctrl->id)
        {
        #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
                case V4L2_CID_ZOOM_ABSOLUTE:
                {
-                       if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
-                       ret = -EINVAL;
-                goto rk_camera_set_ctrl_end;
-               }
+                       
             ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
                        if (ret == 0) {
                                pcdev->zoominfo.zoom_rate = sctrl->value;
@@ -2867,6 +3333,31 @@ static int rk_camera_set_ctrl(struct soc_camera_device *icd,
                        break;
                }
     #endif
+
+        case V4L2_CID_HDR:
+        {            
+            if (pcdev->hdr_info.en != sctrl->value) {
+                pcdev->hdr_info.en = sctrl->value;
+                if (sctrl->value) {
+                                       struct device *control = to_soc_camera_control(pcdev->icd);
+                                       struct v4l2_subdev *sd=dev_get_drvdata(control);
+
+                    printk("hdr on\n");
+                    pcdev->hdr_info.frame[0].code = RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1;
+                    pcdev->hdr_info.frame[0].set_ts = 0;
+                    pcdev->hdr_info.frame[0].get_ts = 0;
+                    pcdev->hdr_info.frame[1].code = RK_VIDEOBUF_HDR_EXPOSURE_NORMAL;
+                    pcdev->hdr_info.frame[1].set_ts = 0;
+                    pcdev->hdr_info.frame[1].get_ts = 0;
+                    pcdev->hdr_info.frame[2].code = RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1;
+                    pcdev->hdr_info.frame[2].set_ts = 0;
+                    pcdev->hdr_info.frame[2].get_ts = 0;
+                    v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,RK_VIDEOBUF_HDR_EXPOSURE_NORMAL);
+                }
+            }
+            break;
+        }
+    
                default:
                        ret = -ENOIOCTLCMD;
                        break;
@@ -2875,6 +3366,16 @@ rk_camera_set_ctrl_end:
        return ret;
 }
 
+int rk_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum *fsize)
+{
+    struct device *control = to_soc_camera_control(icd);
+    struct v4l2_subdev *sd;
+
+    sd = dev_get_drvdata(control);
+    return v4l2_subdev_call(sd, video, enum_framesizes, fsize);
+
+}
+
 static struct soc_camera_host_ops rk_soc_camera_host_ops =
 {
     .owner             = THIS_MODULE,
@@ -2883,6 +3384,7 @@ static struct soc_camera_host_ops rk_soc_camera_host_ops =
     .suspend   = rk_camera_suspend,
     .resume            = rk_camera_resume,
     .enum_frameinervals = rk_camera_enum_frameintervals,
+    .enum_fsizes = rk_camera_enum_fsizes,
     .set_crop  = rk_camera_set_crop,
     .get_formats       = rk_camera_get_formats, 
     .put_formats       = rk_camera_put_formats,
@@ -2897,29 +3399,29 @@ static struct soc_camera_host_ops rk_soc_camera_host_ops =
     .set_ctrl = rk_camera_set_ctrl,
     .controls = rk_camera_controls,
     .num_controls = ARRAY_SIZE(rk_camera_controls)
-    
 };
+
 static void rk_camera_cif_iomux(int cif_index)
 {
-#if defined(CONFIG_ARCH_RK3066B)
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
     switch(cif_index){
         case 0:
-            rk30_mux_api_set(GPIO3B3_CIFCLKOUT_NAME, GPIO3B_CIFCLKOUT);
-            write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
+                       iomux_set(CIF0_CLKOUT);
+            write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_4MA));
             write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
             #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
-               rk30_mux_api_set(GPIO3B4_CIFDATA0_HSADCDATA8_NAME, GPIO3B_CIFDATA0);
-               rk30_mux_api_set(GPIO3B5_CIFDATA1_HSADCDATA9_NAME, GPIO3B_CIFDATA1);
+               iomux_set(CIF0_D0);
+               iomux_set(CIF0_D1);
             #endif
             #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
-               rk30_mux_api_set(GPIO3B6_CIFDATA10_I2C3SDA_NAME, GPIO3B_CIFDATA10);
-               rk30_mux_api_set(GPIO3B7_CIFDATA11_I2C3SCL_NAME, GPIO3B_CIFDATA11);
-            RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
+               iomux_set(CIF0_D10);
+               iomux_set(CIF0_D11);
+            RK30_CAM_DEBUG_TRACE("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
             #endif
             
             break;
         default:
-            RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
+            RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
             break;
     }
 #elif defined(CONFIG_ARCH_RK30)
@@ -2955,7 +3457,7 @@ static void rk_camera_cif_iomux(int cif_index)
             rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
             break;
         default:
-            RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
+            RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
             break;
         }
 #endif
@@ -2970,17 +3472,18 @@ static int rk_camera_probe(struct platform_device *pdev)
     struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
     int irq,i;
     int err = 0;
+    struct rk_cif_clk *clk=NULL;
 
     printk("%s version: v%d.%d.%d  Zoom by %s\n",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
         (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);    
 
     if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
-        RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
+        RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
         BUG();
     }
 
     if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
-        RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
+        RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
         BUG();
     }
     
@@ -3001,32 +3504,33 @@ static int rk_camera_probe(struct platform_device *pdev)
        pcdev->hostid = pdev->id;
     /*config output clk*/ // must modify start
     if(IS_CIF0()){
-        pcdev->pd_cif = clk_get(NULL, "pd_cif0");
-        pcdev->aclk_cif = clk_get(NULL, "aclk_cif0");
-        pcdev->hclk_cif = clk_get(NULL, "hclk_cif0");
-        pcdev->cif_clk_in = clk_get(NULL, "cif0_in");
-        pcdev->cif_clk_out = clk_get(NULL, "cif0_out");
+        clk = &cif_clk[0];
+        cif_clk[0].pd_cif = clk_get(NULL, "pd_cif0");
+        cif_clk[0].aclk_cif = clk_get(NULL, "aclk_cif0");
+        cif_clk[0].hclk_cif = clk_get(NULL, "hclk_cif0");
+        cif_clk[0].cif_clk_in = clk_get(NULL, "cif0_in");
+        cif_clk[0].cif_clk_out = clk_get(NULL, "cif0_out");
+        spin_lock_init(&cif_clk[0].lock);
+        cif_clk[0].on = false;
         rk_camera_cif_iomux(0);
     } else {
-        pcdev->pd_cif = clk_get(NULL, "pd_cif1");
-        pcdev->aclk_cif = clk_get(NULL, "aclk_cif1");
-        pcdev->hclk_cif = clk_get(NULL, "hclk_cif1");
-        pcdev->cif_clk_in = clk_get(NULL, "cif1_in");
-        pcdev->cif_clk_out = clk_get(NULL, "cif1_out");
+        clk = &cif_clk[1];
+        cif_clk[1].pd_cif = clk_get(NULL, "pd_cif1");
+        cif_clk[1].aclk_cif = clk_get(NULL, "aclk_cif1");
+        cif_clk[1].hclk_cif = clk_get(NULL, "hclk_cif1");
+        cif_clk[1].cif_clk_in = clk_get(NULL, "cif1_in");
+        cif_clk[1].cif_clk_out = clk_get(NULL, "cif1_out");
+        spin_lock_init(&cif_clk[1].lock);
+        cif_clk[1].on = false;
         
         rk_camera_cif_iomux(1);
     }
     
-    if(IS_ERR(pcdev->pd_cif) || IS_ERR(pcdev->aclk_cif) || IS_ERR(pcdev->hclk_cif) || IS_ERR(pcdev->cif_clk_in) || IS_ERR(pcdev->cif_clk_out)){
-        RKCAMERA_TR(KERN_ERR "%s(%d): failed to get cif clock source\n",__FUNCTION__,__LINE__);
-        err = -ENOENT;
-        goto exit_reqmem_vip;
-    }
     
     dev_set_drvdata(&pdev->dev, pcdev);
     pcdev->res = res;
     pcdev->pdata = pdev->dev.platform_data;             /* ddl@rock-chips.com : Request IO in init function */
-
+       pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl;
        if (pcdev->pdata && pcdev->pdata->io_init) {
         pcdev->pdata->io_init();
     }
@@ -3044,12 +3548,12 @@ static int rk_camera_probe(struct platform_device *pdev)
         
             if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
                 err = -EBUSY;
-                RKCAMERA_TR("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
+                RK30_CAM_DEBUG_TRACE("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
                 goto exit_ioremap_vipmem;
             }
             meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
             if (pcdev->vipmem_virbase == NULL) {
-                RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
+                RK30_CAM_DEBUG_TRACE("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
                 err = -ENXIO;
                 goto exit_ioremap_vipmem;
             }
@@ -3064,6 +3568,9 @@ static int rk_camera_probe(struct platform_device *pdev)
     INIT_LIST_HEAD(&pcdev->camera_work_queue);
     spin_lock_init(&pcdev->lock);
     spin_lock_init(&pcdev->camera_work_lock);
+
+    memset(&pcdev->cropinfo.c,0x00,sizeof(struct v4l2_rect));
+    spin_lock_init(&pcdev->cropinfo.lock);
     sema_init(&pcdev->zoominfo.sem,1);
 
     /*
@@ -3128,8 +3635,7 @@ static int rk_camera_probe(struct platform_device *pdev)
        hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pcdev->fps_timer.timer.function = rk_camera_fps_func;
     pcdev->icd_cb.sensor_cb = NULL;
-
-#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
+#if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
     pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
     pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
@@ -3138,7 +3644,7 @@ static int rk_camera_probe(struct platform_device *pdev)
 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
        pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp; 
 #endif
-    RKCAMERA_DG("%s(%d) Exit  \n",__FUNCTION__,__LINE__);
+    RK30_CAM_DEBUG_TRACE("%s(%d) Exit  \n",__FUNCTION__,__LINE__);
     return 0;
 
 exit_free_irq:
@@ -3216,7 +3722,7 @@ static int __devexit rk_camera_remove(struct platform_device *pdev)
         if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
             meminfo_ptr->vbase = NULL;
         } else {
-            iounmap((void __iomem*)pcdev->vipmem_phybase);
+            iounmap((void __iomem*)pcdev->vipmem_virbase);
             release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
             meminfo_ptr->vbase = NULL;
         }
@@ -3254,7 +3760,7 @@ static int rk_camera_init_async(void *unused)
 
 static int __devinit rk_camera_init(void)
 {
-    RKCAMERA_DG("%s..%s..%d  \n",__FUNCTION__,__FILE__,__LINE__);
+    RK30_CAM_DEBUG_TRACE("%s..%s..%d  \n",__FUNCTION__,__FILE__,__LINE__);
     kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
     return 0;
 }