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:
parent
3b9fec79f5
commit
3fcbdd4946
8 changed files with 103 additions and 27 deletions
|
@ -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;
|
||||||
|
|
|
@ -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__);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 +
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
Loading…
Add table
Reference in a new issue