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
}
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;
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));
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;
}
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] = {
.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)
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
}
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",
.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,
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)
+ {
+ 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)
{
- spin_lock(&(lcdc_dev->driver.cpl_lock));
- complete(&(lcdc_dev->driver.frame_done));
- spin_unlock(&(lcdc_dev->driver.cpl_lock));
+ 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;
}
#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)
#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)
#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);
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++)
{
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)
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;
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)
#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 *
********************************************************************/
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);