rk fb: add get frame time interface that is used for ddr change

This commit is contained in:
zwl
2014-06-11 16:29:24 +08:00
parent d97c2db79b
commit bed6221bcc
3 changed files with 74 additions and 12 deletions

View File

@@ -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){

View File

@@ -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 / 1000;
ft_us = pix_total * pixclock_ns;
return ft_us;
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);
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);

View File

@@ -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;