msm: mdss: Correct settings when on/off happens in dest-scaler

Destination scaler can be turned off within each display commit IOCTL.
When it is disabled, the mixer dimension must be reset to match the
panel configuration. It is also required to update the destination
scaler block when there is a ON/OFF transition because all HW setting is
gone after such power event. Power event includes general suspend
resume, FB driver shutdown and reload, and auto clock gating.

CRs-Fixed: 1077684
Change-Id: I340f778583bb63d6436c4ef8f51ead77a2871625
Signed-off-by: Benjamin Chan <bkchan@codeaurora.org>
This commit is contained in:
Benjamin Chan 2016-09-12 17:58:22 -04:00
parent c6b7d9674c
commit c77c8b03bd
4 changed files with 261 additions and 40 deletions

View file

@ -109,6 +109,9 @@
* QSEED3 parameters needs to be updated. * QSEED3 parameters needs to be updated.
* @DS_ENHANCER_UPDATE: Setting this bit indicates current Desitnation Scaler * @DS_ENHANCER_UPDATE: Setting this bit indicates current Desitnation Scaler
* QSEED3 Detial enhancer parameters need to be updated. * QSEED3 Detial enhancer parameters need to be updated.
* @DS_VALIDATE: Indicate destination data structure parameters are validated
* and can be used for programming the HW and perform a flush.
* @DS_DIRTY_UPDATE: Mark for dirty update for Power resume usecase.
*/ */
#define DS_ENABLE BIT(0) #define DS_ENABLE BIT(0)
#define DS_DUAL_MODE BIT(1) #define DS_DUAL_MODE BIT(1)
@ -116,6 +119,8 @@
#define DS_RIGHT BIT(3) #define DS_RIGHT BIT(3)
#define DS_SCALE_UPDATE BIT(4) #define DS_SCALE_UPDATE BIT(4)
#define DS_ENHANCER_UPDATE BIT(5) #define DS_ENHANCER_UPDATE BIT(5)
#define DS_VALIDATE BIT(6)
#define DS_DIRTY_UPDATE BIT(7)
/** /**
* Destination Scaler DUAL mode overfetch pixel count * Destination Scaler DUAL mode overfetch pixel count
@ -370,6 +375,8 @@ struct mdss_mdp_destination_scaler {
char __iomem *lut_base; char __iomem *lut_base;
u16 src_width; u16 src_width;
u16 src_height; u16 src_height;
u16 last_mixer_width;
u16 last_mixer_height;
u32 flags; u32 flags;
struct mdp_scale_data_v2 scaler; struct mdp_scale_data_v2 scaler;
}; };
@ -1706,6 +1713,7 @@ void mdss_mdp_pp_term(struct device *dev);
int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd); int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd);
void mdss_mdp_pp_dest_scaler_resume(struct mdss_mdp_ctl *ctl);
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl); int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl); int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl);

View file

@ -3508,7 +3508,9 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
if (is_dest_scaling_enable(ctl->mixer_left)) { if (is_dest_scaling_enable(ctl->mixer_left)) {
width = get_ds_input_width(ctl->mixer_left); width = get_ds_input_width(ctl->mixer_left);
height = get_ds_input_height(ctl->mixer_left); height = get_ds_input_height(ctl->mixer_left);
if (ctl->panel_data->next && is_pingpong_split(ctl->mfd)) if (is_dual_lm_single_display(ctl->mfd) ||
(ctl->panel_data->next &&
is_pingpong_split(ctl->mfd)))
width *= 2; width *= 2;
} else { } else {
width = get_panel_width(ctl); width = get_panel_width(ctl);
@ -3548,9 +3550,13 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
} }
if (split_fb) { if (split_fb) {
width = ctl->mfd->split_fb_left; if (is_dest_scaling_enable(ctl->mixer_left)) {
width += (pinfo->lcdc.border_left + width = get_ds_input_width(ctl->mixer_left);
pinfo->lcdc.border_right); } else {
width = ctl->mfd->split_fb_left;
width += (pinfo->lcdc.border_left +
pinfo->lcdc.border_right);
}
} else if (width > max_mixer_width) { } else if (width > max_mixer_width) {
width /= 2; width /= 2;
} }
@ -3576,8 +3582,12 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
return 0; return 0;
} }
if (split_fb) if (split_fb) {
width = ctl->mfd->split_fb_right; if (is_dest_scaling_enable(ctl->mixer_left))
width = get_ds_input_width(ctl->mixer_left);
else
width = ctl->mfd->split_fb_right;
}
if (width < ctl->width) { if (width < ctl->width) {
if (ctl->mixer_right == NULL) { if (ctl->mixer_right == NULL) {
@ -4038,6 +4048,7 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl)
if (ctl->mfd && ctl->panel_data) { if (ctl->mfd && ctl->panel_data) {
ctl->mfd->ipc_resume = true; ctl->mfd->ipc_resume = true;
mdss_mdp_pp_resume(ctl->mfd); mdss_mdp_pp_resume(ctl->mfd);
mdss_mdp_pp_dest_scaler_resume(ctl);
if (is_dsc_compression(&ctl->panel_data->panel_info)) { if (is_dsc_compression(&ctl->panel_data->panel_info)) {
/* /*

View file

@ -67,13 +67,89 @@ static inline void *u64_to_ptr(uint64_t address)
return (void *)(uintptr_t)address; return (void *)(uintptr_t)address;
} }
static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
{
struct mdss_data_type *mdata = ctl->mdata;
struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
if (test_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map)) {
if (ctl->mixer_left && ctl->mixer_right &&
ctl->mixer_left->ds && ctl->mixer_right->ds &&
ctl->mixer_left->ds->scaler.enable &&
ctl->mixer_right->ds->scaler.enable) {
/*
* DUAL mode disable
*/
ctl->mixer_left->width = get_panel_width(ctl);
ctl->mixer_left->height = get_panel_yres(pinfo);
ctl->mixer_left->width /= 2;
ctl->mixer_right->width = ctl->mixer_left->width;
ctl->mixer_right->height = ctl->mixer_left->height;
ctl->mixer_left->roi = (struct mdss_rect) { 0, 0,
ctl->mixer_left->width,
ctl->mixer_left->height };
ctl->mixer_right->roi = (struct mdss_rect) { 0, 0,
ctl->mixer_right->width,
ctl->mixer_right->height };
/*
* Disable destination scaler by resetting the control
* flags and also need to disable in the QSEED3
* settings.
*/
ctl->mixer_left->ds->flags = DS_SCALE_UPDATE |
DS_VALIDATE;
ctl->mixer_right->ds->flags = DS_SCALE_UPDATE |
DS_VALIDATE;
ctl->mixer_left->ds->scaler.enable = 0;
ctl->mixer_left->ds->scaler.detail_enhance.enable = 0;
ctl->mixer_right->ds->scaler.enable = 0;
ctl->mixer_right->ds->scaler.detail_enhance.enable = 0;
pr_debug("DS-Left+Right disable: left:%dx%d, right:%dx%d\n",
ctl->mixer_left->width,
ctl->mixer_left->height,
ctl->mixer_right->width,
ctl->mixer_right->height);
MDSS_XLOG(ctl->mixer_left->width,
ctl->mixer_left->height,
ctl->mixer_right->width,
ctl->mixer_right->height);
} else if (ctl->mixer_left && ctl->mixer_left->ds &&
ctl->mixer_left->ds->scaler.enable) {
/*
* Single DS disable
*/
ctl->mixer_left->width = get_panel_width(ctl);
ctl->mixer_left->height = get_panel_yres(pinfo);
ctl->mixer_left->roi = (struct mdss_rect) { 0, 0,
ctl->mixer_left->width,
ctl->mixer_left->height };
ctl->mixer_left->ds->flags = DS_SCALE_UPDATE |
DS_VALIDATE;
ctl->mixer_left->ds->scaler.enable = 0;
ctl->mixer_left->ds->scaler.detail_enhance.enable = 0;
pr_debug("DS-left disable: wxh=%dx%d\n",
ctl->mixer_left->width,
ctl->mixer_left->height);
MDSS_XLOG(ctl->mixer_left->width,
ctl->mixer_left->height);
}
}
}
static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data, static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
struct mdss_mdp_destination_scaler *ds, struct mdss_mdp_destination_scaler *ds,
u32 max_input_width, u32 max_output_width) u32 max_input_width, u32 max_output_width)
{ {
struct mdp_scale_data_v2 *scale; struct mdp_scale_data_v2 *scale;
ds->flags = (ds_data->flags & MDP_DESTSCALER_ENABLE) ? DS_ENABLE : 0; if (ds_data->flags & MDP_DESTSCALER_ENABLE)
ds->flags |= DS_ENABLE;
else
ds->flags &= ~DS_ENABLE;
if (ds_data->flags & (MDP_DESTSCALER_SCALE_UPDATE | if (ds_data->flags & (MDP_DESTSCALER_SCALE_UPDATE |
MDP_DESTSCALER_ENHANCER_UPDATE)) { MDP_DESTSCALER_ENHANCER_UPDATE)) {
@ -101,8 +177,12 @@ static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
ds->flags |= DS_SCALE_UPDATE; ds->flags |= DS_SCALE_UPDATE;
if (ds_data->flags & MDP_DESTSCALER_ENHANCER_UPDATE) if (ds_data->flags & MDP_DESTSCALER_ENHANCER_UPDATE)
ds->flags |= DS_ENHANCER_UPDATE; ds->flags |= DS_ENHANCER_UPDATE;
ds->src_width = scale->src_width[0];
ds->src_height = scale->src_height[0]; /*
* Update with LM resolution
*/
ds->src_width = ds_data->lm_width;
ds->src_height = ds_data->lm_height;
} }
if (ds_data->flags == 0) { if (ds_data->flags == 0) {
@ -110,6 +190,11 @@ static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
ds_data->dest_scaler_ndx); ds_data->dest_scaler_ndx);
} }
/*
* Confirm all check pass validation, and to be cleared in CTL after
* flush is issued.
*/
ds->flags |= DS_VALIDATE;
return 0; return 0;
} }
@ -118,7 +203,7 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
{ {
struct mdss_data_type *mdata; struct mdss_data_type *mdata;
struct mdss_panel_info *pinfo; struct mdss_panel_info *pinfo;
u16 mxleft_w = 0, mxleft_h = 0, mxright_w = 0, mxright_h = 0;
mdata = ctl->mdata; mdata = ctl->mdata;
/* /*
@ -134,7 +219,7 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
* height. * height.
*/ */
pinfo = &ctl->panel_data->panel_info; pinfo = &ctl->panel_data->panel_info;
if ((ds_data->lm_width > get_panel_xres(pinfo)) || if ((ds_data->lm_width > get_panel_width(ctl)) ||
(ds_data->lm_height > get_panel_yres(pinfo)) || (ds_data->lm_height > get_panel_yres(pinfo)) ||
(ds_data->lm_width == 0) || (ds_data->lm_width == 0) ||
(ds_data->lm_height == 0)) { (ds_data->lm_height == 0)) {
@ -142,14 +227,8 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
ds_data->lm_width, ds_data->lm_height); ds_data->lm_width, ds_data->lm_height);
return -EINVAL; return -EINVAL;
} }
mxleft_w = ds_data->lm_width;
ctl->width = ds_data->lm_width; mxleft_h = ds_data->lm_height;
ctl->height = ds_data->lm_height;
ctl->mixer_left->width = ds_data->lm_width;
ctl->mixer_left->height = ds_data->lm_height;
pr_debug("Update mixer-left width/height: %dx%d\n",
ds_data->lm_width, ds_data->lm_width);
} }
if (ctl->mixer_right && ctl->mixer_right->ds) { if (ctl->mixer_right && ctl->mixer_right->ds) {
@ -174,25 +253,51 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
* Split display both left and right should have the * Split display both left and right should have the
* same width and height * same width and height
*/ */
ctl->mixer_right->width = ds_data->lm_width; mxright_w = ds_data->lm_width;
ctl->mixer_right->height = ds_data->lm_height; mxright_h = ds_data->lm_height;
pr_debug("Update mixer-right width/height: %dx%d\n",
ds_data->lm_width, ds_data->lm_height);
if (ctl->mixer_left && if (ctl->mixer_left &&
((ctl->mixer_right->width != ((mxright_w != mxleft_w) ||
ctl->mixer_left->width) || (mxright_h != mxleft_h))) {
(ctl->mixer_right->height !=
ctl->mixer_left->height))) {
pr_err("Mismatch width/heigth in LM for split display\n"); pr_err("Mismatch width/heigth in LM for split display\n");
return -EINVAL; return -EINVAL;
} }
}
/*
* Update mixer and control dimension after successful
* pre-validation
*/
if (mxleft_w && mxleft_h) {
ctl->mixer_left->ds->last_mixer_width =
ctl->mixer_left->width;
ctl->mixer_left->ds->last_mixer_height =
ctl->mixer_left->height;
ctl->width = mxleft_w;
ctl->height = mxleft_h;
ctl->mixer_left->width = mxleft_w;
ctl->mixer_left->height = mxleft_h;
pr_debug("Update mixer-left width/height: %dx%d\n",
mxleft_w, mxleft_h);
}
if (mxright_w && mxright_h) {
ctl->mixer_right->ds->last_mixer_width =
ctl->mixer_right->width;
ctl->mixer_right->ds->last_mixer_height =
ctl->mixer_right->height;
ctl->mixer_right->width = mxright_w;
ctl->mixer_right->height = mxright_h;
pr_debug("Update mixer-right width/height: %dx%d\n",
mxright_w, mxright_h);
/* /*
* For split display, CTL width should be equal to * For split display, CTL width should be equal to
* whole panel size * whole panel size
*/ */
ctl->width += ds_data->lm_width; ctl->width += mxright_w;
} }
pr_debug("Updated CTL width:%d, height:%d\n", pr_debug("Updated CTL width:%d, height:%d\n",
@ -236,19 +341,23 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
MDSS_MDP_DS_OVERFETCH_SIZE, MDSS_MDP_DS_OVERFETCH_SIZE,
mdata->max_dest_scaler_output_width); mdata->max_dest_scaler_output_width);
if (ret) if (ret)
return ret; goto reset_mixer;
ret = __dest_scaler_data_setup(&ds_data[1], ds_right, ret = __dest_scaler_data_setup(&ds_data[1], ds_right,
mdata->max_dest_scaler_input_width - mdata->max_dest_scaler_input_width -
MDSS_MDP_DS_OVERFETCH_SIZE, MDSS_MDP_DS_OVERFETCH_SIZE,
mdata->max_dest_scaler_output_width); mdata->max_dest_scaler_output_width);
if (ret) if (ret)
return ret; goto reset_mixer;
ds_left->flags &= ~(DS_LEFT|DS_RIGHT); ds_left->flags &= ~(DS_LEFT|DS_RIGHT);
ds_left->flags |= DS_DUAL_MODE; ds_left->flags |= DS_DUAL_MODE;
ds_right->flags &= ~(DS_LEFT|DS_RIGHT); ds_right->flags &= ~(DS_LEFT|DS_RIGHT);
ds_right->flags |= DS_DUAL_MODE; ds_right->flags |= DS_DUAL_MODE;
MDSS_XLOG(ds_left->num, ds_left->src_width,
ds_left->src_height, ds_left->flags,
ds_right->num, ds_right->src_width,
ds_right->src_height, ds_right->flags);
break; break;
case DS_LEFT: case DS_LEFT:
@ -262,6 +371,11 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
ret = __dest_scaler_data_setup(&ds_data[0], ds_left, ret = __dest_scaler_data_setup(&ds_data[0], ds_left,
mdata->max_dest_scaler_input_width, mdata->max_dest_scaler_input_width,
mdata->max_dest_scaler_output_width); mdata->max_dest_scaler_output_width);
if (ret)
goto reset_mixer;
MDSS_XLOG(ds_left->num, ds_left->src_width,
ds_left->src_height, ds_left->flags);
break; break;
case DS_RIGHT: case DS_RIGHT:
@ -276,6 +390,11 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
ret = __dest_scaler_data_setup(&ds_data[0], ds_right, ret = __dest_scaler_data_setup(&ds_data[0], ds_right,
mdata->max_dest_scaler_input_width, mdata->max_dest_scaler_input_width,
mdata->max_dest_scaler_output_width); mdata->max_dest_scaler_output_width);
if (ret)
goto reset_mixer;
MDSS_XLOG(ds_right->num, ds_right->src_width,
ds_right->src_height, ds_right->flags);
break; break;
} }
@ -312,6 +431,40 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
pr_err("Invalid Dest-scaler output width/height: %d/%d\n", pr_err("Invalid Dest-scaler output width/height: %d/%d\n",
scaler_width, scaler_height); scaler_width, scaler_height);
ret = -EINVAL; ret = -EINVAL;
goto reset_mixer;
}
return ret;
reset_mixer:
/* reverting mixer and control dimension */
if (ctl->mixer_left && ctl->mixer_left->ds &&
ctl->mixer_left->ds->last_mixer_width) {
ctl->width = ctl->mixer_left->ds->last_mixer_width;
ctl->height = ctl->mixer_left->ds->last_mixer_height;
ctl->mixer_left->width =
ctl->mixer_left->ds->last_mixer_width;
ctl->mixer_left->height =
ctl->mixer_left->ds->last_mixer_height;
if (ds_left)
ds_left->flags &= ~DS_ENABLE;
MDSS_XLOG(ctl->width, ctl->height,
ctl->mixer_left->width,
ctl->mixer_left->height);
}
if (ctl->mixer_right && ctl->mixer_right->ds &&
ctl->mixer_right->ds->last_mixer_width) {
ctl->width += ctl->mixer_right->ds->last_mixer_width;
ctl->mixer_right->width =
ctl->mixer_right->ds->last_mixer_width;
ctl->mixer_right->height =
ctl->mixer_right->ds->last_mixer_height;
if (ds_right)
ds_right->flags &= ~DS_ENABLE;
MDSS_XLOG(ctl->width, ctl->height,
ctl->mixer_right->width,
ctl->mixer_right->height);
} }
return ret; return ret;
@ -1939,6 +2092,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
enum layer_pipe_q pipe_q_type; enum layer_pipe_q pipe_q_type;
enum layer_zorder_used zorder_used[MDSS_MDP_MAX_STAGE] = {0}; enum layer_zorder_used zorder_used[MDSS_MDP_MAX_STAGE] = {0};
enum mdss_mdp_pipe_rect rect_num; enum mdss_mdp_pipe_rect rect_num;
struct mdp_destination_scaler_data *ds_data;
ret = mutex_lock_interruptible(&mdp5_data->ov_lock); ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
if (ret) if (ret)
@ -2194,11 +2348,10 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
layer->z_order -= MDSS_MDP_STAGE_0; layer->z_order -= MDSS_MDP_STAGE_0;
} }
ds_data = commit->dest_scaler;
if (test_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map) && if (test_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map) &&
commit->dest_scaler && ds_data && (ds_data->flags & MDP_DESTSCALER_ENABLE) &&
commit->dest_scaler_cnt) { commit->dest_scaler_cnt) {
struct mdp_destination_scaler_data *ds_data =
commit->dest_scaler;
/* /*
* Find out which DS block to use based on DS commit info * Find out which DS block to use based on DS commit info
@ -2217,8 +2370,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
} }
ret = mdss_mdp_validate_destination_scaler(mfd, ret = mdss_mdp_validate_destination_scaler(mfd,
commit->dest_scaler, ds_data, ds_mode);
ds_mode);
if (ret) { if (ret) {
pr_err("fail to validate destination scaler\n"); pr_err("fail to validate destination scaler\n");
layer->error_code = ret; layer->error_code = ret;
@ -2472,6 +2624,7 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
struct file *file, struct mdp_layer_commit_v1 *commit) struct file *file, struct mdp_layer_commit_v1 *commit)
{ {
struct mdss_overlay_private *mdp5_data; struct mdss_overlay_private *mdp5_data;
struct mdp_destination_scaler_data *ds_data;
int rc = 0; int rc = 0;
if (!mfd || !commit) { if (!mfd || !commit) {
@ -2505,15 +2658,17 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
} }
} }
if (commit->dest_scaler && commit->dest_scaler_cnt) { ds_data = commit->dest_scaler;
if (ds_data && commit->dest_scaler_cnt &&
(ds_data->flags & MDP_DESTSCALER_ENABLE)) {
rc = mdss_mdp_destination_scaler_pre_validate(mdp5_data->ctl, rc = mdss_mdp_destination_scaler_pre_validate(mdp5_data->ctl,
commit->dest_scaler, ds_data, commit->dest_scaler_cnt);
commit->dest_scaler_cnt);
if (IS_ERR_VALUE(rc)) { if (IS_ERR_VALUE(rc)) {
pr_err("Destination scaler pre-validate failed\n"); pr_err("Destination scaler pre-validate failed\n");
return -EINVAL; return -EINVAL;
} }
} } else
mdss_mdp_disable_destination_scaler_setup(mdp5_data->ctl);
rc = mdss_mdp_avr_validate(mfd, commit); rc = mdss_mdp_avr_validate(mfd, commit);
if (IS_ERR_VALUE(rc)) { if (IS_ERR_VALUE(rc)) {

View file

@ -2480,6 +2480,28 @@ static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer)
if (!test_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map) || !ds) if (!test_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map) || !ds)
return 0; return 0;
/*
* Non-validated DS data will be related to PM event. It is required
* to send out last setup to match the mixer and panel configuration.
*/
if (!(ds->flags & DS_VALIDATE)) {
pr_debug("Apply old DS[%d] for non validate data\n", ds->num);
if (ds->flags & DS_ENABLE)
ds->flags |= (DS_SCALE_UPDATE | DS_ENHANCER_UPDATE);
ds->flags |= DS_VALIDATE;
}
/*
* If mark for dirty update, force update to scaler and detail
* enhancer.
*/
if (ds->flags & DS_DIRTY_UPDATE) {
pr_debug("Scale dirty update requested\n");
ds->flags |= (DS_SCALE_UPDATE | DS_ENHANCER_UPDATE |
DS_VALIDATE);
ds->flags &= ~DS_DIRTY_UPDATE;
}
ds_offset = ds->ds_base; ds_offset = ds->ds_base;
op_mode = readl_relaxed(MDSS_MDP_REG_DEST_SCALER_OP_MODE + op_mode = readl_relaxed(MDSS_MDP_REG_DEST_SCALER_OP_MODE +
ds_offset); ds_offset);
@ -2519,12 +2541,37 @@ static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer)
} }
/* Destinations scaler shared the flush with DSPP in control */ /* Destinations scaler shared the flush with DSPP in control */
if (ds->flags & DS_ENABLE) if (ds->flags & (DS_ENABLE | DS_VALIDATE)) {
pr_debug("FLUSH[%d]: flags:%X, op_mode:%x\n",
ds->num, ds->flags, op_mode);
ctl->flush_bits |= BIT(13 + ds->num); ctl->flush_bits |= BIT(13 + ds->num);
}
ds->flags &= ~DS_VALIDATE;
return 0; return 0;
} }
void mdss_mdp_pp_dest_scaler_resume(struct mdss_mdp_ctl *ctl)
{
if (!ctl || !ctl->mdata) {
pr_err("Invalid ctl\n");
return;
}
if (!test_bit(MDSS_CAPS_DEST_SCALER, ctl->mdata->mdss_caps_map))
return;
if (ctl->mixer_left && ctl->mixer_left->ds) {
ctl->mixer_left->ds->flags |= DS_DIRTY_UPDATE;
pr_debug("DS left mark dirty\n");
}
if (ctl->mixer_right && ctl->mixer_right->ds) {
ctl->mixer_right->ds->flags |= DS_DIRTY_UPDATE;
pr_debug("DS right mark dirty\n");
}
}
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl) int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
{ {
int ret = 0; int ret = 0;