diff options
author | Adrian Salido-Moreno <adrianm@codeaurora.org> | 2015-08-21 15:42:52 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:45:32 -0700 |
commit | d9f95bd8d910d2d889b2eb57e3bb2e51d20d43d1 (patch) | |
tree | f5069fa7484f3d11c47ec4fe651f5a5741bcef94 /drivers/video | |
parent | 9e90c6e5e548d072fc84c171208d00926cef6b14 (diff) |
msm: mdss: fb: fix mismatch between current videomode and modelist
When multiple panel timings are available and enumerating video mode
list, the configuration present in the modelist may differ from the
actual configuration in fb variable info. This may cause issues when
usermode does GET_VSCREENINFO/PUT_VSCREENINFO calls. Fix this by
updating variable info with current timing mode.
Change-Id: Id9d4068bdb4851ffb4bc7e218a0666d1bd64eebe
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
[cip@codeaurora.org: Resolved merge conflict]
Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index e2c9648635d6..29fd5663effd 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -928,11 +928,23 @@ static void mdss_fb_videomode_from_panel_timing(struct fb_videomode *videomode, videomode->upper_margin = pt->v_back_porch; videomode->lower_margin = pt->v_front_porch; videomode->vsync_len = pt->v_pulse_width; - videomode->pixclock = pt->clk_rate; videomode->refresh = pt->frame_rate; videomode->flag = 0; videomode->vmode = 0; videomode->sync = 0; + + if (videomode->refresh) { + unsigned long clk_rate, h_total, v_total; + + h_total = videomode->xres + videomode->left_margin + + videomode->right_margin + videomode->hsync_len; + v_total = videomode->yres + videomode->lower_margin + + videomode->upper_margin + videomode->vsync_len; + clk_rate = h_total * v_total * videomode->refresh; + videomode->pixclock = KHZ2PICOS(clk_rate / 1000); + } else { + videomode->pixclock = KHZ2PICOS(pt->clk_rate / 1000); + } } static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd, @@ -987,6 +999,12 @@ static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd, fbi->monspecs.modedb = modedb; fbi->monspecs.modedb_len = num_timings; + + /* destroy and recreate modelist */ + fb_destroy_modelist(&fbi->modelist); + + if (fbi->mode) + fb_videomode_to_var(&fbi->var, fbi->mode); fb_videomode_to_modelist(modedb, num_timings, &fbi->modelist); return 0; @@ -2265,7 +2283,6 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; int *id; - u64 clk_rate; /* * fb info initialization @@ -2396,7 +2413,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) return ret; } - var->xres = mdss_fb_get_panel_xres(panel_info); + mdss_panelinfo_to_fb_var(panel_info, var); fix->type = panel_info->is_3d_panel; if (mfd->mdp.fb_stride) @@ -2405,28 +2422,13 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) else fix->line_length = var->xres * bpp; - var->yres = panel_info->yres; - if (panel_info->physical_width) - var->width = panel_info->physical_width; - if (panel_info->physical_height) - var->height = panel_info->physical_height; var->xres_virtual = var->xres; var->yres_virtual = panel_info->yres * mfd->fb_page; var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */ - var->upper_margin = panel_info->lcdc.v_back_porch; - var->lower_margin = panel_info->lcdc.v_front_porch; - var->vsync_len = panel_info->lcdc.v_pulse_width; - var->left_margin = panel_info->lcdc.h_back_porch; - var->right_margin = panel_info->lcdc.h_front_porch; - var->hsync_len = panel_info->lcdc.h_pulse_width; - clk_rate = panel_info->clk_rate; - do_div(clk_rate, 1000U); - var->pixclock = (u32) clk_rate; /* * Populate smem length here for uspace to get the - * Framebuffer size when FBIO_FSCREENINFO ioctl is - * called. + * Framebuffer size when FBIO_FSCREENINFO ioctl is called. */ fix->smem_len = PAGE_ALIGN(fix->line_length * var->yres) * mfd->fb_page; @@ -3233,7 +3235,6 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, pinfo->lcdc.h_front_porch = var->right_margin; pinfo->lcdc.h_back_porch = var->left_margin; pinfo->lcdc.h_pulse_width = var->hsync_len; - pinfo->clk_rate = var->pixclock; if (var->grayscale > 1) { format = mdss_grayscale_to_mdp_format(var->grayscale); @@ -3243,15 +3244,22 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, pr_warn("Failed to map grayscale value (%d) to an MDP format\n", var->grayscale); } + + /* + * if greater than 1M, then rate would fall below 1mhz which is not + * even supported. In this case it means clock rate is actually + * passed directly in hz. + */ + if (var->pixclock > SZ_1M) + pinfo->clk_rate = var->pixclock; + else + pinfo->clk_rate = PICOS2KHZ(var->pixclock) * 1000; } static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, struct fb_var_screeninfo *var) { - struct mdss_panel_data *pdata = container_of(pinfo, - struct mdss_panel_data, panel_info); - - var->xres = mdss_fb_get_panel_xres(&pdata->panel_info); + var->xres = mdss_fb_get_panel_xres(pinfo); var->yres = pinfo->yres; var->lower_margin = pinfo->lcdc.v_front_porch - pinfo->prg_fet; @@ -3261,7 +3269,12 @@ static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, var->right_margin = pinfo->lcdc.h_front_porch; var->left_margin = pinfo->lcdc.h_back_porch; var->hsync_len = pinfo->lcdc.h_pulse_width; - var->pixclock = (u32)pinfo->clk_rate; + var->pixclock = KHZ2PICOS(pinfo->clk_rate / 1000); + + if (pinfo->physical_width) + var->width = pinfo->physical_width; + if (pinfo->physical_height) + var->height = pinfo->physical_height; } /** @@ -3610,6 +3623,13 @@ static int mdss_fb_set_par(struct fb_info *info) if (!mode) return -EINVAL; + pr_debug("found mode: %s\n", mode->name); + + if (fb_mode_is_equal(mode, info->mode)) { + pr_debug("mode is equal to current mode\n"); + return 0; + } + ret = mdss_fb_videomode_switch(mfd, mode); if (ret) return ret; |