From 95e93752dfd37d185639b10b543346b85723de77 Mon Sep 17 00:00:00 2001 From: zwl Date: Thu, 14 Aug 2014 10:22:10 +0800 Subject: [PATCH] rk fb: fix hdmi disp err when at ONE_DUAL disp mode and reorganize some code --- drivers/video/rockchip/rk_fb.c | 168 +++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 69 deletions(-) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 8fecb9d72956..42d5408ae4d3 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -464,14 +464,23 @@ char *get_format_string(enum data_format format, char *fmt) */ struct rk_lcdc_driver *rk_get_lcdc_drv(char *name) { - struct rk_fb *inf = platform_get_drvdata(fb_pdev); + struct rk_fb *inf = NULL; + struct rk_lcdc_driver *dev_drv = NULL; int i = 0; + + if (likely(fb_pdev)) + inf = platform_get_drvdata(fb_pdev); + else + return NULL; + for (i = 0; i < inf->num_lcdc; i++) { - if (!strcmp(inf->lcdc_dev_drv[i]->name, name)) + if (!strcmp(inf->lcdc_dev_drv[i]->name, name)) { + dev_drv = inf->lcdc_dev_drv[i]; break; + } } - return inf->lcdc_dev_drv[i]; + return dev_drv; } static struct rk_lcdc_driver *rk_get_prmry_lcdc_drv(void) @@ -1435,10 +1444,21 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv, memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data)); } -static void rk_fb_update_driver(struct rk_lcdc_win *win, +static void rk_fb_update_driver(struct rk_lcdc_driver *dev_drv, + struct rk_lcdc_win *win, struct rk_fb_reg_win_data *reg_win_data) { int i = 0; + struct rk_fb *inf = platform_get_drvdata(fb_pdev); + struct rk_screen *cur_screen; + struct rk_screen primary_screen; + + if (unlikely(!inf) || unlikely(!dev_drv) || + unlikely(!win) || unlikely(!reg_win_data)) + return; + + cur_screen = dev_drv->cur_screen; + rk_fb_get_prmry_screen(&primary_screen); win->area_num = reg_win_data->area_num; win->format = reg_win_data->data_format; @@ -1463,14 +1483,33 @@ static void rk_fb_update_driver(struct rk_lcdc_win *win, if (reg_win_data->reg_area_data[i].smem_start > 0) { win->area[i].smem_start = reg_win_data->reg_area_data[i].smem_start; - win->area[i].xpos = - reg_win_data->reg_area_data[i].xpos; - win->area[i].ypos = - reg_win_data->reg_area_data[i].ypos; - win->area[i].xsize = - reg_win_data->reg_area_data[i].xsize; - win->area[i].ysize = - reg_win_data->reg_area_data[i].ysize; + if (inf->disp_mode == DUAL) { + win->area[i].xpos = + reg_win_data->reg_area_data[i].xpos; + win->area[i].ypos = + reg_win_data->reg_area_data[i].ypos; + win->area[i].xsize = + reg_win_data->reg_area_data[i].xsize; + win->area[i].ysize = + reg_win_data->reg_area_data[i].ysize; + } else { + win->area[i].xpos = + reg_win_data->reg_area_data[i].xpos * + cur_screen->mode.xres / + primary_screen.mode.xres; + win->area[i].ypos = + reg_win_data->reg_area_data[i].ypos * + cur_screen->mode.yres / + primary_screen.mode.yres; + win->area[i].xsize = + reg_win_data->reg_area_data[i].xsize * + cur_screen->mode.xres / + primary_screen.mode.xres; + win->area[i].ysize = + reg_win_data->reg_area_data[i].ysize * + cur_screen->mode.yres / + primary_screen.mode.yres; + } win->area[i].xact = reg_win_data->reg_area_data[i].xact; win->area[i].yact = @@ -1724,7 +1763,7 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv, win = dev_drv->win[i]; win_data = rk_fb_get_win_data(regs, i); if (win_data) { - rk_fb_update_driver(win, win_data); + rk_fb_update_driver(dev_drv, win, win_data); win->state = 1; dev_drv->ops->set_par(dev_drv, i); dev_drv->ops->pan_display(dev_drv, i); @@ -1881,6 +1920,7 @@ static int rk_fb_set_win_buffer(struct fb_info *info, struct fb_fix_screeninfo *fix = &info->fix; struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par; struct rk_screen *screen = dev_drv->cur_screen; + struct rk_screen primary_screen; struct fb_info *fbi = rk_fb->fb[0]; int i, ion_fd, acq_fence_fd; u32 xvir, yvir; @@ -1975,8 +2015,10 @@ static int rk_fb_set_win_buffer(struct fb_info *info, reg_win_data->z_order = -1; reg_win_data->win_id = -1; } + + rk_fb_get_prmry_screen(&primary_screen); for (i = 0; i < reg_win_data->area_num; i++) { - rk_fb_check_config_var(&win_par->area_par[i], screen); + rk_fb_check_config_var(&win_par->area_par[i], &primary_screen); /* visiable pos in panel */ reg_win_data->reg_area_data[i].xpos = win_par->area_par[i].xpos; reg_win_data->reg_area_data[i].ypos = win_par->area_par[i].ypos; @@ -2739,8 +2781,10 @@ static int rk_fb_set_par(struct fb_info *info) ysize = screen->mode.yres; } -/*this is for device like rk2928 ,whic have one lcdc but two display outputs*/ -/*save winameter set by android*/ + /* this is for device like rk2928/rk312x, + * which have one lcdc but two display outputs + * save win parameter set by android + */ if (rk_fb->disp_mode != DUAL) { if (screen->screen_id == 0) { dev_drv->screen0->xsize = xsize; @@ -3076,23 +3120,7 @@ void rk_direct_fb_show(struct fb_info *fbi) rk_fb_pan_display(&fbi->var, fbi); } EXPORT_SYMBOL(rk_direct_fb_show); -#if 0 -static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var, - struct fb_var_screeninfo *hdmi_var) -{ - if (pmy_var->xres < pmy_var->yres) { /* vertical lcd screen */ - hdmi_var->xres = pmy_var->yres; - hdmi_var->yres = pmy_var->xres; - hdmi_var->xres_virtual = pmy_var->yres; - } else { - hdmi_var->xres = pmy_var->xres; - hdmi_var->yres = pmy_var->yres; - hdmi_var->xres_virtual = pmy_var->xres_virtual; - } - return 0; -} -#endif int rk_fb_dpi_open(bool open) { struct rk_lcdc_driver *dev_drv = NULL; @@ -3124,6 +3152,25 @@ int rk_fb_dpi_status(void) return ret; } + +#if 0 +static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var, + struct fb_var_screeninfo *hdmi_var) +{ + if (pmy_var->xres < pmy_var->yres) { /* vertical lcd screen */ + hdmi_var->xres = pmy_var->yres; + hdmi_var->yres = pmy_var->xres; + hdmi_var->xres_virtual = pmy_var->yres; + } else { + hdmi_var->xres = pmy_var->xres; + hdmi_var->yres = pmy_var->yres; + hdmi_var->xres_virtual = pmy_var->xres_virtual; + } + + return 0; +} +#endif + #if 1 /* *function:this function will be called by display device, enable/disable lcdc @@ -3221,7 +3268,6 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) struct rk_lcdc_driver *dev_drv = NULL; struct fb_var_screeninfo *hdmi_var = NULL; struct fb_var_screeninfo *pmy_var = NULL; /* var for primary screen */ - int i; struct fb_fix_screeninfo *hdmi_fix = NULL; char name[6]; int ret; @@ -3236,16 +3282,9 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) dev_drv = rk_fb->lcdc_dev_drv[0]; if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable) dev_drv->trsm_ops->disable(); - rk_disp_pwr_disable(dev_drv); } else { - for (i = 0; i < rk_fb->num_lcdc; i++) { - if (rk_fb->lcdc_dev_drv[i]->prop == EXTEND) { - dev_drv = rk_fb->lcdc_dev_drv[i]; - break; - } - } - - if (i == rk_fb->num_lcdc) { + dev_drv = rk_get_lcdc_drv(name); + if (dev_drv == NULL) { printk(KERN_ERR "%s driver not found!", name); return -ENODEV; } @@ -3253,10 +3292,8 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from", dev_drv->id); - if (rk_fb->num_lcdc == 1) - info = rk_fb->fb[0]; - else if (rk_fb->num_lcdc == 2) - info = rk_fb->fb[dev_drv->lcdc_win_num]; /* the main fb of lcdc1 */ + /* the main fb of lcdc drv */ + info = rk_fb->fb[dev_drv->fb_index_base]; if (dev_drv->screen1) { /* device like rk2928 ,have only one lcdc but two outputs */ if (enable) { @@ -3267,16 +3304,17 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) dev_drv->screen0->lcdc_id = 1; /* connect screen0 to output interface 1 */ dev_drv->cur_screen = dev_drv->screen1; dev_drv->screen0->ext_screen = dev_drv->screen1; - if (dev_drv->screen0->sscreen_get) { + if (dev_drv->screen0->sscreen_get) dev_drv->screen0->sscreen_get(dev_drv->screen0, dev_drv->cur_screen->hdmi_resolution); - } } else { dev_drv->screen1->lcdc_id = 1; /* connect screen1 to output interface 1 */ dev_drv->screen0->lcdc_id = 0; /* connect screen0 to output interface 0 */ dev_drv->cur_screen = dev_drv->screen0; - dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen, + if (dev_drv->screen_ctr_info && + dev_drv->screen_ctr_info->set_screen_info) + dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen, dev_drv->screen_ctr_info->lcd_info); } } else { @@ -3349,11 +3387,10 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) } } - info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0); + /* info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0); */ if (rk_fb->disp_mode != DUAL) { /* rk29_backlight_set(1); */ - rk_disp_pwr_enable(dev_drv); if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable) dev_drv->trsm_ops->enable(); } @@ -3376,24 +3413,19 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id) u16 screen_x, screen_y; u16 xpos, ypos; char name[6]; - int i = 0; sprintf(name, "lcdc%d", lcdc_id); -#if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) - dev_drv = inf->lcdc_dev_drv[0]; -#else - for (i = 0; i < inf->num_lcdc; i++) { - if (inf->lcdc_dev_drv[i]->prop == EXTEND) { - dev_drv = inf->lcdc_dev_drv[i]; - break; + + if (inf->disp_mode == DUAL) { + dev_drv = rk_get_lcdc_drv(name); + if (dev_drv == NULL) { + printk(KERN_ERR "%s driver not found!", name); + return -ENODEV; } + } else { + dev_drv = inf->lcdc_dev_drv[0]; } - if (i == inf->num_lcdc) { - printk(KERN_ERR "%s driver not found!", name); - return -ENODEV; - } -#endif if (inf->num_lcdc == 1) info = inf->fb[0]; else if (inf->num_lcdc == 2) @@ -3403,17 +3435,15 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id) screen_x = dev_drv->cur_screen->mode.xres; screen_y = dev_drv->cur_screen->mode.yres; -#if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP) - if (dev_drv->cur_screen->screen_id == 1) { + if (inf->disp_mode != DUAL && + dev_drv->cur_screen->screen_id == 1) { dev_drv->cur_screen->xpos = (screen_x - screen_x * scale_x / 100) >> 1; dev_drv->cur_screen->ypos = (screen_y - screen_y * scale_y / 100) >> 1; dev_drv->cur_screen->xsize = screen_x * scale_x / 100; dev_drv->cur_screen->ysize = screen_y * scale_y / 100; - } else -#endif - { + } else { xpos = (screen_x - screen_x * scale_x / 100) >> 1; ypos = (screen_y - screen_y * scale_y / 100) >> 1; dev_drv->cur_screen->xsize = screen_x * scale_x / 100; -- 2.34.1