rk fb: add rk31xx interface rk_fb_poll_wait_frame_complete for ddr and fps freq

This commit is contained in:
hjc
2013-08-05 16:30:14 +08:00
parent a98d749559
commit d2f82fa2f0
5 changed files with 176 additions and 21 deletions

View File

@@ -706,8 +706,12 @@ int rk3066b_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id
if((dev_drv->first_frame)) //this is the first frame of the system ,enable frame start interrupt
{
dev_drv->first_frame = 0;
LcdMskReg(lcdc_dev,INT_STATUS,m_FRM_STARTCLEAR | m_FRM_STARTMASK ,
v_FRM_STARTCLEAR(1) | v_FRM_STARTMASK(0));
LcdMskReg(lcdc_dev,INT_STATUS,m_HOR_STARTMASK | m_FRM_STARTMASK | m_SCANNING_MASK |
m_HOR_STARTCLEAR | m_FRM_STARTCLEAR |m_SCANNING_CLEAR | m_SCAN_LINE_NUM,
v_HOR_STARTMASK(1) | v_FRM_STARTMASK(0) | v_SCANNING_MASK(0) |
v_HOR_STARTCLEAR(1) | v_FRM_STARTCLEAR(1) | v_SCANNING_CLEAR(1) |
//v_SCANNING_CLEAR(screen->vsync_len + screen->upper_margin+screen->y_res -1));
v_SCAN_LINE_NUM(screen->vsync_len + screen->upper_margin+screen->y_res -1));
LCDC_REG_CFG_DONE(); // write any value to REG_CFG_DONE let config become effective
}
@@ -1120,7 +1124,7 @@ int rk3066b_lcdc_early_resume(struct rk_lcdc_device_driver *dev_drv)
LcdMskReg(lcdc_dev, INT_STATUS, m_SCANNING_CLEAR | m_FRM_STARTCLEAR | m_HOR_STARTCLEAR |
m_SCANNING_MASK | m_HOR_STARTMASK | m_FRM_STARTMASK ,
v_SCANNING_CLEAR(1) | v_FRM_STARTCLEAR(1) | v_HOR_STARTCLEAR(1) |
v_SCANNING_MASK(1) | v_FRM_STARTMASK(0) | v_HOR_STARTMASK(1));
v_SCANNING_MASK(0) | v_FRM_STARTMASK(0) | v_HOR_STARTMASK(1));
LCDC_REG_CFG_DONE();
}
lcdc_dev->clk_on = 1;
@@ -1137,6 +1141,9 @@ int rk3066b_lcdc_early_resume(struct rk_lcdc_device_driver *dev_drv)
static irqreturn_t rk3066b_lcdc_isr(int irq, void *dev_id)
{
struct rk3066b_lcdc_device *lcdc_dev = (struct rk3066b_lcdc_device *)dev_id;
u32 int_reg = LcdRdReg(lcdc_dev,INT_STATUS);
if(int_reg & m_FRM_START){
ktime_t timestamp = ktime_get();
LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_STARTCLEAR, v_FRM_STARTCLEAR(1));
@@ -1154,7 +1161,10 @@ static irqreturn_t rk3066b_lcdc_isr(int irq, void *dev_id)
lcdc_dev->driver.vsync_info.timestamp = timestamp;
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
}
else if(int_reg & m_SCANNING_FLAG){
LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_STARTCLEAR, v_SCANNING_CLEAR(1));
}
return IRQ_HANDLED;
}
@@ -1191,6 +1201,33 @@ static int rk3066b_set_dsp_lut(struct rk_lcdc_device_driver *dev_drv,int *lut)
return ret;
}
int rk3066b_lcdc_poll_vblank(struct rk_lcdc_device_driver * dev_drv)
{
struct rk3066b_lcdc_device *lcdc_dev =
container_of(dev_drv,struct rk3066b_lcdc_device,driver);
u32 int_reg ;
int ret;
//spin_lock(&lcdc_dev->reg_lock);
if(lcdc_dev->clk_on)
{
int_reg = LcdRdReg(lcdc_dev,INT_STATUS);
if(int_reg & m_SCANNING_FLAG)
{
LcdMskReg(lcdc_dev, INT_STATUS, m_SCANNING_CLEAR,v_SCANNING_CLEAR(1));
ret = RK_LF_STATUS_FC;
}
else
ret = RK_LF_STATUS_FR;
}
else
{
ret = RK_LF_STATUS_NC;
}
//spin_unlock(&lcdc_dev->reg_lock);
return ret;
}
static struct layer_par lcdc_layer[] = {
[0] = {
@@ -1225,6 +1262,7 @@ static struct rk_lcdc_device_driver lcdc_driver = {
.fb_get_layer = rk3066b_fb_get_layer,
.fb_layer_remap = rk3066b_fb_layer_remap,
.set_dsp_lut = rk3066b_set_dsp_lut,
.poll_vblank = rk3066b_lcdc_poll_vblank,
};
#ifdef CONFIG_PM
static int rk3066b_lcdc_suspend(struct platform_device *pdev, pm_message_t state)

View File

@@ -944,8 +944,12 @@ static int rk3188_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int la
if((dev_drv->first_frame)) //this is the first frame of the system ,enable frame start interrupt
{
dev_drv->first_frame = 0;
lcdc_msk_reg(lcdc_dev,INT_STATUS,m_FS_INT_CLEAR |m_FS_INT_EN ,
v_FS_INT_CLEAR(1) | v_FS_INT_EN(1));
lcdc_msk_reg(lcdc_dev,INT_STATUS,m_HS_INT_CLEAR | m_HS_INT_EN |
m_FS_INT_CLEAR | m_FS_INT_EN | m_LF_INT_EN | m_LF_INT_CLEAR |
m_LF_INT_NUM | m_BUS_ERR_INT_CLEAR | m_BUS_ERR_INT_EN,
v_FS_INT_CLEAR(1) | v_FS_INT_EN(1) | v_HS_INT_CLEAR(1) |
v_HS_INT_EN(0) | v_LF_INT_CLEAR(1) | v_LF_INT_EN(1) |
v_LF_INT_NUM(screen->vsync_len + screen->upper_margin+screen->y_res -1));
lcdc_cfg_done(lcdc_dev); // write any value to REG_CFG_DONE let config become effective
}
@@ -1425,6 +1429,33 @@ static int rk3188_lcdc_dpi_status(struct rk_lcdc_device_driver *dev_drv)
return ovl;
}
int rk3188_lcdc_poll_vblank(struct rk_lcdc_device_driver * dev_drv)
{
struct rk3188_lcdc_device *lcdc_dev =
container_of(dev_drv,struct rk3188_lcdc_device,driver);
u32 int_reg ;
int ret;
//spin_lock(&lcdc_dev->reg_lock);
if(lcdc_dev->clk_on)
{
int_reg = lcdc_readl(lcdc_dev,INT_STATUS);
if(int_reg & m_LF_INT_STA)
{
lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,v_LF_INT_CLEAR(1));
ret = RK_LF_STATUS_FC;
}
else
ret = RK_LF_STATUS_FR;
}
else
{
ret = RK_LF_STATUS_NC;
}
//spin_unlock(&lcdc_dev->reg_lock);
return ret;
}
static struct layer_par lcdc_layer[] = {
[0] = {
.name = "win0",
@@ -1459,6 +1490,7 @@ static struct rk_lcdc_device_driver lcdc_driver = {
.fb_get_layer = rk3188_fb_get_layer,
.fb_layer_remap = rk3188_fb_layer_remap,
.set_dsp_lut = rk3188_set_dsp_lut,
.poll_vblank = rk3188_lcdc_poll_vblank,
.dpi_open = rk3188_lcdc_dpi_open,
.dpi_layer_sel = rk3188_lcdc_dpi_layer_sel,
.dpi_status = rk3188_lcdc_dpi_status,
@@ -1469,18 +1501,26 @@ static irqreturn_t rk3188_lcdc_isr(int irq, void *dev_id)
struct rk3188_lcdc_device *lcdc_dev =
(struct rk3188_lcdc_device *)dev_id;
ktime_t timestamp = ktime_get();
lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR, v_FS_INT_CLEAR(1));
if(lcdc_dev->driver.wait_fs) //three buffer ,no need to wait for sync
u32 int_reg = lcdc_readl(lcdc_dev,INT_STATUS);
if(int_reg & m_FS_INT_STA)
{
spin_lock(&(lcdc_dev->driver.cpl_lock));
complete(&(lcdc_dev->driver.frame_done));
spin_unlock(&(lcdc_dev->driver.cpl_lock));
timestamp = ktime_get();
lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,v_FS_INT_CLEAR(1));
if(lcdc_dev->driver.wait_fs) //three buffer ,no need to wait for sync
{
spin_lock(&(lcdc_dev->driver.cpl_lock));
complete(&(lcdc_dev->driver.frame_done));
spin_unlock(&(lcdc_dev->driver.cpl_lock));
}
lcdc_dev->driver.vsync_info.timestamp = timestamp;
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
}
else if(int_reg & m_LF_INT_STA)
{
lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,v_LF_INT_CLEAR(1));
}
lcdc_dev->driver.vsync_info.timestamp = timestamp;
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
return IRQ_HANDLED;
}

View File

@@ -183,7 +183,7 @@
#define m_FS_INT_CLEAR (1<<9)
#define m_LF_INT_CLEAR (1<<10)
#define m_BUS_ERR_INT_CLEAR (1<<11)
#define m_LINE_FLAG_NUM (0xfff<<12)
#define m_LF_INT_NUM (0xfff<<12)
#define v_HS_INT_EN(x) (((x)&1)<<4)
#define v_FS_INT_EN(x) (((x)&1)<<5)
#define v_LF_INT_EN(x) (((x)&1)<<6)
@@ -192,7 +192,7 @@
#define v_FS_INT_CLEAR(x) (((x)&1)<<9)
#define v_LF_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)
#define v_LF_INT_NUM(x) (((x)&0xfff)<<12)
#define ALPHA_CTRL (0x14)

View File

@@ -29,11 +29,14 @@
#include <linux/earlysuspend.h>
#include <asm/div64.h>
#include <asm/uaccess.h>
#include<linux/rk_fb.h>
#include <linux/rk_fb.h>
#include <plat/ipp.h>
#include "hdmi/rk_hdmi.h"
#include <linux/linux_logo.h>
#include <mach/clock.h>
#include <linux/clk.h>
void rk29_backlight_set(bool on);
bool rk29_get_backlight_status(void);
@@ -117,9 +120,14 @@ struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
static struct rk_lcdc_device_driver * rk_get_prmry_lcdc_drv(void)
{
struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
struct rk_fb_inf *inf = NULL;
struct rk_lcdc_device_driver *dev_drv = NULL;
int i = 0;
if(likely(g_fb_pdev))
inf = platform_get_drvdata(g_fb_pdev);
else
return NULL;
for(i = 0; i < inf->num_lcdc;i++)
{
@@ -133,12 +141,41 @@ static struct rk_lcdc_device_driver * rk_get_prmry_lcdc_drv(void)
return dev_drv;
}
//get one frame time
int rk_fb_get_prmry_screen_ft(void)
{
struct rk_lcdc_device_driver *dev_drv = rk_get_prmry_lcdc_drv();
uint32_t pix_count,ft_us,dclk_mhz;
if (0 == dev_drv->id)
dclk_mhz = clk_get_rate(clk_get(NULL, "dclk_lcdc0"))/(1000*1000);
else
dclk_mhz = clk_get_rate(clk_get(NULL, "dclk_lcdc1"))/(1000*1000);
pix_count = (dev_drv->cur_screen->upper_margin + dev_drv->cur_screen->lower_margin + dev_drv->cur_screen->y_res +dev_drv->cur_screen->vsync_len)*
(dev_drv->cur_screen->left_margin + dev_drv->cur_screen->right_margin + dev_drv->cur_screen->x_res + dev_drv->cur_screen->hsync_len); // one frame time ,(pico seconds)
ft_us = pix_count / dclk_mhz;
if(likely(dev_drv))
return ft_us;
else
return 0;
}
static struct rk_lcdc_device_driver * rk_get_extend_lcdc_drv(void)
{
struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
struct rk_fb_inf *inf = NULL;
struct rk_lcdc_device_driver *dev_drv = NULL;
int i = 0;
if(likely(g_fb_pdev))
inf = platform_get_drvdata(g_fb_pdev);
else
return NULL;
for(i = 0; i < inf->num_lcdc; i++)
{
if(inf->lcdc_dev_drv[i]->screen_ctr_info->prop == EXTEND)
@@ -163,6 +200,32 @@ u32 rk_fb_get_prmry_screen_pixclock(void)
struct rk_lcdc_device_driver *dev_drv = rk_get_prmry_lcdc_drv();
return dev_drv->pixclock;
}
int rk_fb_poll_prmry_screen_vblank(void)
{
struct rk_lcdc_device_driver *dev_drv = rk_get_prmry_lcdc_drv();
if(likely(dev_drv))
{
if(dev_drv->poll_vblank)
return dev_drv->poll_vblank(dev_drv);
else
return RK_LF_STATUS_NC;
}
else
return RK_LF_STATUS_NC;
}
bool rk_fb_poll_wait_frame_complete(void)
{
uint32_t timeout = MAX_TIMEOUT;
if(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_NC)
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);
return true;
}
static int rk_fb_open(struct fb_info *info,int user)
{
struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
@@ -1409,6 +1472,8 @@ static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
dev_drv->lcdc_hdmi_process = def_drv->lcdc_hdmi_process;
if(def_drv->lcdc_reg_update)
dev_drv->lcdc_reg_update = def_drv->lcdc_reg_update;
if(def_drv->poll_vblank)
dev_drv->poll_vblank = def_drv->poll_vblank;
if(def_drv->dpi_open)
dev_drv->dpi_open = def_drv->dpi_open;
if(def_drv->dpi_layer_sel)

View File

@@ -62,6 +62,17 @@
#define RK_FBIOPUT_COLOR_KEY_CFG 0x4626
/**rk fb events**/
#define RK_LF_STATUS_FC 0xef
#define RK_LF_STATUS_FR 0xee
#define RK_LF_STATUS_NC 0xfe
#define MAX_TIMEOUT (1600000UL << 6) //>0.64s
extern int rk_fb_poll_prmry_screen_vblank(void);
extern int rk_fb_get_prmry_screen_ft(void);
extern bool rk_fb_poll_wait_frame_complete(void);
/********************************************************************
** display output interface supported by rockchip lcdc *
********************************************************************/
@@ -280,6 +291,7 @@ struct rk_lcdc_device_driver{
int (*set_dsp_lut)(struct rk_lcdc_device_driver *dev_drv,int *lut);
int (*read_dsp_lut)(struct rk_lcdc_device_driver *dev_drv,int *lut);
int (*lcdc_hdmi_process)(struct rk_lcdc_device_driver *dev_drv,int mode); //some lcdc need to some process in hdmi mode
int (*poll_vblank)(struct rk_lcdc_device_driver *dev_drv);
int (*lcdc_rst)(struct rk_lcdc_device_driver *dev_drv);
int (*dpi_open)(struct rk_lcdc_device_driver *dev_drv,bool open);
int (*dpi_layer_sel)(struct rk_lcdc_device_driver *dev_drv,int layer_id);