Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_drv.c
index 81fa87ce18c572cf8d61df057ff22ea2c33693a3..33be480983c351f8519ee3e0fe895da8283a70f5 100755 (executable)
@@ -4,6 +4,8 @@
 #include "camsys_marvin.h"
 #include "camsys_mipicsi_phy.h"
 #include "camsys_gpio.h"
+#include "camsys_soc_priv.h"
+#include "ext_flashled_drv/rk_ext_fshled_ctl.h"
 
 unsigned int camsys_debug=1;
 module_param(camsys_debug, int, S_IRUGO|S_IWUSR);
@@ -28,7 +30,6 @@ static int camsys_i2c_write(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev
     unsigned short msg_times,totallen,onelen;
     struct i2c_msg msg[1];
     struct i2c_adapter *adapter;
-    camsys_extdev_t *extdev;
     
     adapter = i2c_get_adapter(i2cinfo->bus_num);
     if (adapter == NULL) {
@@ -57,7 +58,7 @@ static int camsys_i2c_write(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev
             buf[i] = (i2cinfo->reg_addr>>((i2cinfo->reg_size-1-i)*8))&0xff;
         }
         for (j=0; j<i2cinfo->val_size; j++) {
-            buf[i+j] = (i2cinfo->val>>(i2cinfo->val_size-1-j))&0xff;
+            buf[i+j] = (i2cinfo->val>>((i2cinfo->val_size-1-j)*8))&0xff;  /* ddl@rock-chips.com: v0.a.0 */
         }
         bufp = buf;
         onelen = i2cinfo->val_size + i2cinfo->reg_size;
@@ -80,48 +81,37 @@ static int camsys_i2c_write(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev
     }
 
 end:
-#if 0
-    #if ((defined CONFIG_ARCH_RK319X) || (CONFIG_ARCH_ROCKCHIP))
-    if (!list_empty(&camsys_dev->extdevs.active)) {
-        list_for_each_entry(extdev, &camsys_dev->extdevs.active, active) {
-            if (extdev->phy.type == CamSys_Phy_Cif) {
-                if (extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b) {
-                    //iomux_set(CIF0_D0); // ZYC FOR 32
-                    //iomux_set(CIF0_D1); // ZYC FOR 32
-                }
-            }
-        }
-    }
-    #endif
-#endif
     return err;
 }
 
 static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
 {
-    int err = 0,i,retry=2,tmp;
+    int err = 0,i,retry=2,tmp, num_msg;
     unsigned char buf[8];
     struct i2c_msg msg[2];
     struct i2c_adapter *adapter;
-    camsys_extdev_t *extdev;
     
     adapter = i2c_get_adapter(i2cinfo->bus_num);
     if (adapter == NULL) {
         camsys_err("Get %d i2c adapter is failed!",i2cinfo->bus_num);
         err = -EINVAL;
         goto end;
-    }
-    
-    for (i=0; i<i2cinfo->reg_size; i++) {
-        buf[i] = (i2cinfo->reg_addr>>((i2cinfo->reg_size-1-i)*8))&0xff;
-    }
+    } 
 
-    msg[0].addr = (i2cinfo->slave_addr>>1);
-       msg[0].flags = 0;
-       msg[0].scl_rate = i2cinfo->speed;
-       //msg[0].read_type = 0;
-    msg[0].buf = buf;
-    msg[0].len = i2cinfo->reg_size;
+       num_msg = 0;
+       if (i2cinfo->reg_size) {                /* ddl@rock-chips.com: v0.a.0 */
+           for (i=0; i<i2cinfo->reg_size; i++) {
+               buf[i] = (i2cinfo->reg_addr>>((i2cinfo->reg_size-1-i)*8))&0xff;
+           }
+               
+           msg[0].addr = (i2cinfo->slave_addr>>1);
+               msg[0].flags = 0;
+               msg[0].scl_rate = i2cinfo->speed;
+               //msg[0].read_type = 0;
+           msg[0].buf = buf;
+           msg[0].len = i2cinfo->reg_size;
+               num_msg++;
+       }
     
     msg[1].addr = (i2cinfo->slave_addr>>1);
        msg[1].flags = I2C_M_RD;
@@ -130,9 +120,14 @@ static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
     msg[1].buf = buf;
     msg[1].len = (unsigned short)i2cinfo->val_size;
        err = -EAGAIN;    
+       num_msg++;
 
        while ((retry-- > 0) && (err < 0)) {                                             /* ddl@rock-chips.com :  Transfer again if transent is failed   */
-               err = i2c_transfer(adapter, msg, 2);
+               if (num_msg==1) {                       
+                       err = i2c_transfer(adapter, &msg[1], num_msg);
+               } else {
+                       err = i2c_transfer(adapter, msg, num_msg);
+               }
        
                if (err >= 0) {
             err = 0;
@@ -142,7 +137,8 @@ static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
                }
        }
 
-    if (err==0) {        
+
+    if (err==0) { 
         i2cinfo->val = 0x00;
         for(i=0; i<i2cinfo->val_size; i++) {
             tmp = buf[i];
@@ -151,20 +147,6 @@ static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
     }
     
 end:
-#if 0
-    #if ((defined CONFIG_ARCH_RK319X) || (CONFIG_ARCH_ROCKCHIP))
-    if (!list_empty(&camsys_dev->extdevs.active)) {
-        list_for_each_entry(extdev, &camsys_dev->extdevs.active, active) {
-            if (extdev->phy.type == CamSys_Phy_Cif) {
-                if (extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b) {
-                    //iomux_set(CIF0_D0);//ZYC FOR 32
-                    //iomux_set(CIF0_D1);//ZYC FOR 32
-                }
-            }
-        }
-    }
-    #endif
-#endif 
     return err;
 }
 
@@ -182,25 +164,17 @@ static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *cams
         err = -EINVAL;
         camsys_err("dev_id: 0x%x is not support for camsys!",devio->dev_id);
         goto end;
-    }
-
-#if 0
-    if (devio->phy.type == CamSys_Phy_Mipi) {
-        if (camsys_find_devmem(CAMSYS_REGISTER_MIPIPHY_RES_NAME, camsys_dev) == NULL) {
-            camsys_err("dev_id: 0x%x is connect to MIPI CSI, but %s isn't support",devio->dev_id,
-                dev_name(camsys_dev->miscdev.this_device));
-
-            err = -EINVAL;
-            goto end;
-        }
-    }
-#endif    
+    }  
 
     extdev = camsys_find_extdev(devio->dev_id, camsys_dev);
     if (extdev != NULL) {
-        err = 0;
-        camsys_warn("Extdev(dev_id: 0x%x) has been registered in %s!",
-            devio->dev_id, dev_name(camsys_dev->miscdev.this_device));
+        if (strcmp(extdev->dev_name, devio->dev_name) == 0) {
+            err = 0;
+        } else {
+            err = -EINVAL;    /* ddl@rock-chips.com: v0.0x13.0 */
+            camsys_warn("Extdev(dev_id: 0x%x dev_name: %s) has been registered in %s!",
+                extdev->dev_id, extdev->dev_name,dev_name(camsys_dev->miscdev.this_device));
+        }
         goto end;
     }
 
@@ -210,13 +184,27 @@ static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *cams
         err = -ENOMEM;
         goto end;
     }
-
+    
+    extdev->dev_cfg = devio->dev_cfg;
+    extdev->fl.fl.active = devio->fl.fl.active;
+    extdev->fl.ext_fsh_dev = NULL;
+    //should register external flash device ?
+    if(strlen(devio->fl.fl_drv_name) && (strcmp(devio->fl.fl_drv_name,"Internal") != 0)
+        && (strcmp(devio->fl.fl_drv_name,"NC") != 0)){
+        //register flash device
+        extdev->fl.ext_fsh_dev = camsys_register_ext_fsh_dev(&devio->fl);
+        if(extdev->fl.ext_fsh_dev == NULL){
+            camsys_err("register ext flash %s failed!",devio->fl.fl_drv_name);
+            err = -EINVAL;
+            goto fail;
+        }
+    }
     regulator_info = &devio->avdd;
     regulator = &extdev->avdd;
-    for (i=0; i<4; i++) {
+    for (i=(CamSys_Vdd_Start_Tag+1); i<CamSys_Vdd_End_Tag; i++) {
         if (strcmp(regulator_info->name,"NC")) {
             regulator->ldo = regulator_get(NULL,regulator_info->name);
-            if (IS_ERR(regulator->ldo)) {
+            if (IS_ERR_OR_NULL(regulator->ldo)) {
                 camsys_err("Get %s regulator for dev_id 0x%x failed!",regulator_info->name,devio->dev_id);
                 err = -EINVAL;
                 goto fail;
@@ -239,7 +227,7 @@ static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *cams
 
     gpio_info = &devio->pwrdn;
     gpio = &extdev->pwrdn;
-    for (i=0; i<5; i++) {
+    for (i=(CamSys_Gpio_Start_Tag+1); i<CamSys_Gpio_End_Tag; i++) {
         if (strcmp(gpio_info->name,"NC")) {
             gpio->io = camsys_gpio_get(gpio_info->name);
             if (gpio->io < 0) {
@@ -274,7 +262,10 @@ static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *cams
 
     camsys_dev->iomux(extdev, (void*)camsys_dev);
 
-    camsys_trace(1,"Extdev(dev_id: 0x%x) register success",extdev->dev_id);
+    memcpy(extdev->dev_name,devio->dev_name, sizeof(extdev->dev_name));
+    camsys_trace(1,"Extdev(dev_id: 0x%x  dev_name: %s) register success",
+        extdev->dev_id,
+        extdev->dev_name);
 
     return 0;
 fail:
@@ -302,7 +293,7 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
         }
 
         extdev = camsys_find_extdev(dev_id, camsys_dev);
-        if (extdev != NULL) {
+        if (extdev == NULL) {
             err = -EINVAL;
             camsys_warn("Extdev(dev_id: 0x%x) isn't registered in %s!",
                 dev_id, dev_name(camsys_dev->miscdev.this_device));
@@ -310,7 +301,7 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
         }
 
         regulator = &extdev->avdd;
-        for (i=0; i<4; i++) {
+        for (i=(CamSys_Vdd_Start_Tag+1); i<CamSys_Vdd_End_Tag; i++) {
             if (!IS_ERR_OR_NULL(regulator->ldo)) {
                 while(regulator_is_enabled(regulator->ldo)>0)  
                            regulator_disable(regulator->ldo);
@@ -320,22 +311,27 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
         }
 
         gpio = &extdev->pwrdn;
-        for (i=0; i<4; i++) {
+        for (i=(CamSys_Gpio_Start_Tag+1); i<CamSys_Gpio_End_Tag; i++) {
             if (gpio->io!=0xffffffff) {                    
                 gpio_free(gpio->io);
             }
             gpio++;
         }
 
+        if(extdev->fl.ext_fsh_dev != NULL){
+            camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+        }
         //spin_lock(&camsys_dev->lock);
         mutex_lock(&camsys_dev->extdevs.mut);
         list_del_init(&extdev->list);
         list_del_init(&extdev->active);
         //spin_unlock(&camsys_dev->lock);
         mutex_unlock(&camsys_dev->extdevs.mut);
+        
+        camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
         kfree(extdev);
         extdev = NULL;
-        camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
+        
     } else {
         //spin_lock(&camsys_dev->lock);
         mutex_lock(&camsys_dev->extdevs.mut);
@@ -344,7 +340,7 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
             extdev = list_first_entry(&camsys_dev->extdevs.list, camsys_extdev_t, list);
             if (extdev) {
                 regulator = &extdev->avdd;
-                for (i=0; i<4; i++) {
+                for (i=(CamSys_Vdd_Start_Tag+1); i<CamSys_Vdd_End_Tag; i++) {
                     if (!IS_ERR(regulator->ldo)) {
                         while(regulator_is_enabled(regulator->ldo)>0)  
                                    regulator_disable(regulator->ldo);
@@ -354,12 +350,16 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
                 }
 
                 gpio = &extdev->pwrdn;
-                for (i=0; i<4; i++) {
+                for (i=(CamSys_Gpio_Start_Tag+1); i<CamSys_Gpio_End_Tag; i++) {
                     if (gpio->io!=0xffffffff) {                    
                         gpio_free(gpio->io);
                     }
                     gpio++;
                 }
+
+                if(extdev->fl.ext_fsh_dev != NULL){
+                    camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+                }
                 camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
                 list_del_init(&extdev->list);
                 list_del_init(&extdev->active);
@@ -402,18 +402,21 @@ static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
 
             case CamSys_Rst:
             {
-                camsys_dev->reset_cb(camsys_dev);
+                camsys_dev->reset_cb(camsys_dev, devctl->on);
+                break;
+            } 
+            case CamSys_Flash_Trigger:
+            {
+                camsys_dev->flash_trigger_cb(camsys_dev,devctl->rev[0], devctl->on);
                 break;
             }
-            #if 0
-            //for mipi
-            case CamSys_Gpio_Tag:
+            case CamSys_IOMMU:
             {
-                if((camsys_dev->mipiphy.ops )){
-                    camsys_dev->mipiphy.ops(NULL,NULL,devctl->on);
-                }
+                if(camsys_dev->iommu_cb(camsys_dev, devctl) < 0){
+                    err = -1;
+                    }
+                break;
             }
-            #endif
             default:
                 break;
 
@@ -440,6 +443,8 @@ static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
                             }
                         }
                     }
+                }else if(devctl->ops == CamSys_Flash_Trigger){
+                    err = camsys_ext_fsh_ctrl(extdev->fl.ext_fsh_dev,devctl->rev[0],devctl->on);
                 }
                 
             } else {
@@ -452,26 +457,32 @@ static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
     mutex_unlock(&camsys_dev->extdevs.mut);
     return err;
 }
-static int camsys_phy_ops (camsys_extdev_phy_t *phy, void* ptr, unsigned int on)
+static int camsys_phy_ops (camsys_extdev_t *extdev, camsys_sysctrl_t *devctl, void *ptr)
 {
     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    camsys_mipiphy_t *mipiphy;
     int err = 0;
     
-    if (phy->type == CamSys_Phy_Mipi) {        
-        if (camsys_dev->mipiphy.ops && camsys_dev->mipiphy.clkin_cb) {
-            err =  camsys_dev->mipiphy.clkin_cb(camsys_dev,on);
-            err =  camsys_dev->mipiphy.ops(&phy->info.mipi,&camsys_dev->mipiphy, on);
+    if (extdev->phy.type == CamSys_Phy_Mipi) {
+        mipiphy = (camsys_mipiphy_t*)devctl->rev;
+        if (devctl->on == 0) {
+            mipiphy->phy_index = extdev->phy.info.mipi.phy_index;
+            mipiphy->bit_rate = 0;
+            mipiphy->data_en_bit = 0x00;
         } else {
-            camsys_err("%s isn't support mipi phy",dev_name(camsys_dev->miscdev.this_device));
-            err = -EINVAL;
+            if ((mipiphy->bit_rate == 0) || (mipiphy->data_en_bit == 0)) {
+                *mipiphy = extdev->phy.info.mipi;
+            }
+            if (mipiphy->phy_index != extdev->phy.info.mipi.phy_index) {
+                camsys_warn("mipiphy->phy_index(%d) != extdev->phy.info.mipi.phy_index(%d)!",
+                    mipiphy->phy_index,extdev->phy.info.mipi.phy_index);
+                mipiphy->phy_index = extdev->phy.info.mipi.phy_index;
+                
+            }
         }
-    } else if (phy->type == CamSys_Phy_Cif) {
-        if (camsys_dev->cifphy.ops && camsys_dev->cifphy.clkin_cb) {
-            err =  camsys_dev->cifphy.clkin_cb(camsys_dev,on);
-            err =  camsys_dev->cifphy.ops(&phy->info.cif,&camsys_dev->cifphy, on);
-        } else {
-            //camsys_err("%s isn't support cif phy",dev_name(camsys_dev->miscdev.this_device));
-            //err = -EINVAL;
+        err = camsys_dev->mipiphy[mipiphy->phy_index].ops(ptr,mipiphy);
+        if (err < 0) {
+            camsys_err("extdev(0x%x) mipi phy ops config failed!",extdev->dev_id);
         }
     }
 
@@ -485,20 +496,16 @@ static int camsys_irq_connect(camsys_irqcnnt_t *irqcnnt, camsys_dev_t *camsys_de
 
     if ((irqcnnt->mis != MRV_ISP_MIS) &&
         (irqcnnt->mis != MRV_MIPI_MIS) &&
-        (irqcnnt->mis != MRV_MI_MIS)) {
+        (irqcnnt->mis != MRV_MI_MIS) &&
+        (irqcnnt->mis != MRV_JPG_MIS) &&
+        (irqcnnt->mis != MRV_JPG_ERR_MIS)) {
 
         camsys_err("this thread(pid: %d) irqcnnt->mis(0x%x) is invalidate, irq connect failed!",
             irqcnnt->pid, irqcnnt->mis);
 
         err = -EINVAL;
         goto end;
-    }
-#if 0
-    //zyc for test mipi
-    if((camsys_dev->mipiphy.ops ) && (irqcnnt->mis == MRV_ISP_MIS)){
-        camsys_dev->mipiphy.ops(NULL,NULL,0);
-    }
-#endif    
+    }   
 
     spin_lock_irqsave(&camsys_dev->irq.lock,flags);
     if (!list_empty(&camsys_dev->irq.irq_pool)) {
@@ -598,7 +605,6 @@ static int camsys_irq_wait(camsys_irqsta_t *irqsta, camsys_dev_t *camsys_dev)
                 list_add_tail(&irqstas->list,&irqpool->deactive);
                 spin_unlock_irqrestore(&irqpool->lock,flags);
             } else {
-           //     camsys_warn("Thread(pid: %d) wait irq timeout!!",current->pid);
                 err = -EAGAIN;
             }
         } else {
@@ -700,6 +706,7 @@ static int camsys_open(struct inode *inode, struct file *file)
     int err = 0;
     int minor = iminor(inode);
     camsys_dev_t *camsys_dev;
+    unsigned int i,phycnt;
 
     spin_lock(&camsys_devs.lock);
     list_for_each_entry(camsys_dev, &camsys_devs.devs, list) {
@@ -709,6 +716,20 @@ static int camsys_open(struct inode *inode, struct file *file)
         }
     }
     spin_unlock(&camsys_devs.lock);
+
+    //zyc add
+    INIT_LIST_HEAD(&camsys_dev->extdevs.active);
+    
+    if (camsys_dev->mipiphy != NULL) {
+        phycnt = camsys_dev->mipiphy[0].phycnt;
+         
+        for (i=0; i<phycnt; i++) {
+            if (camsys_dev->mipiphy[i].clkin_cb != NULL) {
+                camsys_dev->mipiphy[i].clkin_cb(camsys_dev,1);
+            }
+        }
+    }
+
     
     if (file->private_data == NULL) {
         camsys_err("Cann't find camsys_dev!");
@@ -725,9 +746,20 @@ end:
 static int camsys_release(struct inode *inode, struct file *file)
 {
     camsys_dev_t *camsys_dev = (camsys_dev_t*)file->private_data;
+    unsigned int i,phycnt;
     
     camsys_irq_disconnect(NULL,camsys_dev, true);
 
+    if (camsys_dev->mipiphy != NULL) {
+        phycnt = camsys_dev->mipiphy[0].phycnt;
+         
+        for (i=0; i<phycnt; i++) {
+            if (camsys_dev->mipiphy[i].clkin_cb != NULL) {
+                camsys_dev->mipiphy[i].clkin_cb(camsys_dev,0);
+            }
+        }
+    }
+
     camsys_trace(1,"%s(%p) is closed",dev_name(camsys_dev->miscdev.this_device),camsys_dev);
 
     return 0;
@@ -737,7 +769,16 @@ static int camsys_release(struct inode *inode, struct file *file)
 * The ioctl() implementation
 */
 
-static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
+typedef struct camsys_querymem_s_32 {
+    camsys_mmap_type_t      mem_type;
+    unsigned int           mem_offset;
+
+    unsigned int            mem_size;
+} camsys_querymem_32_t;
+
+#define CAMSYS_QUREYMEM_32          _IOR(CAMSYS_IOC_MAGIC,  11, camsys_querymem_32_t)
+
+static long camsys_ioctl_compat(struct file *filp,unsigned int cmd, unsigned long arg)
 {
        long err = 0;
     camsys_dev_t *camsys_dev = (camsys_dev_t*)filp->private_data; 
@@ -776,7 +817,223 @@ static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
                 return -EFAULT;
             break;
            }
+           case CAMSYS_QUREYIOMMU:
+           {
+            int iommu_enabled = 0;
+            #ifdef CONFIG_ROCKCHIP_IOMMU
+                               struct device_node * vpu_node =NULL;
+                               int vpu_iommu_enabled = 0;
+                vpu_node = of_find_node_by_name(NULL, "vpu_service");
+                               if(vpu_node){
+                                       of_property_read_u32(vpu_node, "iommu_enabled", &vpu_iommu_enabled);
+                                       of_property_read_u32(camsys_dev->pdev->dev.of_node, "rockchip,isp,iommu_enable", &iommu_enabled);
+                                       of_node_put(vpu_node);
+                                       if(iommu_enabled != vpu_iommu_enabled){
+                                               camsys_err("iommu status not consistent,check the dts file ! isp:%d,vpu:%d",iommu_enabled,vpu_iommu_enabled);
+                                               return -EFAULT;
+                                       }
+                               }
+                       #endif
+            if (copy_to_user((void __user *)arg,(void*)&iommu_enabled, sizeof(iommu_enabled)))
+                return -EFAULT;
+            break;
+           }
+           case CAMSYS_I2CRD:
+           {
+               camsys_i2c_info_t i2cinfo;
+               
+            if (copy_from_user((void*)&i2cinfo,(void __user *)arg, sizeof(camsys_i2c_info_t))) 
+                return -EFAULT;
+
+            err = camsys_i2c_read(&i2cinfo,camsys_dev);
+            if (err==0) {
+                if (copy_to_user((void __user *)arg,(void*)&i2cinfo, sizeof(camsys_i2c_info_t)))
+                    return -EFAULT;
+            }
+            break;
+           }
+
+           case CAMSYS_I2CWR:
+           {
+            camsys_i2c_info_t i2cinfo;
+               
+            if (copy_from_user((void*)&i2cinfo,(void __user *)arg, sizeof(camsys_i2c_info_t))) 
+                return -EFAULT;
+
+            err = camsys_i2c_write(&i2cinfo,camsys_dev);
+            break;
+           }
+
+        case CAMSYS_SYSCTRL:
+        {
+            camsys_sysctrl_t devctl;
+
+            if (copy_from_user((void*)&devctl,(void __user *)arg, sizeof(camsys_sysctrl_t))) 
+                return -EFAULT;
+
+            err = camsys_sysctl(&devctl, camsys_dev);
+            if ((err==0) && (devctl.ops == CamSys_IOMMU)){
+                if (copy_to_user((void __user *)arg,(void*)&devctl, sizeof(camsys_sysctrl_t))) 
+                    return -EFAULT;
+            }
+            break;
+        }
+
+        case CAMSYS_REGRD:
+        {
+
+            break;
+        }
+
+        case CAMSYS_REGWR:
+        {
+
+            break;
+        }
+
+        case CAMSYS_REGISTER_DEVIO:
+        {
+            camsys_devio_name_t devio;
+
+            if (copy_from_user((void*)&devio,(void __user *)arg, sizeof(camsys_devio_name_t))) 
+                return -EFAULT;
+
+            err = camsys_extdev_register(&devio,camsys_dev);
+            break;
+        }
+
+        case CAMSYS_DEREGISTER_DEVIO:
+        {
+            unsigned int dev_id;
+
+            if (copy_from_user((void*)&dev_id,(void __user *)arg, sizeof(unsigned int)))
+                return -EFAULT;
+
+            err = camsys_extdev_deregister(dev_id, camsys_dev, false);
+            break;
+        }
+
+        case CAMSYS_IRQCONNECT:
+        {
+            camsys_irqcnnt_t irqcnnt;
+
+            if (copy_from_user((void*)&irqcnnt,(void __user *)arg, sizeof(camsys_irqcnnt_t))) 
+                return -EFAULT;
+            
+            err = camsys_irq_connect(&irqcnnt, camsys_dev);
+            
+            break;
+        }
+
+        case CAMSYS_IRQWAIT:
+        {
+            camsys_irqsta_t irqsta;
 
+            err = camsys_irq_wait(&irqsta, camsys_dev);
+            if (err==0) {
+                if (copy_to_user((void __user *)arg,(void*)&irqsta, sizeof(camsys_irqsta_t))) 
+                    return -EFAULT;
+            }
+            break;
+        }
+
+        case CAMSYS_IRQDISCONNECT:
+        {
+            camsys_irqcnnt_t irqcnnt;
+
+            if (copy_from_user((void*)&irqcnnt,(void __user *)arg, sizeof(camsys_irqcnnt_t))) 
+                return -EFAULT;
+            err = camsys_irq_disconnect(&irqcnnt,camsys_dev,false);
+                       break;
+        }
+
+               case CAMSYS_QUREYMEM_32:
+               {
+            camsys_querymem_t qmem;
+                       camsys_querymem_32_t qmem32;
+
+            if (copy_from_user((void*)&qmem32,(void __user *)arg, sizeof(camsys_querymem_32_t))) 
+                return -EFAULT;
+
+                       qmem.mem_type = qmem32.mem_type;
+            err = camsys_querymem(camsys_dev,&qmem);
+            if (err == 0) {
+                               qmem32.mem_offset = (unsigned int)qmem.mem_offset;
+                               qmem32.mem_size = qmem.mem_size;
+                if (copy_to_user((void __user *)arg,(void*)&qmem32, sizeof(camsys_querymem_32_t))) 
+                    return -EFAULT;
+            }
+            break;
+               }
+        default :
+            break;
+       }
+
+end:   
+       return err;
+
+}
+
+static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
+{
+       long err = 0;
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)filp->private_data; 
+    
+       if (_IOC_TYPE(cmd) != CAMSYS_IOC_MAGIC) { 
+        camsys_err("ioctl type(%c!=%c) is invalidate\n",_IOC_TYPE(cmd),CAMSYS_IOC_MAGIC);
+        err = -ENOTTY;
+        goto end;
+       }
+       if (_IOC_NR(cmd) > CAMSYS_IOC_MAXNR) {
+        camsys_err("ioctl index(%d>%d) is invalidate\n",_IOC_NR(cmd),CAMSYS_IOC_MAXNR);
+        err = -ENOTTY;
+        goto end;
+       }
+
+    if (_IOC_DIR(cmd) & _IOC_READ)
+        err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));    
+    else if (_IOC_DIR(cmd) & _IOC_WRITE)
+        err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+
+    if (err) {
+        camsys_err("ioctl(0x%x) operation not permitted for %s",cmd,dev_name(camsys_dev->miscdev.this_device));
+        err = -EFAULT;
+        goto end;
+    }
+
+       switch (cmd) {
+
+           case CAMSYS_VERCHK:
+           {
+               camsys_version_t camsys_ver;
+               
+            camsys_ver.drv_ver = CAMSYS_DRIVER_VERSION;
+            camsys_ver.head_ver = CAMSYS_HEAD_VERSION;
+            if (copy_to_user((void __user *)arg,(void*)&camsys_ver, sizeof(camsys_version_t)))
+                return -EFAULT;
+            break;
+           }
+           case CAMSYS_QUREYIOMMU:
+           {
+            int iommu_enabled = 0;
+            #ifdef CONFIG_ROCKCHIP_IOMMU
+                               struct device_node * vpu_node =NULL;
+                               int vpu_iommu_enabled = 0;
+                vpu_node = of_find_node_by_name(NULL, "vpu_service");
+                               if(vpu_node){
+                                       of_property_read_u32(vpu_node, "iommu_enabled", &vpu_iommu_enabled);
+                                       of_property_read_u32(camsys_dev->pdev->dev.of_node, "rockchip,isp,iommu_enable", &iommu_enabled);
+                                       of_node_put(vpu_node);
+                                       if(iommu_enabled != vpu_iommu_enabled){
+                                               camsys_err("iommu status not consistent,check the dts file ! isp:%d,vpu:%d",iommu_enabled,vpu_iommu_enabled);
+                                               return -EFAULT;
+                                       }
+                               }
+                       #endif
+            if (copy_to_user((void __user *)arg,(void*)&iommu_enabled, sizeof(iommu_enabled)))
+                return -EFAULT;
+            break;
+           }
            case CAMSYS_I2CRD:
            {
                camsys_i2c_info_t i2cinfo;
@@ -811,6 +1068,10 @@ static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
                 return -EFAULT;
 
             err = camsys_sysctl(&devctl, camsys_dev);
+            if ((err==0) && (devctl.ops == CamSys_IOMMU)){
+                if (copy_to_user((void __user *)arg,(void*)&devctl, sizeof(camsys_sysctrl_t))) 
+                    return -EFAULT;
+            }
             break;
         }
 
@@ -897,7 +1158,7 @@ static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
             }
             break;
         }
-       
+               
         default :
             break;
        }
@@ -906,6 +1167,8 @@ end:
        return err;
 
 }
+
+
 /*
  * VMA operations.
  */
@@ -994,6 +1257,7 @@ struct file_operations camsys_fops = {
     .release =          camsys_release,
        .unlocked_ioctl =   camsys_ioctl,
        .mmap =             camsys_mmap,
+       .compat_ioctl = camsys_ioctl_compat,
 };
 
 static int camsys_platform_probe(struct platform_device *pdev){
@@ -1004,14 +1268,14 @@ static int camsys_platform_probe(struct platform_device *pdev){
     unsigned long i2cmem;
        camsys_meminfo_t *meminfo;
     unsigned int irq_id;
+    
     err = of_address_to_resource(dev->of_node, 0, &register_res);
     if (err < 0){
         camsys_err("Get register resource from %s platform device failed!",pdev->name);
         err = -ENODEV;
         goto fail_end;
-        }
+    }
 
     //map irqs
     irq_id = irq_of_parse_and_map(dev->of_node, 0);
     if (irq_id < 0) {
@@ -1042,28 +1306,34 @@ static int camsys_platform_probe(struct platform_device *pdev){
     
     INIT_LIST_HEAD(&camsys_dev->devmems.memslist);
 
+    // get soc operation
+    camsys_dev->soc = (void*)camsys_soc_get();
+    if (camsys_dev->soc == NULL) {
+        err = -ENODEV;
+        goto fail_end;
+    }
 
-        //Register mem init
+    //Register mem init
     meminfo = kzalloc(sizeof(camsys_meminfo_t),GFP_KERNEL);
     if (meminfo == NULL) {
         err = -ENOMEM;
         goto request_mem_fail;
     }
 
-    meminfo->vir_base = (unsigned int)devm_ioremap_resource(dev, &register_res);
+    meminfo->vir_base = (unsigned long)devm_ioremap_resource(dev, &register_res);
     if (!meminfo->vir_base){
         camsys_err("%s ioremap %s failed",dev_name(&pdev->dev), CAMSYS_REGISTER_MEM_NAME);
         err = -ENXIO;
         goto request_mem_fail;
-        }
-
+    }
+       rk_isp_base = meminfo->vir_base;
     strlcpy(meminfo->name, CAMSYS_REGISTER_MEM_NAME,sizeof(meminfo->name));
     meminfo->phy_base = register_res.start;
     meminfo->size = register_res.end - register_res.start + 1;  
     list_add_tail(&meminfo->list, &camsys_dev->devmems.memslist);
 
 
-        //I2c mem init
+    //I2c mem init
     i2cmem = __get_free_page(GFP_KERNEL);
     if (i2cmem == 0) {
         camsys_err("Allocate i2cmem failed!");
@@ -1125,12 +1395,12 @@ static int camsys_platform_probe(struct platform_device *pdev){
     list_for_each_entry(meminfo, &camsys_dev->devmems.memslist, list) {
         if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME) == 0) {
             camsys_dev->devmems.i2cmem = meminfo;
-            camsys_trace(1,"    I2c memory (phy: 0x%x vir: 0x%x size: 0x%x)",
+            camsys_trace(1,"    I2c memory (phy: 0x%lx vir: 0x%lx size: 0x%x)",
                         meminfo->phy_base,meminfo->vir_base,meminfo->size);
         }
         if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME) == 0) {
             camsys_dev->devmems.registermem = meminfo;
-            camsys_trace(1,"    Register memory (phy: 0x%x vir: 0x%x size: 0x%x)",
+            camsys_trace(1,"    Register memory (phy: 0x%lx vir: 0x%lx size: 0x%x)",
                         meminfo->phy_base,meminfo->vir_base,meminfo->size);
         }
     }
@@ -1145,7 +1415,7 @@ static int camsys_platform_probe(struct platform_device *pdev){
     list_add_tail(&camsys_dev->list, &camsys_devs.devs);
     spin_unlock(&camsys_devs.lock);
 
-    
+    camsys_init_ext_fsh_module();  
     camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
     return 0;
 request_mem_fail:
@@ -1207,9 +1477,9 @@ static int  camsys_platform_remove(struct platform_device *pdev)
         if (!list_empty(&camsys_dev->extdevs.list)) {
             camsys_extdev_deregister(0,camsys_dev,true);
         }
-
-        if (camsys_dev->mipiphy.remove) 
-            camsys_dev->mipiphy.remove(pdev);
+        if (camsys_dev->mipiphy != NULL) {
+            camsys_dev->mipiphy->remove(pdev);
+        }
         if (camsys_dev->cifphy.remove)
             camsys_dev->cifphy.remove(pdev);
         camsys_dev->platform_remove(pdev);
@@ -1220,6 +1490,8 @@ static int  camsys_platform_remove(struct platform_device *pdev)
         list_del_init(&camsys_dev->list);
         spin_unlock(&camsys_devs.lock);
 
+        camsys_deinit_ext_fsh_module();
+
         kfree(camsys_dev);
         camsys_dev=NULL;
     } else {
@@ -1253,8 +1525,10 @@ static int __init camsys_platform_init(void)
         CAMSYS_DRIVER_VERSION&0xff,
         (CAMSYS_HEAD_VERSION&0xff0000)>>16, (CAMSYS_HEAD_VERSION&0xff00)>>8,
         CAMSYS_HEAD_VERSION&0xff);
+
     spin_lock_init(&camsys_devs.lock);
     INIT_LIST_HEAD(&camsys_devs.devs);
+    camsys_soc_init();
     platform_driver_register(&camsys_platform_driver);
    // platform_driver_probe(&camsys_platform_driver, camsys_platform_probe_new);
     
@@ -1264,6 +1538,7 @@ static int __init camsys_platform_init(void)
 static void __exit camsys_platform_exit(void)  
 {
     platform_driver_unregister(&camsys_platform_driver);
+    camsys_soc_deinit();
 } 
 
 module_init(camsys_platform_init);