msm: mdss: add partial update support for dsc based smart panels
When Display Stream Compression (DSC) based smart panel is used, MDSS can drive data to panel in various different data path topologies. Now when partial update is enabled, along with change in data path topologies, DSC configuration also changes, i.e. number of slices per line, number of encoders used, picture size etc. Enable left+right or left-only partial update for DSC based smart panels. Change-Id: I03b5eb6c7f0b010078ccc0112d8ce3aca2da6b7b Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org> [cip@codeaurora.org: Resolved merge conflict] Signed-off-by: Clarence Ip <cip@codeaurora.org>
This commit is contained in:
parent
3eea3c01d0
commit
502daaa260
10 changed files with 455 additions and 185 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
struct mdss_mdp_ctl *main_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->mixer_left->ctl->is_master)
|
||||
main_ctl = pipe->mixer_left->ctl;
|
||||
else
|
||||
main_ctl = mdss_mdp_get_main_ctl(pipe->mixer_left->ctl);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 (!main_ctl) {
|
||||
pr_err("Error: couldn't find main_ctl for pipe%d\n",
|
||||
pipe->num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mdss_mdp_crop_rect(&src, &dst, &ctl_roi);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
mdss_mdp_crop_rect(&src, &dst, &roi);
|
||||
|
||||
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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue