Merge "msm: mdss: add multiple partial update support"

This commit is contained in:
Linux Build Service Account 2016-11-08 11:18:38 -08:00 committed by Gerrit - the friendly Code Review server
commit cb51868198
19 changed files with 468 additions and 60 deletions

View file

@ -350,8 +350,13 @@ the fps window.
as below:
--> Reset GPIO value
--> Sleep value (in ms)
- qcom,partial-update-enabled: Boolean used to enable partial
- qcom,partial-update-enabled: String used to enable partial
panel update for command mode panels.
"none": partial update is disabled
"single_roi": default enable mode, only single roi is sent to panel
"dual_roi": two rois are merged into one big roi. Panel ddic should be able
to process two roi's along with the DCS command to send two rois.
disabled if property is not specified.
- qcom,mdss-dsi-horizontal-line-idle: List of width ranges (EC - SC) in pixels indicating
additional idle time in dsi clock cycles that is needed
to compensate for smaller line width.
@ -632,7 +637,7 @@ Example:
qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
qcom,mdss-tear-check-frame-rate = <6000>;
qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,dcs-cmd-by-left;
qcom,mdss-dsi-lp11-init;
qcom,mdss-dsi-init-delay-us = <100>;

View file

@ -388,7 +388,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@ -432,7 +432,7 @@
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};

View file

@ -376,7 +376,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};

View file

@ -409,7 +409,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@ -432,7 +432,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};
@ -480,7 +480,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 2 4 2 20 20>;
};

View file

@ -629,7 +629,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, 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
@ -343,7 +343,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@ -387,7 +387,7 @@
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};

View file

@ -397,7 +397,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@ -420,7 +420,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};
@ -468,7 +468,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};

View file

@ -382,7 +382,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&tlmm 51 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,partial-update-enabled;
qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 2 4 2 20 20>;
};

View file

@ -468,6 +468,7 @@ struct mdss_dsi_ctrl_pdata {
bool cmd_sync_wait_trigger;
struct mdss_rect roi;
struct mdss_dsi_dual_pu_roi dual_roi;
struct pwm_device *pwm_bl;
u32 pclk_rate;
u32 byte_clk_rate;

View file

@ -447,28 +447,82 @@ static int mdss_dsi_roi_merge(struct mdss_dsi_ctrl_pdata *ctrl,
static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */
static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */
/*
* Some panels can support multiple ROIs as part of the below commands
*/
static char caset_dual[] = {0x2a, 0x00, 0x00, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */
static char paset_dual[] = {0x2b, 0x00, 0x00, 0x05, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */
/* pack into one frame before sent */
static struct dsi_cmd_desc set_col_page_addr_cmd[] = {
{{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset)}, caset}, /* packed */
{{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset},
};
/* pack into one frame before sent */
static struct dsi_cmd_desc set_dual_col_page_addr_cmd[] = { /*packed*/
{{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset_dual)}, caset_dual},
{{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset_dual)}, paset_dual},
};
static void __mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
struct mdss_rect *roi, bool dual_roi)
{
if (dual_roi) {
struct mdss_rect *first, *second;
first = &ctrl->panel_data.panel_info.dual_roi.first_roi;
second = &ctrl->panel_data.panel_info.dual_roi.second_roi;
caset_dual[1] = (((first->x) & 0xFF00) >> 8);
caset_dual[2] = (((first->x) & 0xFF));
caset_dual[3] = (((first->x - 1 + first->w) & 0xFF00) >> 8);
caset_dual[4] = (((first->x - 1 + first->w) & 0xFF));
/* skip the MPU setting byte*/
caset_dual[6] = (((second->x) & 0xFF00) >> 8);
caset_dual[7] = (((second->x) & 0xFF));
caset_dual[8] = (((second->x - 1 + second->w) & 0xFF00) >> 8);
caset_dual[9] = (((second->x - 1 + second->w) & 0xFF));
set_dual_col_page_addr_cmd[0].payload = caset_dual;
paset_dual[1] = (((first->y) & 0xFF00) >> 8);
paset_dual[2] = (((first->y) & 0xFF));
paset_dual[3] = (((first->y - 1 + first->h) & 0xFF00) >> 8);
paset_dual[4] = (((first->y - 1 + first->h) & 0xFF));
/* skip the MPU setting byte */
paset_dual[6] = (((second->y) & 0xFF00) >> 8);
paset_dual[7] = (((second->y) & 0xFF));
paset_dual[8] = (((second->y - 1 + second->h) & 0xFF00) >> 8);
paset_dual[9] = (((second->y - 1 + second->h) & 0xFF));
set_dual_col_page_addr_cmd[1].payload = paset_dual;
} else {
caset[1] = (((roi->x) & 0xFF00) >> 8);
caset[2] = (((roi->x) & 0xFF));
caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8);
caset[4] = (((roi->x - 1 + roi->w) & 0xFF));
set_col_page_addr_cmd[0].payload = caset;
paset[1] = (((roi->y) & 0xFF00) >> 8);
paset[2] = (((roi->y) & 0xFF));
paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8);
paset[4] = (((roi->y - 1 + roi->h) & 0xFF));
set_col_page_addr_cmd[1].payload = paset;
}
pr_debug("%s Sending 2A 2B cmnd with dual_roi=%d\n", __func__,
dual_roi);
}
static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
struct mdss_rect *roi, int unicast)
{
struct dcs_cmd_req cmdreq;
struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
bool dual_roi = pinfo->dual_roi.enabled;
caset[1] = (((roi->x) & 0xFF00) >> 8);
caset[2] = (((roi->x) & 0xFF));
caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8);
caset[4] = (((roi->x - 1 + roi->w) & 0xFF));
set_col_page_addr_cmd[0].payload = caset;
paset[1] = (((roi->y) & 0xFF00) >> 8);
paset[2] = (((roi->y) & 0xFF));
paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8);
paset[4] = (((roi->y - 1 + roi->h) & 0xFF));
set_col_page_addr_cmd[1].payload = paset;
__mdss_dsi_send_col_page_addr(ctrl, roi, dual_roi);
memset(&cmdreq, 0, sizeof(cmdreq));
cmdreq.cmds_cnt = 2;
@ -478,7 +532,9 @@ static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
cmdreq.rlen = 0;
cmdreq.cb = NULL;
cmdreq.cmds = set_col_page_addr_cmd;
/* Send default or dual roi 2A/2B cmd */
cmdreq.cmds = dual_roi ? set_dual_col_page_addr_cmd :
set_col_page_addr_cmd;
mdss_dsi_cmdlist_put(ctrl, &cmdreq);
}
@ -1837,6 +1893,41 @@ error:
pinfo->esd_check_enabled = false;
}
static void mdss_dsi_parse_partial_update_caps(struct device_node *np,
struct mdss_dsi_ctrl_pdata *ctrl)
{
struct mdss_panel_info *pinfo;
const char *data;
pinfo = &ctrl->panel_data.panel_info;
data = of_get_property(np, "qcom,partial-update-enabled", NULL);
if (data && !strcmp(data, "single_roi"))
pinfo->partial_update_supported =
PU_SINGLE_ROI;
else if (data && !strcmp(data, "dual_roi"))
pinfo->partial_update_supported =
PU_DUAL_ROI;
else if (data && !strcmp(data, "none"))
pinfo->partial_update_supported =
PU_NOT_SUPPORTED;
else
pinfo->partial_update_supported =
PU_NOT_SUPPORTED;
if (pinfo->mipi.mode == DSI_CMD_MODE) {
pinfo->partial_update_enabled = pinfo->partial_update_supported;
pr_info("%s: partial_update_enabled=%d\n", __func__,
pinfo->partial_update_enabled);
ctrl->set_col_page_addr = mdss_dsi_set_col_page_addr;
if (pinfo->partial_update_enabled) {
pinfo->partial_update_roi_merge =
of_property_read_bool(np,
"qcom,partial-update-roi-merge");
}
}
}
static int mdss_dsi_parse_panel_features(struct device_node *np,
struct mdss_dsi_ctrl_pdata *ctrl)
{
@ -1849,19 +1940,7 @@ static int mdss_dsi_parse_panel_features(struct device_node *np,
pinfo = &ctrl->panel_data.panel_info;
pinfo->partial_update_supported = of_property_read_bool(np,
"qcom,partial-update-enabled");
if (pinfo->mipi.mode == DSI_CMD_MODE) {
pinfo->partial_update_enabled = pinfo->partial_update_supported;
pr_info("%s: partial_update_enabled=%d\n", __func__,
pinfo->partial_update_enabled);
ctrl->set_col_page_addr = mdss_dsi_set_col_page_addr;
if (pinfo->partial_update_enabled) {
pinfo->partial_update_roi_merge =
of_property_read_bool(np,
"qcom,partial-update-roi-merge");
}
}
mdss_dsi_parse_partial_update_caps(np, ctrl);
pinfo->dcs_cmd_by_left = of_property_read_bool(np,
"qcom,dcs-cmd-by-left");

View file

@ -564,7 +564,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
"min_fps=%d\nmax_fps=%d\npanel_name=%s\n"
"primary_panel=%d\nis_pluggable=%d\ndisplay_id=%s\n"
"is_cec_supported=%d\nis_pingpong_split=%d\n"
"dfps_porch_mode=%d\n",
"dfps_porch_mode=%d\npu_roi_cnt=%d\ndual_dsi=%d",
pinfo->partial_update_enabled,
pinfo->roi_alignment.xstart_pix_align,
pinfo->roi_alignment.width_pix_align,
@ -577,7 +577,8 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
pinfo->panel_name, pinfo->is_prim_panel,
pinfo->is_pluggable, pinfo->display_id,
pinfo->is_cec_supported, is_pingpong_split(mfd),
dfps_porch_mode);
dfps_porch_mode, pinfo->partial_update_enabled,
is_panel_split(mfd));
return ret;
}
@ -3282,6 +3283,7 @@ int mdss_fb_atomic_commit(struct fb_info *info,
mfd->msm_fb_backup.atomic_commit = true;
mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi;
mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi;
mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags;
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);

View file

@ -829,6 +829,9 @@ struct mdss_mdp_pipe {
struct mdss_mdp_format_params *src_fmt;
struct mdss_mdp_plane_sizes src_planes;
/* flag to re-store roi in case of pu dual-roi validation error */
bool restore_roi;
/* compression ratio from the source format */
struct mult_factor comp_ratio;
@ -1849,7 +1852,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
const struct mdss_rect *sci_rect);
void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
struct mdss_rect *dst_rect,
const struct mdss_rect *sci_rect);
const struct mdss_rect *sci_rect, bool normalize);
void rect_copy_mdss_to_mdp(struct mdp_rect *user, struct mdss_rect *kernel);
void rect_copy_mdp_to_mdss(struct mdp_rect *user, struct mdss_rect *kernel);
bool mdss_rect_overlap_check(struct mdss_rect *rect1, struct mdss_rect *rect2);

View file

@ -728,7 +728,7 @@ int mdss_mdp_get_pipe_overlap_bw(struct mdss_mdp_pipe *pipe,
/* crop rectangles */
if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
mdss_mdp_crop_rect(&src, &dst, roi);
mdss_mdp_crop_rect(&src, &dst, roi, true);
/*
* when doing vertical decimation lines will be skipped, hence there is
@ -1108,7 +1108,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
/* crop rectangles */
if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
mdss_mdp_crop_rect(&src, &dst, roi);
mdss_mdp_crop_rect(&src, &dst, roi, true);
pr_debug("v_total=%d, xres=%d fps=%d\n", v_total, xres, fps);
pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) dst_y=%d bpp=%d yuv=%d\n",

View file

@ -521,6 +521,56 @@ static void __update_avr_info(struct mdss_mdp_ctl *ctl,
ctl->avr_info.avr_mode = MDSS_MDP_AVR_ONE_SHOT;
}
/*
* __validate_dual_partial_update() - validation function for
* dual partial update ROIs
*
* - This function uses the commit structs "left_roi" and "right_roi"
* to pass the first and second ROI information for the multiple
* partial update feature.
* - Supports only SINGLE DSI with a max of 2 PU ROIs.
* - Not supported along with destination scalar.
* - Not supported when source-split is disabled.
* - Not supported with ping-pong split enabled.
*/
static int __validate_dual_partial_update(
struct mdss_mdp_ctl *ctl, struct mdp_layer_commit_v1 *commit)
{
struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
struct mdss_data_type *mdata = ctl->mdata;
struct mdss_rect first_roi, second_roi;
int ret = 0;
struct mdp_destination_scaler_data *ds_data = commit->dest_scaler;
if (!mdata->has_src_split
|| (is_panel_split(ctl->mfd))
|| (is_pingpong_split(ctl->mfd))
|| (ds_data && commit->dest_scaler_cnt &&
ds_data->flags & MDP_DESTSCALER_ENABLE)) {
pr_err("Invalid mode multi pu src_split:%d, split_mode:%d, ds_cnt:%d\n",
mdata->has_src_split, ctl->mfd->split_mode,
commit->dest_scaler_cnt);
ret = -EINVAL;
goto end;
}
rect_copy_mdp_to_mdss(&commit->left_roi, &first_roi);
rect_copy_mdp_to_mdss(&commit->right_roi, &second_roi);
if (!is_valid_pu_dual_roi(pinfo, &first_roi, &second_roi))
ret = -EINVAL;
MDSS_XLOG(ctl->num, first_roi.x, first_roi.y, first_roi.w, first_roi.h,
second_roi.x, second_roi.y, second_roi.w, second_roi.h,
ret);
pr_debug("Multiple PU ROIs - roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}, ret:%d\n",
first_roi.x, first_roi.y, first_roi.w, first_roi.h,
second_roi.x, second_roi.y, second_roi.w,
second_roi.h, ret);
end:
return ret;
}
/*
* __layer_needs_src_split() - check needs source split configuration
* @layer: input layer
@ -1000,6 +1050,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pipe->is_handed_off = false;
pipe->async_update = (layer->flags & MDP_LAYER_ASYNC) ? true : false;
pipe->csc_coeff_set = layer->color_space;
pipe->restore_roi = false;
if (mixer->ctl) {
pipe->dst.x += mixer->ctl->border_x_off;
@ -1007,7 +1058,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pr_debug("border{%d,%d}\n", mixer->ctl->border_x_off,
mixer->ctl->border_y_off);
}
pr_debug("src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n",
pr_debug("pipe:%d src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n", pipe->num,
pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h,
pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h);
@ -2625,6 +2676,7 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
{
struct mdss_overlay_private *mdp5_data;
struct mdp_destination_scaler_data *ds_data;
struct mdss_panel_info *pinfo;
int rc = 0;
if (!mfd || !commit) {
@ -2658,6 +2710,23 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
}
}
pinfo = mfd->panel_info;
if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
rc = __validate_dual_partial_update(mdp5_data->ctl,
commit);
if (IS_ERR_VALUE(rc)) {
pr_err("Multiple pu pre-validate fail\n");
return rc;
}
}
} else {
if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
pr_err("Multiple partial update not supported!\n");
return -EINVAL;
}
}
ds_data = commit->dest_scaler;
if (ds_data && commit->dest_scaler_cnt &&
(ds_data->flags & MDP_DESTSCALER_ENABLE)) {

View file

@ -1861,12 +1861,109 @@ int mdss_mode_switch_post(struct msm_fb_data_type *mfd, u32 mode)
return rc;
}
static void __restore_pipe(struct mdss_mdp_pipe *pipe)
{
if (!pipe->restore_roi)
return;
pr_debug("restoring pipe:%d dst from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n",
pipe->num, pipe->dst.x, pipe->dst.y,
pipe->dst.w, pipe->dst.h, pipe->layer.dst_rect.x,
pipe->layer.dst_rect.y, pipe->layer.dst_rect.w,
pipe->layer.dst_rect.h);
pr_debug("restoring pipe:%d src from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n",
pipe->num, pipe->src.x, pipe->src.y,
pipe->src.w, pipe->src.h, pipe->layer.src_rect.x,
pipe->layer.src_rect.y, pipe->layer.src_rect.w,
pipe->layer.src_rect.h);
pipe->src.x = pipe->layer.src_rect.x;
pipe->src.y = pipe->layer.src_rect.y;
pipe->src.w = pipe->layer.src_rect.w;
pipe->src.h = pipe->layer.src_rect.h;
pipe->dst.x = pipe->layer.dst_rect.x;
pipe->dst.y = pipe->layer.dst_rect.y;
pipe->dst.w = pipe->layer.dst_rect.w;
pipe->dst.h = pipe->layer.dst_rect.h;
}
/**
* __crop_adjust_pipe_rect() - Adjust pipe roi for dual partial
* update feature.
* @pipe: pipe to check against.
* @dual_roi: roi's for the dual partial roi.
*
* For dual PU ROI case, the layer mixer is configured
* by merging the two width aligned ROIs (first_roi and
* second_roi) vertically. So, the y-offset of all the
* pipes belonging to the second_roi needs to adjusted
* accordingly. Also the cropping of the pipe's src/dst
* rect has to be done with respect to the ROI the pipe
* is intersecting with, before the adjustment.
*/
static int __crop_adjust_pipe_rect(struct mdss_mdp_pipe *pipe,
struct mdss_dsi_dual_pu_roi *dual_roi)
{
u32 adjust_h;
u32 roi_y_pos;
int ret = 0;
pipe->restore_roi = false;
if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->first_roi)) {
mdss_mdp_crop_rect(&pipe->src, &pipe->dst,
&dual_roi->first_roi, false);
pipe->restore_roi = true;
} else if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->second_roi)) {
mdss_mdp_crop_rect(&pipe->src, &pipe->dst,
&dual_roi->second_roi, false);
adjust_h = dual_roi->second_roi.y;
roi_y_pos = dual_roi->first_roi.y + dual_roi->first_roi.h;
if (adjust_h > roi_y_pos) {
adjust_h = adjust_h - roi_y_pos;
pipe->dst.y -= adjust_h;
} else {
pr_err("wrong y-pos adjust_y:%d roi_y_pos:%d\n",
adjust_h, roi_y_pos);
ret = -EINVAL;
}
pipe->restore_roi = true;
} else {
ret = -EINVAL;
}
pr_debug("crop/adjusted p:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d} r:%d\n",
pipe->num, pipe->src.x, pipe->src.y,
pipe->src.w, pipe->src.h, pipe->dst.x,
pipe->dst.y, pipe->dst.w, pipe->dst.h,
pipe->restore_roi);
if (ret) {
pr_err("dual roi error p%d dst{%d,%d,%d,%d}",
pipe->num, pipe->dst.x, pipe->dst.y, pipe->dst.w,
pipe->dst.h);
pr_err(" roi1{%d,%d,%d,%d} roi2{%d,%d,%d,%d}\n",
dual_roi->first_roi.x, dual_roi->first_roi.y,
dual_roi->first_roi.w, dual_roi->first_roi.h,
dual_roi->second_roi.x, dual_roi->second_roi.y,
dual_roi->second_roi.w, dual_roi->second_roi.h);
}
return ret;
}
static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
struct mdp_display_commit *commit)
{
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
struct mdss_dsi_dual_pu_roi *dual_roi = &pinfo->dual_roi;
struct mdss_rect l_roi = {0}, r_roi = {0};
struct mdp_rect tmp_roi = {0};
bool skip_partial_update = true;
@ -1881,6 +1978,39 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
rect_copy_mdp_to_mdss(&commit->l_roi, &l_roi);
rect_copy_mdp_to_mdss(&commit->r_roi, &r_roi);
/*
* In case of dual partial update ROI, update the two ROIs to dual_roi
* struct and combine both the ROIs and assign it as a merged ROI in
* l_roi, as MDP would need only the merged ROI information for all
* LM settings.
*/
if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
if (!is_valid_pu_dual_roi(pinfo, &l_roi, &r_roi)) {
pr_err("Invalid dual roi - fall back to full screen update\n");
goto set_roi;
}
dual_roi->first_roi = (struct mdss_rect)
{l_roi.x, l_roi.y, l_roi.w, l_roi.h};
dual_roi->second_roi = (struct mdss_rect)
{r_roi.x, r_roi.y, r_roi.w, r_roi.h};
dual_roi->enabled = true;
l_roi.h += r_roi.h;
memset(&r_roi, 0, sizeof(struct mdss_rect));
pr_debug("Dual ROI - first_roi:{%d,%d,%d,%d}, second_roi:{%d,%d,%d,%d}\n",
dual_roi->first_roi.x, dual_roi->first_roi.y,
dual_roi->first_roi.w, dual_roi->first_roi.h,
dual_roi->second_roi.x, dual_roi->second_roi.y,
dual_roi->second_roi.w, dual_roi->second_roi.h);
} else {
dual_roi->enabled = false;
}
}
pr_debug("input: l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n",
l_roi.x, l_roi.y, l_roi.w, l_roi.h,
r_roi.x, r_roi.y, r_roi.w, r_roi.h);
@ -1926,12 +2056,24 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
}
list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
pr_debug("pipe:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d}\n",
pipe->num, pipe->src.x, pipe->src.y,
pipe->src.w, pipe->src.h, pipe->dst.x,
pipe->dst.y, pipe->dst.w, pipe->dst.h);
if (dual_roi->enabled) {
if (__crop_adjust_pipe_rect(pipe, dual_roi)) {
skip_partial_update = true;
break;
}
}
if (!__is_roi_valid(pipe, &l_roi, &r_roi)) {
skip_partial_update = true;
pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d\n",
pipe->num,
pipe->dst.x, pipe->dst.y,
pipe->dst.w, pipe->dst.h);
pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d, dual_pu_roi:%d\n",
pipe->num, pipe->dst.x, pipe->dst.y,
pipe->dst.w, pipe->dst.h,
dual_roi->enabled);
break;
}
}
@ -1946,13 +2088,24 @@ set_roi:
ctl->mixer_right->width,
ctl->mixer_right->height};
}
if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
if (dual_roi->enabled) {
/* we failed pu validation, restore pipes */
list_for_each_entry(pipe,
&mdp5_data->pipes_used, list)
__restore_pipe(pipe);
}
dual_roi->enabled = false;
}
}
pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n",
pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n",
(l_roi.w && l_roi.h && r_roi.w && r_roi.h) ? "left+right" :
((l_roi.w && l_roi.h) ? "left-only" : "right-only"),
l_roi.x, l_roi.y, l_roi.w, l_roi.h,
r_roi.x, r_roi.y, r_roi.w, r_roi.h);
r_roi.x, r_roi.y, r_roi.w, r_roi.h,
dual_roi->enabled);
mdss_mdp_set_roi(ctl, &l_roi, &r_roi);
}

View file

@ -1998,7 +1998,7 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
dst.x -= left_lm_w_from_mfd(pipe->mfd);
}
mdss_mdp_crop_rect(&src, &dst, &roi);
mdss_mdp_crop_rect(&src, &dst, &roi, true);
if (mdata->has_src_split && is_right_mixer) {
/*

View file

@ -241,7 +241,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
struct mdss_rect *dst_rect,
const struct mdss_rect *sci_rect)
const struct mdss_rect *sci_rect, bool normalize)
{
struct mdss_rect res;
mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
@ -253,9 +253,17 @@ void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
src_rect->w = res.w;
src_rect->h = res.h;
}
*dst_rect = (struct mdss_rect)
{(res.x - sci_rect->x), (res.y - sci_rect->y),
res.w, res.h};
/* adjust dest rect based on the sci_rect starting */
if (normalize) {
*dst_rect = (struct mdss_rect) {(res.x - sci_rect->x),
(res.y - sci_rect->y), res.w, res.h};
/* return the actual cropped intersecting rect */
} else {
*dst_rect = (struct mdss_rect) {res.x, res.y,
res.w, res.h};
}
}
}

View file

@ -137,6 +137,25 @@ enum {
SIM_HW_TE_MODE,
};
/*
* enum partial_update_mode - Different modes for partial update feature
*
* @PU_NOT_SUPPORTED: Feature is not supported on target.
* @PU_SINGLE_ROI: Default mode, only one ROI is triggered to the
* panel(one on each DSI in case of split dsi)
* @PU_DUAL_ROI: Support for sending two roi's that are clubbed
* together as one big single ROI. This is only
* supported on certain panels that have this
* capability in their DDIC.
*
*/
enum {
PU_NOT_SUPPORTED = 0,
PU_SINGLE_ROI,
PU_DUAL_ROI,
};
struct mdss_rect {
u16 x;
u16 y;
@ -664,6 +683,50 @@ struct mdss_panel_roi_alignment {
u32 min_height;
};
/*
* Nomeclature used to represent partial ROI in case of
* dual roi when the panel supports it. Region marked (XXX) is
* the extended roi to align with the second roi since LM output
* has to be rectangle.
*
* For single ROI, only the first ROI will be used in the struct.
* DSI driver will merge it based on the partial_update_roi_merge
* property.
*
* -------------------------------
* | DSI0 | DSI1 |
* -------------------------------
* | | |
* | | |
* | =========|=======----+ |
* | | | |XXXX| |
* | | First| Roi |XXXX| |
* | | | |XXXX| |
* | =========|=======----+ |
* | | |
* | | |
* | | |
* | +----================= |
* | |XXXX| | | |
* | |XXXX| Second Roi | |
* | |XXXX| | | |
* | +----====|============ |
* | | |
* | | |
* | | |
* | | |
* | | |
* ------------------------------
*
*/
struct mdss_dsi_dual_pu_roi {
struct mdss_rect first_roi;
struct mdss_rect second_roi;
bool enabled;
};
struct mdss_panel_info {
u32 xres;
u32 yres;
@ -689,6 +752,7 @@ struct mdss_panel_info {
u32 vic; /* video identification code */
u32 deep_color;
struct mdss_rect roi;
struct mdss_dsi_dual_pu_roi dual_roi;
int pwm_pmic_gpio;
int pwm_lpg_chan;
int pwm_period;
@ -723,8 +787,8 @@ struct mdss_panel_info {
u32 cont_splash_enabled;
bool esd_rdy;
bool partial_update_supported; /* value from dts if pu is supported */
bool partial_update_enabled; /* is pu currently allowed */
u32 partial_update_supported; /* value from dts if pu is supported */
u32 partial_update_enabled; /* is pu currently allowed */
u32 dcs_cmd_by_left;
u32 partial_update_roi_merge;
struct ion_handle *splash_ihdl;
@ -1000,6 +1064,27 @@ static inline bool is_lm_configs_dsc_compatible(struct mdss_panel_info *pinfo,
return true;
}
static inline bool is_valid_pu_dual_roi(struct mdss_panel_info *pinfo,
struct mdss_rect *first_roi, struct mdss_rect *second_roi)
{
if ((first_roi->x != second_roi->x) || (first_roi->w != second_roi->w)
|| (first_roi->y > second_roi->y)
|| ((first_roi->y + first_roi->h) > second_roi->y)
|| (is_dsc_compression(pinfo) &&
!is_lm_configs_dsc_compatible(pinfo,
first_roi->w, first_roi->h) &&
!is_lm_configs_dsc_compatible(pinfo,
second_roi->w, second_roi->h))) {
pr_err("Invalid multiple PU ROIs, roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}\n",
first_roi->x, first_roi->y, first_roi->w,
first_roi->h, second_roi->x, second_roi->y,
second_roi->w, second_roi->h);
return false;
}
return true;
}
int mdss_register_panel(struct platform_device *pdev,
struct mdss_panel_data *pdata);

View file

@ -147,6 +147,9 @@ VALIDATE/COMMIT FLAG CONFIGURATION
*/
#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
/* Flag to indicate dual partial ROI update */
#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20
/* Flag to enable concurrent writeback for the frame */
#define MDP_COMMIT_CWB_EN 0x800