From 3ac820be0591bbf26bbbee71332c9b9dfff4c92d Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Sat, 2 Aug 2014 19:03:44 +0800 Subject: [PATCH] rk3036 lcdc: add set_overscan callback function to set overscan. --- drivers/video/rockchip/lcdc/rk3036_lcdc.c | 73 +++++++++++++++------ drivers/video/rockchip/rkfb_sysfs.c | 5 +- include/linux/rk_fb.h | 80 ++++++++++++----------- 3 files changed, 97 insertions(+), 61 deletions(-) diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.c b/drivers/video/rockchip/lcdc/rk3036_lcdc.c index 32e01b9de214..08ab74b48b7f 100755 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.c @@ -255,8 +255,8 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev, v_DSP_STX(win->area[0].dsp_stx) | v_DSP_STY(win->area[0].dsp_sty)); lcdc_writel(lcdc_dev, WIN0_DSP_INFO, - v_DSP_WIDTH(win->area[0].xsize) | - v_DSP_HEIGHT(win->area[0].ysize)); + v_DSP_WIDTH(win->post_cfg.xsize) | + v_DSP_HEIGHT(win->post_cfg.ysize)); lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr); @@ -279,8 +279,8 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev, v_ACT_WIDTH(win->area[0].xact) | v_ACT_HEIGHT(win->area[0].yact)); lcdc_writel(lcdc_dev, WIN1_DSP_INFO, - v_DSP_WIDTH(win->area[0].xsize) | - v_DSP_HEIGHT(win->area[0].ysize)); + v_DSP_WIDTH(win->post_cfg.xsize) | + v_DSP_HEIGHT(win->post_cfg.ysize)); lcdc_writel(lcdc_dev, WIN1_DSP_ST, v_DSP_STX(win->area[0].dsp_stx) | v_DSP_STY(win->area[0].dsp_sty)); @@ -719,21 +719,35 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id) } spin_lock(&lcdc_dev->reg_lock); - win->area[0].dsp_stx = win->area[0].xpos + - screen->mode.left_margin + + win->post_cfg.xpos = win->area[0].xpos * (dev_drv->overscan.left + + dev_drv->overscan.right)/200 + screen->mode.xres * + (100 - dev_drv->overscan.left) / 200; + + win->post_cfg.ypos = win->area[0].ypos * (dev_drv->overscan.top + + dev_drv->overscan.bottom)/200 + + screen->mode.yres * + (100 - dev_drv->overscan.top) / 200; + win->post_cfg.xsize = win->area[0].xsize * + (dev_drv->overscan.left + + dev_drv->overscan.right)/200; + win->post_cfg.ysize = win->area[0].ysize * + (dev_drv->overscan.top + + dev_drv->overscan.bottom)/200; + + win->area[0].dsp_stx = win->post_cfg.xpos + screen->mode.left_margin + screen->mode.hsync_len; if (screen->mode.vmode == FB_VMODE_INTERLACED) { - win->area[0].ysize /= 2; - win->area[0].dsp_sty = win->area[0].ypos/2 + + win->post_cfg.ysize /= 2; + win->area[0].dsp_sty = win->post_cfg.ypos/2 + screen->mode.upper_margin + screen->mode.vsync_len; } else { - win->area[0].dsp_sty = win->area[0].ypos + + win->area[0].dsp_sty = win->post_cfg.ypos + screen->mode.upper_margin + screen->mode.vsync_len; } - win->scale_yrgb_x = calscale(win->area[0].xact, win->area[0].xsize); - win->scale_yrgb_y = calscale(win->area[0].yact, win->area[0].ysize); + win->scale_yrgb_x = calscale(win->area[0].xact, win->post_cfg.xsize); + win->scale_yrgb_y = calscale(win->area[0].yact, win->post_cfg.ysize); switch (win->format) { case ARGB888: win->fmt_cfg = VOP_FORMAT_ARGB888; @@ -759,9 +773,9 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id) if (win_id == 0) { win->fmt_cfg = VOP_FORMAT_YCBCR444; win->scale_cbcr_x = calscale(win->area[0].xact, - win->area[0].xsize); + win->post_cfg.xsize); win->scale_cbcr_y = calscale(win->area[0].yact, - win->area[0].ysize); + win->post_cfg.ysize); win->swap_rb = 0; } else { dev_err(lcdc_dev->driver.dev, @@ -773,9 +787,9 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id) if (win_id == 0) { win->fmt_cfg = VOP_FORMAT_YCBCR422; win->scale_cbcr_x = calscale((win->area[0].xact / 2), - win->area[0].xsize); + win->post_cfg.xsize); win->scale_cbcr_y = calscale(win->area[0].yact, - win->area[0].ysize); + win->post_cfg.ysize); win->swap_rb = 0; } else { dev_err(lcdc_dev->driver.dev, @@ -787,9 +801,9 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id) if (win_id == 0) { win->fmt_cfg = VOP_FORMAT_YCBCR420; win->scale_cbcr_x = calscale(win->area[0].xact / 2, - win->area[0].xsize); + win->post_cfg.xsize); win->scale_cbcr_y = calscale(win->area[0].yact / 2, - win->area[0].ysize); + win->post_cfg.ysize); win->swap_rb = 0; } else { dev_err(lcdc_dev->driver.dev, @@ -804,13 +818,13 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id) } spin_unlock(&lcdc_dev->reg_lock); - DBG(1, "lcdc%d>>%s\n" + DBG(2, "lcdc%d>>%s\n" ">>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n" ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id, __func__, get_format_string(win->format, fmt), - win->area[0].xact, win->area[0].yact, win->area[0].xsize, - win->area[0].ysize, win->area[0].xvir, win->area[0].yvir, - win->area[0].xpos, win->area[0].ypos); + win->area[0].xact, win->area[0].yact, win->post_cfg.xsize, + win->post_cfg.ysize, win->area[0].xvir, win->area[0].yvir, + win->post_cfg.xpos, win->post_cfg.ypos); return 0; } @@ -1201,6 +1215,22 @@ static int rk3036_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open) return 0; } +static int rk3036_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv, + struct overscan *overscan) +{ + int i; + + dev_drv->overscan = *overscan; + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + if (dev_drv->win[i] && dev_drv->win[i]->state) { + rk3036_lcdc_set_par(dev_drv, i); + rk3036_lcdc_pan_display(dev_drv, i); + } + } + rk3036_lcdc_cfg_done(dev_drv); + return 0; +} + static int rk3036_fb_win_remap(struct rk_lcdc_driver *dev_drv, enum fb_win_map_order order) { @@ -1368,6 +1398,7 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = { .get_dsp_bcsh_hue = rk3036_lcdc_get_bcsh_hue, .get_dsp_bcsh_bcs = rk3036_lcdc_get_bcsh_bcs, .open_bcsh = rk3036_lcdc_open_bcsh, + .set_overscan = rk3036_lcdc_set_overscan, }; static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev) diff --git a/drivers/video/rockchip/rkfb_sysfs.c b/drivers/video/rockchip/rkfb_sysfs.c index a0bbcc380cb8..9065168330be 100755 --- a/drivers/video/rockchip/rkfb_sysfs.c +++ b/drivers/video/rockchip/rkfb_sysfs.c @@ -508,8 +508,9 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr, } } - dev_drv->ops->load_screen(dev_drv, 1); - dev_drv->ops->cfg_done(dev_drv); + if (dev_drv->ops->set_overscan) + dev_drv->ops->set_overscan(dev_drv, &screen->overscan); + return count; } diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 4abc5e21e2d0..60c8e558a3ab 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -105,7 +105,7 @@ //#define USE_ION_MMU 1 #if defined(CONFIG_ION_ROCKCHIP) -extern struct ion_client *rockchip_ion_client_create(const char * name); +extern struct ion_client *rockchip_ion_client_create(const char *name); #endif extern int rk_fb_poll_prmry_screen_vblank(void); @@ -396,48 +396,50 @@ struct rk_fb_trsm_ops { }; struct rk_lcdc_drv_ops { - int (*open) (struct rk_lcdc_driver * dev_drv, int layer_id, bool open); + int (*open) (struct rk_lcdc_driver *dev_drv, int layer_id, bool open); int (*win_direct_en)(struct rk_lcdc_driver *dev_drv, int win_id, int en); - int (*init_lcdc) (struct rk_lcdc_driver * dev_drv); - int (*ioctl) (struct rk_lcdc_driver * dev_drv, unsigned int cmd, + int (*init_lcdc) (struct rk_lcdc_driver *dev_drv); + int (*ioctl) (struct rk_lcdc_driver *dev_drv, unsigned int cmd, unsigned long arg, int layer_id); - int (*suspend) (struct rk_lcdc_driver * dev_drv); - int (*resume) (struct rk_lcdc_driver * dev_drv); - int (*blank) (struct rk_lcdc_driver * dev_drv, int layer_id, + int (*suspend) (struct rk_lcdc_driver *dev_drv); + int (*resume) (struct rk_lcdc_driver *dev_drv); + int (*blank) (struct rk_lcdc_driver *dev_drv, int layer_id, int blank_mode); - int (*set_par) (struct rk_lcdc_driver * dev_drv, int layer_id); - int (*pan_display) (struct rk_lcdc_driver * dev_drv, int layer_id); + int (*set_par) (struct rk_lcdc_driver *dev_drv, int layer_id); + int (*pan_display) (struct rk_lcdc_driver *dev_drv, int layer_id); int (*direct_set_addr)(struct rk_lcdc_driver *drv, int win_id, u32 addr); - int (*lcdc_reg_update) (struct rk_lcdc_driver * dev_drv); - ssize_t(*get_disp_info) (struct rk_lcdc_driver * dev_drv, char *buf, + int (*lcdc_reg_update) (struct rk_lcdc_driver *dev_drv); + ssize_t(*get_disp_info) (struct rk_lcdc_driver *dev_drv, char *buf, int layer_id); - int (*load_screen) (struct rk_lcdc_driver * dev_drv, bool initscreen); - int (*get_win_state) (struct rk_lcdc_driver * dev_drv, int layer_id); - int (*ovl_mgr) (struct rk_lcdc_driver * dev_drv, int swap, bool set); //overlay manager - int (*fps_mgr) (struct rk_lcdc_driver * dev_drv, int fps, bool set); - int (*fb_get_win_id) (struct rk_lcdc_driver * dev_drv, const char *id); //find layer for fb - int (*fb_win_remap) (struct rk_lcdc_driver * dev_drv, + int (*load_screen) (struct rk_lcdc_driver *dev_drv, bool initscreen); + int (*get_win_state) (struct rk_lcdc_driver *dev_drv, int layer_id); + int (*ovl_mgr) (struct rk_lcdc_driver *dev_drv, int swap, bool set); /*overlay manager*/ + int (*fps_mgr) (struct rk_lcdc_driver *dev_drv, int fps, bool set); + int (*fb_get_win_id) (struct rk_lcdc_driver *dev_drv, const char *id); /*find layer for fb*/ + int (*fb_win_remap) (struct rk_lcdc_driver *dev_drv, enum fb_win_map_order order); - int (*set_dsp_lut) (struct rk_lcdc_driver * dev_drv, int *lut); - int (*read_dsp_lut) (struct rk_lcdc_driver * dev_drv, int *lut); - int (*lcdc_hdmi_process) (struct rk_lcdc_driver * dev_drv, int mode); //some lcdc need to some process in hdmi mode + int (*set_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut); + int (*read_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut); + int (*lcdc_hdmi_process) (struct rk_lcdc_driver *dev_drv, int mode); /*some lcdc need to some process in hdmi mode*/ int (*set_irq_to_cpu)(struct rk_lcdc_driver *dev_drv,int enable); - int (*poll_vblank) (struct rk_lcdc_driver * dev_drv); - int (*lcdc_rst) (struct rk_lcdc_driver * dev_drv); - int (*dpi_open) (struct rk_lcdc_driver * dev_drv, bool open); - int (*dpi_win_sel) (struct rk_lcdc_driver * dev_drv, int layer_id); - int (*dpi_status) (struct rk_lcdc_driver * dev_drv); - int (*get_dsp_addr)(struct rk_lcdc_driver * dev_drv,unsigned int *dsp_addr); - int (*set_dsp_cabc) (struct rk_lcdc_driver * dev_drv, int mode); + int (*poll_vblank) (struct rk_lcdc_driver *dev_drv); + int (*lcdc_rst) (struct rk_lcdc_driver *dev_drv); + int (*dpi_open) (struct rk_lcdc_driver *dev_drv, bool open); + int (*dpi_win_sel) (struct rk_lcdc_driver *dev_drv, int layer_id); + int (*dpi_status) (struct rk_lcdc_driver *dev_drv); + int (*get_dsp_addr)(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr); + int (*set_dsp_cabc) (struct rk_lcdc_driver *dev_drv, int mode); int (*set_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue); int (*set_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value); int (*get_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode); int (*get_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode); int (*open_bcsh)(struct rk_lcdc_driver *dev_drv, bool open); int (*set_screen_scaler) (struct rk_lcdc_driver *dev_drv, struct rk_screen *screen, bool enable); - int (*dump_reg) (struct rk_lcdc_driver * dev_drv); - int (*mmu_en) (struct rk_lcdc_driver * dev_drv); - int (*cfg_done) (struct rk_lcdc_driver * dev_drv); + int (*dump_reg) (struct rk_lcdc_driver *dev_drv); + int (*mmu_en) (struct rk_lcdc_driver *dev_drv); + int (*cfg_done) (struct rk_lcdc_driver *dev_drv); + int (*set_overscan) (struct rk_lcdc_driver *dev_drv, + struct overscan *overscan); }; struct rk_fb_area_par { @@ -552,16 +554,18 @@ struct rk_lcdc_driver { char mmu_dts_name[40]; struct device *mmu_dev; int iommu_enabled; - + struct rk_fb_reg_area_data reg_area_data; struct mutex fb_win_id_mutex; - struct completion frame_done; //sync for pan_display,whe we set a new frame address to lcdc register,we must make sure the frame begain to display - spinlock_t cpl_lock; //lock for completion frame done + struct completion frame_done; /*sync for pan_display,whe we set a new + frame address to lcdc register,we must + make sure the frame begain to display*/ + spinlock_t cpl_lock; /*lock for completion frame done */ int first_frame; struct rk_fb_vsync vsync_info; struct rk_fb_frame_time frame_time; - int wait_fs; //wait for new frame start in kernel + int wait_fs; /*wait for new frame start in kernel */ struct sw_sync_timeline *timeline; int timeline_max; int suspend_flag; @@ -602,14 +606,14 @@ struct rk_fb { int num_lcdc; #if defined(CONFIG_ION_ROCKCHIP) - struct ion_client * ion_client; + struct ion_client *ion_client; #endif }; extern int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type); -extern struct rk_fb_trsm_ops * rk_fb_trsm_ops_get(int type); +extern struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type); extern int rk_fb_register(struct rk_lcdc_driver *dev_drv, struct rk_lcdc_win *win, int id); extern int rk_fb_unregister(struct rk_lcdc_driver *dev_drv); @@ -629,11 +633,11 @@ extern int rk_fb_dpi_open(bool open); extern int rk_fb_dpi_layer_sel(int layer_id); extern int rk_fb_dpi_status(void); -extern int rk_fb_switch_screen(struct rk_screen * screen, int enable, int lcdc_id); +extern int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id); extern int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id); extern int rkfb_create_sysfs(struct fb_info *fbi); extern char *get_format_string(enum data_format, char *fmt); extern int support_uboot_display(void); -extern int rk_fb_calc_fps(struct rk_screen * screen, u32 pixclock); +extern int rk_fb_calc_fps(struct rk_screen *screen, u32 pixclock); extern int rk_get_real_fps(int time); #endif -- 2.34.1