From bed6221bccfbf07e67474879cf87ac06a0780870 Mon Sep 17 00:00:00 2001 From: zwl Date: Wed, 11 Jun 2014 16:29:24 +0800 Subject: [PATCH] rk fb: add get frame time interface that is used for ddr change --- drivers/video/rockchip/lcdc/rk3288_lcdc.c | 9 +++- drivers/video/rockchip/rk_fb.c | 66 +++++++++++++++++++---- include/linux/rk_fb.h | 11 +++- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/drivers/video/rockchip/lcdc/rk3288_lcdc.c b/drivers/video/rockchip/lcdc/rk3288_lcdc.c index 8b7e51ff2610..e6be48c0f98b 100755 --- a/drivers/video/rockchip/lcdc/rk3288_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3288_lcdc.c @@ -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){ diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index e1ed621108a7..0ac480050796 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -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); diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index e00fc7145927..e5b31a74486b 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -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; -- 2.34.1