Merge "msm: mdss: add multiple partial update support"
This commit is contained in:
commit
cb51868198
19 changed files with 468 additions and 60 deletions
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue