diff options
| author | Adrian Salido-Moreno <adrianm@codeaurora.org> | 2012-11-28 18:41:33 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:13:31 -0700 |
| commit | 38bc092bedf35a134aeefc98fee3bb3f94a2bf3c (patch) | |
| tree | 991d6748222fde4bdddd39ff8dbb46b009e40e86 /drivers/video/fbdev | |
| parent | bba940fc54569763b20e9282a62840df030e76ac (diff) | |
msm: mdss: support panel resolution changes
Allow framebuffer resolution changes to be propagated to panel driver to
support different display resolutions. Use a new panel event so that
panel driver can take the decision of accepting new params.
Change-Id: I04b26cbb4d06a3cbc9c4416fbb7202bb185eee9b
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 61 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.h | 6 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_wb.c | 42 |
5 files changed, 83 insertions, 32 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 253208f792a6..ec8570414b3f 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -317,7 +317,8 @@ static int mdss_fb_remove(struct platform_device *pdev) return 0; } -static inline int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int e) +static inline int mdss_fb_send_panel_event( + struct msm_fb_data_type *mfd, int e, void *arg) { struct mdss_panel_data *pdata; @@ -330,7 +331,7 @@ static inline int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int e) pr_debug("sending event=%d for fb%d\n", e, mfd->index); if (pdata->event_handler) - return pdata->event_handler(pdata, e, NULL); + return pdata->event_handler(pdata, e, arg); return 0; } @@ -344,7 +345,7 @@ static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd) pr_debug("mdss_fb suspend index=%d\n", mfd->index); - ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND); + ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND, NULL); if (ret) { pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret); return ret; @@ -375,7 +376,7 @@ static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd) pr_debug("mdss_fb resume index=%d\n", mfd->index); - ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME); + ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME, NULL); if (ret) { pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret); return ret; @@ -854,10 +855,6 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) var->hsync_len = panel_info->lcdc.h_pulse_width; var->pixclock = panel_info->clk_rate / 1000; - mfd->var_xres = var->xres; - mfd->var_yres = var->yres; - mfd->var_pixclock = var->pixclock; - if (panel_info->type == MIPI_VIDEO_PANEL) { var->reserved[4] = panel_info->mipi.frame_rate; } else { @@ -1004,6 +1001,22 @@ static int mdss_fb_pan_display(struct fb_var_screeninfo *var, return 0; } +static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, + struct mdss_panel_info *pinfo) +{ + pinfo->xres = var->xres; + pinfo->yres = var->yres; + pinfo->lcdc.v_front_porch = var->upper_margin; + pinfo->lcdc.v_back_porch = var->lower_margin; + pinfo->lcdc.v_pulse_width = var->vsync_len; + pinfo->lcdc.h_front_porch = var->left_margin; + pinfo->lcdc.h_back_porch = var->right_margin; + pinfo->lcdc.h_pulse_width = var->hsync_len; + pinfo->clk_rate = var->pixclock; + /* todo: find how to pass CEA vic through framebuffer APIs */ + pinfo->vic = var->reserved[3]; +} + static int mdss_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -1096,16 +1109,25 @@ static int mdss_fb_check_var(struct fb_var_screeninfo *var, if ((var->xres == 0) || (var->yres == 0)) return -EINVAL; - if ((var->xres > mfd->panel_info->xres) || - (var->yres > mfd->panel_info->yres)) - return -EINVAL; - if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; if (var->yoffset > (var->yres_virtual - var->yres)) return -EINVAL; + if (mfd->panel_info) { + struct mdss_panel_info panel_info; + int rc; + + memcpy(&panel_info, mfd->panel_info, sizeof(panel_info)); + mdss_fb_var_to_panelinfo(var, &panel_info); + rc = mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS, + &panel_info); + if (IS_ERR_VALUE(rc)) + return rc; + mfd->panel_reconfig = rc; + } + return 0; } @@ -1114,7 +1136,6 @@ static int mdss_fb_set_par(struct fb_info *info) struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; struct fb_var_screeninfo *var = &info->var; int old_imgType; - int blank = 0; old_imgType = mfd->fb_imgType; switch (var->bits_per_pixel) { @@ -1146,22 +1167,14 @@ static int mdss_fb_set_par(struct fb_info *info) return -EINVAL; } - if ((mfd->var_pixclock != var->pixclock) || - (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) || - (mfd->var_pixclock != var->pixclock) || - (mfd->var_xres != var->xres) || - (mfd->var_yres != var->yres)))) { - mfd->var_xres = var->xres; - mfd->var_yres = var->yres; - mfd->var_pixclock = var->pixclock; - blank = 1; - } mfd->fbi->fix.line_length = mdss_fb_line_length(mfd->index, var->xres, var->bits_per_pixel / 8); - if (blank) { + if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) { mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable); + mdss_fb_var_to_panelinfo(var, mfd->panel_info); mdss_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable); + mfd->panel_reconfig = false; } return 0; diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index b2414ef7fd80..8679608589ec 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -62,6 +62,8 @@ struct msm_fb_data_type { int op_enable; u32 fb_imgType; + int panel_reconfig; + u32 dst_format; int vsync_pending; ktime_t vsync_time; @@ -100,10 +102,6 @@ struct msm_fb_data_type { struct platform_device *pdev; - u32 var_xres; - u32 var_yres; - u32 var_pixclock; - u32 mdp_fb_page_protection; struct mdss_mdp_ctl *ctl; diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index bd7371b14fd1..31cc5270f010 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -391,8 +391,8 @@ static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd) return -ENODEV; } - width = mfd->fbi->var.xres; - height = mfd->fbi->var.yres; + width = pdata->panel_info.xres; + height = pdata->panel_info.yres; if (width > (2 * MAX_MIXER_WIDTH)) { pr_err("unsupported resolution\n"); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 34f19f63027b..24701b229eba 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -64,6 +64,7 @@ enum mdss_intf_events { MDSS_EVENT_CLOSE, MDSS_EVENT_SUSPEND, MDSS_EVENT_RESUME, + MDSS_EVENT_CHECK_PARAMS, }; /* panel info type */ @@ -179,6 +180,7 @@ struct mdss_panel_info { u32 frame_count; u32 is_3d_panel; u32 out_format; + u32 vic; /* video identification code */ struct lcd_panel_info lcd; struct lcdc_panel_info lcdc; diff --git a/drivers/video/fbdev/msm/mdss_wb.c b/drivers/video/fbdev/msm/mdss_wb.c index 7352ea6f9bd0..33442ae7dfa6 100644 --- a/drivers/video/fbdev/msm/mdss_wb.c +++ b/drivers/video/fbdev/msm/mdss_wb.c @@ -26,11 +26,49 @@ #include "mdss_panel.h" +/** + * mdss_wb_check_params - check new panel info params + * @pdata: current panel information + * @new: updates to panel info + * + * Checks if there are any changes that require panel reconfiguration + * in order to be reflected on writeback buffer. + * + * Return negative errno if invalid input, zero if there is no panel reconfig + * needed and non-zero if reconfiguration is needed. + */ +static int mdss_wb_check_params(struct mdss_panel_data *pdata, + struct mdss_panel_info *new) +{ + struct mdss_panel_info *old; + + if (!pdata || !new) { + pr_err("%s: Invalid input\n", __func__); + return -EINVAL; + } + + old = &pdata->panel_info; + + if ((old->xres != new->xres) || (old->yres != new->yres)) + return 1; + + return 0; +} + static int mdss_wb_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { - pr_debug("%s: event=%d\n", __func__, event); - return 0; + int rc = 0; + + switch (event) { + case MDSS_EVENT_CHECK_PARAMS: + rc = mdss_wb_check_params(pdata, (struct mdss_panel_info *)arg); + break; + default: + pr_debug("%s: panel event (%d) not handled\n", __func__, event); + break; + } + return rc; } static int mdss_wb_parse_dt(struct platform_device *pdev, |
