summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorAdrian Salido-Moreno <adrianm@codeaurora.org>2012-11-28 18:41:33 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:13:31 -0700
commit38bc092bedf35a134aeefc98fee3bb3f94a2bf3c (patch)
tree991d6748222fde4bdddd39ff8dbb46b009e40e86 /drivers/video/fbdev
parentbba940fc54569763b20e9282a62840df030e76ac (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.c61
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_wb.c42
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,