rk30 fb:add sys interface to change fps
authoryxj <yxj@rock-chips.com>
Mon, 30 Apr 2012 08:44:48 +0000 (16:44 +0800)
committeryxj <yxj@rock-chips.com>
Mon, 30 Apr 2012 08:46:35 +0000 (16:46 +0800)
the path is  sys/class/graphics/fbx/fps`

drivers/video/rockchip/chips/rk30_lcdc.c
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_fb.h
include/linux/rk_screen.h

index b18a10f0df133984e87cd07caf1c926dfd8603f8..9ce62be385bfffb20e027e78cf53d7633871691e 100644 (file)
@@ -101,6 +101,8 @@ static int rk30_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscre
        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;
@@ -204,7 +206,13 @@ static int rk30_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscre
        }
        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)
@@ -312,7 +320,7 @@ static  int win0_display(struct rk30_lcdc_device *lcdc_dev,struct layer_par *par
                LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
        }
        spin_unlock(&lcdc_dev->reg_lock);
-       
+
        return 0;
        
 }
@@ -570,7 +578,7 @@ int rk30_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id)
        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");
@@ -634,7 +642,7 @@ swap:1 win0 on the top of win1
 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;
@@ -660,12 +668,48 @@ static int rk30_ovl_mgr(struct rk_lcdc_device_driver *dev_drv,int swap,bool set)
 
        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);
@@ -730,8 +774,9 @@ static struct rk_lcdc_device_driver lcdc_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)
index 8a9a78bd531a978ea702cb89355c35a7ed4afc78..05d57ec1f14339bf4fbffe8dacd1dd38e679fb61 100644 (file)
@@ -778,6 +778,7 @@ static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
        dev_drv->get_layer_state= def_drv->get_layer_state;
        dev_drv->get_disp_info  = def_drv->get_disp_info;
        dev_drv->ovl_mgr        = def_drv->ovl_mgr;
+       dev_drv->fps_mgr        = def_drv->fps_mgr;
        init_layer_par(dev_drv);
        init_completion(&dev_drv->frame_done);
        spin_lock_init(&dev_drv->cpl_lock);
index 17f8fafa746a5b7a24c5a2a64401dd5dcc08fbf1..fd3edf96aa4d50d4ef690b89d806b54de48afc20 100644 (file)
@@ -152,6 +152,46 @@ static ssize_t set_overlay(struct device *dev,struct device_attribute *attr,
        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),
@@ -159,6 +199,7 @@ static struct device_attribute rkfb_attrs[] = {
        __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)
index bc909f9ee470a49bf54bc5832265f456893a1bc4..1cee768e66a4ccb4fa2739c3d27c12cdf31cf3a9 100644 (file)
@@ -212,6 +212,7 @@ struct rk_lcdc_device_driver{
        int (*load_screen)(struct rk_lcdc_device_driver *dev_drv, bool initscreen);
        int (*get_layer_state)(struct rk_lcdc_device_driver *dev_drv,int layer_id);
        int (*ovl_mgr)(struct rk_lcdc_device_driver *dev_drv,int swap,bool set);  //overlay manager
+       int (*fps_mgr)(struct rk_lcdc_device_driver *dev_drv,int fps,bool set);
        
 };
 
index d6ebe7bcfea26dec03a5edc24a34b04368818502..efa47e53cde0d2868cbceda4719927c923f30bc1 100644 (file)
@@ -92,19 +92,19 @@ struct rk29lcd_info {
 
 /* 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;
@@ -112,6 +112,7 @@ typedef struct rk29fb_screen {
        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;
@@ -125,34 +126,34 @@ typedef struct rk29fb_screen {
        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);