add isp driver for rk3288
authorzyc <zyc@rock-chips.com>
Fri, 21 Mar 2014 08:53:22 +0000 (16:53 +0800)
committerzyc <zyc@rock-chips.com>
Fri, 21 Mar 2014 08:54:26 +0000 (16:54 +0800)
16 files changed:
arch/arm/boot/dts/rk3288-pinctrl.dtsi
arch/arm/boot/dts/rk3288.dtsi
drivers/media/Kconfig
drivers/media/Makefile
drivers/media/video/rk_camsys/Kconfig [new file with mode: 0755]
drivers/media/video/rk_camsys/Makefile [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_cif.c [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_cif.h [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_drv.c [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_gpio.h [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_internal.h [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_marvin.c [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_marvin.h [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_mipicsi_phy.c [new file with mode: 0755]
drivers/media/video/rk_camsys/camsys_mipicsi_phy.h [new file with mode: 0755]
include/media/camsys_head.h [new file with mode: 0755]

index ade638143e984dfe2f259744c48d51edd536226b..e542b012afcbadacfbe2cce21b78606324d91dba 100755 (executable)
                };
 
                
+               isp_pin {
+                       isp_mipi:isp_mipi{
+                               rockchip,pins = <CIF_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;                      
+                       };
+                       isp_dvp_sync_d2d9:isp_dvp_force {
+                               rockchip,pins = <CIF_DATA2>,<CIF_DATA3>,
+                                                               <CIF_DATA4>,<CIF_DATA5>,
+                                                               <CIF_DATA6>,<CIF_DATA7>,
+                                                               <CIF_DATA8>,<CIF_DATA9>,
+                                                               <CIF_VSYNC>,<CIF_HREF>,
+                                                               <CIF_CLKIN>,<CIF_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+
+                       };
+                       
+                       isp_dvp_d0d1:isp_d0d1   {
+                               rockchip,pins = <CIF_DATA0>,<CIF_DATA1>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       isp_dvpd10d11:ispd10d11 {
+                               rockchip,pins = <CIF_DATA10>,<CIF_DATA11>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       isp_shutter:isp_shutter         {
+                               rockchip,pins = <ISP_SHUTTEREN>,<ISP_SHUTTERTRIG>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       isp_flash_trigger:isp_trigger {
+                               rockchip,pins = <ISP_FLASHTRIGOUTSPI1_CS0>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       isp_prelight:isp_prelight       {
+                               rockchip,pins = <ISP_PRELIGHTTRIGSPI1_RXD>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+               };
 
        };
 };
index 27cc2ec22ba27e2e5a5e0b02bfe4773ea2feae89..44a64d75ab1520dc194c9b1c0c1eedf60e11d1dc 100755 (executable)
                                                     >;           
             };
 
+          isp:isp@0xFF910000{
+               compatible = "rockchip,isp";
+               reg = <0xFF910000 0x10000>;
+               interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates16 2>, <&clk_gates16 1>, <&clk_isp>, <&clk_isp_jpe>, <&dummy>, <&clk_cif_out>;
+                       clock_names = "aclk_isp", "hclk_isp", "clk_isp", "clk_isp_jpe", "pclkin_isp", "clk_vipout";
+                       pinctrl-names = "default", "isp_dvp8bit","isp_dvp10bit","isp_dvp12bit";
+                       pinctrl-0 = <&isp_mipi>;
+                       pinctrl-1 = <&isp_mipi &isp_dvp_sync_d2d9>;
+                       pinctrl-2 = <&isp_mipi &isp_dvp_sync_d2d9 &isp_dvp_d0d1>;
+                       pinctrl-3 = <&isp_mipi &isp_dvp_sync_d2d9 &isp_dvp_d0d1 &isp_dvpd10d11>;
+                       
+                       status = "disabled";
+       };
+        
+
 };
index 8270388e2a0d2b703f2d08e2cc95533ff434dc14..8c14041057d80ce676819463bf90f41e3d6c2777 100644 (file)
@@ -198,5 +198,6 @@ config MEDIA_ATTACH
 source "drivers/media/i2c/Kconfig"
 source "drivers/media/tuners/Kconfig"
 source "drivers/media/dvb-frontends/Kconfig"
+source "drivers/media/video/rk_camsys/Kconfig"
 
 endif # MEDIA_SUPPORT
index 620f275a45c9903069a1ebd7bb24370de71f3f4e..fe039e96f9c873bfb95891c7ab30b08f0ca7dc5d 100644 (file)
@@ -31,3 +31,4 @@ obj-y += rc/
 obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/
 obj-$(CONFIG_VIDEO_DEV) += radio/
 
+obj-y += video/rk_camsys/
diff --git a/drivers/media/video/rk_camsys/Kconfig b/drivers/media/video/rk_camsys/Kconfig
new file mode 100755 (executable)
index 0000000..c4aba69
--- /dev/null
@@ -0,0 +1,18 @@
+config CAMSYS_DRV
+       tristate "camsys driver "
+       default n
+       
+menu "RockChip camera system driver"
+       depends on CAMSYS_DRV
+       
+config CAMSYS_MRV
+       tristate "camsys driver for marvin isp "
+       default n
+       ---help---
+
+config CAMSYS_CIF
+       tristate "camsys driver for cif "
+       default n
+       ---help---
+
+endmenu          
diff --git a/drivers/media/video/rk_camsys/Makefile b/drivers/media/video/rk_camsys/Makefile
new file mode 100755 (executable)
index 0000000..4c0cc6a
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for rockchip camsys driver
+#
+obj-$(CONFIG_CAMSYS_DRV) += camsys_drv.o 
+obj-$(CONFIG_CAMSYS_MRV) += camsys_marvin.o camsys_mipicsi_phy.o
+obj-$(CONFIG_CAMSYS_CIF) += camsys_cif.o
+
diff --git a/drivers/media/video/rk_camsys/camsys_cif.c b/drivers/media/video/rk_camsys/camsys_cif.c
new file mode 100755 (executable)
index 0000000..96e5964
--- /dev/null
@@ -0,0 +1,340 @@
+#include "camsys_cif.h"
+
+static const char miscdev_cif0_name[] = CAMSYS_CIF0_DEVNAME;
+static const char miscdev_cif1_name[] = CAMSYS_CIF1_DEVNAME;
+
+static int camsys_cif_iomux_cb(camsys_extdev_t *extdev,void *ptr)
+{
+    unsigned int cif_index;
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+
+    if (strcmp(dev_name(camsys_dev->miscdev.this_device), CAMSYS_CIF1_DEVNAME)==0) {
+        cif_index = 1;
+    } else {
+        cif_index = 0;
+    }
+    
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
+    switch(cif_index){
+        case 0:
+        {
+                   iomux_set(CIF0_CLKOUT);
+            write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
+            write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));            
+            break;
+        }
+        default:
+            camsys_err("Cif index(%d) is invalidate!!!\n",cif_index);
+            break;
+    }
+#elif defined(CONFIG_ARCH_RK30)
+    switch(cif_index){
+        case 0:
+        {
+            rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);            
+            break;
+        }
+        case 1:
+        {
+            rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
+            rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
+            rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
+            rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
+            rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
+            rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
+            rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
+            rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
+            
+            rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
+            rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
+            rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
+            rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
+            rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
+            rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
+            rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
+            rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
+            break;
+        }
+        default:
+            camsys_err("Cif index(%d) is invalidate!!!\n", cif_index);
+            break;
+        }
+#elif defined(CONFIG_ARCH_RK319X)
+    switch(cif_index){
+        case 0:
+        {
+            unsigned int cif_vol_sel;
+            //set cif vol domain
+            cif_vol_sel = __raw_readl(RK30_GRF_BASE+0x018c);
+               __raw_writel( (cif_vol_sel |0x20002),RK30_GRF_BASE+0x018c);
+            //set driver strength
+               __raw_writel(0xffffffff, RK30_GRF_BASE+0x01dc);
+               
+            iomux_set(CIF0_CLKOUT);
+            iomux_set(CIF0_CLKIN);
+            iomux_set(CIF0_HREF);
+            iomux_set(CIF0_VSYNC);
+            iomux_set(CIF0_D0);
+            iomux_set(CIF0_D1);
+            iomux_set(CIF0_D2);
+            iomux_set(CIF0_D3);
+            iomux_set(CIF0_D4);
+            iomux_set(CIF0_D5);
+            iomux_set(CIF0_D6);
+            iomux_set(CIF0_D7);
+            iomux_set(CIF0_D8);
+            iomux_set(CIF0_D9);
+            camsys_trace(1, "%s cif iomux success\n",dev_name(camsys_dev->miscdev.this_device));
+            break;
+        }
+        case 1:
+        default:
+            camsys_err("Cif index(%d) is invalidate!!!\n", cif_index);
+            break;
+        }
+#endif
+                
+    return 0;
+}
+static int camsys_cif_clkin_cb(void *ptr, unsigned int on)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
+    
+    spin_lock(&clk->lock);
+    if (on && !clk->in_on) {        
+        clk_enable(clk->pd_cif);
+        clk_enable(clk->aclk_cif);
+       clk_enable(clk->hclk_cif);
+       clk_enable(clk->cif_clk_in);
+       
+        clk->in_on = true;
+        camsys_trace(1, "%s clock in turn on",dev_name(camsys_dev->miscdev.this_device));
+    } else if (!on && clk->in_on) {
+        clk_disable(clk->aclk_cif);
+       clk_disable(clk->hclk_cif);
+       clk_disable(clk->cif_clk_in);           
+       clk_disable(clk->pd_cif);
+        clk->in_on = false;
+        camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
+    }
+    spin_unlock(&clk->lock);
+    return 0;
+}
+
+static int camsys_cif_clkout_cb(void *ptr, unsigned int on)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    camsys_cif_clk_t *clk = (camsys_cif_clk_t*)camsys_dev->clk;
+    struct clk *cif_clk_out_div;
+    
+    
+    spin_lock(&clk->lock);
+    if (on && (clk->out_on != on)) {        
+        clk_enable(clk->cif_clk_out);
+        clk_set_rate(clk->cif_clk_out,on);
+       
+        clk->out_on = on;
+        camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
+                    clk->out_on);
+    } else if (!on && clk->out_on) {
+        if (strcmp(dev_name(camsys_dev->miscdev.this_device),miscdev_cif1_name)==0) {
+            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");
+            }
+        }
+
+        if(!IS_ERR_OR_NULL(cif_clk_out_div)) {
+            clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
+            clk_put(cif_clk_out_div);
+        } else {
+            camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
+        }
+        clk_disable(clk->cif_clk_out);
+        clk->out_on = 0;
+
+        camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
+    }
+    spin_unlock(&clk->lock);
+
+    {
+  //  __raw_writel(0x00, CRU_PCLK_REG30+RK30_CRU_BASE);
+    }
+
+    return 0;
+}
+
+static irqreturn_t camsys_cif_irq(int irq, void *data)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
+    camsys_irqstas_t *irqsta;
+    camsys_irqpool_t *irqpool;
+    unsigned int intsta,frmsta;
+
+    intsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
+    frmsta = __raw_readl(camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
+   printk("get oneframe,intsta = 0x%x \n",intsta);
+    if (intsta & 0x200) {
+        __raw_writel(0x200,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
+        __raw_writel(0xf000,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
+    }
+
+    if (intsta &0x01) {
+        __raw_writel(0x01,camsys_dev->devmems.registermem->vir_base + CIF_INITSTA);
+        __raw_writel(0x02,camsys_dev->devmems.registermem->vir_base + CIF_FRAME_STATUS);
+        __raw_writel(0xf001,camsys_dev->devmems.registermem->vir_base + CIF_CTRL);
+    }    
+    
+    spin_lock(&camsys_dev->irq.lock);
+    list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
+        spin_lock(&irqpool->lock);
+        if (!list_empty(&irqpool->deactive)) {
+            irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
+            irqsta->sta.mis = intsta;
+            irqsta->sta.ris = intsta;
+            list_del_init(&irqsta->list);            
+            list_add_tail(&irqsta->list,&irqpool->active);
+            irqsta = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
+            //wake_up_all(&camsys_dev->irq.irq_done);
+            wake_up(&irqpool->done);
+        }
+        spin_unlock(&irqpool->lock);
+    }
+    spin_unlock(&camsys_dev->irq.lock);
+   
+    return IRQ_HANDLED;
+}
+
+static int camsys_cif_remove(struct platform_device *pdev)
+{
+    camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
+    camsys_cif_clk_t *cif_clk;
+    
+    if (camsys_dev->clk != NULL) {
+        cif_clk = (camsys_cif_clk_t*)camsys_dev->clk;
+        if (cif_clk->out_on) 
+            camsys_cif_clkout_cb(camsys_dev->clk, 0);
+        if (cif_clk->in_on)
+            camsys_cif_clkin_cb(camsys_dev->clk, 0);
+
+        if (cif_clk->pd_cif)
+            clk_put(cif_clk->pd_cif);
+        if (cif_clk->aclk_cif)
+            clk_put(cif_clk->aclk_cif);
+        if (cif_clk->hclk_cif)
+            clk_put(cif_clk->hclk_cif);
+        if (cif_clk->cif_clk_in)
+            clk_put(cif_clk->cif_clk_in);
+        if (cif_clk->cif_clk_out)
+            clk_put(cif_clk->cif_clk_out);
+    
+        kfree(cif_clk);
+        cif_clk = NULL;
+    }
+
+    return 0;
+}
+
+int camsys_cif_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
+{
+    int err = 0;   
+    camsys_cif_clk_t *cif_clk;
+
+    //Irq init
+    err = request_irq(camsys_dev->irq.irq_id, camsys_cif_irq, 0, CAMSYS_CIF_IRQNAME,camsys_dev);
+    if (err) {
+        camsys_err("request irq for %s failed",CAMSYS_CIF_IRQNAME);
+        goto end;
+    }
+
+    //Clk and Iomux init
+    cif_clk = kzalloc(sizeof(camsys_cif_clk_t),GFP_KERNEL);
+    if (cif_clk == NULL) {
+        camsys_err("Allocate camsys_cif_clk_t failed!");
+        err = -EINVAL;
+        goto end;
+    }
+    
+    if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
+        cif_clk->pd_cif = clk_get(NULL, "pd_cif1");
+        cif_clk->aclk_cif = clk_get(NULL, "aclk_cif1");
+        cif_clk->hclk_cif = clk_get(NULL, "hclk_cif1");
+        cif_clk->cif_clk_in = clk_get(NULL, "cif1_in");
+        cif_clk->cif_clk_out = clk_get(NULL, "cif1_out");
+        spin_lock_init(&cif_clk->lock);
+        cif_clk->in_on = false;
+        cif_clk->out_on = false;
+    } else {           
+        cif_clk->pd_cif = clk_get(NULL, "pd_cif0");
+        cif_clk->aclk_cif = clk_get(NULL, "aclk_cif0");
+        cif_clk->hclk_cif = clk_get(NULL, "hclk_cif0");
+        cif_clk->cif_clk_in = clk_get(NULL, "pclkin_cif0");
+        cif_clk->cif_clk_out = clk_get(NULL, "cif0_out");
+        spin_lock_init(&cif_clk->lock);
+        cif_clk->in_on = false;
+        cif_clk->out_on = false;
+    }
+    camsys_dev->clk = (void*)cif_clk;
+    camsys_dev->clkin_cb = camsys_cif_clkin_cb;
+    camsys_dev->clkout_cb = camsys_cif_clkout_cb;
+    camsys_dev->iomux = camsys_cif_iomux_cb;
+    
+    //Misc device init
+    camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
+    if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
+        camsys_dev->miscdev.name = miscdev_cif1_name;
+        camsys_dev->miscdev.nodename = miscdev_cif1_name;        
+    } else {
+        camsys_dev->miscdev.name = miscdev_cif0_name;
+        camsys_dev->miscdev.nodename = miscdev_cif0_name;
+    }
+    camsys_dev->miscdev.fops = &camsys_fops;
+    err = misc_register(&camsys_dev->miscdev);
+    if (err < 0) {
+        camsys_trace(1,"Register /dev/%s misc device failed",camsys_dev->miscdev.name);
+        goto misc_register_failed;
+    } else {
+        camsys_trace(1,"Register /dev/%s misc device success",camsys_dev->miscdev.name);
+    }
+
+    //Variable init
+    if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_CIF1_NAME) == 0) {
+        camsys_dev->dev_id = CAMSYS_DEVID_CIF_1;
+    } else {
+        camsys_dev->dev_id = CAMSYS_DEVID_CIF_0;
+    }
+    camsys_dev->platform_remove = camsys_cif_remove;
+
+    return 0;
+
+misc_register_failed:
+    if (!IS_ERR(camsys_dev->miscdev.this_device)) {
+        misc_deregister(&camsys_dev->miscdev);
+    }
+
+    if (cif_clk) {
+
+        if (cif_clk->pd_cif)
+            clk_put(cif_clk->pd_cif);
+        if (cif_clk->aclk_cif)
+            clk_put(cif_clk->aclk_cif);
+        if (cif_clk->hclk_cif)
+            clk_put(cif_clk->hclk_cif);
+        if (cif_clk->cif_clk_in)
+            clk_put(cif_clk->cif_clk_in);
+        if (cif_clk->cif_clk_out)
+            clk_put(cif_clk->cif_clk_out);
+    
+        kfree(cif_clk);
+        cif_clk = NULL;
+    }
+    
+end:
+    return err;
+}
+EXPORT_SYMBOL_GPL(camsys_cif_probe_cb);
+
diff --git a/drivers/media/video/rk_camsys/camsys_cif.h b/drivers/media/video/rk_camsys/camsys_cif.h
new file mode 100755 (executable)
index 0000000..61f6626
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __CAMSYS_CIF_H__
+#define __CAMSYS_CIF_H__
+
+#include "camsys_internal.h"
+
+#define CAMSYS_CIF_IRQNAME                   "CifIrq"
+
+
+#define CIF_BASE                                0x00
+#define CIF_CTRL                                (CIF_BASE)
+#define CIF_INITSTA                             (CIF_BASE+0x08)
+#define CIF_FRAME_STATUS                        (CIF_BASE+0x60)
+#define CIF_LAST_LINE                           (CIF_BASE+0x68)
+#define CIF_LAST_PIX                            (CIF_BASE+0x6c)
+#define CRU_PCLK_REG30                           0xbc
+
+
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) || defined(CONFIG_ARCH_ROCKCHIP)
+//GRF_IO_CON3                        0x100
+#define CIF_DRIVER_STRENGTH_2MA            (0x00 << 12)
+#define CIF_DRIVER_STRENGTH_4MA            (0x01 << 12)
+#define CIF_DRIVER_STRENGTH_8MA            (0x02 << 12)
+#define CIF_DRIVER_STRENGTH_12MA           (0x03 << 12)
+#define CIF_DRIVER_STRENGTH_MASK           (0x03 << 28)
+
+//GRF_IO_CON4                        0x104
+#define CIF_CLKOUT_AMP_3V3                 (0x00 << 10)
+#define CIF_CLKOUT_AMP_1V8                 (0x01 << 10)
+#define CIF_CLKOUT_AMP_MASK                (0x01 << 26)
+
+#define write_grf_reg(addr, val)           __raw_writel(val, addr+RK_GRF_VIRT)
+#define read_grf_reg(addr)                 __raw_readl(addr+RK_GRF_VIRT)
+#define mask_grf_reg(addr, msk, val)       write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
+#else
+#define write_grf_reg(addr, val)  
+#define read_grf_reg(addr)                 0
+#define mask_grf_reg(addr, msk, val)   
+#endif
+
+
+typedef struct camsys_cif_clk_s {
+       struct clk *pd_cif;
+       struct clk *aclk_cif;
+    struct clk *hclk_cif;
+    struct clk *cif_clk_in;
+    bool in_on;
+    
+    struct clk *cif_clk_out;
+    unsigned int out_on;
+    
+    spinlock_t lock;    
+} camsys_cif_clk_t;
+
+
+int camsys_cif_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev);
+
+#endif
+
diff --git a/drivers/media/video/rk_camsys/camsys_drv.c b/drivers/media/video/rk_camsys/camsys_drv.c
new file mode 100755 (executable)
index 0000000..fb2a2a0
--- /dev/null
@@ -0,0 +1,1422 @@
+#include <media/camsys_head.h>
+
+#include "camsys_cif.h"
+#include "camsys_marvin.h"
+#include "camsys_mipicsi_phy.h"
+#include "camsys_gpio.h"
+
+unsigned int camsys_debug=1;
+module_param(camsys_debug, int, S_IRUGO|S_IWUSR);
+
+static int drv_version = CAMSYS_DRIVER_VERSION;
+module_param(drv_version, int, S_IRUGO);
+static int head_version = CAMSYS_HEAD_VERSION;
+module_param(head_version, int, S_IRUGO);
+
+
+typedef struct camsys_devs_s {
+    spinlock_t lock;
+    struct list_head devs;
+} camsys_devs_t;
+
+static camsys_devs_t camsys_devs;
+
+static int camsys_i2c_write(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
+{
+    int err = 0,i,j;
+    unsigned char buf[8],*bufp;
+    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) {
+        camsys_err("Get %d i2c adapter is failed!",i2cinfo->bus_num);
+        err = -EINVAL;
+        goto end;
+    }
+    
+    if (i2cinfo->i2cbuf_directly) {
+        if (camsys_dev->devmems.i2cmem == NULL) {
+            camsys_err("%s has not i2c mem, it isn't support i2c buf write!",dev_name(camsys_dev->miscdev.this_device));
+            err = -EINVAL;
+            goto end;
+        }
+        totallen = (i2cinfo->i2cbuf_bytes&0xffff);
+        onelen = (i2cinfo->i2cbuf_bytes&0xffff0000)>>16;
+        msg_times = totallen/onelen;
+        if (totallen > camsys_dev->devmems.i2cmem->size) {
+            camsys_err("Want to write 0x%x bytes, i2c memory(size: 0x%x) is overlap",totallen,camsys_dev->devmems.i2cmem->size);
+            err = -EINVAL;
+            goto end;
+        }
+        bufp = (unsigned char*)camsys_dev->devmems.i2cmem->vir_base;        
+    } else {
+        for (i=0; i<i2cinfo->reg_size; i++) {
+            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;
+        }
+        bufp = buf;
+        onelen = i2cinfo->val_size + i2cinfo->reg_size;
+        msg_times = 1;
+    }
+    
+       err = -EAGAIN;    
+    msg->addr = (i2cinfo->slave_addr>>1);
+    msg->flags = 0;
+    msg->scl_rate = i2cinfo->speed;
+   // msg->read_type = 0; 
+    msg->len = onelen;
+    for (i=0; i<msg_times; i++) {        
+        msg->buf = bufp+i*onelen;        
+               err = i2c_transfer(adapter, msg, 1);            
+               if (err < 0) {
+            camsys_err("i2c write dev(addr:0x%x) failed!",i2cinfo->slave_addr);
+                       udelay(10);
+               }
+    }
+
+end:
+    #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
+    return err;
+}
+
+static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
+{
+    int err = 0,i,retry=2,tmp;
+    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;
+    
+    msg[1].addr = (i2cinfo->slave_addr>>1);
+       msg[1].flags = I2C_M_RD;
+       msg[1].scl_rate = i2cinfo->speed;
+//     msg[1].read_type = 0;
+    msg[1].buf = buf;
+    msg[1].len = (unsigned short)i2cinfo->val_size;
+       err = -EAGAIN;    
+
+       while ((retry-- > 0) && (err < 0)) {                                             /* ddl@rock-chips.com :  Transfer again if transent is failed   */
+               err = i2c_transfer(adapter, msg, 2);
+       
+               if (err >= 0) {
+            err = 0;
+               } else {
+                       camsys_err("i2c read dev(addr:0x%x) failed,try again-%d!",i2cinfo->slave_addr,retry);
+                       udelay(10);
+               }
+       }
+
+    if (err==0) {        
+        i2cinfo->val = 0x00;
+        for(i=0; i<i2cinfo->val_size; i++) {
+            tmp = buf[i];
+            i2cinfo->val |= (tmp<<((i2cinfo->val_size-1-i)*8));
+        }
+    }
+    
+end:
+    #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
+    return err;
+}
+
+
+static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *camsys_dev)
+{
+    int err = 0,i;
+    camsys_extdev_t *extdev;
+    camsys_regulator_info_t *regulator_info;
+    camsys_regulator_t *regulator;
+    camsys_gpio_info_t *gpio_info;
+    camsys_gpio_t *gpio;
+    
+    
+    if ((devio->dev_id & CAMSYS_DEVID_EXTERNAL) == 0) {
+        err = -EINVAL;
+        camsys_err("dev_id: 0x%x is not support for camsys!",devio->dev_id);
+        goto end;
+    }
+
+    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;
+        }
+    }
+    
+
+    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));
+        goto end;
+    }
+
+    extdev = kzalloc(sizeof(camsys_extdev_t),GFP_KERNEL);
+    if (extdev == NULL) {
+        camsys_err("alloc camsys_extdev_t failed!");
+        err = -ENOMEM;
+        goto end;
+    }
+
+    regulator_info = &devio->avdd;
+    regulator = &extdev->avdd;
+    for (i=0; i<4; i++) {
+        if (strcmp(regulator_info->name,"NC")) {
+            regulator->ldo = regulator_get(NULL,regulator_info->name);
+            if (IS_ERR(regulator->ldo)) {
+                camsys_err("Get %s regulator for dev_id 0x%x failed!",regulator_info->name,devio->dev_id);
+                err = -EINVAL;
+                goto fail;
+            }
+            
+            regulator->min_uv = regulator_info->min_uv;
+            regulator->max_uv = regulator_info->max_uv;
+            camsys_trace(1,"Get %s regulator(min: %duv  max: %duv) for dev_id 0x%x success",
+                        regulator_info->name,regulator->min_uv,regulator->max_uv,
+                        devio->dev_id);
+        } else {
+            regulator->ldo = NULL;
+            regulator->min_uv = 0;
+            regulator->max_uv = 0;
+        }
+
+        regulator++;
+        regulator_info++;
+    }
+
+    gpio_info = &devio->pwrdn;
+    gpio = &extdev->pwrdn;
+    for (i=0; i<4; i++) {
+        if (strcmp(gpio_info->name,"NC")) {
+            gpio->io = camsys_gpio_get(gpio_info->name);
+            if (gpio->io < 0) {
+                camsys_err("Get %s gpio for dev_id 0x%x failed!",gpio_info->name,devio->dev_id);
+                err = -EINVAL;
+                goto fail;
+            }
+            if (gpio_request(gpio->io,"camsys_gpio")<0) {
+                camsys_err("Request %s(%d) failed",gpio_info->name,gpio->io);
+            }
+            gpio->active = gpio_info->active;
+            camsys_trace(1,"Get %s(%d) gpio(active: %d) for dev_id 0x%x success!",
+                        gpio_info->name,gpio->io,gpio->active,devio->dev_id);
+        } else {
+            gpio->io = 0xffffffff;
+            gpio->active = 0xffffffff;
+        }
+
+        gpio++;
+        gpio_info++;
+    }
+
+    extdev->pdev = camsys_dev->pdev;
+    extdev->phy = devio->phy;
+    extdev->clk = devio->clk;
+    extdev->dev_id = devio->dev_id;
+    //spin_lock(&camsys_dev->lock);
+    mutex_lock(&camsys_dev->extdevs.mut);
+    list_add_tail(&extdev->list, &camsys_dev->extdevs.list);
+    //spin_unlock(&camsys_dev->lock);
+    mutex_unlock(&camsys_dev->extdevs.mut);
+
+    camsys_dev->iomux(extdev, (void*)camsys_dev);
+
+    camsys_trace(1,"Extdev(dev_id: 0x%x) register success",extdev->dev_id);
+
+    return 0;
+fail:
+    if (extdev) { 
+        kfree(extdev);
+        extdev = NULL;
+    }
+end:
+    
+    return err;
+}
+
+static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_dev, bool all)
+{
+    int err = 0,i;
+    camsys_extdev_t *extdev;
+    camsys_regulator_t *regulator;
+    camsys_gpio_t *gpio;
+
+    if (all == false) {
+        if ((dev_id & CAMSYS_DEVID_EXTERNAL) == 0) {
+            err = -EINVAL;
+            camsys_err("dev_id: 0x%x is not support for %s!",dev_id, dev_name(camsys_dev->miscdev.this_device));
+            goto end;
+        }
+
+        extdev = camsys_find_extdev(dev_id, camsys_dev);
+        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));
+            goto end;
+        }
+
+        regulator = &extdev->avdd;
+        for (i=0; i<4; i++) {
+            if (!IS_ERR_OR_NULL(regulator->ldo)) {
+                while(regulator_is_enabled(regulator->ldo)>0)  
+                           regulator_disable(regulator->ldo);
+                       regulator_put(regulator->ldo);
+            }
+            regulator++;
+        }
+
+        gpio = &extdev->pwrdn;
+        for (i=0; i<4; i++) {
+            if (gpio->io!=0xffffffff) {                    
+                gpio_free(gpio->io);
+            }
+            gpio++;
+        }
+
+        //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);
+        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);
+        while (!list_empty(&camsys_dev->extdevs.list)) {
+
+            extdev = list_first_entry(&camsys_dev->extdevs.list, camsys_extdev_t, list);
+            if (extdev) {
+                regulator = &extdev->avdd;
+                for (i=0; i<4; i++) {
+                    if (!IS_ERR(regulator->ldo)) {
+                        while(regulator_is_enabled(regulator->ldo)>0)  
+                                   regulator_disable(regulator->ldo);
+                               regulator_put(regulator->ldo);
+                    }
+                    regulator++; 
+                }
+
+                gpio = &extdev->pwrdn;
+                for (i=0; i<4; i++) {
+                    if (gpio->io!=0xffffffff) {                    
+                        gpio_free(gpio->io);
+                    }
+                    gpio++;
+                }
+                camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
+                list_del_init(&extdev->list);
+                list_del_init(&extdev->active);
+                kfree(extdev);
+                extdev=NULL;
+            }
+        }
+        //spin_unlock(&camsys_dev->lock);        
+        mutex_unlock(&camsys_dev->extdevs.mut);
+        camsys_trace(1, "All extdev is deregister success!");
+    }
+    
+
+end:    
+    return err;
+
+}
+
+static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
+{
+    int i;
+    int err = 0;    
+    camsys_extdev_t *extdev,*extdev2;
+
+    //spin_lock(&camsys_dev->lock);
+    mutex_lock(&camsys_dev->extdevs.mut);
+       if(devctl->ops == 0xaa){
+               dump_stack();
+               return 0;
+       }
+    //Internal 
+    if (camsys_dev->dev_id & devctl->dev_mask) {
+        switch (devctl->ops)
+        {
+            case CamSys_ClkIn:
+            {
+                camsys_dev->clkin_cb(camsys_dev,devctl->on);
+                break;
+            }
+
+            case CamSys_Rst:
+            {
+                camsys_dev->reset_cb(camsys_dev);
+                break;
+            }
+            default:
+                break;
+
+        }
+    }
+
+    //External
+    for (i=0; i<8; i++) {
+        if (devctl->dev_mask & (1<<(i+24))) {
+            extdev = camsys_find_extdev((1<<(i+24)), camsys_dev);
+            if (extdev) {
+                camsys_sysctl_extdev(extdev, devctl, camsys_dev);
+
+                if (devctl->ops == CamSys_ClkIn) {
+                    if (devctl->on) {
+                        list_add_tail(&extdev->active,&camsys_dev->extdevs.active);
+                    } else {
+                        if (!list_empty(&camsys_dev->extdevs.active)) {    /* ddla@rock-chips.com: v0.0.7 */
+                            list_for_each_entry(extdev2, &camsys_dev->extdevs.active, active) {
+                                if (extdev2 == extdev) {
+                                    list_del_init(&extdev->active);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                
+            } else {
+                camsys_err("Can not find dev_id 0x%x device in %s!", (1<<(i+24)), dev_name(camsys_dev->miscdev.this_device));
+            }
+        }
+    }
+
+    //spin_unlock(&camsys_dev->lock);
+    mutex_unlock(&camsys_dev->extdevs.mut);
+    return err;
+}
+static int camsys_phy_ops (camsys_extdev_phy_t *phy, void* ptr, unsigned int on)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    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);
+        } else {
+            camsys_err("%s isn't support mipi phy",dev_name(camsys_dev->miscdev.this_device));
+            err = -EINVAL;
+        }
+    } 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;
+        }
+    }
+
+    return err;
+}
+static int camsys_irq_connect(camsys_irqcnnt_t *irqcnnt, camsys_dev_t *camsys_dev)
+{
+    int err = 0,i;
+    camsys_irqpool_t *irqpool; 
+    unsigned long int flags;
+
+    if ((irqcnnt->mis != MRV_ISP_MIS) &&
+        (irqcnnt->mis != MRV_MIPI_MIS) &&
+        (irqcnnt->mis != MRV_MI_MIS)) {
+
+        camsys_err("this thread(pid: %d) irqcnnt->mis(0x%x) is invalidate, irq connect failed!",
+            irqcnnt->pid, irqcnnt->mis);
+
+        err = -EINVAL;
+        goto end;
+    }
+        
+    spin_lock_irqsave(&camsys_dev->irq.lock,flags);
+    if (!list_empty(&camsys_dev->irq.irq_pool)) {
+        list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
+            if (irqpool->pid == irqcnnt->pid) {
+                camsys_warn("this thread(pid: %d) had been connect irq!",current->pid);
+                spin_unlock(&camsys_dev->irq.lock);
+                goto end;
+            }
+        }
+    }
+    spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
+    
+    irqpool = kzalloc(sizeof(camsys_irqpool_t),GFP_KERNEL);
+    if (irqpool) {
+        spin_lock_init(&irqpool->lock);
+        irqpool->pid = irqcnnt->pid;
+        irqpool->timeout = irqcnnt->timeout;
+        irqpool->mis = irqcnnt->mis;
+        irqpool->icr = irqcnnt->icr;
+        INIT_LIST_HEAD(&irqpool->active);
+        INIT_LIST_HEAD(&irqpool->deactive);
+        init_waitqueue_head(&irqpool->done);
+        for (i=0; i<CAMSYS_IRQPOOL_NUM; i++) {
+            list_add_tail(&irqpool->pool[i].list, &irqpool->deactive);
+        }
+    }
+    
+    spin_lock_irqsave(&camsys_dev->irq.lock,flags);
+    //camsys_dev->irq.timeout = irqcnnt->timeout;
+    list_add_tail(&irqpool->list, &camsys_dev->irq.irq_pool);
+    spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
+    camsys_trace(1, "Thread(pid: %d) connect %s irq success! mis: 0x%x icr: 0x%x ", irqpool->pid, dev_name(camsys_dev->miscdev.this_device),
+        irqpool->mis,irqpool->icr);
+
+end:
+    return err;
+}
+static int active_list_isnot_empty(camsys_irqpool_t *irqpool)
+{
+    int err;
+    unsigned long int flags;
+    
+    spin_lock_irqsave(&irqpool->lock,flags);
+    err = list_empty(&irqpool->active);
+    spin_unlock_irqrestore(&irqpool->lock,flags);
+
+    return !err;
+    
+}
+static int camsys_irq_wait(camsys_irqsta_t *irqsta, camsys_dev_t *camsys_dev)
+{
+    int err = 0;
+    bool find_pool = false;
+    camsys_irqstas_t *irqstas;
+    camsys_irqpool_t *irqpool;
+    unsigned long int flags;
+    
+    spin_lock_irqsave(&camsys_dev->irq.lock,flags);
+    if (!list_empty(&camsys_dev->irq.irq_pool)) {
+        list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
+            if (irqpool->pid == current->pid) {
+                find_pool = true;
+                break;
+            }
+        }
+    }
+    spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
+
+    if (find_pool == false) {
+        camsys_err("this thread(pid: %d) hasn't been connect irq, so wait irq failed!",current->pid);
+        err = -EINVAL;
+        goto end;
+    }
+    
+    
+    spin_lock_irqsave(&irqpool->lock,flags);
+    if (!list_empty(&irqpool->active)) {
+        irqstas = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
+        *irqsta = irqstas->sta;
+        list_del_init(&irqstas->list);
+        list_add_tail(&irqstas->list,&irqpool->deactive);
+        spin_unlock_irqrestore(&irqpool->lock,flags);
+    } else {
+        spin_unlock_irqrestore(&irqpool->lock,flags);
+        
+        wait_event_interruptible_timeout(irqpool->done,
+            active_list_isnot_empty(irqpool),
+            usecs_to_jiffies(irqpool->timeout));
+
+        if (irqpool->pid == current->pid) {
+            if (active_list_isnot_empty(irqpool)) {
+                spin_lock_irqsave(&irqpool->lock,flags);
+                irqstas = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
+                *irqsta = irqstas->sta;
+                list_del_init(&irqstas->list);
+                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 {
+            camsys_warn("Thread(pid: %d) has been disconnect!",current->pid);
+            err = -EAGAIN;
+        }
+    }
+
+    if (err == 0) {
+        camsys_trace(3,"Thread(pid: %d) has been wake up for irq(mis: 0x%x ris:0x%x)!",
+                     current->pid, irqsta->mis, irqsta->ris);
+    }
+
+end:
+    return err;
+}
+
+static int camsys_irq_disconnect(camsys_irqcnnt_t *irqcnnt, camsys_dev_t *camsys_dev, bool all)
+{
+    int err = 0;
+    bool find_pool = false;
+    camsys_irqpool_t *irqpool;    
+    unsigned long int flags;
+    
+    if (all == false) {
+        spin_lock_irqsave(&camsys_dev->irq.lock,flags);
+        printk("%s++++++++++++++++\n",__func__);
+               if (!list_empty(&camsys_dev->irq.irq_pool)) {
+            list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
+                if (irqpool->pid == irqcnnt->pid) {
+                    find_pool = true;
+                    irqpool->pid = 0;
+                    break;
+                }
+            }
+        }
+               printk("%s -------------\n",__func__);
+        spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
+
+        if (find_pool == false) {
+            camsys_err("this thread(pid: %d) have not been connect irq!, disconnect failed",current->pid);         
+        } else {
+            wake_up_all(&irqpool->done);
+        }
+
+        camsys_trace(1, "Thread(pid: %d) disconnect %s irq success!", irqcnnt->pid, dev_name(camsys_dev->miscdev.this_device));
+   } else {
+        spin_lock_irqsave(&camsys_dev->irq.lock,flags);
+        while (!list_empty(&camsys_dev->irq.irq_pool)) {
+            irqpool = list_first_entry(&camsys_dev->irq.irq_pool, camsys_irqpool_t, list);
+            list_del_init(&irqpool->list);
+            irqpool->pid = 0;
+            wake_up_all(&irqpool->done);
+            kfree(irqpool);
+            irqpool = NULL;
+        }
+        spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
+
+        camsys_trace(1, "All thread disconnect %s irq success!", dev_name(camsys_dev->miscdev.this_device));
+   }
+
+
+    return err;
+}
+
+static int camsys_querymem (camsys_dev_t *camsys_dev,  camsys_querymem_t *qmem)
+{
+    int err = 0;
+    
+    if (qmem->mem_type == CamSys_Mmap_RegisterMem) {
+        if (camsys_dev->devmems.registermem == NULL) {
+            camsys_err("%s register memory isn't been register!", dev_name(camsys_dev->miscdev.this_device));
+            err = -EINVAL;
+            goto end;
+        }
+
+        qmem->mem_size = camsys_dev->devmems.registermem->size;
+        qmem->mem_offset = CamSys_Mmap_RegisterMem*PAGE_SIZE;
+    } else if (qmem->mem_type == CamSys_Mmap_I2cMem) {
+        if (camsys_dev->devmems.i2cmem== NULL) {
+            camsys_err("%s i2c memory isn't been register!", dev_name(camsys_dev->miscdev.this_device));
+            err = -EINVAL;
+            goto end;
+        }
+
+        qmem->mem_size = camsys_dev->devmems.i2cmem->size;
+        qmem->mem_offset = CamSys_Mmap_I2cMem*PAGE_SIZE;
+    } else {
+        camsys_err("%d memory type have not in %s memory list",qmem->mem_type,dev_name(camsys_dev->miscdev.this_device));
+        err = -EINVAL;
+        goto end;
+    }
+    
+
+    return 0;
+end: 
+    return err;
+}
+static int camsys_open(struct inode *inode, struct file *file)
+{
+    int err = 0;
+    int minor = iminor(inode);
+    camsys_dev_t *camsys_dev;
+
+    spin_lock(&camsys_devs.lock);
+    list_for_each_entry(camsys_dev, &camsys_devs.devs, list) {
+        if (camsys_dev->miscdev.minor == minor) {
+            file->private_data = (void*)(camsys_dev);
+            break;
+        }
+    }
+    spin_unlock(&camsys_devs.lock);
+    
+    if (file->private_data == NULL) {
+        camsys_err("Cann't find camsys_dev!");
+        err = -ENODEV;
+        goto end;
+    } else {     
+        camsys_trace(1,"%s(%p) is opened!",dev_name(camsys_dev->miscdev.this_device),camsys_dev);
+    }
+
+end:
+    return err;
+}
+
+static int camsys_release(struct inode *inode, struct file *file)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)file->private_data;
+    
+    camsys_irq_disconnect(NULL,camsys_dev, true);
+
+    camsys_trace(1,"%s(%p) is closed",dev_name(camsys_dev->miscdev.this_device),camsys_dev);
+
+    return 0;
+}
+
+/*
+* The ioctl() implementation
+*/
+
+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_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);
+            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;
+               printk("disconnect ++++++++++++++++\n"); 
+            err = camsys_irq_disconnect(&irqcnnt,camsys_dev,false);
+            printk("disconnect ----------------\n");
+                       break;
+        }
+
+        
+        case CAMSYS_QUREYMEM:
+        {
+            camsys_querymem_t qmem;
+
+            if (copy_from_user((void*)&qmem,(void __user *)arg, sizeof(camsys_querymem_t))) 
+                return -EFAULT;
+            
+            err = camsys_querymem(camsys_dev,&qmem);
+            if (err == 0) {
+                if (copy_to_user((void __user *)arg,(void*)&qmem, sizeof(camsys_querymem_t))) 
+                    return -EFAULT;
+            }
+            break;
+        }
+       
+        default :
+            break;
+       }
+
+end:   
+       return err;
+
+}
+/*
+ * VMA operations.
+ */
+static void camsys_vm_open(struct vm_area_struct *vma)
+{
+    camsys_meminfo_t *meminfo = (camsys_meminfo_t*)vma->vm_private_data;
+
+    meminfo->vmas++;
+    return;
+}
+
+static void camsys_vm_close(struct vm_area_struct *vma)
+{
+    camsys_meminfo_t *meminfo = (camsys_meminfo_t*)vma->vm_private_data;
+
+    meminfo->vmas--;
+    return;
+}
+
+static const struct vm_operations_struct camsys_vm_ops = {
+       .open           = camsys_vm_open,
+       .close          = camsys_vm_close,
+};
+
+int camsys_mmap(struct file *flip, struct vm_area_struct *vma)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)flip->private_data;
+       unsigned long addr, start, size;    
+       camsys_mmap_type_t mem_type;
+       camsys_meminfo_t *meminfo;              
+       int ret = 0;
+
+    mem_type = vma->vm_pgoff;     
+    
+    if (mem_type == CamSys_Mmap_RegisterMem) {
+        if (camsys_dev->devmems.registermem != NULL) {
+            meminfo = camsys_dev->devmems.registermem;
+        } else {
+            camsys_err("this camsys device has not register mem!");
+            ret = -EINVAL;
+            goto done;
+        }
+    } else if (mem_type == CamSys_Mmap_I2cMem) {
+        if (camsys_dev->devmems.i2cmem != NULL) {
+            meminfo = camsys_dev->devmems.i2cmem;
+        } else {
+            camsys_err("this camsys device has not i2c mem!");
+            ret = -EINVAL;
+            goto done;
+        }
+    } else {
+        camsys_err("mmap buffer type %d is invalidate!",mem_type);
+        ret = -EINVAL;
+        goto done;
+    }
+    
+    size = vma->vm_end - vma->vm_start;
+    if (size > meminfo->size) {
+        ret = -ENOMEM;
+        camsys_err("mmap size(0x%lx) > memory size(0x%x), so failed!",size,meminfo->size);
+        goto done;
+    }
+    
+       start = vma->vm_start;
+       addr = __phys_to_pfn(meminfo->phy_base);    
+       
+    if (remap_pfn_range(vma, start, addr,size,pgprot_noncached(vma->vm_page_prot))) { 
+        
+        ret = -EAGAIN;
+        goto done;
+    }
+    
+    vma->vm_ops = &camsys_vm_ops;
+    vma->vm_flags |= VM_IO;
+    vma->vm_flags |=VM_ACCOUNT;//same as VM_RESERVED;
+    vma->vm_private_data = (void*)meminfo;
+    camsys_vm_open(vma);
+
+done:
+       return ret;
+}
+
+struct file_operations camsys_fops = {
+       .owner =            THIS_MODULE,
+    .open =             camsys_open,
+    .release =          camsys_release,
+       .unlocked_ioctl =   camsys_ioctl,
+       .mmap =             camsys_mmap,
+};
+
+static int camsys_platform_probe_new(struct platform_device *pdev){
+    int err = 0;
+       camsys_dev_t *camsys_dev;
+    struct resource register_res ;
+    struct device *dev = &pdev->dev;
+    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) {
+        camsys_err("Get irq resource from %s platform device failed!",pdev->name);
+        err = -ENODEV;
+        goto fail_end;
+    }
+
+    camsys_dev = (camsys_dev_t*)devm_kzalloc(&pdev->dev,sizeof(camsys_dev_t), GFP_KERNEL);
+    if (camsys_dev == NULL) {
+        camsys_err("Allocate camsys_dev for %s platform device failed",pdev->name);
+        err = -ENOMEM;
+        goto fail_end;
+    }
+
+    //spin_lock_init(&camsys_dev->lock);
+    mutex_init(&camsys_dev->extdevs.mut);
+    INIT_LIST_HEAD(&camsys_dev->extdevs.list);
+    INIT_LIST_HEAD(&camsys_dev->extdevs.active);
+    INIT_LIST_HEAD(&camsys_dev->list);
+    
+
+    //IRQ init
+    camsys_dev->irq.irq_id = irq_id;  
+    spin_lock_init(&camsys_dev->irq.lock);
+    INIT_LIST_HEAD(&camsys_dev->irq.irq_pool); 
+    //init_waitqueue_head(&camsys_dev->irq.irq_done);
+    
+    INIT_LIST_HEAD(&camsys_dev->devmems.memslist);
+
+
+        //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);
+    if (!meminfo->vir_base){
+        camsys_err("%s ioremap %s failed",dev_name(&pdev->dev), CAMSYS_REGISTER_MEM_NAME);
+        err = -ENXIO;
+        goto request_mem_fail;
+        }
+
+    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
+    i2cmem = __get_free_page(GFP_KERNEL);
+    if (i2cmem == 0) {
+        camsys_err("Allocate i2cmem failed!");
+        err = -ENOMEM;
+        goto request_mem_fail;
+    }
+    SetPageReserved(virt_to_page(i2cmem));
+    
+    meminfo = kzalloc(sizeof(camsys_meminfo_t),GFP_KERNEL);
+    if (meminfo == NULL) {
+        err = -ENOMEM;
+        goto request_mem_fail;
+    }
+    strlcpy(meminfo->name,CAMSYS_I2C_MEM_NAME,sizeof(meminfo->name));
+    meminfo->vir_base = i2cmem;
+    meminfo->phy_base = virt_to_phys((void*)i2cmem);
+    meminfo->size = PAGE_SIZE;
+    list_add_tail(&meminfo->list, &camsys_dev->devmems.memslist);
+
+    {
+        unsigned int *tmpp;
+
+        tmpp = (unsigned int*)meminfo->vir_base;
+        *tmpp = 0xfa561243;
+    }
+
+    //Special init
+
+    {        
+        if (camsys_mipiphy_probe_cb(pdev, camsys_dev) <0) {
+            camsys_err("Mipi phy probe failed!");
+        }
+    }
+    
+    if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_MARVIN_NAME) == 0) {
+        #if (defined(CONFIG_CAMSYS_MRV))
+        camsys_mrv_probe_cb(pdev, camsys_dev);        
+        #else
+        camsys_err("Marvin controller camsys driver haven't been complie!!!");
+        #endif
+    } else {
+        #if (defined(CONFIG_CAMSYS_CIF))
+        camsys_cif_probe_cb(pdev,camsys_dev);
+        #else
+        camsys_err("CIF controller camsys driver haven't been complie!!!");
+        #endif
+    }
+
+    camsys_trace(1, "%s memory:",dev_name(&pdev->dev));
+    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)",
+                        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)",
+                        meminfo->phy_base,meminfo->vir_base,meminfo->size);
+        }
+    }
+
+    camsys_dev->phy_cb = camsys_phy_ops;
+    platform_set_drvdata(pdev,(void*)camsys_dev);
+    //Camsys_devs list add    
+    spin_lock(&camsys_devs.lock);    
+    list_add_tail(&camsys_dev->list, &camsys_devs.devs);
+    spin_unlock(&camsys_devs.lock);
+
+    
+    camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
+    return 0;
+request_mem_fail:
+    if (camsys_dev != NULL) {
+    
+        while(!list_empty(&camsys_dev->devmems.memslist)) {
+            meminfo = list_first_entry(&camsys_dev->devmems.memslist, camsys_meminfo_t, list);
+            if (meminfo) {
+                list_del_init(&meminfo->list);
+                if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME)==0) {
+                    iounmap((void __iomem *)meminfo->vir_base);
+                    release_mem_region(meminfo->phy_base,meminfo->size);
+                } else if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME)==0) {
+                    kfree((void*)meminfo->vir_base);
+                }
+                kfree(meminfo);
+                meminfo = NULL;
+            }
+        } 
+    
+        kfree(camsys_dev);
+        camsys_dev = NULL;
+    }
+fail_end:
+    return -1;
+
+    
+}
+#if 0
+static int camsys_platform_probe(struct platform_device *pdev)
+{
+    int err = 0;
+    unsigned int irq_id;
+    camsys_dev_t *camsys_dev;
+    unsigned long i2cmem;
+    camsys_meminfo_t *meminfo;
+    struct resource *register_res, *mipiphy_register_res;
+
+    camsys_trace(1, "Probe %s device now", dev_name(&pdev->dev));
+    register_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, CAMSYS_REGISTER_RES_NAME);
+    if (register_res == NULL) {
+        camsys_err("Get register resource from %s platform device failed!",pdev->name);
+        err = -ENODEV;
+        goto fail_end;
+    }
+
+    mipiphy_register_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, CAMSYS_REGISTER_MIPIPHY_RES_NAME);
+    
+    irq_id = platform_get_irq_byname(pdev, CAMSYS_IRQ_RES_NAME);
+    if (irq_id < 0) {
+        camsys_err("Get irq resource from %s platform device failed!",pdev->name);
+        err = -ENODEV;
+        goto fail_end;
+    }
+    
+    camsys_dev = (camsys_dev_t*)kzalloc(sizeof(camsys_dev_t), GFP_KERNEL);
+    if (camsys_dev == NULL) {
+        camsys_err("Allocate camsys_dev for %s platform device failed",pdev->name);
+        err = -ENOMEM;
+        goto fail_end;
+    }
+
+    //spin_lock_init(&camsys_dev->lock);
+    mutex_init(&camsys_dev->extdevs.mut);
+    INIT_LIST_HEAD(&camsys_dev->extdevs.list);
+    INIT_LIST_HEAD(&camsys_dev->extdevs.active);
+    INIT_LIST_HEAD(&camsys_dev->list);
+    
+
+    //IRQ init
+    camsys_dev->irq.irq_id = irq_id;  
+    spin_lock_init(&camsys_dev->irq.lock);
+    INIT_LIST_HEAD(&camsys_dev->irq.irq_pool); 
+    //init_waitqueue_head(&camsys_dev->irq.irq_done);
+    
+    INIT_LIST_HEAD(&camsys_dev->devmems.memslist);
+    if (!request_mem_region(register_res->start, register_res->end - register_res->start + 1,
+                            dev_name(&pdev->dev))) {
+        err = -ENOMEM;
+        goto request_mem_fail;
+    }
+
+    //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)ioremap(register_res->start, register_res->end - register_res->start + 1);
+    if (meminfo->vir_base == 0) {
+        camsys_err("%s ioremap %s failed",dev_name(&pdev->dev), CAMSYS_REGISTER_MEM_NAME);
+        err = -ENXIO;
+        goto request_mem_fail;
+    }
+
+    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
+    i2cmem = __get_free_page(GFP_KERNEL);
+    if (i2cmem == 0) {
+        camsys_err("Allocate i2cmem failed!");
+        err = -ENOMEM;
+        goto request_mem_fail;
+    }
+    SetPageReserved(virt_to_page(i2cmem));
+    
+    meminfo = kzalloc(sizeof(camsys_meminfo_t),GFP_KERNEL);
+    if (meminfo == NULL) {
+        err = -ENOMEM;
+        goto request_mem_fail;
+    }
+    strlcpy(meminfo->name,CAMSYS_I2C_MEM_NAME,sizeof(meminfo->name));
+    meminfo->vir_base = i2cmem;
+    meminfo->phy_base = virt_to_phys((void*)i2cmem);
+    meminfo->size = PAGE_SIZE;
+    list_add_tail(&meminfo->list, &camsys_dev->devmems.memslist);
+
+    {
+        unsigned int *tmpp;
+
+        tmpp = (unsigned int*)meminfo->vir_base;
+        *tmpp = 0xfa561243;
+    }
+
+    //Special init
+
+    if (mipiphy_register_res) {        
+        if (camsys_mipiphy_probe_cb(pdev, camsys_dev) <0) {
+            camsys_err("Mipi phy probe failed!");
+        }
+    }
+    
+    if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_MARVIN_NAME) == 0) {
+        #if (defined(CONFIG_CAMSYS_MRV))
+        camsys_mrv_probe_cb(pdev, camsys_dev);        
+        #else
+        camsys_err("Marvin controller camsys driver haven't been complie!!!");
+        #endif
+    } else {
+        #if (defined(CONFIG_CAMSYS_CIF))
+        camsys_cif_probe_cb(pdev,camsys_dev);
+        #else
+        camsys_err("CIF controller camsys driver haven't been complie!!!");
+        #endif
+    }
+
+    camsys_trace(1, "%s memory:",dev_name(&pdev->dev));
+    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)",
+                        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)",
+                        meminfo->phy_base,meminfo->vir_base,meminfo->size);
+        }
+    }
+
+    camsys_dev->phy_cb = camsys_phy_ops;
+    camsys_dev->pdev    =   pdev;
+    platform_set_drvdata(pdev,(void*)camsys_dev);
+    
+    //Camsys_devs list add    
+    spin_lock(&camsys_devs.lock);    
+    list_add_tail(&camsys_dev->list, &camsys_devs.devs);
+    spin_unlock(&camsys_devs.lock);
+
+    
+    camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
+    return 0;
+request_mem_fail:
+    if (camsys_dev != NULL) {
+    
+        while(!list_empty(&camsys_dev->devmems.memslist)) {
+            meminfo = list_first_entry(&camsys_dev->devmems.memslist, camsys_meminfo_t, list);
+            if (meminfo) {
+                list_del_init(&meminfo->list);
+                if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME)==0) {
+                    iounmap((void __iomem *)meminfo->vir_base);
+                    release_mem_region(meminfo->phy_base,meminfo->size);
+                } else if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME)==0) {
+                    kfree((void*)meminfo->vir_base);
+                }
+                kfree(meminfo);
+                meminfo = NULL;
+            }
+        } 
+    
+        kfree(camsys_dev);
+        camsys_dev = NULL;
+    }
+fail_end:
+    return -1;
+}
+#endif
+static int  camsys_platform_remove(struct platform_device *pdev)
+{
+    camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
+    camsys_meminfo_t *meminfo;
+    
+    if (camsys_dev) {
+
+        //Mem deinit
+        while(!list_empty(&camsys_dev->devmems.memslist)) {
+            meminfo = list_first_entry(&camsys_dev->devmems.memslist, camsys_meminfo_t, list);
+            if (meminfo) {
+                list_del_init(&meminfo->list);
+                if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME)==0) {
+                    iounmap((void __iomem *)meminfo->vir_base);
+                    release_mem_region(meminfo->phy_base,meminfo->size);
+                } else if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME)==0) {
+                    kfree((void*)meminfo->vir_base);
+                }
+                kfree(meminfo);
+                meminfo = NULL;
+            }
+        }        
+
+        //Irq deinit
+        if (camsys_dev->irq.irq_id) {
+            free_irq(camsys_dev->irq.irq_id, camsys_dev);
+            camsys_irq_disconnect(NULL,camsys_dev,true);
+        }
+
+        //Extdev deinit
+        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->cifphy.remove)
+            camsys_dev->cifphy.remove(pdev);
+        camsys_dev->platform_remove(pdev);
+
+        misc_deregister(&camsys_dev->miscdev);
+        
+        spin_lock(&camsys_devs.lock);
+        list_del_init(&camsys_dev->list);
+        spin_unlock(&camsys_devs.lock);
+
+        kfree(camsys_dev);
+        camsys_dev=NULL;
+    } else {
+        camsys_err("This platform device havn't obtain camsys_dev!");
+    }
+
+    return 0;
+}
+
+
+static const struct of_device_id cif_of_match[] = {
+    { .compatible = "rodkchip,isp" },
+};
+MODULE_DEVICE_TABLE(of, cif_of_match);
+
+static struct platform_driver camsys_platform_driver =
+{
+    .driver    = {
+        .name  = CAMSYS_PLATFORM_DRV_NAME,
+        .of_match_table = cif_of_match,
+    },
+    .probe             = camsys_platform_probe_new,
+    .remove            = (camsys_platform_remove),
+};
+
+
+static int __init camsys_platform_init(void)  
+{
+    printk("CamSys driver version: v%d.%d.%d,  CamSys head file version: v%d.%d.%d\n",
+        (CAMSYS_DRIVER_VERSION&0xff0000)>>16, (CAMSYS_DRIVER_VERSION&0xff00)>>8,
+        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);
+    platform_driver_register(&camsys_platform_driver);
+
+    
+    return 0;
+}  
+  
+static void __exit camsys_platform_exit(void)  
+{
+    platform_driver_unregister(&camsys_platform_driver);
+} 
+
+module_init(camsys_platform_init);             
+module_exit(camsys_platform_exit);     
+
+MODULE_DESCRIPTION("RockChip Camera System");
+MODULE_AUTHOR("<ddl@rock-chips>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/rk_camsys/camsys_gpio.h b/drivers/media/video/rk_camsys/camsys_gpio.h
new file mode 100755 (executable)
index 0000000..6d6e81e
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __RKCAMSYS_GPIO_H__
+#define __RKCAMSYS_GPIO_H__
+
+//#include <mach/gpio.h>
+#include <asm/gpio.h>
+#if defined(CONFIG_ARCH_ROCKCHIP)
+#define RK30_PIN0_PA0 (0)
+#define NUM_GROUP      (32)
+#define GPIO_BANKS     (9)
+#endif
+
+static inline unsigned int camsys_gpio_group_pin(unsigned char *io_name)
+{
+    unsigned char *pin_char;
+    unsigned char pin;
+
+    if (strstr(io_name, "PA")) {
+        pin_char = strstr(io_name, "PA");
+        pin_char += 2;
+        pin = *pin_char - 0x30;
+    } else if (strstr(io_name, "PB")) {
+        pin_char = strstr(io_name, "PB");
+        pin_char += 2;
+        pin = *pin_char - 0x30;
+        pin += 8;
+    } else if (strstr(io_name, "PC")) {
+        pin_char = strstr(io_name, "PC");
+        pin_char += 2;
+        pin = *pin_char - 0x30;
+        pin += 16;
+    } else if (strstr(io_name, "PD")) {
+        pin_char = strstr(io_name, "PD");
+        pin_char += 2;
+        pin = *pin_char - 0x30;
+        pin += 24;
+    }
+
+    return pin;
+}
+
+static inline unsigned int camsys_gpio_group(unsigned char *io_name)
+{
+    unsigned int group;
+    
+    if (strstr(io_name,"PIN0")) {
+        group = 0;        
+    } else if (strstr(io_name,"PIN1")) {
+        group = 1;      
+    } else if (strstr(io_name,"PIN2")) {
+        group = 2;      
+    } else if (strstr(io_name,"PIN3")) {
+        group = 3;      
+    } else if (strstr(io_name,"PIN4")) {
+        group = 4;      
+    } else if (strstr(io_name,"PIN5")) {
+        group = 5;      
+    } else if (strstr(io_name,"PIN6")) {
+        group = 6;      
+    } 
+
+    return group;
+}
+
+static inline unsigned int camsys_gpio_get(unsigned char *io_name)
+{
+    unsigned int gpio;
+    unsigned int group;
+    unsigned int group_pin;
+    
+#if (defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) || defined(CONFIG_ARCH_RK319X) ||defined(CONFIG_ARCH_ROCKCHIP))
+    if (strstr(io_name, "RK30_")) {
+        gpio = RK30_PIN0_PA0;
+        group = camsys_gpio_group(io_name);
+        group_pin = camsys_gpio_group_pin(io_name);
+        
+        if (group >= GPIO_BANKS) {
+            gpio = 0xffffffff;
+        } else {
+            gpio += group*NUM_GROUP + group_pin; 
+        }
+    }
+
+#endif
+
+
+    return gpio;
+}
+
+#endif
+
diff --git a/drivers/media/video/rk_camsys/camsys_internal.h b/drivers/media/video/rk_camsys/camsys_internal.h
new file mode 100755 (executable)
index 0000000..e027dca
--- /dev/null
@@ -0,0 +1,313 @@
+#ifndef __RKCAMSYS_INTERNAL_H__
+#define __RKCAMSYS_INTERNAL_H__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>      
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/fs.h>  
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/types.h>       
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h>       
+#include <linux/clk.h>
+#include <linux/seq_file.h>
+#include <linux/cdev.h>
+#include <linux/miscdevice.h> 
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/regulator/machine.h>
+#include <linux/log2.h>
+//#include <mach/io.h>
+//#include <mach/gpio.h>
+//#include <mach/iomux.h>
+//#include <mach/cru.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+
+#include <asm/gpio.h>
+#include <asm/system.h>        
+#include <asm/uaccess.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <media/camsys_head.h>
+/*
+*               C A M S Y S   D R I V E R   V E R S I O N 
+*
+*v0.0.1:
+*        1) test version;
+*v0.0.2:
+*        1) add mipi csi phy;
+*v0.0.3:
+*        1) add support cif phy for marvin;
+*v0.0.4:
+*        1) add clock information in struct camsys_devio_name_s;
+*v0.0.5:
+*        1) set isp clock at 32MHz;
+*v0.0.6:
+*        1) iomux d0 d1 for cif phy raw10 in rk319x after i2c operated;
+*        2) check mis value in camsys_irq_connect;
+*        3) add soft rest callback;
+*v0.0.7:
+*        1) check extdev is activate or not before delete from camsys_dev active list;
+*/
+#define CAMSYS_DRIVER_VERSION                   KERNEL_VERSION(0,0,6)
+
+
+#define CAMSYS_PLATFORM_DRV_NAME                "RockChip-CamSys"
+#define CAMSYS_PLATFORM_MARVIN_NAME             "Platform_MarvinDev"
+#define CAMSYS_PLATFORM_CIF0_NAME               "Platform_Cif0Dev"
+#define CAMSYS_PLATFORM_CIF1_NAME               "Platform_Cif1Dev"
+
+#define CAMSYS_REGISTER_RES_NAME                "CamSys_RegMem"
+#define CAMSYS_REGISTER_MIPIPHY_RES_NAME        "CamSys_RegMem_MipiPhy"
+#define CAMSYS_IRQ_RES_NAME                     "CamSys_Irq"
+
+#define CAMSYS_REGISTER_MEM_NAME                CAMSYS_REGISTER_RES_NAME
+#define CAMSYS_I2C_MEM_NAME                     "CamSys_I2cMem"
+
+#define CAMSYS_NAMELEN_MIN(a)                   ((strlen(a)>(CAMSYS_NAME_LEN-1))?(CAMSYS_NAME_LEN-1):strlen(a))
+#define CAMSYS_IRQPOOL_NUM                      128
+
+extern unsigned int camsys_debug;
+
+#define camsys_trace(level, msg,...) \
+       do { \
+               if (1/*camsys_debug >= level*/) \
+                       printk("D%d:%s(%d): " msg "\n",level, __FUNCTION__,__LINE__, ## __VA_ARGS__); \
+       } while (0)
+
+#define camsys_warn(msg,...)  printk(KERN_ERR "W:%s(%d): " msg "\n", __FUNCTION__,__LINE__, ## __VA_ARGS__)
+#define camsys_err(msg,...)   printk(KERN_ERR "E:%s(%d): " msg "\n", __FUNCTION__,__LINE__, ## __VA_ARGS__)
+
+
+typedef struct camsys_irqstas_s {
+    camsys_irqsta_t       sta;
+    struct list_head      list;
+} camsys_irqstas_t;
+
+typedef struct camsys_irqpool_s {
+    pid_t                 pid;
+    unsigned int          timeout;             //us
+    unsigned int          mis;
+    unsigned int          icr;
+    
+
+    spinlock_t            lock;                       // lock for list
+    camsys_irqstas_t      pool[CAMSYS_IRQPOOL_NUM];
+    struct list_head      active;
+    struct list_head      deactive;
+
+    struct list_head      list;
+
+    wait_queue_head_t     done;
+} camsys_irqpool_t;
+
+typedef struct camsys_irq_s {
+    unsigned int          irq_id;
+
+    spinlock_t            lock;             //lock for timeout and irq_connect in ioctl
+    //unsigned int          timeout;
+    
+    //wait_queue_head_t     irq_done;
+
+    struct list_head      irq_pool;
+} camsys_irq_t;
+
+typedef struct camsys_meminfo_s {
+    unsigned char name[32];
+    unsigned int phy_base;
+    unsigned int vir_base;
+    unsigned int size;
+    unsigned int vmas;
+
+    struct list_head list;
+    
+} camsys_meminfo_t;
+
+typedef struct camsys_devmems_s {
+    camsys_meminfo_t *registermem;
+    camsys_meminfo_t *i2cmem;
+    struct list_head memslist;
+} camsys_devmems_t;
+
+typedef struct camsys_regulator_s {
+    struct regulator  *ldo;
+    int               min_uv;
+    int               max_uv;
+} camsys_regulator_t;
+
+typedef struct camsys_gpio_s {
+    unsigned int      io;
+    unsigned int      active;
+} camsys_gpio_t;
+typedef struct camsys_flash_s {
+    camsys_gpio_t        fl;
+} camsys_flash_t;
+typedef struct camsys_extdev_s {
+    unsigned int             dev_id;
+    camsys_regulator_t       avdd;
+    camsys_regulator_t       dovdd;
+    camsys_regulator_t       dvdd;
+    camsys_regulator_t       afvdd;
+    
+    camsys_gpio_t            pwrdn;
+    camsys_gpio_t            rst;
+    camsys_gpio_t            afpwr;
+    camsys_gpio_t            afpwrdn;
+
+    camsys_flash_t           fl;
+
+    camsys_extdev_phy_t      phy;
+    camsys_extdev_clk_t      clk;
+    
+    unsigned int             dev_cfg;
+
+    struct platform_device *pdev;
+    
+    struct list_head         list;
+    struct list_head         active;
+} camsys_extdev_t;
+
+typedef struct camsys_phyinfo_s {
+    void               *clk;
+    camsys_meminfo_t   *reg;    
+
+    int (*clkin_cb)(void *ptr, unsigned int on);
+    int (*ops) (void *phy, void *phyinfo, unsigned int on);
+    int (*remove)(struct platform_device *pdev);
+} camsys_phyinfo_t;
+
+typedef struct camsys_exdevs_s {
+    struct mutex          mut;
+    struct list_head      list;
+    struct list_head      active;
+} camsys_exdevs_t;
+
+typedef struct camsys_dev_s {
+    unsigned int          dev_id;        
+
+    camsys_irq_t          irq;
+    camsys_devmems_t      devmems;
+    struct miscdevice     miscdev;  
+    void                  *clk;
+
+    camsys_phyinfo_t      mipiphy;
+    camsys_phyinfo_t      cifphy;
+
+    camsys_exdevs_t       extdevs;    
+    struct list_head      list;
+    struct platform_device *pdev;
+
+    int (*clkin_cb)(void *ptr, unsigned int on);
+    int (*clkout_cb)(void *ptr,unsigned int on);
+    int (*reset_cb)(void *ptr);
+    int (*phy_cb) (camsys_extdev_phy_t *phy,void* ptr, unsigned int on);
+    int (*iomux)(camsys_extdev_t *extdev,void *ptr);
+    int (*platform_remove)(struct platform_device *pdev);
+} camsys_dev_t;
+
+
+static inline camsys_extdev_t* camsys_find_extdev(unsigned int dev_id, camsys_dev_t *camsys_dev)
+{
+    camsys_extdev_t *extdev;
+
+    if (!list_empty(&camsys_dev->extdevs.list)) {
+        list_for_each_entry(extdev, &camsys_dev->extdevs.list, list) {
+            if (extdev->dev_id == dev_id) {
+                return extdev;
+            }
+        }
+    }    
+    return NULL;
+}
+
+static inline camsys_meminfo_t* camsys_find_devmem(char *name, camsys_dev_t *camsys_dev)
+{
+    camsys_meminfo_t *devmem;
+
+    if (!list_empty(&camsys_dev->devmems.memslist)) {
+        list_for_each_entry(devmem, &camsys_dev->devmems.memslist, list) {
+            if (strcmp(devmem->name, name) == 0) {
+                return devmem;
+            }
+        }
+    }
+    camsys_err("%s memory have not been find in %s!",name,dev_name(camsys_dev->miscdev.this_device));
+    return NULL;
+}
+
+
+static inline int camsys_sysctl_extdev(camsys_extdev_t *extdev, camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
+{
+    int err = 0;
+    camsys_regulator_t *regulator;
+    camsys_gpio_t *gpio;
+    
+    if (devctl->ops < CamSys_Vdd_Tag) {
+        regulator = &extdev->avdd;
+        regulator += devctl->ops;
+
+        //printk("regulator: %p  regulator->ldo: %p\n",regulator,regulator->ldo);
+        if (!IS_ERR_OR_NULL(regulator->ldo)) {
+            if (devctl->on) {
+                regulator_set_voltage(regulator->ldo,regulator->min_uv,regulator->max_uv);
+                regulator_enable(regulator->ldo);
+                camsys_trace(1,"Sysctl %d success, regulator set (%d,%d) uv!",devctl->ops, regulator->min_uv,regulator->max_uv);
+            } else {
+                while(regulator_is_enabled(regulator->ldo)>0)  
+                               regulator_disable(regulator->ldo);
+                           camsys_trace(1,"Sysctl %d success, regulator off!",devctl->ops);
+            }
+        } else {
+            camsys_err("Sysctl %d failed, because regulator ldo is NULL!",devctl->ops);
+            err = -EINVAL;
+            goto end;
+        }
+    } else if (devctl->ops < CamSys_Gpio_Tag) {
+        gpio = &extdev->pwrdn;
+        gpio += devctl->ops - CamSys_Vdd_Tag -1;
+
+        if (gpio->io != 0xffffffff) {
+            if (devctl->on) {
+                gpio_direction_output(gpio->io, gpio->active);
+                gpio_set_value(gpio->io, gpio->active);
+                camsys_trace(1,"Sysctl %d success, gpio(%d) set %d",devctl->ops, gpio->io, gpio->active);
+            } else {
+                gpio_direction_output(gpio->io, !gpio->active);
+                gpio_set_value(gpio->io, !gpio->active);
+                camsys_trace(1,"Sysctl %d success, gpio(%d) set %d",devctl->ops, gpio->io, !gpio->active);
+            }
+        } else {
+            camsys_err("Sysctl %d failed, because gpio is NULL!",devctl->ops);
+            err = -EINVAL;
+            goto end;
+        }
+    } else if (devctl->ops == CamSys_ClkIn) {
+        if (camsys_dev->clkout_cb)
+            camsys_dev->clkout_cb(camsys_dev, extdev->clk.in_rate);
+        if (camsys_dev->phy_cb)
+            camsys_dev->phy_cb(&extdev->phy, camsys_dev, devctl->on);
+    }
+
+end:
+    return err;
+}
+
+extern struct file_operations camsys_fops;
+#endif
diff --git a/drivers/media/video/rk_camsys/camsys_marvin.c b/drivers/media/video/rk_camsys/camsys_marvin.c
new file mode 100755 (executable)
index 0000000..2953557
--- /dev/null
@@ -0,0 +1,391 @@
+#include "camsys_marvin.h"
+
+static const char miscdev_name[] = CAMSYS_MARVIN_DEVNAME;
+
+
+static int camsys_mrv_iomux_cb(camsys_extdev_t *extdev,void *ptr)
+{  
+    unsigned int cif_vol_sel;
+#if 0    
+    if (extdev->dev_cfg & CAMSYS_DEVCFG_FLASHLIGHT) {
+        iomux_set(ISP_FLASH_TRIG);  
+        if (extdev->fl.fl.io != 0xffffffff) {
+            iomux_set(ISP_FL_TRIG);
+        }
+    } 
+
+    if (extdev->dev_cfg & CAMSYS_DEVCFG_PREFLASHLIGHT) {
+        iomux_set(ISP_PRELIGHT_TRIG);
+    }
+    
+    if (extdev->dev_cfg & CAMSYS_DEVCFG_SHUTTER) {
+        iomux_set(ISP_SHUTTER_OPEN);
+        iomux_set(ISP_SHUTTER_TRIG);
+    }
+
+    iomux_set(CIF0_CLKOUT);
+#endif
+
+    struct pinctrl      *pinctrl;
+    struct pinctrl_state    *state;
+    int retval = 0;
+    char state_str[20] = {0};
+
+    struct device *dev = &(extdev->pdev->dev);
+    
+    if (extdev->phy.type == CamSys_Phy_Cif) {
+        if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_8b)&& (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
+
+           strcpy(state_str,"isp_dvp8bit");
+
+        }
+
+        if ((extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b)&& (extdev->phy.info.cif.fmt <= CamSys_Fmt_Raw_12b)) {
+           strcpy(state_str,"isp_dvp10bit");
+        }
+
+        if (extdev->phy.info.cif.fmt == CamSys_Fmt_Raw_12b) {
+           strcpy(state_str,"isp_dvp12bit");
+
+        }
+    }else{
+           strcpy(state_str,"default");
+    }
+
+    //mux CIF0_CLKOUT
+
+    pinctrl = devm_pinctrl_get(dev);
+    if (IS_ERR(pinctrl)) {
+        camsys_err("%s:Get pinctrl failed!\n",__func__);
+        return -1;
+    }
+    state = pinctrl_lookup_state(pinctrl,
+                         state_str);
+    if (IS_ERR(state)){
+        dev_err(dev, "%s:could not get %s pinstate\n",__func__,state_str);
+        return -1;
+        }
+
+    if (!IS_ERR(state)) {
+        retval = pinctrl_select_state(pinctrl, state);
+        if (retval){
+            dev_err(dev,
+                "%s:could not set %s pins\n",__func__,state_str);
+                return -1;
+
+                }
+    }
+
+    //set cif vol domain
+    if (extdev->phy.type == CamSys_Phy_Cif) {
+
+        #if 0
+        if (!IS_ERR_OR_NULL(extdev->dovdd.ldo)) {
+            if (extdev->dovdd.max_uv >= 25000000) {
+                __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
+            } else {
+                __raw_writel((1<<(1+16)),RK30_GRF_BASE+0x018c);
+            }
+        } else {
+            __raw_writel(((1<<1)|(1<<(1+16))),RK30_GRF_BASE+0x018c);
+        }
+        #else
+        __raw_writel(((1<<1)|(1<<(1+16))),RK_GRF_VIRT+0x018c);
+        #endif
+        
+        //set driver strength
+        __raw_writel(0xffffffff, RK_GRF_VIRT+0x01dc);   
+    }
+    
+    return 0;
+}
+
+static int camsys_mrv_reset_cb(void *ptr)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    #if 0 //do nothing ,zyc
+    cru_set_soft_reset(SOFT_RST_ISP,true);
+    udelay(100);
+    cru_set_soft_reset(SOFT_RST_ISP,false);
+    #endif
+    camsys_trace(1, "%s soft reset\n",dev_name(camsys_dev->miscdev.this_device));
+    return 0;
+}
+
+static int camsys_mrv_clkin_cb(void *ptr, unsigned int on)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
+    
+    spin_lock(&clk->lock);
+    if (on && !clk->in_on) {        
+        clk_enable(clk->pd_isp);
+        clk_enable(clk->aclk_isp);
+       clk_enable(clk->hclk_isp);      
+       clk_enable(clk->isp);
+       clk_enable(clk->isp_jpe);
+       clk_enable(clk->pclkin_isp);
+       
+        clk->in_on = true;
+
+        camsys_trace(1, "%s clock in turn on",dev_name(camsys_dev->miscdev.this_device));
+        camsys_mrv_reset_cb(ptr);       
+        
+    } else if (!on && clk->in_on) {
+        clk_disable(clk->pd_isp);
+        clk_disable(clk->aclk_isp);
+       clk_disable(clk->hclk_isp);
+       clk_disable(clk->isp);
+       clk_disable(clk->isp_jpe);
+       clk_disable(clk->pclkin_isp);
+        clk->in_on = false;
+        camsys_trace(1, "%s clock in turn off",dev_name(camsys_dev->miscdev.this_device));
+    }
+    spin_unlock(&clk->lock);
+    return 0;
+}
+
+static int camsys_mrv_clkout_cb(void *ptr, unsigned int on)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
+    camsys_mrv_clk_t *clk = (camsys_mrv_clk_t*)camsys_dev->clk;
+    struct clk *cif_clk_out_div;
+    
+    spin_lock(&clk->lock);
+    if (on && (clk->out_on != on)) {        
+        clk_enable(clk->cif_clk_out);
+        clk_set_rate(clk->cif_clk_out,on);
+       
+        clk->out_on = on;
+        camsys_trace(1, "%s clock out(rate: %dHz) turn on",dev_name(camsys_dev->miscdev.this_device),
+                    clk->out_on);
+    } else if (!on && clk->out_on) {
+        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");
+        }
+
+        if(!IS_ERR_OR_NULL(cif_clk_out_div)) {
+            clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
+            clk_put(cif_clk_out_div);
+        } else {
+            camsys_warn("%s clock out may be not off!", dev_name(camsys_dev->miscdev.this_device));
+        }
+        clk_disable(clk->cif_clk_out);
+        clk->out_on = 0;
+
+        camsys_trace(1, "%s clock out turn off",dev_name(camsys_dev->miscdev.this_device));
+    }
+    spin_unlock(&clk->lock);    
+
+    return 0;
+}
+static irqreturn_t camsys_mrv_irq(int irq, void *data)
+{
+    camsys_dev_t *camsys_dev = (camsys_dev_t*)data;
+    camsys_irqstas_t *irqsta;
+    camsys_irqpool_t *irqpool;
+    unsigned int isp_mis,mipi_mis,mi_mis,*mis;
+
+    isp_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_MIS));
+    mipi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_MIS));
+    mi_mis = __raw_readl((void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_MIS));    
+
+    __raw_writel(isp_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_ISP_ICR)); 
+    __raw_writel(mipi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MIPI_ICR)); 
+    __raw_writel(mi_mis, (void volatile *)(camsys_dev->devmems.registermem->vir_base + MRV_MI_ICR)); 
+    
+    spin_lock(&camsys_dev->irq.lock);
+    if (!list_empty(&camsys_dev->irq.irq_pool)) {
+        list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
+            if (irqpool->pid != 0) {
+                switch(irqpool->mis)
+                {
+                    case MRV_ISP_MIS:
+                    {
+                        mis = &isp_mis;
+                        break;
+                    }
+
+                    case MRV_MIPI_MIS:
+                    {
+                        mis = &mipi_mis;
+                        break;
+                    }
+                    case MRV_MI_MIS:
+                    {
+                        mis = &mi_mis;
+                        break;
+                    }
+
+                    default:     
+                    {
+                        camsys_trace(2,"Thread(pid:%d) irqpool mis(%d) is invalidate",irqpool->pid,irqpool->mis);
+                        goto end;
+                    }
+                }
+
+                if (*mis != 0) {
+                    spin_lock(&irqpool->lock);
+                    if (!list_empty(&irqpool->deactive)) {
+                        irqsta = list_first_entry(&irqpool->deactive, camsys_irqstas_t, list);
+                        irqsta->sta.mis = *mis;                                                 
+                        list_del_init(&irqsta->list);            
+                        list_add_tail(&irqsta->list,&irqpool->active);                        
+                        wake_up(&irqpool->done);
+                    }
+                    spin_unlock(&irqpool->lock);
+                }
+            }
+        }
+    }
+end:    
+    spin_unlock(&camsys_dev->irq.lock);
+
+    return IRQ_HANDLED;
+}
+static int camsys_mrv_remove_cb(struct platform_device *pdev)
+{
+    camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
+    camsys_mrv_clk_t *mrv_clk=NULL;
+
+    if (camsys_dev->clk != NULL) {
+
+        mrv_clk = (camsys_mrv_clk_t*)camsys_dev->clk;
+        if (mrv_clk->out_on)
+            camsys_mrv_clkout_cb(mrv_clk,0);
+        if (mrv_clk->in_on)
+            camsys_mrv_clkin_cb(mrv_clk,0);
+    
+        if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
+            clk_put(mrv_clk->pd_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
+            clk_put(mrv_clk->aclk_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
+            clk_put(mrv_clk->hclk_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
+            clk_put(mrv_clk->isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
+            clk_put(mrv_clk->isp_jpe);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
+            clk_put(mrv_clk->pclkin_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
+            clk_put(mrv_clk->cif_clk_out);
+        }
+
+        kfree(mrv_clk);
+        mrv_clk = NULL;
+    }
+
+    return 0;
+}
+int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
+{
+    int err = 0;   
+    camsys_mrv_clk_t *mrv_clk=NULL;
+    //struct clk *clk_parent;
+    
+    err = request_irq(camsys_dev->irq.irq_id, camsys_mrv_irq, 0, CAMSYS_MARVIN_IRQNAME,camsys_dev);
+    if (err) {
+        camsys_err("request irq for %s failed",CAMSYS_MARVIN_IRQNAME);
+        goto end;
+    }
+
+    //Clk and Iomux init
+    mrv_clk = kzalloc(sizeof(camsys_mrv_clk_t),GFP_KERNEL);
+    if (mrv_clk == NULL) {
+        camsys_err("Allocate camsys_mrv_clk_t failed!");
+        err = -EINVAL;
+        goto clk_failed;
+    }
+     
+   // mrv_clk->pd_isp = devm_clk_get(&pdev->dev, "pd_isp");
+    mrv_clk->pd_isp = NULL;
+    mrv_clk->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
+    mrv_clk->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
+    mrv_clk->isp = devm_clk_get(&pdev->dev, "clk_isp");
+    mrv_clk->isp_jpe = devm_clk_get(&pdev->dev, "clk_isp_jpe");
+    mrv_clk->pclkin_isp = devm_clk_get(&pdev->dev, "pclkin_isp");
+    mrv_clk->cif_clk_out = devm_clk_get(&pdev->dev, "clk_vipout");
+    if (/*IS_ERR_OR_NULL(mrv_clk->pd_isp) ||*/ IS_ERR_OR_NULL(mrv_clk->aclk_isp) || IS_ERR_OR_NULL(mrv_clk->hclk_isp) ||
+        IS_ERR_OR_NULL(mrv_clk->isp) || IS_ERR_OR_NULL(mrv_clk->isp_jpe) || IS_ERR_OR_NULL(mrv_clk->pclkin_isp) || 
+        IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
+        camsys_err("Get %s clock resouce failed!\n",miscdev_name);
+        err = -EINVAL;
+        goto clk_failed;
+    }
+    
+    clk_set_rate(mrv_clk->isp,320000000);
+    clk_set_rate(mrv_clk->isp_jpe,320000000);
+    
+    spin_lock_init(&mrv_clk->lock);
+    
+    mrv_clk->in_on = false;
+    mrv_clk->out_on = 0;
+        
+    camsys_dev->clk = (void*)mrv_clk;
+    camsys_dev->clkin_cb = camsys_mrv_clkin_cb;
+    camsys_dev->clkout_cb = camsys_mrv_clkout_cb;
+    camsys_dev->reset_cb = camsys_mrv_reset_cb;
+    camsys_dev->iomux = camsys_mrv_iomux_cb;
+    
+    camsys_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
+    camsys_dev->miscdev.name = miscdev_name;
+    camsys_dev->miscdev.nodename = miscdev_name;
+    camsys_dev->miscdev.fops = &camsys_fops;
+
+    err = misc_register(&camsys_dev->miscdev);
+    if (err < 0) {
+        camsys_err("misc register %s failed!",miscdev_name);
+        goto misc_register_failed;
+    }   
+
+    //Variable init
+    camsys_dev->dev_id = CAMSYS_DEVID_MARVIN;
+    camsys_dev->platform_remove = camsys_mrv_remove_cb;
+    
+    return 0;
+misc_register_failed:
+    if (!IS_ERR_OR_NULL(camsys_dev->miscdev.this_device)) {
+        misc_deregister(&camsys_dev->miscdev);
+    }
+
+clk_failed:
+    if (mrv_clk != NULL) {
+        if (!IS_ERR_OR_NULL(mrv_clk->pd_isp)) {
+            clk_put(mrv_clk->pd_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->aclk_isp)) {
+            clk_put(mrv_clk->aclk_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->hclk_isp)) {
+            clk_put(mrv_clk->hclk_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->isp)) {
+            clk_put(mrv_clk->isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->isp_jpe)) {
+            clk_put(mrv_clk->isp_jpe);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->pclkin_isp)) {
+            clk_put(mrv_clk->pclkin_isp);
+        }
+        if (!IS_ERR_OR_NULL(mrv_clk->cif_clk_out)) {
+            clk_put(mrv_clk->cif_clk_out);
+        }
+
+        kfree(mrv_clk);
+        mrv_clk = NULL;
+    }
+    
+end:
+    return err;
+}
+EXPORT_SYMBOL_GPL(camsys_mrv_probe_cb);
+
diff --git a/drivers/media/video/rk_camsys/camsys_marvin.h b/drivers/media/video/rk_camsys/camsys_marvin.h
new file mode 100755 (executable)
index 0000000..7b92edd
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __CAMSYS_MARVIN_H__
+#define __CAMSYS_MARVIN_H__
+
+#include "camsys_internal.h"
+
+#define CAMSYS_MARVIN_IRQNAME                   "MarvinIrq"
+
+
+
+#define MRV_ISP_BASE                            0x400
+#define MRV_ISP_RIS                             (MRV_ISP_BASE+0x1c0)
+#define MRV_ISP_MIS                             (MRV_ISP_BASE+0x1c4)
+#define MRV_ISP_ICR                             (MRV_ISP_BASE+0x1c8)
+
+#define MRV_MIPI_BASE                           0x1C00
+#define MRV_MIPI_MIS                            (MRV_MIPI_BASE+0x10)
+#define MRV_MIPI_ICR                            (MRV_MIPI_BASE+0x14)
+
+#define MRV_MI_BASE                             (0x1400)
+#define MRV_MI_MIS                              (MRV_MI_BASE+0x100)
+#define MRV_MI_ICR                              (MRV_MI_BASE+0x104)
+
+
+
+typedef struct camsys_mrv_clk_s {
+    struct clk      *pd_isp;
+    struct clk      *hclk_isp;
+    struct clk      *aclk_isp;
+    struct clk      *isp;
+    struct clk      *isp_jpe;
+    struct clk      *pclkin_isp;
+    bool             in_on;
+
+    struct clk      *cif_clk_out;
+    unsigned int     out_on;
+
+    spinlock_t       lock;
+} camsys_mrv_clk_t;
+
+int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev);
+
+#endif
+
+
diff --git a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.c
new file mode 100755 (executable)
index 0000000..62335ad
--- /dev/null
@@ -0,0 +1,126 @@
+#include "camsys_mipicsi_phy.h"
+
+#if defined(CONFIG_ARCH_ROCKCHIP)
+//GRF_SOC_CON14
+//bit 0     dphy_rx0_testclr
+//bit 1     dphy_rx0_testclk
+//bit 2     dphy_rx0_testen
+//bit 3:10 dphy_rx0_testdin
+#define GRF_SOC_CON14_OFFSET    (0x027c)
+#define DPHY_RX0_TESTCLR_MASK   (0x1<<16)
+#define DPHY_RX0_TESTCLK_MASK   (0x1<<17)
+#define DPHY_RX0_TESTEN_MASK    (0x1<<18)
+#define DPHY_RX0_TESTDIN_MASK   (0xff<<19)
+
+#define DPHY_RX0_TESTCLR    (1<<0)
+#define DPHY_RX0_TESTCLK    (1<<1)
+#define DPHY_RX0_TESTEN     (1<<2)
+#define DPHY_RX0_TESTDIN_OFFSET    (3)
+
+
+//GRF_SOC_CON6
+//bit 0 grf_con_disable_isp
+//bit 1 grf_con_isp_dphy_sel  1'b0 mipi phy rx0
+#define GRF_SOC_CON6_OFFSET    (0x025c)
+#define MIPI_PHY_RX0_MASK       (0x1<<16)
+#define MIPI_PHY_RX0            (0x1<<0)
+
+#endif
+
+static void phy0_WriteReg(uint8_t addr, uint8_t data)
+{
+
+    //TESTEN =1,TESTDIN=addr
+    write_grf_reg(GRF_SOC_CON14_OFFSET,(( addr << DPHY_RX0_TESTDIN_OFFSET) |DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN| DPHY_RX0_TESTEN_MASK)); 
+    //TESTCLK=0
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK); 
+    //TESTEN =0,TESTDIN=data
+    write_grf_reg(GRF_SOC_CON14_OFFSET, (( data << DPHY_RX0_TESTDIN_OFFSET)|DPHY_RX0_TESTDIN_MASK |DPHY_RX0_TESTEN)); 
+    //TESTCLK=1
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK |DPHY_RX0_TESTCLK); 
+
+}
+
+static uint8_t phy0_ReadReg(uint8_t addr)  //read 0xff968034 bit8~15
+{
+    uint8_t data = 0;
+    //TESTEN =1,TESTDIN=addr
+    write_grf_reg(GRF_SOC_CON14_OFFSET,(( addr << DPHY_RX0_TESTDIN_OFFSET) |DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN| DPHY_RX0_TESTEN_MASK)); 
+    //TESTCLK=0
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK); 
+
+    data = ((read_grf_reg(GRF_SOC_CON14_OFFSET) >> DPHY_RX0_TESTDIN_OFFSET) & (0xff));
+
+    camsys_err("%s phy addr = 0x%x,value = 0x%x\n",__func__,addr,data);
+    return data ;
+
+    
+}
+
+
+static void PHY0_Init(int numLane,int clkfreq)
+{
+    
+//  select phy rx0
+    write_grf_reg(GRF_SOC_CON6_OFFSET, MIPI_PHY_RX0_MASK | MIPI_PHY_RX0); 
+
+//TESTCLK=1
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK |DPHY_RX0_TESTCLK); 
+//TESTCLR=1    
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK |DPHY_RX0_TESTCLK | DPHY_RX0_TESTCLR_MASK |DPHY_RX0_TESTCLR);   
+//TESTCLR=0  zyc
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK |DPHY_RX0_TESTCLK); 
+
+//**********************************************************************//
+
+//set clock lane
+    phy0_WriteReg(0x34,0x14);
+
+//set lane 0
+ /********************
+    500-550M 0x0E
+    600-650M 0x10
+    720M     0x12
+    360M     0x2A
+    *******************/
+    phy0_WriteReg(0x44,0x10);
+ //**********************************************************************//
+
+//Normal operation
+    phy0_ReadReg(0x00);                           
+    //TESTCLK=1
+    write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK |DPHY_RX0_TESTCLK); 
+
+    //TESTEN =0
+    write_grf_reg(GRF_SOC_CON14_OFFSET, (DPHY_RX0_TESTEN)); 
+
+ }
+
+
+static int camsys_mipiphy_ops (void *phy, void *phyinfo, unsigned int on)
+{
+    PHY0_Init(1,0);
+    return 0;
+}
+
+static int camsys_mipiphy_clkin_cb(void *ptr, unsigned int on)
+{
+    return 0;
+}
+
+static int camsys_mipiphy_remove_cb(struct platform_device *pdev)
+{
+    return 0;
+}
+int camsys_mipiphy_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
+{
+    camsys_dev->mipiphy.clkin_cb = camsys_mipiphy_clkin_cb;
+    camsys_dev->mipiphy.ops = camsys_mipiphy_ops;
+    camsys_dev->mipiphy.remove = camsys_mipiphy_remove_cb;
+
+    return 0;
+  
+}
+
diff --git a/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h b/drivers/media/video/rk_camsys/camsys_mipicsi_phy.h
new file mode 100755 (executable)
index 0000000..4c0d64c
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __CAMSYS_MIPICSI_PHY_H__
+#define __CAMSYS_MIPICSI_PHY_H__
+
+#include "camsys_internal.h"
+
+#if defined(CONFIG_ARCH_ROCKCHIP)
+
+#define write_grf_reg(addr, val)           __raw_writel(val, addr+RK_GRF_VIRT)
+#define read_grf_reg(addr)                 __raw_readl(addr+RK_GRF_VIRT)
+#define mask_grf_reg(addr, msk, val)       write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
+#else
+#define write_grf_reg(addr, val)  
+#define read_grf_reg(addr)                 0
+#define mask_grf_reg(addr, msk, val)   
+#endif
+
+
+typedef struct camsys_mipiphy_clk_s {
+    struct clk       *pd_mipi_csi;
+    struct clk       *pclk_mipiphy_csi;
+    bool             in_on;
+    spinlock_t       lock;
+} camsys_mipiphy_clk_t;
+
+
+int camsys_mipiphy_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev);
+
+#endif
diff --git a/include/media/camsys_head.h b/include/media/camsys_head.h
new file mode 100755 (executable)
index 0000000..3adc33a
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef __RKCAMSYS_HEAR_H__
+#define __RKCAMSYS_HEAR_H__
+
+#include <linux/ioctl.h>
+
+/*
+*               C A M S Y S   H E A D   F I L E   V E R S I O N 
+*
+*v0.0.1:
+*        1) test version;
+*v0.0.2:
+*        1) modify camsys_irqcnnt_t;
+*v0.0.3:
+*        1) add support cif phy for marvin;
+*v0.0.4:
+*        1) add clock information in struct camsys_devio_name_s;
+*/
+#define CAMSYS_HEAD_VERSION           KERNEL_VERSION(0,0,4)
+
+#define CAMSYS_MARVIN_DEVNAME         "camsys_marvin"           
+#define CAMSYS_CIF0_DEVNAME           "camsys_cif0"
+#define CAMSYS_CIF1_DEVNAME           "camsys_cif1"
+
+#define CAMSYS_NAME_LEN               32
+  
+#define CAMSYS_DEVID_MARVIN           0x00000001
+#define CAMSYS_DEVID_CIF_0            0x00000002
+#define CAMSYS_DEVID_CIF_1            0x00000004
+#define CAMSYS_DEVID_INTERNAL         0x000000FF
+
+#define CAMSYS_DEVID_SENSOR_1A        0x01000000
+#define CAMSYS_DEVID_SENSOR_1B        0x02000000
+#define CAMSYS_DEVID_SENSOR_2         0x04000000
+#define CAMSYS_DEVID_EXTERNAL         0xFF000000
+#define CAMSYS_DEVID_EXTERNAL_NUM     8
+
+#define CAMSYS_DEVCFG_FLASHLIGHT      0x00000001
+#define CAMSYS_DEVCFG_PREFLASHLIGHT   0x00000002
+#define CAMSYS_DEVCFG_SHUTTER         0x00000004
+
+typedef struct camsys_irqsta_s {
+    unsigned int ris;                 //Raw interrupt status
+    unsigned int mis;                 //Masked interrupt status
+} camsys_irqsta_t;
+
+typedef struct camsys_irqcnnt_s {
+    int          pid;
+    unsigned int timeout;             //us
+
+    unsigned int mis;
+    unsigned int icr;                 
+} camsys_irqcnnt_t;
+
+typedef enum camsys_mmap_type_e {     //this type can be filled in mmap offset argument      
+    CamSys_Mmap_RegisterMem,
+    CamSys_Mmap_I2cMem,
+
+    CamSys_Mmap_End
+} camsys_mmap_type_t;
+
+typedef struct camsys_querymem_s {
+    camsys_mmap_type_t      mem_type;
+    unsigned long           mem_offset;
+
+    unsigned int            mem_size;
+} camsys_querymem_t;
+
+typedef struct camsys_i2c_info_s {
+    unsigned char     bus_num;
+    unsigned short    slave_addr;
+    unsigned int      reg_addr;       //i2c device register address
+    unsigned int      reg_size;       //register address size
+    unsigned int      val;
+    unsigned int      val_size;       //register value size
+    unsigned int      i2cbuf_directly;
+    unsigned int      i2cbuf_bytes;   
+    unsigned int      speed;          //100000 == 100KHz
+} camsys_i2c_info_t;
+
+typedef struct camsys_reginfo_s {
+    unsigned int      dev_mask;
+    unsigned int      reg_offset;
+    unsigned int      val;
+} camsys_reginfo_t;
+
+typedef enum camsys_sysctrl_ops_e {
+    CamSys_Avdd =0,
+    CamSys_Dovdd,
+    CamSys_Dvdd,
+    CamSys_Afvdd,
+
+    CamSys_Vdd_Tag = 10,
+    
+    CamSys_PwrDn,
+    CamSys_Rst,
+    CamSys_AfPwr,
+    CamSys_AfPwrDn,
+
+    CamSys_Gpio_Tag = 50,
+
+    CamSys_ClkIn   
+} camsys_sysctrl_ops_t;
+
+typedef struct camsys_regulator_info_s {
+    unsigned char     name[CAMSYS_NAME_LEN];
+    int               min_uv;
+    int               max_uv;
+} camsys_regulator_info_t;
+
+typedef struct camsys_gpio_info_s {
+    unsigned char     name[CAMSYS_NAME_LEN];
+    unsigned int      active;
+} camsys_gpio_info_t;
+
+typedef struct camsys_sysctrl_s {
+    unsigned int              dev_mask;
+    camsys_sysctrl_ops_t      ops;
+    unsigned int              on;
+} camsys_sysctrl_t;
+
+typedef struct camsys_flash_info_s {
+    camsys_gpio_info_t        fl;
+} camsys_flash_info_t;
+
+typedef struct camsys_mipiphy_s {
+    unsigned int                data_en_bit;        //data lane enable bit;
+} camsys_mipiphy_t;
+
+typedef enum camsys_fmt_e {
+    CamSys_Fmt_Yuv420_8b = 0x18,
+    CamSys_Fmt_Yuv420_10b = 0x19,
+    CamSys_Fmt_LegacyYuv420_8b = 0x19,
+
+    CamSys_Fmt_Yuv422_8b = 0x1e,
+    CamSys_Fmt_Yuv422_10b = 0x1f,
+
+    CamSys_Fmt_Raw_6b = 0x28,
+    CamSys_Fmt_Raw_7b = 0x29,
+    CamSys_Fmt_Raw_8b = 0x2a,
+    CamSys_Fmt_Raw_10b = 0x2b,
+    CamSys_Fmt_Raw_12b = 0x2c,
+    CamSys_Fmt_Raw_14b = 0x2d,
+} camsys_fmt_t;
+
+typedef struct camsys_cifphy_s {
+    unsigned int                cif_num; 
+    camsys_fmt_t                fmt;
+} camsys_cifphy_t;
+
+typedef enum camsys_phy_type_e {
+    CamSys_Phy_Mipi,
+    CamSys_Phy_Cif,
+
+    CamSys_Phy_end
+} camsys_phy_type_t;
+
+typedef struct camsys_extdev_phy_s {
+    camsys_phy_type_t           type;
+    union {
+        camsys_mipiphy_t            mipi;
+        camsys_cifphy_t             cif;
+    } info;
+    
+} camsys_extdev_phy_t;
+
+typedef struct camsys_extdev_clk_s {
+    unsigned int in_rate;
+} camsys_extdev_clk_t;
+
+typedef struct camsys_devio_name_s {
+    unsigned int                dev_id;
+    
+    camsys_regulator_info_t     avdd;         // sensor avdd power regulator name
+    camsys_regulator_info_t     dovdd;        // sensor dovdd power regulator name
+    camsys_regulator_info_t     dvdd;         // sensor dvdd power regulator name    "NC" describe no regulator
+    camsys_regulator_info_t     afvdd; 
+
+    camsys_gpio_info_t          pwrdn;        // standby gpio name
+    camsys_gpio_info_t          rst;          // hard reset gpio name  
+    camsys_gpio_info_t          afpwr;        // auto focus vcm driver ic power gpio name
+    camsys_gpio_info_t          afpwrdn;      // auto focus vcm driver ic standby gpio 
+
+    camsys_flash_info_t         fl;
+
+    camsys_extdev_phy_t         phy;
+    camsys_extdev_clk_t         clk;
+    
+    unsigned int                dev_cfg;     // function bit mask configuration 
+} camsys_devio_name_t;
+
+typedef struct camsys_version_s {
+    unsigned int drv_ver;
+    unsigned int head_ver;
+} camsys_version_t;
+
+/*
+ *     I O C T L   C O D E S   F O R    R O C K C H I P S   C A M S Y S   D E V I C E S
+ *
+ */
+#define CAMSYS_IOC_MAGIC  'M'
+#define CAMSYS_IOC_MAXNR  12
+
+#define CAMSYS_VERCHK            _IOR(CAMSYS_IOC_MAGIC,  0, camsys_version_t)
+
+#define CAMSYS_I2CRD             _IOWR(CAMSYS_IOC_MAGIC,  1, camsys_i2c_info_t)
+#define CAMSYS_I2CWR             _IOW(CAMSYS_IOC_MAGIC,  2, camsys_i2c_info_t)
+
+#define CAMSYS_SYSCTRL           _IOW(CAMSYS_IOC_MAGIC,  3, camsys_sysctrl_t) 
+#define CAMSYS_REGRD             _IOWR(CAMSYS_IOC_MAGIC,  4, camsys_reginfo_t)
+#define CAMSYS_REGWR             _IOW(CAMSYS_IOC_MAGIC,  5, camsys_reginfo_t)
+#define CAMSYS_REGISTER_DEVIO    _IOW(CAMSYS_IOC_MAGIC,  6, camsys_devio_name_t)
+#define CAMSYS_DEREGISTER_DEVIO  _IOW(CAMSYS_IOC_MAGIC,  7, unsigned int)
+#define CAMSYS_IRQCONNECT        _IOW(CAMSYS_IOC_MAGIC,  8, camsys_irqcnnt_t)
+#define CAMSYS_IRQWAIT           _IOR(CAMSYS_IOC_MAGIC,  9, camsys_irqsta_t)
+#define CAMSYS_IRQDISCONNECT     _IOW(CAMSYS_IOC_MAGIC,   10, camsys_irqcnnt_t)
+
+#define CAMSYS_QUREYMEM          _IOR(CAMSYS_IOC_MAGIC,  11, camsys_querymem_t)
+#endif