mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
rk fb: add rk31xx interface rk_fb_poll_wait_frame_complete for ddr and fps freq
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user