From: zwl Date: Fri, 9 May 2014 01:20:26 +0000 (+0800) Subject: rk3288 lcdc: add support overscan X-Git-Tag: firefly_0821_release~5321 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5009b35348716e6cc2a9b39228aa577444a4c27d;p=firefly-linux-kernel-4.4.55.git rk3288 lcdc: add support overscan --- diff --git a/drivers/video/rockchip/lcdc/rk3288_lcdc.c b/drivers/video/rockchip/lcdc/rk3288_lcdc.c index a4e053a9a7ad..483bb4cd145a 100755 --- a/drivers/video/rockchip/lcdc/rk3288_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3288_lcdc.c @@ -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)) { diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 809a1b78df6d..a1b7c4cf2e54 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -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); diff --git a/drivers/video/rockchip/rkfb_sysfs.c b/drivers/video/rockchip/rkfb_sysfs.c index ed8d93359232..12788397ea06 100755 --- a/drivers/video/rockchip/rkfb_sysfs.c +++ b/drivers/video/rockchip/rkfb_sysfs.c @@ -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) diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index e0655cfa4262..4d57d110daea 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -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;