int ret = -EINVAL;
struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
rk_screen *screen = lcdc_dev->screen;
+ u64 ft;
+ int fps;
u16 face;
u16 mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend;
u16 right_margin = screen->right_margin;
}
lcdc_dev->driver.pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
clk_enable(lcdc_dev->dclk);
- printk("%s: dclk:%lu ",lcdc_dev->driver.name,clk_get_rate(lcdc_dev->dclk));
+
+ ft = (u64)(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
+ (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len)*
+ (dev_drv->pixclock); // one frame time ,(pico seconds)
+ fps = div64_u64(1000000000000llu,ft);
+ screen->ft = 1000/fps;
+ printk("%s: dclk:%lu>>fps:%d ",lcdc_dev->driver.name,clk_get_rate(lcdc_dev->dclk),fps);
if(initscreen)
{
if(screen->lcdc_aclk)
LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
}
spin_unlock(&lcdc_dev->reg_lock);
-
+
return 0;
}
spin_lock_irqsave(&dev_drv->cpl_lock,flags);
init_completion(&dev_drv->frame_done);
spin_unlock_irqrestore(&dev_drv->cpl_lock,flags);
- timeout = wait_for_completion_interruptible_timeout(&dev_drv->frame_done,msecs_to_jiffies(25));
+ timeout = wait_for_completion_interruptible_timeout(&dev_drv->frame_done,msecs_to_jiffies(dev_drv->screen->ft+5));
if(!timeout)
{
printk(KERN_ERR "wait for new frame start time out!\n");
set : 1 set overlay
0 get overlay state
************************************/
-static int rk30_ovl_mgr(struct rk_lcdc_device_driver *dev_drv,int swap,bool set)
+static int rk30_lcdc_ovl_mgr(struct rk_lcdc_device_driver *dev_drv,int swap,bool set)
{
struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
int ovl;
return ovl;
}
-static int rk30_get_disp_info(struct rk_lcdc_device_driver *dev_drv,int layer_id)
+static int rk30_lcdc_get_disp_info(struct rk_lcdc_device_driver *dev_drv,int layer_id)
{
struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
return 0;
}
+
+/*******************************************
+lcdc fps manager,set or get lcdc fps
+set:0 get
+ 1 set
+********************************************/
+static int rk30_lcdc_fps_mgr(struct rk_lcdc_device_driver *dev_drv,int fps,bool set)
+{
+ struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
+ rk_screen * screen = dev_drv->screen;
+ u64 ft = 0;
+ u32 dotclk;
+ int ret;
+
+ if(set)
+ {
+ ft = div_u64(1000000000000llu,fps);
+ dev_drv->pixclock = div_u64(ft,(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
+ (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len));
+ dotclk = div_u64(1000000000000llu,dev_drv->pixclock);
+ ret = clk_set_rate(lcdc_dev->dclk, dotclk);
+ if(ret)
+ {
+ printk(KERN_ERR ">>>>>> set lcdc%d dclk failed\n",lcdc_dev->id);
+ }
+ dev_drv->pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+
+ }
+
+ ft = (u64)(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
+ (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len)*
+ (dev_drv->pixclock); // one frame time ,(pico seconds)
+ fps = div64_u64(1000000000000llu,ft);
+ screen->ft = 1000/fps ; //one frame time in ms
+ return fps;
+}
int rk30_lcdc_early_suspend(struct rk_lcdc_device_driver *dev_drv)
{
struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
.pan_display = rk30_lcdc_pan_display,
.load_screen = rk30_load_screen,
.get_layer_state = rk30_lcdc_get_layer_state,
- .ovl_mgr = rk30_ovl_mgr,
- .get_disp_info = rk30_get_disp_info,
+ .ovl_mgr = rk30_lcdc_ovl_mgr,
+ .get_disp_info = rk30_lcdc_get_disp_info,
+ .fps_mgr = rk30_lcdc_fps_mgr,
};
#ifdef CONFIG_PM
static int rk30_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
return count;
}
+
+static ssize_t show_fps(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct rk_lcdc_device_driver * dev_drv =
+ (struct rk_lcdc_device_driver * )fbi->par;
+ int fps;
+ fps = dev_drv->fps_mgr(dev_drv,0,0);
+ if(fps < 0)
+ {
+ return fps;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "fps:%d\n",fps);
+
+}
+
+static ssize_t set_fps(struct device *dev,struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct rk_lcdc_device_driver * dev_drv =
+ (struct rk_lcdc_device_driver * )fbi->par;
+ int fps;
+ int ret;
+ ret = kstrtoint(buf, 0, &fps);
+ if(ret)
+ {
+ return ret;
+ }
+ ret = dev_drv->fps_mgr(dev_drv,fps,1);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ return count;
+}
+
static struct device_attribute rkfb_attrs[] = {
__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
__ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
__ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
__ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
+ __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
};
int rkfb_create_sysfs(struct fb_info *fbi)
/* Screen description */
typedef struct rk29fb_screen {
- /* screen type & hardware connect format & out face */
- u16 type;
- u16 hw_format;
- u16 face;
+ /* screen type & hardware connect format & out face */
+ u16 type;
+ u16 hw_format;
+ u16 face;
/* Screen size */
u16 x_res;
u16 y_res;
- u16 width;
- u16 height;
+ u16 width;
+ u16 height;
- u32 mode;
- /* Timing */
+ u32 mode;
+ /* Timing */
u32 pixclock;
u16 left_margin;
u16 right_margin;
u16 upper_margin;
u16 lower_margin;
u16 vsync_len;
+ u8 ft; //the time need to display one frame,in ms
#ifdef CONFIG_HDMI_DUAL_DISP
/* Scaler mode Timing */
u32 s_pixclock;
u16 s_vsync_st;
#endif
u8 hdmi_resolution;
- /* mcu need */
+ /* mcu need */
u8 mcu_wrperiod;
- u8 mcu_usefmk;
- u8 mcu_frmrate;
+ u8 mcu_usefmk;
+ u8 mcu_frmrate;
- /* Pin polarity */
+ /* Pin polarity */
u8 pin_hsync;
u8 pin_vsync;
u8 pin_den;
u8 pin_dclk;
- u32 lcdc_aclk;
+ u32 lcdc_aclk;
u8 pin_dispon;
/* Swap rule */
- u8 swap_rb;
- u8 swap_rg;
- u8 swap_gb;
- u8 swap_delta;
- u8 swap_dumy;
-
- /* Operation function*/
- int (*init)(void);
- int (*standby)(u8 enable);
- int (*refresh)(u8 arg);
- int (*scandir)(u16 dir);
- int (*disparea)(u8 area);
- int (*sscreen_get)(struct rk29fb_screen *screen, u8 resolution);
- int (*sscreen_set)(struct rk29fb_screen *screen, bool type);// 1: use scaler 0:bypass
+ u8 swap_rb;
+ u8 swap_rg;
+ u8 swap_gb;
+ u8 swap_delta;
+ u8 swap_dumy;
+
+ /* Operation function*/
+ int (*init)(void);
+ int (*standby)(u8 enable);
+ int (*refresh)(u8 arg);
+ int (*scandir)(u16 dir);
+ int (*disparea)(u8 area);
+ int (*sscreen_get)(struct rk29fb_screen *screen, u8 resolution);
+ int (*sscreen_set)(struct rk29fb_screen *screen, bool type);// 1: use scaler 0:bypass
} rk_screen;
extern void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info);