rk30 fb: fix load_creen init err,add frame start interrupt for sync
authoryxj <yxj@rock-chips.com>
Fri, 30 Mar 2012 04:17:29 +0000 (12:17 +0800)
committeryxj <yxj@rock-chips.com>
Fri, 30 Mar 2012 04:17:59 +0000 (12:17 +0800)
drivers/video/rockchip/chips/rk30_lcdc.c
drivers/video/rockchip/chips/rk30_lcdc.h
drivers/video/rockchip/rk_fb.c
include/linux/rk_fb.h

index 26a7a1af000e481df9083be17cd5e08c4023c3e2..13d1c6bace466eb092215611c09c18a63e586107 100644 (file)
@@ -73,6 +73,9 @@ static int init_rk30_lcdc(struct rk30_lcdc_device *lcdc_dev)
        }
        clk_enable(lcdc_dev->hclk);  //enable aclk for register config
        LcdSetBit(lcdc_dev,DSP_CTRL0, m_LCDC_AXICLK_AUTO_ENABLE);//eanble axi-clk auto gating for low power
+       LcdMskReg(lcdc_dev,INT_STATUS,m_FRM_START_INT_CLEAR | m_BUS_ERR_INT_CLEAR | m_LINE_FLAG_INT_EN |
+              m_FRM_START_INT_EN | m_HOR_START_INT_EN,v_FRM_START_INT_CLEAR(1) | v_BUS_ERR_INT_CLEAR(0) |
+              v_LINE_FLAG_INT_EN(0) | v_FRM_START_INT_EN(1) | v_HOR_START_INT_EN(0));
        LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);  // write any value to  REG_CFG_DONE let config become effective
        return 0;
 }
@@ -384,7 +387,10 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
 
 {
        u32 xact, yact, xvir, yvir, xpos, ypos;
-       u32 ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY;
+       u32 ScaleYrgbX = 0x1000;
+       u32 ScaleYrgbY = 0x1000;
+       u32 ScaleCbrX = 0x1000;
+       u32 ScaleCbrY = 0x1000;
        
        xact = par->xact;                       
        yact = par->yact;
@@ -482,7 +488,7 @@ int rk30_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id)
                printk(KERN_ERR "screen is null!\n");
                return -ENOENT; 
        }
-       
+       wait_for_completion(&dev_drv->frame_done);
        if(layer_id==0)
        {
                par = &(dev_drv->layer_par[0]);
@@ -493,6 +499,7 @@ int rk30_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id)
                par = &(dev_drv->layer_par[1]);
                win1_display(lcdc_dev,par);
        }
+       INIT_COMPLETION(dev_drv->frame_done);
        
     return 0;
 }
@@ -529,6 +536,15 @@ int rk30_lcdc_resume(struct layer_par *layer_par)
     return 0;
 }
 
+static irqreturn_t rk30_lcdc_isr(int irq, void *dev_id)
+{
+       struct rk30_lcdc_device *lcdc_dev = (struct rk30_lcdc_device *)dev_id;
+       LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_START_INT_CLEAR, v_FRM_START_INT_CLEAR(1));
+       //LcdMskReg(lcdc_dev, INT_STATUS, m_LINE_FLAG_INT_CLEAR, v_LINE_FLAG_INT_CLEAR(1));
+       complete_all(&(lcdc_dev->driver.frame_done));
+       return IRQ_HANDLED;
+}
+
 static struct layer_par lcdc_layer[] = {
        [0] = {
                .name           = "win0",
@@ -560,7 +576,6 @@ static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
        rk_screen *screen;
        struct resource *res = NULL;
        struct resource *mem;
-       
        int ret = 0;
        
        /*************Malloc rk30lcdc_inf and set it to pdev for drvdata**********/
@@ -607,8 +622,23 @@ static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
                ret = -ENXIO;
                goto err2;
        }
+       
        lcdc_dev->preg = (LCDC_REG*)lcdc_dev->reg_vir_base;
        printk("lcdc%d:reg_phy_base = 0x%08x,reg_vir_base:0x%p\n",pdev->id,lcdc_dev->reg_phy_base, lcdc_dev->preg);
+       lcdc_dev->irq = platform_get_irq(pdev, 0);
+       if(lcdc_dev->irq < 0)
+       {
+               dev_err(&pdev->dev, "cannot find IRQ\n");
+               goto err3;
+       }
+       ret = request_irq(lcdc_dev->irq, rk30_lcdc_isr, IRQF_DISABLED,dev_name(&pdev->dev),lcdc_dev);
+       if (ret)
+       {
+              dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n", lcdc_dev->irq, ret);
+              ret = -EBUSY;
+              goto err3;
+       }
+       
        init_lcdc_device_driver(&lcdc_driver,&(lcdc_dev->driver),lcdc_dev->id);
        lcdc_dev->driver.dev=&pdev->dev;
        
@@ -620,7 +650,7 @@ static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
        if(ret < 0)
        {
                printk(KERN_ERR "init rk30 lcdc failed!\n");
-               goto err3;
+               goto err4;
        }
        ret = rk30_load_screen(&(lcdc_dev->driver),1);
        if(ret < 0)
@@ -633,12 +663,14 @@ static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
        if(ret < 0)
        {
                printk(KERN_ERR "registe fb for lcdc0 failed!\n");
-               goto err3;
+               goto err4;
        }
        printk("rk30 lcdc%d probe ok!\n",lcdc_dev->id);
 
        return 0;
 
+err4:
+       free_irq(lcdc_dev->irq, pdev);
 err3:  
        iounmap(lcdc_dev->reg_vir_base);
 err2:
index f8a8fbec4d442d7790edc03c2bdbccf919863350..2e48095ddabd6b2e3f5c3966ef1e6d2190eaa7f5 100644 (file)
@@ -40,7 +40,7 @@ typedef volatile struct tagLCDC_REG
     unsigned int WIN0_SCL_OFFSET;         //0x50 Win0 Cbr scaling start point offset
     unsigned int WIN1_YRGB_MST;           //0x54 Win1 active YRGB memory start address
     unsigned int WIN1_CBR_MST;            //0x58 Win1 active Cbr memory start address
-       unsigned int WIN1_VIR;                //0x5c WIN1 virtual display width/height
+    unsigned int WIN1_VIR;                //0x5c WIN1 virtual display width/height
     unsigned int WIN1_ACT_INFO;           //0x60 Win1 active window width/height
     unsigned int WIN1_DSP_INFO;           //0x64 Win1 display width/height on panel
     unsigned int WIN1_DSP_ST;             //0x68 Win1 display start point on panel
@@ -228,26 +228,29 @@ typedef volatile struct tagLCDC_REG
 
 
 //LCDC_INT_STATUS
-#define m_HOR_START         (1<<0)
-#define m_FRM_START         (1<<1)
-#define m_SCANNING_FLAG     (1<<2)
-#define m_HOR_STARTMASK     (1<<3)
-#define m_FRM_STARTMASK     (1<<4)
-#define m_SCANNING_MASK     (1<<5)
-#define m_HOR_STARTCLEAR    (1<<6)
-#define m_FRM_STARTCLEAR    (1<<7)
-#define m_SCANNING_CLEAR    (1<<8)
-#define m_SCAN_LINE_NUM     (0x7ff<<9)
-#define v_HOR_START(x)         (((x)&1)<<0)
-#define v_FRM_START(x)         (((x)&1)<<1)
-#define v_SCANNING_FLAG(x)     (((x)&1)<<2)
-#define v_HOR_STARTMASK(x)     (((x)&1)<<3)
-#define v_FRM_STARTMASK(x)     (((x)&1)<<4)
-#define v_SCANNING_MASK(x)     (((x)&1)<<5)
-#define v_HOR_STARTCLEAR(x)    (((x)&1)<<6)
-#define v_FRM_STARTCLEAR(x)    (((x)&1)<<7)
-#define v_SCANNING_CLEAR(x)    (((x)&1)<<8)
-#define v_SCAN_LINE_NUM(x)     (((x)&0x7ff)<<9)
+#define v_HOR_START_INT_STA        (1<<0)  //status
+#define v_FRM_START_INT_STA        (1<<1)
+#define v_LINE_FLAG_INT_STA        (1<<2)
+#define v_BUS_ERR_INT_STA         (1<<3)
+#define m_HOR_START_INT_EN                (1<<4)  //enable
+#define m_FRM_START_INT_EN          (1<<5)
+#define m_LINE_FLAG_INT_EN         (1<<6)
+#define m_BUS_ERR_INT_EN          (1<<7)
+#define m_HOR_START_INT_CLEAR      (1<<8) //auto clear
+#define m_FRM_START_INT_CLEAR      (1<<9)
+#define m_LINE_FLAG_INT_CLEAR      (1<<10)
+#define m_BUS_ERR_INT_CLEAR        (1<<11)
+#define m_LINE_FLAG_NUM                   (0xfff<<12)
+#define v_HOR_START_INT_EN(x)      (((x)&1)<<4)
+#define v_FRM_START_INT_EN(x)      (((x)&1)<<5)
+#define v_LINE_FLAG_INT_EN(x)      (((x)&1)<<6)
+#define v_BUS_ERR_INT_EN(x)       (((x)&1)<<7)
+#define v_HOR_START_INT_CLEAR(x)      (((x)&1)<<8)
+#define v_FRM_START_INT_CLEAR(x)     (((x)&1)<<9)
+#define v_LINE_FLAG_INT_CLEAR(x)     (((x)&1)<<10)
+#define v_BUS_ERR_INT_CLEAR(x)        (((x)&1)<<11)
+#define v_LINE_FLAG_NUM(x)        (((x)&0xfff)<<12)
+
 
 
 //LCDC_MCU_TIMING_CTRL
@@ -456,6 +459,8 @@ struct rk30_lcdc_device{
        void __iomem *reg_vir_base;  // virtual basic address of lcdc register
        u32 reg_phy_base;       // physical basic address of lcdc register
        u32 len;               // physical map length of lcdc register
+
+       unsigned int            irq;
        
        struct clk              *hclk;                          //lcdc AHP clk
        struct clk              *dclk;                          //lcdc dclk
index 0e2aa8e23a9a31d0273fe68b2f8bf2ceeb302598..abd811ab368ff9208cadfbd8c987a579114470ff 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/earlysuspend.h>
 #include <asm/div64.h>
@@ -733,7 +732,8 @@ int init_lcdc_device_driver(struct rk_lcdc_device_driver *def_drv,
        dev_drv->pan_display = def_drv->pan_display;
        dev_drv->suspend = def_drv->suspend;
        dev_drv->resume = def_drv->resume;
-       dev_drv->load_screen = dev_drv->load_screen;
+       dev_drv->load_screen = def_drv->load_screen;
+       init_completion(&dev_drv->frame_done);
        
        return 0;
 }
index c3907d2b80fe822faac03b845c1fc45a448027ed..e1a3ee3452ae97b5fe612e23fc9ea60b6a52471a 100644 (file)
@@ -1,4 +1,4 @@
-/* drivers/video/rk30_fb.h
+/* drivers/video/rk_fb.h
  *
  * Copyright (C) 2010 ROCKCHIP, Inc.
  *
@@ -16,6 +16,9 @@
 #ifndef __ARCH_ARM_MACH_RK30_FB_H
 #define __ARCH_ARM_MACH_RK30_FB_H
 
+
+#include<linux/completion.h>
+
 #define RK30_MAX_LCDC_SUPPORT  4
 #define RK30_MAX_LAYER_SUPPORT 4
 #define RK_MAX_FB_SUPPORT     4
@@ -183,6 +186,9 @@ struct rk_lcdc_device_driver{
        int fb_index_base;                     //the first fb index of the lcdc device
        rk_screen *screen;
        u32 pixclock;
+
+       struct completion  frame_done;
+       
        int (*ioctl)(struct rk_lcdc_device_driver *dev_drv, unsigned int cmd,unsigned long arg,int layer_id);
        int (*suspend)(struct layer_par *layer_par);
        int (*resume)(struct layer_par *layer_par);