summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h5
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c34
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h49
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c370
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c53
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c33
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c73
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h2
10 files changed, 456 insertions, 186 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 09bbd4c9e605..d207387f482a 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1952,9 +1952,14 @@ static int mdss_dsi_set_stream_size(struct mdss_panel_data *pdata)
/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
if (dsc) {
- stream_ctrl = ((dsc->bytes_in_slice + 1) << 16) |
- (pdata->panel_info.mipi.vc << 8) | DTYPE_DCS_LWRITE;
- stream_total = roi->h << 16 | dsc->pclk_per_line;
+ u16 byte_num = dsc->bytes_per_pkt;
+
+ if (pinfo->mipi.insert_dcs_cmd)
+ byte_num++;
+
+ stream_ctrl = (byte_num << 16) | (pinfo->mipi.vc << 8) |
+ DTYPE_DCS_LWRITE;
+ stream_total = dsc->pic_height << 16 | dsc->pclk_per_line;
} else {
stream_ctrl = (((roi->w * 3) + 1) << 16) |
@@ -1987,6 +1992,9 @@ static int mdss_dsi_set_stream_size(struct mdss_panel_data *pdata)
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x194, idle);
+ if (dsc)
+ mdss_dsi_dsc_config(ctrl_pdata, dsc);
+
return 0;
}
@@ -2058,11 +2066,13 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
int power_state;
u32 mode;
+ struct mdss_panel_info *pinfo;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ pinfo = &pdata->panel_info;
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
pr_debug("%s+: ctrl=%d event=%d\n", __func__, ctrl_pdata->ndx, event);
@@ -2135,6 +2145,10 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
rc = mdss_dsi_blank(pdata, MDSS_PANEL_POWER_OFF);
}
break;
+ case MDSS_EVENT_DSC_PPS_SEND:
+ if (pinfo->compression_mode == COMPRESSION_DSC)
+ mdss_dsi_panel_dsc_pps_send(ctrl_pdata, pinfo);
+ break;
case MDSS_EVENT_ENABLE_PARTIAL_ROI:
rc = mdss_dsi_ctl_partial_roi(pdata);
break;
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 0f5a3fae8fae..f96c3b584c94 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -633,8 +633,11 @@ int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl,
struct mdss_intf_recovery *recovery);
-void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_unregister_bl_settings(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct mdss_panel_info *pinfo);
+void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsc_desc *dsc);
static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module)
{
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 852d232d00ca..ed5256e2f7cf 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1089,8 +1089,7 @@ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
return ret;
}
-static void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsc_desc *dsc)
+void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc)
{
u32 data, offset;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index a7f9a2cf38de..8357428471d7 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -709,7 +709,7 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT);
if (pinfo->compression_mode == COMPRESSION_DSC)
- mdss_dsi_panel_dsc_pps_send(ctrl);
+ mdss_dsi_panel_dsc_pps_send(ctrl, pinfo);
if (ctrl->ds_registered) {
if (ctrl->dba_ops.video_on)
@@ -1171,15 +1171,14 @@ static int mdss_dsc_to_buf(struct dsc_desc *dsc, char *buf,
return DSC_PPS_LEN; /* 128 */
}
-void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl)
+void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct mdss_panel_info *pinfo)
{
- struct mdss_panel_info *pinfo;
struct dsc_desc *dsc;
struct dsi_panel_cmds pcmds;
struct dsi_cmd_desc cmd;
- pinfo = &(ctrl->panel_data.panel_info);
- if (pinfo->compression_mode != COMPRESSION_DSC)
+ if (!pinfo || (pinfo->compression_mode != COMPRESSION_DSC))
return;
memset(&pcmds, 0, sizeof(pcmds));
@@ -1214,7 +1213,7 @@ int mdss_dsc_initial_line_calc(int bpc, int xmit_delay,
return CEIL(total_pixels, slice_width);
}
-static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
+void mdss_dsc_parameters_calc(struct dsc_desc *dsc, int width, int height)
{
int bpp, bpc;
int mux_words_size;
@@ -1227,7 +1226,20 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
int data;
int final_value, final_scale;
int slice_per_line, bytes_in_slice, total_bytes;
- struct dsc_desc *dsc = &timing->dsc;
+
+ if (!dsc || !width || !height)
+ return;
+
+ dsc->pic_width = width;
+ dsc->pic_height = height;
+
+ if ((dsc->pic_width % dsc->slice_width) ||
+ (dsc->pic_height % dsc->slice_height)) {
+ pr_err("Error: pic_dim=%dx%d has to be multiple of slice_dim=%dx%d\n",
+ dsc->pic_width, dsc->pic_height,
+ dsc->slice_width, dsc->slice_height);
+ return;
+ }
dsc->rc_model_size = 8192; /* rate_buffer_size */
dsc->first_line_bpg_offset = 12;
@@ -1246,11 +1258,6 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
dsc->range_max_qp = dsc_rc_range_max_qp;
dsc->range_bpg_offset = dsc_rc_range_bpg_offset;
- dsc->initial_lines = 2;
-
- dsc->pic_width = timing->xres;
- dsc->pic_height = timing->yres;
-
bpp = dsc->bpp;
bpc = dsc->bpc;
@@ -1304,7 +1311,6 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
if ((dsc->slice_width * bpp) % 8)
dsc->chunk_size++;
-
/* rbs-min */
min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset +
dsc->initial_xmit_delay * bpp +
@@ -1479,7 +1485,7 @@ static int mdss_dsi_parse_dsc_params(struct device_node *np,
dsc->config_by_manufacture_cmd = of_property_read_bool(np,
"qcom,mdss-dsc-config-by-manufacture-cmd");
- mdss_dsc_parameters_calc(timing);
+ mdss_dsc_parameters_calc(&timing->dsc, timing->xres, timing->yres);
timing->compression_mode = COMPRESSION_DSC;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 85b0d613f40f..d26926a16952 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -278,6 +278,12 @@ struct mdss_mdp_ctl {
u32 slave_intf_num; /* ping-pong split */
u32 intf_type;
+ /*
+ * false: for sctl in DUAL_LM_DUAL_DISPLAY
+ * true: everything else
+ */
+ bool is_master;
+
u32 opmode;
u32 flush_bits;
u32 flush_reg_data;
@@ -328,10 +334,26 @@ struct mdss_mdp_ctl {
struct work_struct recover_work;
struct work_struct remove_underrun_handler;
+ /*
+ * This ROI is aligned to as per following guidelines and
+ * sent to the panel driver.
+ *
+ * 1. DUAL_LM_DUAL_DISPLAY
+ * Panel = 1440x2560
+ * CTL0 = 720x2560 (LM0=720x2560)
+ * CTL1 = 720x2560 (LM1=720x2560)
+ * Both CTL's ROI will be (0-719)x(0-2599)
+ * 2. DUAL_LM_SINGLE_DISPLAY
+ * Panel = 1440x2560
+ * CTL0 = 1440x2560 (LM0=720x2560 and LM1=720x2560)
+ * CTL0's ROI will be (0-1429)x(0-2599)
+ * 3. SINGLE_LM_SINGLE_DISPLAY
+ * Panel = 1080x1920
+ * CTL0 = 1080x1920 (LM0=1080x1920)
+ * CTL0's ROI will be (0-1079)x(0-1919)
+ */
struct mdss_rect roi;
struct mdss_rect roi_bkup;
- u8 roi_changed;
- u8 valid_roi;
bool cmd_autorefresh_en;
int autorefresh_frame_cnt;
@@ -361,7 +383,11 @@ struct mdss_mdp_mixer {
u8 params_changed;
u16 width;
u16 height;
+
+ bool valid_roi;
+ bool roi_changed;
struct mdss_rect roi;
+
u8 cursor_enabled;
u16 cursor_hotx;
u16 cursor_hoty;
@@ -724,6 +750,21 @@ enum mdss_mdp_clt_intf_event_flags {
#define mfd_to_wb(mfd) (((struct mdss_overlay_private *)\
(mfd->mdp.private1))->wb)
+/**
+ * - mdss_mdp_is_both_lm_valid
+ * @main_ctl - pointer to a main ctl
+ *
+ * Function checks if both layer mixers are active or not. This can be useful
+ * when partial update is enabled on either MDP_DUAL_LM_SINGLE_DISPLAY or
+ * MDP_DUAL_LM_DUAL_DISPLAY .
+ */
+static inline bool mdss_mdp_is_both_lm_valid(struct mdss_mdp_ctl *main_ctl)
+{
+ return (main_ctl && main_ctl->is_master &&
+ main_ctl->mixer_left && main_ctl->mixer_left->valid_roi &&
+ main_ctl->mixer_right && main_ctl->mixer_right->valid_roi);
+}
+
static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
struct mdss_mdp_ctl *ctl)
{
@@ -1346,4 +1387,8 @@ struct mdss_mdp_writeback *mdss_mdp_wb_assign(u32 id, u32 reg_index);
struct mdss_mdp_writeback *mdss_mdp_wb_alloc(u32 caps, u32 reg_index);
void mdss_mdp_wb_free(struct mdss_mdp_writeback *wb);
+void mdss_dsc_parameters_calc(struct dsc_desc *dsc, int width, int height);
+void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl,
+ struct mdss_panel_info *pinfo);
+
#endif /* MDSS_MDP_H */
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index ecf59e4f81a0..df392a9b779d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2391,76 +2391,48 @@ static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl,
return 0;
}
-static int __mdss_mdp_ctl_dsc_enable(bool enable,
- struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pinfo)
+static inline void mdss_mdp_ctl_dsc_enable(struct mdss_mdp_mixer *mixer)
{
- u32 data;
- u32 *lp;
- char *cp;
- int i, bpp, lsb;
- char __iomem *offset, *off;
- struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- struct dsc_desc *dsc = &pinfo->dsc;
-
- if (!mixer || !pinfo) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- if (pinfo->compression_mode != COMPRESSION_DSC) {
- pr_err("invalid compression mode = %d\n",
- pinfo->compression_mode);
- return -EPERM;
- }
-
- if (mixer->num != MDSS_MDP_INTF_LAYERMIXER0 &&
- mixer->num != MDSS_MDP_INTF_LAYERMIXER1) {
- pr_err("mix%d doesn't support DSC.\n", mixer->num);
- return -EPERM;
- }
-
- if (!enable) {
- mdss_mdp_pingpong_write(mixer->pingpong_base,
- MDSS_MDP_REG_PP_DSC_MODE, 0);
- return 0;
- }
-
- /* dsc enable */
mdss_mdp_pingpong_write(mixer->pingpong_base,
MDSS_MDP_REG_PP_DSC_MODE, 1);
+}
+
+static inline void mdss_mdp_ctl_dsc_disable(struct mdss_mdp_mixer *mixer)
+{
+ mdss_mdp_pingpong_write(mixer->pingpong_base,
+ MDSS_MDP_REG_PP_DSC_MODE, 0);
+}
+
+static void mdss_mdp_ctl_dsc_config(struct mdss_mdp_mixer *mixer,
+ struct dsc_desc *dsc, u32 mode)
+{
+ u32 data;
+ int bpp, lsb;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ char __iomem *offset = mdata->mdp_base;
data = mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP);
- data |= BIT(18); /* endian flip */
+ data |= BIT(18); /* endian flip */
mdss_mdp_pingpong_write(mixer->pingpong_base,
MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP, data);
- if (pinfo->type == MIPI_VIDEO_PANEL)
- data = BIT(2); /* vieo mode */
-
- /* split display with independent decoders is not handled yet */
- if (pinfo->is_split_display)
- data |= BIT(0);
-
- /* need to handle a use-case of single_lm_pp_split_dsc_merge */
- if ((mixer->ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
- (pinfo->dsc_enc_total == 2))
- data |= (BIT(0) | BIT(1));
-
- offset = mdata->mdp_base;
-
/* dce0_sel->pp0, dce1_sel->pp1 */
writel_relaxed(0x0, offset + MDSS_MDP_REG_DCE_SEL);
- if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0)
+ if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0) {
offset += MDSS_MDP_DSC_0_OFFSET;
- else
+ } else if (mixer->num == MDSS_MDP_INTF_LAYERMIXER1) {
offset += MDSS_MDP_DSC_1_OFFSET;
+ } else {
+ pr_err("invalid mixer numer=%d\n", mixer->num);
+ return;
+ }
- writel_relaxed(data, offset + MDSS_MDP_REG_DSC_COMMON_MODE);
+ writel_relaxed(mode, offset + MDSS_MDP_REG_DSC_COMMON_MODE);
- data = dsc->ich_reset_value | dsc->ich_reset_override;
- data <<= 28;
+ data = dsc->ich_reset_override << 28;
+ data |= dsc->ich_reset_value << 29;
data |= (dsc->initial_lines << 20);
data |= ((dsc->slice_last_group_size - 1) << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
@@ -2495,9 +2467,11 @@ static int __mdss_mdp_ctl_dsc_enable(bool enable,
data = dsc->chunk_size << 16;
writel_relaxed(data, offset + MDSS_MDP_REG_DSC_CHUNK_SIZE);
- pr_debug("pic_w=%d pic_h=%d, slice_h=%d slice_w=%d, chunk=%d\n",
- dsc->pic_width, dsc->pic_height,
- dsc->slice_width, dsc->slice_height, dsc->chunk_size);
+ pr_debug("mix%d pic_w=%d pic_h=%d, slice_h=%d slice_w=%d, chunk=%d\n",
+ mixer->num, dsc->pic_width, dsc->pic_height,
+ dsc->slice_width, dsc->slice_height, dsc->chunk_size);
+ MDSS_XLOG(mixer->num, dsc->pic_width, dsc->pic_height,
+ dsc->slice_width, dsc->slice_height, dsc->chunk_size);
data = dsc->initial_dec_delay << 16;
data |= dsc->initial_xmit_delay;
@@ -2538,6 +2512,28 @@ static int __mdss_mdp_ctl_dsc_enable(bool enable,
data |= dsc->quant_incr_limit0 << 4;
data |= dsc->edge_factor;
writel_relaxed(data, offset + MDSS_MDP_REG_DSC_RC);
+}
+
+static void mdss_mdp_ctl_dsc_config_thresh(struct mdss_mdp_mixer *mixer,
+ struct mdss_panel_info *pinfo)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ struct dsc_desc *dsc = &pinfo->dsc;
+ char __iomem *offset, *off;
+ u32 *lp;
+ char *cp;
+ int i;
+
+ offset = mdata->mdp_base;
+
+ if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0) {
+ offset += MDSS_MDP_DSC_0_OFFSET;
+ } else if (mixer->num == MDSS_MDP_INTF_LAYERMIXER1) {
+ offset += MDSS_MDP_DSC_1_OFFSET;
+ } else {
+ pr_err("invalid mixer numer=%d\n", mixer->num);
+ return;
+ }
lp = dsc->buf_thresh;
off = offset + MDSS_MDP_REG_DSC_RC_BUF_THRESH;
@@ -2566,25 +2562,97 @@ static int __mdss_mdp_ctl_dsc_enable(bool enable,
writel_relaxed(*cp++, off);
off += 4;
}
-
- return 0;
}
-static int mdss_mdp_ctl_dsc_enable(bool enable,
- struct mdss_mdp_ctl *ctl, struct mdss_panel_info *pinfo)
+/* called for each ctl */
+void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl,
+ struct mdss_panel_info *pinfo)
{
- int rc;
- struct mdss_mdp_mixer *mixer = ctl->mixer_left;
+ struct mdss_mdp_mixer *mixer_left = ctl->mixer_left;
+ struct mdss_mdp_mixer *mixer_right = NULL;
+ struct dsc_desc *dsc = &pinfo->dsc;
+ u32 pic_width = 0, pic_height = 0;
+ u32 mode = 0;
+ bool recalc_dsc_params = false;
- rc = __mdss_mdp_ctl_dsc_enable(enable, mixer, pinfo);
- if (rc)
- return rc;
+ if (pinfo->type == MIPI_VIDEO_PANEL)
+ mode = BIT(2);
- if (mixer->ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY)
- rc = __mdss_mdp_ctl_dsc_enable(enable,
- ctl->mixer_right, pinfo);
+ /* pingpong split with DSC needs to be handled */
+ if (is_split_lm(ctl->mfd)) {
+ struct mdss_mdp_ctl *main_ctl;
- return rc;
+ if (ctl->is_master)
+ main_ctl = ctl;
+ else
+ main_ctl = mdss_mdp_get_main_ctl(ctl);
+
+ if (!main_ctl) {
+ pr_err("%pS: invalid input\n",
+ __builtin_return_address(0));
+ return;
+ }
+
+ /*
+ * two independent decoders on DDIC requires
+ * split 2p2d mode but it is not supported yet.
+ */
+ if (mdss_mdp_is_both_lm_valid(main_ctl))
+ mode |= BIT(0); /* assumming 1 decoder on panel side */
+
+ if (main_ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) {
+
+ mixer_right = main_ctl->mixer_right;
+
+ /* DSC Merge */
+ if ((pinfo->dsc_enc_total == 2) &&
+ (mdss_mdp_is_both_lm_valid(main_ctl)))
+ mode |= BIT(1);
+ }
+ }
+
+ if (mixer_left->valid_roi) {
+ pic_width = mixer_left->roi.w;
+ pic_height = mixer_left->roi.h;
+ recalc_dsc_params = true;
+ }
+
+ if (mixer_right && mixer_right->valid_roi) {
+ pic_width += mixer_right->roi.w;
+ pic_height = mixer_right->roi.h; /* height on both lm is same */
+ recalc_dsc_params = true;
+ }
+
+ /* re-calculate DSC params before configuring them to MDP */
+ if (recalc_dsc_params)
+ mdss_dsc_parameters_calc(dsc, pic_width, pic_height);
+
+ if (mixer_left->valid_roi) {
+ mdss_mdp_ctl_dsc_config(mixer_left, dsc, mode);
+ mdss_mdp_ctl_dsc_config_thresh(mixer_left, pinfo);
+ mdss_mdp_ctl_dsc_enable(mixer_left);
+ } else {
+ mdss_mdp_ctl_dsc_disable(mixer_left);
+ }
+
+ if (mixer_right) {
+ if (mixer_right->valid_roi) {
+ mdss_mdp_ctl_dsc_config(mixer_right, dsc, mode);
+ mdss_mdp_ctl_dsc_config_thresh(mixer_right, pinfo);
+ mdss_mdp_ctl_dsc_enable(mixer_right);
+ } else {
+ mdss_mdp_ctl_dsc_disable(mixer_right);
+ }
+ }
+ pr_debug("mix%d: valid_roi=%d mix%d: valid_roi=%d mode=%d, pic_dim:%dx%d\n",
+ mixer_left->num, mixer_left->valid_roi,
+ mixer_right ? mixer_right->num : -1,
+ mixer_right ? mixer_right->valid_roi : -1,
+ mode, pic_width, pic_height);
+ MDSS_XLOG(mixer_left->num, mixer_left->valid_roi,
+ mixer_right ? mixer_right->num : -1,
+ mixer_right ? mixer_right->valid_roi : -1,
+ mode, pic_width, pic_height);
}
static int mdss_mdp_ctl_fbc_enable(int enable,
@@ -2711,7 +2779,8 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
ctl->mixer_left->width = width;
ctl->mixer_left->height = height;
ctl->mixer_left->roi = (struct mdss_rect) {0, 0, width, height};
- ctl->valid_roi = true;
+ ctl->mixer_left->valid_roi = true;
+ ctl->mixer_left->roi_changed = true;
if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
pr_debug("dual display detected\n");
@@ -2737,7 +2806,11 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
ctl->mixer_right->height = height;
ctl->mixer_right->roi = (struct mdss_rect)
{0, 0, width, height};
+ ctl->mixer_right->valid_roi = true;
+ ctl->mixer_right->roi_changed = true;
} else if (ctl->mixer_right) {
+ ctl->mixer_right->valid_roi = false;
+ ctl->mixer_right->roi_changed = false;
mdss_mdp_mixer_free(ctl->mixer_right);
ctl->mixer_right = NULL;
}
@@ -2991,7 +3064,8 @@ int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
mixer->height = sctl->height;
mixer->roi = (struct mdss_rect)
{0, 0, mixer->width, mixer->height};
- sctl->valid_roi = true;
+ mixer->valid_roi = true;
+ mixer->roi_changed = true;
sctl->mixer_left = mixer;
return mdss_mdp_set_split_ctl(ctl, sctl);
@@ -3150,10 +3224,8 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl)
if (ctl->panel_data->panel_info.compression_mode ==
COMPRESSION_DSC) {
- ret = mdss_mdp_ctl_dsc_enable(1, ctl,
+ mdss_mdp_ctl_dsc_setup(ctl,
&ctl->panel_data->panel_info);
- if (ret)
- pr_err("Failed to restore DSC mode\n");
} else if (ctl->panel_data->panel_info.compression_mode ==
COMPRESSION_FBC) {
ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left,
@@ -3258,9 +3330,7 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff)
mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize);
if (pinfo->compression_mode == COMPRESSION_DSC) {
- ret = mdss_mdp_ctl_dsc_enable(true, ctl, pinfo);
- if (ret)
- pr_err("dsc_enable failed. rc=%d\n", ret);
+ mdss_mdp_ctl_dsc_setup(ctl, pinfo);
} else if (pinfo->compression_mode == COMPRESSION_FBC) {
ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left,
pinfo);
@@ -3484,29 +3554,6 @@ int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery)
return (!cnt) ? -EAGAIN : 0;
}
-static void mdss_mdp_set_mixer_roi(struct mdss_mdp_ctl *ctl,
- struct mdss_rect *roi)
-{
- struct mdss_rect mixer_roi;
-
- ctl->valid_roi = (roi->w && roi->h);
- ctl->roi_changed = 0;
- if (!mdss_rect_cmp(roi, &ctl->roi)) {
- ctl->roi = *roi;
- ctl->roi_changed++;
-
- mixer_roi = ctl->mixer_left->roi;
- if ((mixer_roi.w != roi->w) ||
- (mixer_roi.h != roi->h)) {
- ctl->mixer_left->roi = *roi;
- ctl->mixer_left->params_changed++;
- }
- }
-
- pr_debug("ROI requested: [%d]: [%d, %d, %d, %d]\n",
- ctl->num, ctl->roi.x, ctl->roi.y, ctl->roi.w, ctl->roi.h);
-}
-
/*
* mdss_mdp_mixer_update_pipe_map() - keep track of pipe configuration in mixer
* @master_ctl: mdp controller.
@@ -3529,9 +3576,31 @@ static void mdss_mdp_mixer_update_pipe_map(struct mdss_mdp_ctl *master_ctl,
mixer->pipe_mapped = mixer->next_pipe_map;
}
+static void mdss_mdp_set_mixer_roi(struct mdss_mdp_mixer *mixer,
+ struct mdss_rect *roi)
+{
+ mixer->valid_roi = (roi->w && roi->h);
+ mixer->roi_changed = false;
+
+ if (!mdss_rect_cmp(roi, &mixer->roi)) {
+ mixer->roi = *roi;
+ mixer->params_changed++;
+ mixer->roi_changed = true;
+ }
+
+ pr_debug("mixer%d ROI %s: [%d, %d, %d, %d]\n",
+ mixer->num, mixer->roi_changed ? "changed" : "not changed",
+ mixer->roi.x, mixer->roi.y, mixer->roi.w, mixer->roi.h);
+ MDSS_XLOG(mixer->num, mixer->roi_changed, mixer->valid_roi,
+ mixer->roi.x, mixer->roi.y, mixer->roi.w, mixer->roi.h);
+}
+
+/* only call from master ctl */
void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
struct mdss_rect *l_roi, struct mdss_rect *r_roi)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
/* Reset ROI when we have (1) invalid ROI (2) feature disabled */
if ((!l_roi->w && l_roi->h) || (l_roi->w && !l_roi->h) ||
(!r_roi->w && r_roi->h) || (r_roi->w && !r_roi->h) ||
@@ -3549,10 +3618,45 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
}
}
- mdss_mdp_set_mixer_roi(ctl, l_roi);
+ mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi);
+ ctl->roi = ctl->mixer_left->roi;
- if (ctl->mixer_right)
- mdss_mdp_set_mixer_roi(ctl->mixer_right->ctl, r_roi);
+ if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+
+ mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi);
+ sctl->roi = sctl->mixer_left->roi;
+ } else if (ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) {
+
+ 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;
+
+ /* right_only, update roi.x as per CTL ROI guidelines */
+ if (!ctl->mixer_left->valid_roi)
+ ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
+ ctl->mixer_right->roi.x;
+ }
+
+ /*
+ * When source split is enabled, dst_x of all pipes staged on right
+ * layer-mixer (LM) has to be greater than left LM's width.
+ * Now when partial update is enabled, let's say frame N is updating
+ * full panel width so both LMs are valid thus source split is enabled
+ * and dst_x of all pipes is as per above requirement. Now when frame
+ * N+1 is right-only update without any geomatry changes, pipe's params
+ * are not changed and right LM's roi is also not changed. So if
+ * params are not changed then pipe's register programming is skipped.
+ * So for that right-only update, pipe's dst_x remains same
+ * as frame N, which not correct and can lead to unknown behaviour.
+ * Fix this by identifying this condition and forcing roi changed for
+ * right LM.
+ */
+ if (is_split_lm(ctl->mfd) && mdata->has_src_split &&
+ (!ctl->mixer_left->valid_roi && ctl->mixer_left->roi_changed) &&
+ (ctl->mixer_right->valid_roi && !ctl->mixer_right->roi_changed))
+ ctl->mixer_right->roi_changed = true;
}
u32 mdss_mdp_get_mixer_mask(u32 pipe_num, u32 stage)
@@ -3628,8 +3732,21 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
return;
}
- if (!ctl->valid_roi)
+ if (!mixer->valid_roi) {
+ /*
+ * resetting mixer config is specifically needed when split
+ * mode is MDP_DUAL_LM_SINGLE_DISPLAY but update is only on
+ * one side.
+ */
+ off = __mdss_mdp_ctl_get_mixer_off(mixer);
+ mdss_mdp_ctl_write(ctl, off, 0);
+ /* Program ctl layer extension bits */
+ mdss_mdp_ctl_write(ctl,
+ off + MDSS_MDP_REG_CTL_LAYER_EXTN_OFFSET, 0);
+
+ MDSS_XLOG(mixer->num, XLOG_FUNC_EXIT);
return;
+ }
trace_mdp_mixer_update(mixer->num);
pr_debug("setup mixer=%d\n", mixer->num);
@@ -4415,8 +4532,7 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
{
struct mdss_mdp_ctl *sctl = NULL;
int ret = 0;
- bool is_bw_released;
- int split_enable;
+ bool is_bw_released, split_lm_valid;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 ctl_flush_bits = 0, sctl_flush_bits = 0;
@@ -4433,6 +4549,8 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
return 0;
}
+ split_lm_valid = mdss_mdp_is_both_lm_valid(ctl);
+
sctl = mdss_mdp_get_split_ctl(ctl);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
@@ -4450,26 +4568,22 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
}
/* left update */
- if (ctl->valid_roi)
+ if (ctl->mixer_left->valid_roi)
mdss_mdp_ctl_perf_set_transaction_status(ctl,
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
/* right update */
- if (sctl && sctl->valid_roi)
+ if (sctl && sctl->mixer_left->valid_roi)
mdss_mdp_ctl_perf_set_transaction_status(sctl,
PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
- if (mdata->has_src_split) {
- if (sctl)
- sctl->mixer_left->src_split_req =
- (ctl->valid_roi == sctl->valid_roi);
- else if (ctl->mixer_right) /* single ctl, dual LM */
- ctl->mixer_right->src_split_req = ctl->valid_roi;
- }
+ if (ctl->mixer_right)
+ ctl->mixer_right->src_split_req =
+ mdata->has_src_split && split_lm_valid;
if (is_bw_released || ctl->force_screen_state ||
- (ctl->mixer_left && ctl->mixer_left->params_changed) ||
- (ctl->mixer_right && ctl->mixer_right->params_changed)) {
+ (ctl->mixer_left->params_changed) ||
+ (ctl->mixer_right && ctl->mixer_right->params_changed)) {
ATRACE_BEGIN("prepare_fnc");
if (ctl->ops.prepare_fnc)
ret = ctl->ops.prepare_fnc(ctl, arg);
@@ -4500,12 +4614,10 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
/*
* With partial frame update, enable split display bit only
- * when validity of ROI's on both the DSI's are identical
+ * when validity of ROI's on both the DSI's are identical.
*/
- if (sctl) {
- split_enable = (ctl->valid_roi == sctl->valid_roi);
- mdss_mdp_ctl_split_display_enable(split_enable, ctl, sctl);
- }
+ if (sctl)
+ mdss_mdp_ctl_split_display_enable(split_lm_valid, ctl, sctl);
ATRACE_BEGIN("postproc_programming");
if (ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER)
@@ -4629,7 +4741,8 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
sctl_flush_bits);
sctl->flush_bits = 0;
}
- MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits);
+ MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits,
+ split_lm_valid);
wmb();
ctl->flush_reg_data = ctl_flush_bits;
ctl->flush_bits = 0;
@@ -4637,7 +4750,9 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
mdss_mdp_mixer_update_pipe_map(ctl, MDSS_MDP_MIXER_MUX_LEFT);
mdss_mdp_mixer_update_pipe_map(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
- if (sctl && !ctl->valid_roi && sctl->valid_roi) {
+ /* right-only kickoff */
+ if (!ctl->mixer_left->valid_roi &&
+ sctl && sctl->mixer_left->valid_roi) {
/*
* Seperate kickoff on DSI1 is needed only when we have
* ONLY right half updating on a dual DSI panel
@@ -4649,11 +4764,6 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
ret = ctl->ops.display_fnc(ctl, arg); /* DSI0 kickoff */
}
- if (sctl)
- sctl->valid_roi = 0;
-
- ctl->valid_roi = 0;
-
if (ret)
pr_warn("ctl %d error displaying frame\n", ctl->num);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index 1e90a2bd852d..e39c4c5daab0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1510,11 +1510,40 @@ static void mdss_mdp_cmd_set_sync_ctx(
}
}
+/* only master ctl is valid and pingpong split with DSC is pending */
+static void mdss_mdp_cmd_dsc_reconfig(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_panel_info *pinfo, *spinfo;
+ struct mdss_mdp_ctl *sctl = NULL;
+ bool changed = false;
+
+ if (!ctl || !ctl->is_master)
+ return;
+
+ pinfo = &ctl->panel_data->panel_info;
+ if (pinfo->compression_mode != COMPRESSION_DSC)
+ return;
+
+ sctl = mdss_mdp_get_split_ctl(ctl);
+
+ changed = ctl->mixer_left->roi_changed;
+ if (ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY)
+ changed |= ctl->mixer_right->roi_changed;
+
+ if (changed)
+ mdss_mdp_ctl_dsc_setup(ctl, pinfo);
+
+ if (sctl && sctl->mixer_left->roi_changed) {
+ spinfo = &sctl->panel_data->panel_info;
+ mdss_mdp_ctl_dsc_setup(sctl, spinfo);
+ }
+}
+
static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl)
{
- int rc = 0;
+ int rc = -EINVAL;
- if (!ctl->panel_data->panel_info.partial_update_supported)
+ if (!ctl->panel_data->panel_info.partial_update_enabled)
return rc;
/* set panel col and page addr */
@@ -1525,9 +1554,9 @@ static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl)
static int mdss_mdp_cmd_set_stream_size(struct mdss_mdp_ctl *ctl)
{
- int rc = 0;
+ int rc = -EINVAL;
- if (!ctl->panel_data->panel_info.partial_update_supported)
+ if (!ctl->panel_data->panel_info.partial_update_enabled)
return rc;
/* set dsi controller stream size */
@@ -1759,6 +1788,8 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
*/
mdss_mdp_resource_control(ctl, MDP_RSRC_CTL_EVENT_KICKOFF);
+ mdss_mdp_cmd_dsc_reconfig(ctl);
+
mdss_mdp_cmd_set_partial_roi(ctl);
/*
@@ -1814,11 +1845,21 @@ int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl, bool locked)
{
struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
+ if (!ctl)
+ return -EINVAL;
+
pr_debug("%s: called for ctl%d\n", __func__, ctl->num);
ctx = (struct mdss_mdp_cmd_ctx *)ctl->intf_ctx[MASTER_CTX];
- if (is_pingpong_split(ctl->mfd))
+ if (is_pingpong_split(ctl->mfd)) {
sctx = (struct mdss_mdp_cmd_ctx *)ctl->intf_ctx[SLAVE_CTX];
+ } else if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+
+ if (sctl)
+ sctx = (struct mdss_mdp_cmd_ctx *)
+ sctl->intf_ctx[MASTER_CTX];
+ }
if (mdss_mdp_cmd_tearcheck_setup(ctx, locked)) {
pr_warn("%s: ctx%d tearcheck setup failed\n", __func__,
@@ -2309,6 +2350,8 @@ void mdss_mdp_switch_roi_reset(struct mdss_mdp_ctl *ctl)
if (sctl && sctl->panel_data)
sctl->panel_data->panel_info.roi = sctl->roi;
+ mdss_mdp_cmd_dsc_reconfig(ctl);
+
mdss_mdp_cmd_set_partial_roi(ctl);
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 1faa13be73eb..f8c41c4dc97b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1618,8 +1618,27 @@ static bool __is_roi_valid(struct mdss_mdp_pipe *pipe,
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 left_lm_w = left_lm_w_from_mfd(pipe->mfd);
- if (pipe->src_split_req)
- roi.w += r_roi->w;
+ if (pipe->src_split_req) {
+ if (roi.w) {
+ /* left_roi is valid */
+ roi.w += r_roi->w;
+ } else {
+ /*
+ * if we come here then left_roi is zero but pipe's
+ * output is crossing LM boundary if it was Full Screen
+ * update. In such case, if right ROI's (x+w) is less
+ * than pipe's dst_x then #2 check will fail even
+ * though in full coordinate system it is valid.
+ * ex:
+ * left_lm_w = 800;
+ * pipe->dst.x = 400;
+ * pipe->dst.w = 800;
+ * r_roi.x + r_roi.w = 300;
+ * To avoid such pitfall, extend ROI for comparison.
+ */
+ roi.w += left_lm_w + r_roi->w;
+ }
+ }
if (mdata->has_src_split && is_right_mixer)
dst.x -= left_lm_w;
@@ -1777,7 +1796,7 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
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_rect l_roi, r_roi;
+ struct mdss_rect l_roi = {0}, r_roi = {0};
struct mdp_rect tmp_roi = {0};
bool skip_partial_update = true;
@@ -1851,6 +1870,13 @@ set_roi:
ctl->mixer_right->height};
}
}
+
+ pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %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);
+
mdss_mdp_set_roi(ctl, &l_roi, &r_roi);
}
@@ -4455,6 +4481,7 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
rc = PTR_ERR(ctl);
goto error;
}
+ ctl->is_master = true;
ctl->vsync_handler.vsync_handler =
mdss_mdp_overlay_handle_vsync;
ctl->vsync_handler.cmd_post_flush = false;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 1cea4cc40ea3..b14dd179953e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -1812,36 +1812,47 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
if (!pipe->mixer_left->ctl->is_video_mode &&
(pipe->mixer_left->type != MDSS_MDP_MIXER_TYPE_WRITEBACK)) {
- struct mdss_rect ctl_roi = pipe->mixer_left->ctl->roi;
+ struct mdss_rect roi = pipe->mixer_left->roi;
bool is_right_mixer = pipe->mixer_left->is_right_mixer;
- /* main_ctl can be NULL, check validity before use */
- struct mdss_mdp_ctl *main_ctl =
- mdss_mdp_get_main_ctl(pipe->mixer_left->ctl);
-
- /* adjust roi or dst_x before crop is applied */
- if (pipe->src_split_req) {
- int r_roi_w = ctl_roi.w;
- struct mdss_mdp_ctl *sctl;
-
- if (pipe->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
- sctl = mdss_mdp_get_split_ctl(
- pipe->mixer_left->ctl);
- if (sctl)
- r_roi_w = sctl->roi.w;
- }
+ struct mdss_mdp_ctl *main_ctl;
+
+ if (pipe->mixer_left->ctl->is_master)
+ main_ctl = pipe->mixer_left->ctl;
+ else
+ main_ctl = mdss_mdp_get_main_ctl(pipe->mixer_left->ctl);
+
+ if (!main_ctl) {
+ pr_err("Error: couldn't find main_ctl for pipe%d\n",
+ pipe->num);
+ return -EINVAL;
+ }
- ctl_roi.w += r_roi_w;
- } else if (mdata->has_src_split && is_right_mixer && main_ctl) {
- dst.x -= main_ctl->mixer_left->width;
+ if (pipe->src_split_req && main_ctl->mixer_right->valid_roi) {
+ /*
+ * pipe is staged on both mixers, expand roi to span
+ * both mixers before cropping pipe's dimensions.
+ */
+ roi.w += main_ctl->mixer_right->roi.w;
+ } else if (mdata->has_src_split && is_right_mixer) {
+ /*
+ * pipe is only on right mixer but since source-split
+ * is enabled, its dst_x is full panel coordinate
+ * aligned where as ROI is mixer coordinate aligned.
+ * Modify dst_x before applying ROI crop.
+ */
+ dst.x -= left_lm_w_from_mfd(pipe->mfd);
}
- mdss_mdp_crop_rect(&src, &dst, &ctl_roi);
+ mdss_mdp_crop_rect(&src, &dst, &roi);
- /* re-adjust dst_x */
- if (mdata->has_src_split && is_right_mixer && main_ctl) {
- /* update valid on left + right */
- if (main_ctl->valid_roi)
- dst.x += main_ctl->roi.w;
+ if (mdata->has_src_split && is_right_mixer) {
+ /*
+ * re-adjust dst_x only if both mixers are active,
+ * meaning right mixer will be working in source
+ * split mode.
+ */
+ if (mdss_mdp_is_both_lm_valid(main_ctl))
+ dst.x += main_ctl->mixer_left->roi.w;
}
if (pipe->flags & MDP_FLIP_LR) {
@@ -2150,6 +2161,7 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
u32 params_changed;
u32 opmode = 0;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ bool roi_changed = false;
if (!pipe) {
pr_err("pipe not setup properly for queue\n");
@@ -2173,6 +2185,15 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
ctl = pipe->mixer_left->ctl;
+ roi_changed = pipe->mixer_left->roi_changed;
+
+ /*
+ * if pipe is staged on 2 mixers then it is possible that only
+ * right mixer roi has changed.
+ */
+ if (pipe->mixer_right)
+ roi_changed |= pipe->mixer_right->roi_changed;
+
/*
* Reprogram the pipe when there is no dedicated wfd blk and
* virtual mixer is allocated for the DMA pipe during concurrent
@@ -2181,7 +2202,7 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
params_changed = (pipe->params_changed) ||
((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
(pipe->mixer_left->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) &&
- (ctl->mdata->mixer_switched)) || ctl->roi_changed;
+ (ctl->mdata->mixer_switched)) || roi_changed;
if (params_changed) {
bool is_realtime = !((ctl->intf_num == MDSS_MDP_NO_INTF)
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 737f4076ac57..8c232ce89ad9 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -198,6 +198,7 @@ struct mdss_intf_recovery {
* - 1 clock enable
* @MDSS_EVENT_DSI_CMDLIST_KOFF: acquire dsi_mdp_busy lock before kickoff.
* @MDSS_EVENT_ENABLE_PARTIAL_ROI: Event to update ROI of the panel.
+ * @MDSS_EVENT_DSC_PPS_SEND: Event to send DSC PPS command to panel.
* @MDSS_EVENT_DSI_STREAM_SIZE: Event to update DSI controller's stream size
* @MDSS_EVENT_DSI_UPDATE_PANEL_DATA: Event to update the dsi driver structures
* based on the dsi mode passed as argument.
@@ -239,6 +240,7 @@ enum mdss_intf_events {
MDSS_EVENT_PANEL_CLK_CTRL,
MDSS_EVENT_DSI_CMDLIST_KOFF,
MDSS_EVENT_ENABLE_PARTIAL_ROI,
+ MDSS_EVENT_DSC_PPS_SEND,
MDSS_EVENT_DSI_STREAM_SIZE,
MDSS_EVENT_DSI_UPDATE_PANEL_DATA,
MDSS_EVENT_REGISTER_RECOVERY_HANDLER,