msm: mdss: modify how pingpong-split is used for a given panel
In the current implementation, driver makes a decision to use pingpong-split data path if HW supports pingpong-split and connected panel is a dual-DSI. However, in the high tier targets like msm8996 it is possible to use dual-dsi panels in multiple modes, i.e with single layer mixer + pingpong-split or dual layer mixer. So the correct place to define if pingpong-split will be used or not is with panel configuration not with the MDP driver. In order to support this, MDP device node will continue using its property qcom,has-pingpong-split to tell driver that underlying HW supports pingpong-split. Introduce a new panel property, qcom,split-mode, which will be used to decide if pingpong-split for a given panel should be used or not. Change-Id: I210e7f2a8b03d5c8a161241120c7d3c7081fa971 Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org> Signed-off-by: Shivaraj Shetty <shivaraj@codeaurora.org>
This commit is contained in:
parent
cc0963f525
commit
c4b4c0a31c
9 changed files with 60 additions and 35 deletions
|
@ -419,20 +419,22 @@ Optional properites:
|
|||
mixers to reduce power.
|
||||
Ex: Normally 1080x1920 display uses single DSI and thus one layer
|
||||
mixer. But if we use two layer mixers then mux the output of
|
||||
those mixers two into single stream and route it to single DSI
|
||||
those two mixers into single stream and route it to single DSI
|
||||
then we can lower the clock requirements of MDP. To use this
|
||||
configuration we need two fill this array with <540 540>.
|
||||
This property should not be used if underlying display is using
|
||||
two DSI panels such a way that each carrying half the display.
|
||||
Both values doesn't have to be same, but recommended, however sum of
|
||||
both values has to be equal to the panel-width.
|
||||
By default two mixer streams are merged using 2D mux, however if
|
||||
2 DSC encoders are used then merge is performed within compression
|
||||
engine.
|
||||
- qcom,split-mode: String property indicating which split mode MDP should use. Valid
|
||||
entries are "pingpong-split" and "dualctl-split".
|
||||
This property is mutually exclusive with qcom,lm-split.
|
||||
- qcom,mdss-dsc-encoders: An integer value indicating how many DSC encoders should be used
|
||||
to drive data stream to DSI.
|
||||
Default value is 1 and max value is 2.
|
||||
2 encoder should be used only if qcom,mdss-lm-split is used.
|
||||
2 encoder should be used only if qcom,mdss-lm-split or
|
||||
qcom,split-mode with pingpong-split is used.
|
||||
- qcom,mdss-dsc-slice-height: An integer value indicates the dsc slice height.
|
||||
- qcom,mdss-dsc-slice-width: An integer value indicates the dsc slice width.
|
||||
Multiple of slice width should be equal to panel-width.
|
||||
|
@ -690,5 +692,12 @@ Example:
|
|||
qcom,mdss-dsc-config-by-manufacture-cmd;
|
||||
};
|
||||
|
||||
dsi_sim_vid_config2: config2 {
|
||||
qcom,split-mode = "dualctl-split";
|
||||
};
|
||||
|
||||
dsi_sim_vid_config3: config3 {
|
||||
qcom,split-mode = "pingpong-split";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -373,10 +373,6 @@ Optional properties:
|
|||
clients.
|
||||
- qcom,mdss-dram-channels: This represents the number of channels in the
|
||||
Bus memory controller.
|
||||
- qcom,mdss-ppb-off: Array of offset addresses of ping pong buffer control registers.
|
||||
The offsets are calculated from the "mdp_phys" base address
|
||||
specified. The number of offsets should match the
|
||||
number of ping pong buffers available in the hardware.
|
||||
- qcom,regs-dump-mdp: This array represents the registers offsets that
|
||||
will be dumped from the mdp when the debug logging
|
||||
is enabled; each entry in the table is an start and
|
||||
|
@ -484,6 +480,16 @@ Fudge Factors: Fudge factors are used to boost demand for
|
|||
configuration, second element for robust.
|
||||
- qcom,mdss-has-pingpong-split: Boolean property to indicate if destination
|
||||
split feature is available or not in the target.
|
||||
- qcom,mdss-slave-pingpong-off: Offset address for the extra TE block which needs
|
||||
to be programmed when pingpong split feature is enabled.
|
||||
Offset is calculated from the "mdp_phys"
|
||||
register value. Mandatory when qcom,mdss-has-pingpong-split
|
||||
is enabled.
|
||||
- qcom,mdss-ppb-off: Array of offset addresses of ping pong buffer control registers.
|
||||
The offsets are calculated from the "mdp_phys" base address
|
||||
specified. The number of offsets should match the
|
||||
number of ping pong buffers available in the hardware.
|
||||
Mandatory when qcom,mdss-has-pingpong-split is enabled.
|
||||
- qcom,mdss-cdm-off: Array of offset addresses for the available
|
||||
chroma down modules that can convert RGB data
|
||||
to YUV before sending it to the interface
|
||||
|
@ -500,11 +506,6 @@ Fudge Factors: Fudge factors are used to boost demand for
|
|||
- qcom,max-pipe-width: This value specifies the maximum MDP SSPP width
|
||||
the device supports. If not specified, a default value
|
||||
of 2048 will be applied.
|
||||
- qcom,mdss-slave-pingpong-off: Offset address for the extra TE block which needs
|
||||
to be programmed when pingpong split feature is enabled.
|
||||
Offset is calculated from the "mdp_phys"
|
||||
register value. Mandatory when qcom,mdss-has-pingpong-split
|
||||
is enabled.
|
||||
|
||||
Optional subnodes:
|
||||
- mdss_fb: Child nodes representing the frame buffer virtual devices.
|
||||
|
|
|
@ -1475,7 +1475,7 @@ end:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int mdss_dsi_parse_compression_params(struct device_node *np,
|
||||
static int mdss_dsi_parse_topology_config(struct device_node *np,
|
||||
struct dsi_panel_timing *pt, struct mdss_panel_data *panel_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -1483,11 +1483,13 @@ static int mdss_dsi_parse_compression_params(struct device_node *np,
|
|||
const char *data;
|
||||
struct mdss_panel_timing *timing = &pt->timing;
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
|
||||
struct mdss_panel_info *pinfo;
|
||||
struct device_node *cfg_np;
|
||||
|
||||
ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
|
||||
panel_data);
|
||||
cfg_np = ctrl_pdata->panel_data.cfg_np;
|
||||
pinfo = &ctrl_pdata->panel_data.panel_info;
|
||||
|
||||
if (!cfg_np && of_find_property(np, "qcom,config-select", NULL)) {
|
||||
cfg_np = of_parse_phandle(np, "qcom,config-select", 0);
|
||||
|
@ -1507,9 +1509,22 @@ static int mdss_dsi_parse_compression_params(struct device_node *np,
|
|||
goto end;
|
||||
}
|
||||
}
|
||||
pr_info("%s: cfg_node name %s lm_split:%dx%d\n", __func__,
|
||||
cfg_np->name,
|
||||
timing->lm_widths[0], timing->lm_widths[1]);
|
||||
rc = of_property_read_string(cfg_np, "qcom,split-mode", &data);
|
||||
if (!rc && !strcmp(data, "pingpong-split"))
|
||||
pinfo->use_pingpong_split = true;
|
||||
|
||||
if (((timing->lm_widths[0]) || (timing->lm_widths[1])) &&
|
||||
pinfo->use_pingpong_split) {
|
||||
pr_err("%s: pingpong_split cannot be used when lm-split[%d,%d] is specified\n",
|
||||
__func__,
|
||||
timing->lm_widths[0], timing->lm_widths[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("%s: cfg_node name %s lm_split:%dx%d pp_split:%s\n",
|
||||
__func__, cfg_np->name,
|
||||
timing->lm_widths[0], timing->lm_widths[1],
|
||||
pinfo->use_pingpong_split ? "yes" : "no");
|
||||
}
|
||||
|
||||
if ((timing->lm_widths[0] == 0) && (timing->lm_widths[1] == 0))
|
||||
|
@ -2237,8 +2252,7 @@ static int mdss_dsi_panel_config_res_properties(struct device_node *np,
|
|||
"qcom,mdss-dsi-timing-switch-command",
|
||||
"qcom,mdss-dsi-timing-switch-command-state");
|
||||
|
||||
rc = mdss_dsi_parse_compression_params(np, pt,
|
||||
panel_data);
|
||||
rc = mdss_dsi_parse_topology_config(np, pt, panel_data);
|
||||
if (rc) {
|
||||
pr_err("%s: parsing compression params failed. rc:%d\n",
|
||||
__func__, rc);
|
||||
|
|
|
@ -1065,15 +1065,14 @@ static int mdss_fb_probe(struct platform_device *pdev)
|
|||
if (pdata->panel_info.is_split_display) {
|
||||
struct mdss_panel_data *pnext = pdata->next;
|
||||
|
||||
/*
|
||||
* currently pingpong-split is not a choice from device tree
|
||||
* and it is handled in overlay_init. Fix this.
|
||||
*/
|
||||
mfd->split_fb_left = pdata->panel_info.lm_widths[0];
|
||||
if (pnext)
|
||||
mfd->split_fb_right = pnext->panel_info.lm_widths[0];
|
||||
|
||||
mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY;
|
||||
if (pdata->panel_info.use_pingpong_split)
|
||||
mfd->split_mode = MDP_PINGPONG_SPLIT;
|
||||
else
|
||||
mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY;
|
||||
} else if ((pdata->panel_info.lm_widths[0] != 0) &&
|
||||
(pdata->panel_info.lm_widths[1] != 0)) {
|
||||
mfd->split_fb_left = pdata->panel_info.lm_widths[0];
|
||||
|
|
|
@ -381,9 +381,7 @@ static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd)
|
|||
/* Function returns true for either any kind of dual display */
|
||||
static inline bool is_panel_split(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
return mfd &&
|
||||
(mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY ||
|
||||
mfd->split_mode == MDP_PINGPONG_SPLIT);
|
||||
return mfd && mfd->panel_info && mfd->panel_info->is_split_display;
|
||||
}
|
||||
/* Function returns true, if Layer Mixer split is Set */
|
||||
static inline bool is_split_lm(struct msm_fb_data_type *mfd)
|
||||
|
|
|
@ -2039,10 +2039,6 @@ static int mdss_mdp_parse_dt(struct platform_device *pdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = mdss_mdp_parse_dt_ppb_off(pdev);
|
||||
if (rc)
|
||||
pr_debug("Info in device tree: ppb offset not configured\n");
|
||||
|
||||
rc = mdss_mdp_parse_dt_cdm(pdev);
|
||||
if (rc)
|
||||
pr_debug("CDM offset not found in device tree\n");
|
||||
|
@ -3259,6 +3255,11 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
|
|||
}
|
||||
mdata->slave_pingpong_base = mdata->mdss_io.base +
|
||||
slave_pingpong_off;
|
||||
rc = mdss_mdp_parse_dt_ppb_off(pdev);
|
||||
if (rc) {
|
||||
pr_err("Error in device tree: ppb offset not configured\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2826,6 +2826,12 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
|
|||
else
|
||||
offset = MDSS_MDP_CTL0;
|
||||
|
||||
if (is_pingpong_split(mfd) && !mdata->has_pingpong_split) {
|
||||
pr_err("Error: pp_split cannot be enabled on fb%d if HW doesn't support it\n",
|
||||
mfd->index);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ctl = mdss_mdp_ctl_alloc(mdata, offset);
|
||||
if (!ctl) {
|
||||
pr_err("unable to allocate ctl\n");
|
||||
|
|
|
@ -4992,10 +4992,6 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
|
|||
|
||||
mfd->mdp.private1 = mdp5_data;
|
||||
mfd->wait_for_kickoff = true;
|
||||
if (is_panel_split(mfd) && mdp5_data->mdata->has_pingpong_split) {
|
||||
mfd->split_fb_left = mfd->split_fb_right = 0;
|
||||
mfd->split_mode = MDP_PINGPONG_SPLIT;
|
||||
}
|
||||
|
||||
rc = mdss_mdp_overlay_fb_parse_dt(mfd);
|
||||
if (rc)
|
||||
|
|
|
@ -582,6 +582,7 @@ struct mdss_panel_info {
|
|||
bool dynamic_switch_pending;
|
||||
bool is_lpm_mode;
|
||||
bool is_split_display; /* two DSIs in one display, pp split or not */
|
||||
bool use_pingpong_split;
|
||||
|
||||
/*
|
||||
* index[0] = left layer mixer, value of 0 not valid
|
||||
|
|
Loading…
Add table
Reference in a new issue