rk fb: add get frame time interface that is used for ddr change
authorzwl <zwl@rock-chips.com>
Wed, 11 Jun 2014 08:29:24 +0000 (16:29 +0800)
committerzwl <zwl@rock-chips.com>
Wed, 11 Jun 2014 08:29:24 +0000 (16:29 +0800)
drivers/video/rockchip/lcdc/rk3288_lcdc.c
drivers/video/rockchip/rk_fb.c
include/linux/rk_fb.h

index 8b7e51ff261005bc4893548b98eb7f5bb695424c..e6be48c0f98bd1ffe4540be41e27ddb8c143f75f 100755 (executable)
@@ -1271,7 +1271,7 @@ static int rk3288_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
        val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
            v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0) |
            v_DSP_LINE_FLAG_NUM(screen->mode.vsync_len + screen->mode.upper_margin +
-           screen->mode.yres -1);
+           screen->mode.yres);
        lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);  
 #if 0
                 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
@@ -3093,6 +3093,9 @@ int rk3288_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
        if (lcdc_dev->clk_on &&(!dev_drv->suspend_flag)){
                int_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
                if (int_reg & m_LINE_FLAG_INTR_STS) {
+                       lcdc_dev->driver.frame_time.last_framedone_t =
+                                       lcdc_dev->driver.frame_time.framedone_t;
+                       lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
                        lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
                                     v_LINE_FLAG_INTR_CLR(1));
                        ret = RK_LF_STATUS_FC;
@@ -3445,6 +3448,7 @@ static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
            (struct lcdc_device *)dev_id;
        ktime_t timestamp = ktime_get();
        u32 intr0_reg;
+
        intr0_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
 
        if(intr0_reg & m_FS_INTR_STS){
@@ -3464,6 +3468,9 @@ static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
                wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
 
        }else if(intr0_reg & m_LINE_FLAG_INTR_STS){
+               lcdc_dev->driver.frame_time.last_framedone_t =
+                               lcdc_dev->driver.frame_time.framedone_t;
+               lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
                lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
                             v_LINE_FLAG_INTR_CLR(1));
        }else if(intr0_reg & m_BUS_ERROR_INTR_STS){
index e1ed621108a7d26672ccdc6cc034fbc708850220..0ac48005079670cdf6dfb4fb1bdf96ec958933eb 100755 (executable)
@@ -512,27 +512,75 @@ static struct rk_lcdc_driver *rk_get_prmry_lcdc_drv(void)
        return dev_drv;
 }
 
-int rk_fb_get_prmry_screen_ft(void)
+/*
+ * get one frame time of the prmry screen, unit: us
+ */
+u32 rk_fb_get_prmry_screen_ft(void)
 {
        struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
-       uint32_t htotal, vtotal, pix_total, ft_us, pixclock_ns;
+       uint32_t htotal, vtotal, pixclock_ps;
+       u64 pix_total, ft_us;
 
        if (unlikely(!dev_drv))
                return 0;
 
-       pixclock_ns = dev_drv->pixclock / 1000;
+       pixclock_ps = dev_drv->pixclock;
 
-       htotal = (dev_drv->cur_screen->mode.upper_margin +
+       vtotal = (dev_drv->cur_screen->mode.upper_margin +
                 dev_drv->cur_screen->mode.lower_margin +
                 dev_drv->cur_screen->mode.yres +
                 dev_drv->cur_screen->mode.vsync_len);
-       vtotal = (dev_drv->cur_screen->mode.left_margin +
+       htotal = (dev_drv->cur_screen->mode.left_margin +
+                dev_drv->cur_screen->mode.right_margin +
+                dev_drv->cur_screen->mode.xres +
+                dev_drv->cur_screen->mode.hsync_len);
+       pix_total = htotal * vtotal;
+       ft_us = pix_total * pixclock_ps;
+       do_div(ft_us, 1000000);
+       if (dev_drv->frame_time.ft == 0)
+               dev_drv->frame_time.ft = ft_us;
+
+       ft_us = dev_drv->frame_time.framedone_t - dev_drv->frame_time.last_framedone_t;
+       do_div(ft_us, 1000);
+       dev_drv->frame_time.ft = min(dev_drv->frame_time.ft, ft_us);
+       return dev_drv->frame_time.ft;
+}
+
+/*
+ * get the vblanking time of the prmry screen, unit: us
+ */
+u32 rk_fb_get_prmry_screen_vbt(void)
+{
+       struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+       uint32_t htotal, vblank, pixclock_ps;
+       u64 pix_blank, vbt_us;
+
+       if (unlikely(!dev_drv))
+               return 0;
+
+       pixclock_ps = dev_drv->pixclock;
+
+       htotal = (dev_drv->cur_screen->mode.left_margin +
                 dev_drv->cur_screen->mode.right_margin +
                 dev_drv->cur_screen->mode.xres +
                 dev_drv->cur_screen->mode.hsync_len);
-       pix_total = htotal * vtotal / 1000;
-       ft_us = pix_total * pixclock_ns;
-       return ft_us;
+       vblank = (dev_drv->cur_screen->mode.upper_margin +
+                dev_drv->cur_screen->mode.lower_margin +
+                dev_drv->cur_screen->mode.vsync_len);
+       pix_blank = htotal * vblank;
+       vbt_us = pix_blank * pixclock_ps;
+       do_div(vbt_us, 1000000);
+       return (u32)vbt_us;
+}
+
+/*
+ * get the frame done time of the prmry screen, unit: us
+ */
+u64 rk_fb_get_prmry_screen_framedone_t(void)
+{
+       struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+
+       return dev_drv->frame_time.framedone_t;
 }
 
 static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
@@ -591,12 +639,10 @@ bool rk_fb_poll_wait_frame_complete(void)
                }
                return false;
        }
-
        while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FR) && --timeout)
                ;
        while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FC) && --timeout)
                ;
-
        if (likely(dev_drv)) {
                if (dev_drv->ops->set_irq_to_cpu)
                        dev_drv->ops->set_irq_to_cpu(dev_drv, 1);
index e00fc7145927b05b40442196e9491e15b523b309..e5b31a74486bdfb807fa23957c3efd7c193f01d0 100755 (executable)
@@ -103,7 +103,9 @@ extern struct ion_client *rockchip_ion_client_create(const char * name);
 #endif
 
 extern int rk_fb_poll_prmry_screen_vblank(void);
-extern int rk_fb_get_prmry_screen_ft(void);
+extern u32 rk_fb_get_prmry_screen_ft(void);
+extern u32 rk_fb_get_prmry_screen_vbt(void);
+extern u64 rk_fb_get_prmry_screen_framedone_t(void);
 extern bool rk_fb_poll_wait_frame_complete(void);
 
 /********************************************************************
@@ -242,6 +244,12 @@ struct rk_fb_rgb {
        struct fb_bitfield transp;
 };
 
+struct rk_fb_frame_time {
+       u64 last_framedone_t;
+       u64 framedone_t;
+       u32 ft;
+};
+
 struct rk_fb_vsync {
        wait_queue_head_t wait;
        ktime_t timestamp;
@@ -533,6 +541,7 @@ struct rk_lcdc_driver {
        spinlock_t cpl_lock;    //lock for completion  frame done
        int first_frame;
        struct rk_fb_vsync vsync_info;
+       struct rk_fb_frame_time frame_time;
        int wait_fs;            //wait for new frame start in kernel
        struct sw_sync_timeline *timeline;
        int                     timeline_max;