msm: mdss: Add partial update support for dest-scaler
When applying partial update for command mode panel, the ROI is calculated from the mixer ROI. When destination scaling is enabled, the ROI for command mode panel should be the ROI after the scaling. This panel ROI is provided from the user mode where the scaling is calculated from. CRs-Fixed: 1082694 Change-Id: Iac899e5130fdd7d34e598998f4b5cab601cf7a22 Signed-off-by: Benjamin Chan <bkchan@codeaurora.org>
This commit is contained in:
parent
715bb59eea
commit
1e531fd402
4 changed files with 184 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -124,6 +124,7 @@
|
|||
#define DS_ENHANCER_UPDATE BIT(5)
|
||||
#define DS_VALIDATE BIT(6)
|
||||
#define DS_DIRTY_UPDATE BIT(7)
|
||||
#define DS_PU_ENABLE BIT(8)
|
||||
|
||||
/**
|
||||
* Destination Scaler DUAL mode overfetch pixel count
|
||||
|
@ -386,6 +387,7 @@ struct mdss_mdp_destination_scaler {
|
|||
u16 last_mixer_height;
|
||||
u32 flags;
|
||||
struct mdp_scale_data_v2 scaler;
|
||||
struct mdss_rect panel_roi;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1169,6 +1171,14 @@ static inline int is_dest_scaling_enable(struct mdss_mdp_mixer *mixer)
|
|||
mixer && mixer->ds && (mixer->ds->flags & DS_ENABLE));
|
||||
}
|
||||
|
||||
static inline int is_dest_scaling_pu_enable(struct mdss_mdp_mixer *mixer)
|
||||
{
|
||||
if (is_dest_scaling_enable(mixer))
|
||||
return (mixer->ds->flags & DS_PU_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 get_ds_input_width(struct mdss_mdp_mixer *mixer)
|
||||
{
|
||||
struct mdss_mdp_destination_scaler *ds;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -4652,7 +4652,15 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
|
|||
previous_frame_pu_type = mdss_mdp_get_pu_type(ctl);
|
||||
if (ctl->mixer_left) {
|
||||
mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi);
|
||||
ctl->roi = ctl->mixer_left->roi;
|
||||
if (is_dest_scaling_enable(ctl->mixer_left))
|
||||
ctl->roi = ctl->mixer_left->ds->panel_roi;
|
||||
else
|
||||
ctl->roi = ctl->mixer_left->roi;
|
||||
|
||||
pr_debug("ctl->mixer_left: [%d %d %d %d] ds:%d\n",
|
||||
ctl->roi.x, ctl->roi.y,
|
||||
ctl->roi.w, ctl->roi.h,
|
||||
is_dest_scaling_enable(ctl->mixer_left));
|
||||
}
|
||||
|
||||
if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
|
||||
|
@ -4660,20 +4668,43 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
|
|||
|
||||
if (sctl && sctl->mixer_left) {
|
||||
mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi);
|
||||
sctl->roi = sctl->mixer_left->roi;
|
||||
if (is_dest_scaling_enable(sctl->mixer_left))
|
||||
sctl->roi = sctl->mixer_left->ds->panel_roi;
|
||||
else
|
||||
sctl->roi = sctl->mixer_left->roi;
|
||||
|
||||
pr_debug("sctl->mixer_left: [%d %d %d %d] ds:%d\n",
|
||||
sctl->roi.x, sctl->roi.y,
|
||||
sctl->roi.w, sctl->roi.h,
|
||||
is_dest_scaling_enable(sctl->mixer_left));
|
||||
|
||||
}
|
||||
} else if (is_dual_lm_single_display(ctl->mfd) && ctl->mixer_right) {
|
||||
|
||||
mdss_mdp_set_mixer_roi(ctl->mixer_right, r_roi);
|
||||
|
||||
/* in this case, CTL_ROI is a union of left+right ROIs. */
|
||||
ctl->roi.w += ctl->mixer_right->roi.w;
|
||||
if (is_dest_scaling_enable(ctl->mixer_right))
|
||||
ctl->roi.w += ctl->mixer_right->ds->panel_roi.w;
|
||||
else
|
||||
ctl->roi.w += ctl->mixer_right->roi.w;
|
||||
|
||||
/* right_only, update roi.x as per CTL ROI guidelines */
|
||||
if (ctl->mixer_left && !ctl->mixer_left->valid_roi) {
|
||||
ctl->roi = ctl->mixer_right->roi;
|
||||
ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
|
||||
ctl->mixer_right->roi.x;
|
||||
if (is_dest_scaling_enable(ctl->mixer_right)) {
|
||||
ctl->roi = ctl->mixer_right->ds->panel_roi;
|
||||
ctl->roi.x =
|
||||
get_ds_output_width(ctl->mixer_left) +
|
||||
ctl->mixer_right->ds->panel_roi.x;
|
||||
} else {
|
||||
ctl->roi = ctl->mixer_right->roi;
|
||||
ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
|
||||
ctl->mixer_right->roi.x;
|
||||
}
|
||||
pr_debug("ctl->mixer_right_only : [%d %d %d %d] ds:%d\n",
|
||||
ctl->roi.x, ctl->roi.y,
|
||||
ctl->roi.w, ctl->roi.h,
|
||||
is_dest_scaling_enable(ctl->mixer_right));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,9 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
|
|||
ctl->mixer_right->roi = (struct mdss_rect) { 0, 0,
|
||||
ctl->mixer_right->width,
|
||||
ctl->mixer_right->height };
|
||||
if (split_ctl)
|
||||
split_ctl->mixer_left->roi =
|
||||
ctl->mixer_right->roi;
|
||||
|
||||
/*
|
||||
* Disable destination scaler by resetting the control
|
||||
|
@ -173,6 +176,46 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
|
|||
}
|
||||
}
|
||||
|
||||
static int __dest_scaler_panel_roi_update(
|
||||
struct mdp_destination_scaler_data *ds_data,
|
||||
struct mdss_mdp_destination_scaler *ds)
|
||||
{
|
||||
if (ds_data->flags & MDP_DESTSCALER_ROI_ENABLE) {
|
||||
/*
|
||||
* Updating PANEL ROI info, used in partial update
|
||||
*/
|
||||
if ((ds_data->panel_roi.w > ds->scaler.dst_width) ||
|
||||
(ds_data->panel_roi.h >
|
||||
ds->scaler.dst_height) ||
|
||||
(ds_data->panel_roi.w == 0) ||
|
||||
(ds_data->panel_roi.h == 0)) {
|
||||
pr_err("Invalid panel ROI parameter for dest-scaler-%d: [%d %d %d %d]\n",
|
||||
ds_data->dest_scaler_ndx,
|
||||
ds_data->panel_roi.x,
|
||||
ds_data->panel_roi.y,
|
||||
ds_data->panel_roi.w,
|
||||
ds_data->panel_roi.h);
|
||||
ds->flags &= ~DS_PU_ENABLE;
|
||||
return -EINVAL;
|
||||
}
|
||||
ds->panel_roi.x = ds_data->panel_roi.x;
|
||||
ds->panel_roi.y = ds_data->panel_roi.y;
|
||||
ds->panel_roi.w = ds_data->panel_roi.w;
|
||||
ds->panel_roi.h = ds_data->panel_roi.h;
|
||||
ds->flags |= DS_PU_ENABLE;
|
||||
pr_debug("dest-scaler[%d] panel_roi update: [%d,%d,%d,%d]\n",
|
||||
ds->num,
|
||||
ds_data->panel_roi.x, ds_data->panel_roi.y,
|
||||
ds_data->panel_roi.w, ds_data->panel_roi.h);
|
||||
MDSS_XLOG(ds->num, ds_data->panel_roi.x, ds_data->panel_roi.y,
|
||||
ds_data->panel_roi.w, ds_data->panel_roi.h);
|
||||
} else {
|
||||
ds->flags &= ~DS_PU_ENABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
|
||||
struct mdss_mdp_destination_scaler *ds,
|
||||
u32 max_input_width, u32 max_output_width)
|
||||
|
@ -218,6 +261,9 @@ static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
|
|||
ds->src_height = ds_data->lm_height;
|
||||
}
|
||||
|
||||
if (__dest_scaler_panel_roi_update(ds_data, ds))
|
||||
return -EINVAL;
|
||||
|
||||
if (ds_data->flags == 0) {
|
||||
pr_debug("Disabling destination scaler-%d\n",
|
||||
ds_data->dest_scaler_ndx);
|
||||
|
@ -341,6 +387,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
int ret = 0;
|
||||
struct mdss_data_type *mdata;
|
||||
struct mdss_mdp_ctl *ctl;
|
||||
struct mdss_mdp_ctl *sctl;
|
||||
struct mdss_mdp_destination_scaler *ds_left = NULL;
|
||||
struct mdss_mdp_destination_scaler *ds_right = NULL;
|
||||
struct mdss_panel_info *pinfo;
|
||||
|
@ -350,6 +397,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
if (ds_data) {
|
||||
mdata = mfd_to_mdata(mfd);
|
||||
ctl = mfd_to_ctl(mfd);
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
|
||||
if (ctl->mixer_left)
|
||||
ds_left = ctl->mixer_left->ds;
|
||||
|
@ -357,6 +405,9 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
if (ctl->mixer_right)
|
||||
ds_right = ctl->mixer_right->ds;
|
||||
|
||||
if (sctl && sctl->mixer_left && ds_right)
|
||||
sctl->mixer_left->ds = ds_right;
|
||||
|
||||
switch (ds_mode) {
|
||||
case DS_DUAL_MODE:
|
||||
if (!ds_left || !ds_right) {
|
||||
|
@ -379,6 +430,20 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
if (ret)
|
||||
goto reset_mixer;
|
||||
|
||||
if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
|
||||
pinfo = &ctl->panel_data->panel_info;
|
||||
if (ds_right->panel_roi.x >=
|
||||
get_panel_xres(pinfo)) {
|
||||
ds_right->panel_roi.x -=
|
||||
get_panel_xres(pinfo);
|
||||
} else {
|
||||
pr_err("SCTL DS right roi.x:%d < left panel width:%d\n",
|
||||
ds_right->panel_roi.x,
|
||||
get_panel_xres(pinfo));
|
||||
goto reset_mixer;
|
||||
}
|
||||
}
|
||||
|
||||
ds_left->flags &= ~(DS_LEFT|DS_RIGHT);
|
||||
ds_left->flags |= DS_DUAL_MODE;
|
||||
ds_right->flags &= ~(DS_LEFT|DS_RIGHT);
|
||||
|
@ -403,6 +468,17 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
if (ret)
|
||||
goto reset_mixer;
|
||||
|
||||
/*
|
||||
* For Partial update usecase, it is possible switching
|
||||
* from Left+Right mode to Left only mode. So make sure
|
||||
* cleanup the DS_RIGHT flags.
|
||||
*/
|
||||
if (ds_right) {
|
||||
ds_right->flags &=
|
||||
~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
|
||||
ds_right->flags |= DS_VALIDATE;
|
||||
}
|
||||
|
||||
MDSS_XLOG(ds_left->num, ds_left->src_width,
|
||||
ds_left->src_height, ds_left->flags);
|
||||
break;
|
||||
|
@ -422,6 +498,26 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
if (ret)
|
||||
goto reset_mixer;
|
||||
|
||||
if (ds_left) {
|
||||
ds_left->flags &=
|
||||
~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
|
||||
ds_left->flags |= DS_VALIDATE;
|
||||
}
|
||||
|
||||
if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
|
||||
pinfo = &ctl->panel_data->panel_info;
|
||||
if (ds_right->panel_roi.x >=
|
||||
get_panel_xres(pinfo)) {
|
||||
ds_right->panel_roi.x -=
|
||||
get_panel_xres(pinfo);
|
||||
} else {
|
||||
pr_err("SCTL DS-right-only roi.x:%d < Left panel width:%d\n",
|
||||
ds_right->panel_roi.x,
|
||||
get_panel_xres(pinfo));
|
||||
goto reset_mixer;
|
||||
}
|
||||
}
|
||||
|
||||
MDSS_XLOG(ds_right->num, ds_right->src_width,
|
||||
ds_right->src_height, ds_right->flags);
|
||||
break;
|
||||
|
@ -444,11 +540,11 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
|
|||
pinfo = &ctl->panel_data->panel_info;
|
||||
scaler_width = 0;
|
||||
scaler_height = 0;
|
||||
if (ds_left && ds_left->flags) {
|
||||
if (ds_left && (ds_left->flags & DS_ENABLE)) {
|
||||
scaler_width += ds_left->scaler.dst_width;
|
||||
scaler_height = ds_left->scaler.dst_height;
|
||||
}
|
||||
if (ds_right && ds_right->flags) {
|
||||
if (ds_right && (ds_right->flags & DS_ENABLE)) {
|
||||
scaler_width += ds_right->scaler.dst_width;
|
||||
scaler_height = ds_right->scaler.dst_height;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -1930,6 +1930,39 @@ static void __restore_pipe(struct mdss_mdp_pipe *pipe)
|
|||
pipe->restore_roi = false;
|
||||
}
|
||||
|
||||
static void __restore_dest_scaler_roi(struct mdss_mdp_ctl *ctl)
|
||||
{
|
||||
struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
|
||||
struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
|
||||
if (is_dest_scaling_pu_enable(ctl->mixer_left)) {
|
||||
ctl->mixer_left->ds->panel_roi.x = 0;
|
||||
ctl->mixer_left->ds->panel_roi.y = 0;
|
||||
ctl->mixer_left->ds->panel_roi.w = get_panel_xres(pinfo);
|
||||
ctl->mixer_left->ds->panel_roi.h = get_panel_yres(pinfo);
|
||||
|
||||
if ((ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) &&
|
||||
sctl) {
|
||||
if (ctl->panel_data->next)
|
||||
pinfo = &ctl->panel_data->next->panel_info;
|
||||
sctl->mixer_left->ds->panel_roi.x = 0;
|
||||
sctl->mixer_left->ds->panel_roi.y = 0;
|
||||
sctl->mixer_left->ds->panel_roi.w =
|
||||
get_panel_xres(pinfo);
|
||||
sctl->mixer_left->ds->panel_roi.h =
|
||||
get_panel_yres(pinfo);
|
||||
} else if (ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) {
|
||||
ctl->mixer_right->ds->panel_roi.x =
|
||||
get_panel_xres(pinfo);
|
||||
ctl->mixer_right->ds->panel_roi.y = 0;
|
||||
ctl->mixer_right->ds->panel_roi.w =
|
||||
get_panel_xres(pinfo);
|
||||
ctl->mixer_right->ds->panel_roi.h =
|
||||
get_panel_yres(pinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __adjust_pipe_rect() - Adjust pipe roi for dual partial update feature.
|
||||
* @pipe: pipe to check against.
|
||||
|
@ -2145,6 +2178,9 @@ set_roi:
|
|||
}
|
||||
dual_roi->enabled = false;
|
||||
}
|
||||
|
||||
if (pinfo->partial_update_enabled)
|
||||
__restore_dest_scaler_roi(ctl);
|
||||
}
|
||||
|
||||
pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n",
|
||||
|
|
Loading…
Add table
Reference in a new issue