rk3288 lcdc: add support overscan
authorzwl <zwl@rock-chips.com>
Fri, 9 May 2014 01:20:26 +0000 (09:20 +0800)
committerzwl <zwl@rock-chips.com>
Fri, 9 May 2014 01:20:50 +0000 (09:20 +0800)
drivers/video/rockchip/lcdc/rk3288_lcdc.c
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_fb.h

index a4e053a9a7ad59fab7bc1555f35cc83896ca6dcc..483bb4cd145a7951350d2a8b8df42009aec60303 100755 (executable)
@@ -929,10 +929,11 @@ static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
        
        h_total = hsync_len + left_margin  + x_res + right_margin;
        v_total = vsync_len + upper_margin + y_res + lower_margin;
-       screen->post_dsp_stx=0;
-       screen->post_dsp_sty=0;
-       screen->post_xsize =x_res;
-       screen->post_ysize = y_res;
+
+       screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
+       screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
+       screen->post_xsize = x_res * (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
+       screen->post_ysize = y_res * (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
        
        spin_lock(&lcdc_dev->reg_lock);
        if (likely(lcdc_dev->clk_on)) {
index 809a1b78df6dd67d235118c1e7bfb3e05fd83f45..a1b7c4cf2e54920be29baf88ee9b3486b2b39701 100755 (executable)
@@ -2861,6 +2861,10 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
        mutex_init(&dev_drv->fb_win_id_mutex);
        dev_drv->ops->fb_win_remap(dev_drv, FB_DEFAULT_ORDER);
        dev_drv->first_frame = 1;
+       dev_drv->overscan.left = 100;
+       dev_drv->overscan.top = 100;
+       dev_drv->overscan.right = 100;
+       dev_drv->overscan.bottom = 100;
        rk_disp_pwr_ctr_parse_dt(dev_drv);
        if (dev_drv->prop == PRMRY) {
                rk_fb_set_prmry_screen(screen);
index ed8d93359232d5b328b2bacd4c417a8d3b7a834b..12788397ea06a66ef1e278ff786091880f8e35dc 100755 (executable)
@@ -371,6 +371,80 @@ static ssize_t set_dsp_bcs(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
+static ssize_t show_scale(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       struct rk_lcdc_driver *dev_drv =
+           (struct rk_lcdc_driver *)fbi->par;
+       return snprintf(buf, PAGE_SIZE, "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
+               (dev_drv->overscan.left + dev_drv->overscan.right)/2,
+               (dev_drv->overscan.top + dev_drv->overscan.bottom)/2,
+               dev_drv->overscan.left, dev_drv->overscan.top,
+               dev_drv->overscan.right, dev_drv->overscan.bottom);
+}
+
+static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       struct rk_lcdc_driver *dev_drv =
+           (struct rk_lcdc_driver *)fbi->par;
+       u32 left, top, right, bottom;
+
+       if (!strncmp(buf, "overscan", 8)) {
+               sscanf(buf, "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
+               if (left > 0 && left <= 100)
+                       dev_drv->overscan.left = left;
+               if (top > 0 && top <= 100)
+                       dev_drv->overscan.top = top;
+               if (right > 0 && right <= 100)
+                       dev_drv->overscan.right = right;
+               if (bottom > 0 && bottom <= 100)
+                       dev_drv->overscan.bottom = bottom;
+       } else if (!strncmp(buf, "left", 4)) {
+               sscanf(buf, "left=%d", &left);
+               if (left > 0 && left <= 100)
+                       dev_drv->overscan.left = left;
+       } else if (!strncmp(buf, "top", 3)) {
+               sscanf(buf, "top=%d", &top);
+               if (top > 0 && top <= 100)
+                       dev_drv->overscan.top = top;
+       } else if (!strncmp(buf, "right", 5)) {
+               sscanf(buf, "right=%d", &right);
+               if (right > 0 && right <= 100)
+                       dev_drv->overscan.right = right;
+       } else if (!strncmp(buf, "bottom", 6)) {
+               sscanf(buf, "bottom=%d", &bottom);
+               if (bottom > 0 && bottom <= 100)
+                       dev_drv->overscan.bottom = bottom;
+       } else if (!strncmp(buf, "xscale", 6)) {
+               sscanf(buf, "xscale=%d", &left);
+               if (left > 0 && left <= 100) {
+                       dev_drv->overscan.left = left;
+                       dev_drv->overscan.right = left;
+               }
+       } else if (!strncmp(buf, "yscale", 6)) {
+               sscanf(buf, "yscale=%d", &left);
+               if (left > 0 && left <= 100) {
+                       dev_drv->overscan.top = left;
+                       dev_drv->overscan.bottom = left;
+               }
+       } else {
+               sscanf(buf, "%d", &left);
+               if (left > 0 && left <= 100) {
+                       dev_drv->overscan.left = left;
+                       dev_drv->overscan.right = left;
+                       dev_drv->overscan.top = left;
+                       dev_drv->overscan.bottom = left;
+               }
+       }
+//     printk("%d %d %d %d\n", dev_drv->overscan.left, dev_drv->overscan.top, dev_drv->overscan.right, dev_drv->overscan.bottom);
+       dev_drv->ops->load_screen(dev_drv, 1);
+       dev_drv->ops->cfg_done(dev_drv);
+       return count;
+}
+
 static struct device_attribute rkfb_attrs[] = {
        __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
        __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
@@ -385,6 +459,7 @@ static struct device_attribute rkfb_attrs[] = {
        __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
        __ATTR(hue, S_IRUGO | S_IWUSR, show_hue, set_hue),
        __ATTR(bcs, S_IRUGO | S_IWUSR, show_dsp_bcs, set_dsp_bcs),
+       __ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
 };
 
 int rkfb_create_sysfs(struct fb_info *fbi)
index e0655cfa42629a27119997190b22824c1529989a..4d57d110daea1b91124f2a577e1a19d9f6bb8c4e 100755 (executable)
@@ -475,6 +475,13 @@ struct rk_fb_reg_data {
        //int     fence_wait_begin;
 };
 
+struct overscan {
+       unsigned char left;
+       unsigned char top;
+       unsigned char right;
+       unsigned char bottom;
+};
+
 struct rk_lcdc_driver {
        char name[6];
        int id;
@@ -489,6 +496,7 @@ struct rk_lcdc_driver {
        struct rk_screen *screen0;      //some platform have only one lcdc,but extend
        struct rk_screen *screen1;      //two display devices for dual display,such as rk2918,rk2928
        struct rk_screen *cur_screen;   //screen0 is primary screen ,like lcd panel,screen1 is  extend screen,like hdmi
+       struct overscan overscan;
        u32 pixclock;
 
        char fb0_win_id;