msm: mdss: add support of border area

Add border_x_off and border_y_off to track the
left/right/top/bottom border parameters defined
at panel dtsi file. Adding border_x_off and
border_y_off to pipe's destination x and y so that
border can be formed during blending operation at
mixer.

Change-Id: I29673df30318c7d9064adae996da62823db3230d
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
[mattw@codeaurora.org: resolved trivial context conflict]
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
This commit is contained in:
Kuogee Hsieh 2014-10-17 10:18:47 -07:00 committed by David Keitel
parent 3b9fec79f5
commit 3fcbdd4946
8 changed files with 103 additions and 27 deletions

View file

@ -960,8 +960,11 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
height = pdata->panel_info.yres; height = pdata->panel_info.yres;
if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
dummy_xres = pdata->panel_info.lcdc.xres_pad; dummy_xres = mult_frac((pdata->panel_info.lcdc.border_left +
dummy_yres = pdata->panel_info.lcdc.yres_pad; pdata->panel_info.lcdc.border_right),
dst_bpp, pdata->panel_info.bpp);
dummy_yres = pdata->panel_info.lcdc.border_top +
pdata->panel_info.lcdc.border_bottom;
} }
vsync_period = vspw + vbp + height + dummy_yres + vfp; vsync_period = vspw + vbp + height + dummy_yres + vfp;

View file

@ -1405,15 +1405,23 @@ static int mdss_panel_parse_dt(struct device_node *np,
"qcom,mdss-pan-physical-height-dimension", &tmp); "qcom,mdss-pan-physical-height-dimension", &tmp);
pinfo->physical_height = (!rc ? tmp : 0); pinfo->physical_height = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp); rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
pinfo->lcdc.xres_pad = (!rc ? tmp : 0); pinfo->lcdc.border_left = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp); rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
if (!rc) if (!rc)
pinfo->lcdc.xres_pad += tmp; pinfo->lcdc.border_right = tmp;
pinfo->lcdc.xres_pad = (pinfo->lcdc.border_left +
pinfo->lcdc.border_right);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp); rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
pinfo->lcdc.yres_pad = (!rc ? tmp : 0); pinfo->lcdc.border_top = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp); rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
if (!rc) if (!rc)
pinfo->lcdc.yres_pad += tmp; pinfo->lcdc.border_bottom = tmp;
pinfo->lcdc.yres_pad = (pinfo->lcdc.border_top +
pinfo->lcdc.border_bottom);
rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp); rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
if (rc) { if (rc) {
pr_err("%s:%d, bpp not specified\n", __func__, __LINE__); pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);

View file

@ -209,6 +209,8 @@ struct mdss_mdp_ctl {
u16 width; u16 width;
u16 height; u16 height;
u16 border_x_off;
u16 border_y_off;
u32 dst_format; u32 dst_format;
bool is_secure; bool is_secure;
@ -724,7 +726,18 @@ static inline bool mdss_mdp_ctl_is_power_on_lp(struct mdss_mdp_ctl *ctl)
static inline u32 left_lm_w_from_mfd(struct msm_fb_data_type *mfd) static inline u32 left_lm_w_from_mfd(struct msm_fb_data_type *mfd)
{ {
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
return (ctl && ctl->mixer_left) ? ctl->mixer_left->width : 0; struct mdss_panel_info *pinfo = mfd->panel_info;
int width = 0;
if (ctl && ctl->mixer_left) {
width = ctl->mixer_left->width;
width -= (pinfo->lcdc.border_left + pinfo->lcdc.border_right);
pr_debug("ctl=%d mw=%d l=%d r=%d w=%d\n",
ctl->num, ctl->mixer_left->width,
pinfo->lcdc.border_left, pinfo->lcdc.border_right,
width);
}
return width;
} }
static inline bool mdss_mdp_is_tile_format(struct mdss_mdp_format_params *fmt) static inline bool mdss_mdp_is_tile_format(struct mdss_mdp_format_params *fmt)

View file

@ -452,6 +452,24 @@ exit:
return; return;
} }
static inline u32 get_panel_yres(struct mdss_panel_info *pinfo)
{
u32 yres;
yres = pinfo->yres + pinfo->lcdc.border_top +
pinfo->lcdc.border_bottom;
return yres;
}
static inline u32 get_panel_xres(struct mdss_panel_info *pinfo)
{
u32 xres;
xres = pinfo->xres + pinfo->lcdc.border_left +
pinfo->lcdc.border_right;
return xres;
}
/** /**
* mdss_mdp_perf_calc_pipe() - calculate performance numbers required by pipe * mdss_mdp_perf_calc_pipe() - calculate performance numbers required by pipe
* @pipe: Source pipe struct containing updated pipe params * @pipe: Source pipe struct containing updated pipe params
@ -510,7 +528,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
fps = mdss_panel_get_framerate(pinfo); fps = mdss_panel_get_framerate(pinfo);
v_total = mdss_panel_get_vtotal(pinfo); v_total = mdss_panel_get_vtotal(pinfo);
} }
xres = pinfo->xres; xres = get_panel_xres(pinfo);
is_fbc = pinfo->fbc.enabled; is_fbc = pinfo->fbc.enabled;
h_total = mdss_panel_get_htotal(pinfo, false); h_total = mdss_panel_get_htotal(pinfo, false);
} else { } else {
@ -1785,6 +1803,8 @@ static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_ctl *split_ctl) struct mdss_mdp_ctl *split_ctl)
{ {
struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_panel_info *pinfo;
if (!ctl || !split_ctl || !mdata) if (!ctl || !split_ctl || !mdata)
return -ENODEV; return -ENODEV;
@ -1792,6 +1812,11 @@ static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl,
/* setup split ctl mixer as right mixer of original ctl so that /* setup split ctl mixer as right mixer of original ctl so that
* original ctl can work the same way as dual pipe solution */ * original ctl can work the same way as dual pipe solution */
ctl->mixer_right = split_ctl->mixer_left; ctl->mixer_right = split_ctl->mixer_left;
pinfo = &ctl->panel_data->panel_info;
/* add x offset from left ctl's border */
split_ctl->border_x_off += (pinfo->lcdc.border_left +
pinfo->lcdc.border_right);
return 0; return 0;
} }
@ -1862,9 +1887,9 @@ static inline u32 get_panel_width(struct mdss_mdp_ctl *ctl)
{ {
u32 width; u32 width;
width = ctl->panel_data->panel_info.xres; width = get_panel_xres(&ctl->panel_data->panel_info);
width += (ctl->panel_data->next && is_split_dst(ctl->mfd)) ? if (ctl->panel_data->next && is_split_dst(ctl->mfd))
ctl->panel_data->next->panel_info.xres : 0; width += get_panel_xres(&ctl->panel_data->next->panel_info);
return width; return width;
} }
@ -1875,16 +1900,20 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
u32 width, height; u32 width, height;
int split_fb; int split_fb;
u32 max_mixer_width; u32 max_mixer_width;
struct mdss_panel_info *pinfo;
if (!ctl || !ctl->panel_data) { if (!ctl || !ctl->panel_data) {
pr_err("invalid ctl handle\n"); pr_err("invalid ctl handle\n");
return -ENODEV; return -ENODEV;
} }
pinfo = &ctl->panel_data->panel_info;
split_ctl = mdss_mdp_get_split_ctl(ctl); split_ctl = mdss_mdp_get_split_ctl(ctl);
width = get_panel_width(ctl); width = get_panel_width(ctl);
height = ctl->panel_data->panel_info.yres; height = get_panel_yres(pinfo);
max_mixer_width = ctl->mdata->max_mixer_width; max_mixer_width = ctl->mdata->max_mixer_width;
split_fb = (ctl->mfd->split_fb_left && split_fb = (ctl->mfd->split_fb_left &&
@ -1918,10 +1947,13 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
} }
} }
if (split_fb) if (split_fb) {
width = ctl->mfd->split_fb_left; width = ctl->mfd->split_fb_left;
else if (width > max_mixer_width) width += (pinfo->lcdc.border_left +
pinfo->lcdc.border_right);
} else if (width > max_mixer_width) {
width /= 2; width /= 2;
}
ctl->mixer_left->width = width; ctl->mixer_left->width = width;
ctl->mixer_left->height = height; ctl->mixer_left->height = height;
@ -2020,6 +2052,7 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
struct mdss_mdp_ctl *ctl; struct mdss_mdp_ctl *ctl;
struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_data_type *mdata = mfd_to_mdata(mfd);
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_panel_info *pinfo;
if (pdata->panel_info.type == WRITEBACK_PANEL) if (pdata->panel_info.type == WRITEBACK_PANEL)
offset = mdss_mdp_get_wb_ctl_support(mdata, false); offset = mdss_mdp_get_wb_ctl_support(mdata, false);
@ -2032,10 +2065,13 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
pinfo = &pdata->panel_info;
ctl->mfd = mfd; ctl->mfd = mfd;
ctl->panel_data = pdata; ctl->panel_data = pdata;
ctl->is_video_mode = false; ctl->is_video_mode = false;
ctl->perf_release_ctl_bw = false; ctl->perf_release_ctl_bw = false;
ctl->border_x_off = pinfo->lcdc.border_left;
ctl->border_y_off = pinfo->lcdc.border_top;
switch (pdata->panel_info.type) { switch (pdata->panel_info.type) {
case EDP_PANEL: case EDP_PANEL:
@ -2154,8 +2190,9 @@ int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
return -ENODEV; return -ENODEV;
} }
sctl->width = pdata->panel_info.xres; sctl->width = get_panel_xres(&pdata->panel_info);
sctl->height = pdata->panel_info.yres; sctl->height = get_panel_yres(&pdata->panel_info);
sctl->roi = (struct mdss_rect){0, 0, sctl->width, sctl->height}; sctl->roi = (struct mdss_rect){0, 0, sctl->width, sctl->height};
ctl->mixer_left = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_INTF, ctl->mixer_left = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_INTF,

View file

@ -1236,15 +1236,21 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp); dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp);
itp.width = mult_frac((pinfo->xres + pinfo->lcdc.xres_pad), itp.width = mult_frac((pinfo->xres + pinfo->lcdc.border_left +
dst_bpp, pinfo->bpp); pinfo->lcdc.border_right), dst_bpp, pinfo->bpp);
itp.height = pinfo->yres + pinfo->lcdc.yres_pad; itp.height = pinfo->yres + pinfo->lcdc.border_top +
pinfo->lcdc.border_bottom;
itp.border_clr = pinfo->lcdc.border_clr; itp.border_clr = pinfo->lcdc.border_clr;
itp.underflow_clr = pinfo->lcdc.underflow_clr; itp.underflow_clr = pinfo->lcdc.underflow_clr;
itp.hsync_skew = pinfo->lcdc.hsync_skew; itp.hsync_skew = pinfo->lcdc.hsync_skew;
itp.xres = mult_frac(pinfo->xres, dst_bpp, pinfo->bpp); /* tg active area is not work, hence yres should equal to height */
itp.yres = pinfo->yres; itp.xres = mult_frac((pinfo->xres + pinfo->lcdc.border_left +
pinfo->lcdc.border_right), dst_bpp, pinfo->bpp);
itp.yres = pinfo->yres + pinfo->lcdc.border_top +
pinfo->lcdc.border_bottom;
itp.h_back_porch = pinfo->lcdc.h_back_porch; itp.h_back_porch = pinfo->lcdc.h_back_porch;
itp.h_front_porch = pinfo->lcdc.h_front_porch; itp.h_front_porch = pinfo->lcdc.h_front_porch;
itp.v_back_porch = pinfo->lcdc.v_back_porch; itp.v_back_porch = pinfo->lcdc.v_back_porch;

View file

@ -806,6 +806,11 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
pipe->dst.w = req->dst_rect.w; pipe->dst.w = req->dst_rect.w;
pipe->dst.h = req->dst_rect.h; pipe->dst.h = req->dst_rect.h;
if (mixer->ctl) {
pipe->dst.x += mixer->ctl->border_x_off;
pipe->dst.y += mixer->ctl->border_y_off;
}
if (mfd->panel_orientation & MDP_FLIP_LR) if (mfd->panel_orientation & MDP_FLIP_LR)
pipe->dst.x = pipe->mixer_left->width pipe->dst.x = pipe->mixer_left->width
- pipe->dst.x - pipe->dst.w; - pipe->dst.x - pipe->dst.w;

View file

@ -216,6 +216,10 @@ struct lcd_panel_info {
u32 border_clr; u32 border_clr;
u32 underflow_clr; u32 underflow_clr;
u32 hsync_skew; u32 hsync_skew;
u32 border_top;
u32 border_bottom;
u32 border_left;
u32 border_right;
/* Pad width */ /* Pad width */
u32 xres_pad; u32 xres_pad;
/* Pad height */ /* Pad height */
@ -517,7 +521,9 @@ static inline int mdss_panel_get_vtotal(struct mdss_panel_info *pinfo)
{ {
return pinfo->yres + pinfo->lcdc.v_back_porch + return pinfo->yres + pinfo->lcdc.v_back_porch +
pinfo->lcdc.v_front_porch + pinfo->lcdc.v_front_porch +
pinfo->lcdc.v_pulse_width; pinfo->lcdc.v_pulse_width+
pinfo->lcdc.border_top +
pinfo->lcdc.border_bottom;
} }
/* /*
@ -533,10 +539,11 @@ static inline int mdss_panel_get_vtotal(struct mdss_panel_info *pinfo)
static inline int mdss_panel_get_htotal(struct mdss_panel_info *pinfo, bool static inline int mdss_panel_get_htotal(struct mdss_panel_info *pinfo, bool
consider_fbc) consider_fbc)
{ {
int adj_xres = pinfo->xres; int adj_xres = pinfo->xres + pinfo->lcdc.border_left +
pinfo->lcdc.border_right;
if (consider_fbc && pinfo->fbc.enabled) if (consider_fbc && pinfo->fbc.enabled)
adj_xres = mult_frac(pinfo->xres, adj_xres = mult_frac(adj_xres,
pinfo->fbc.target_bpp, pinfo->bpp); pinfo->fbc.target_bpp, pinfo->bpp);
return adj_xres + pinfo->lcdc.h_back_porch + return adj_xres + pinfo->lcdc.h_back_porch +

View file

@ -633,9 +633,6 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
if (ctrl_pdata->refresh_clk_rate || (frame_rate != if (ctrl_pdata->refresh_clk_rate || (frame_rate !=
panel_info->mipi.frame_rate) || panel_info->mipi.frame_rate) ||
(!panel_info->clk_rate)) { (!panel_info->clk_rate)) {
h_period += panel_info->lcdc.xres_pad;
v_period += panel_info->lcdc.yres_pad;
if (lanes > 0) { if (lanes > 0) {
panel_info->clk_rate = panel_info->clk_rate =
((h_period * v_period * ((h_period * v_period *