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 |
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;
(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){
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){
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)
}
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);
#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);
/********************************************************************
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;
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;