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.
|
mixers to reduce power.
|
||||||
Ex: Normally 1080x1920 display uses single DSI and thus one layer
|
Ex: Normally 1080x1920 display uses single DSI and thus one layer
|
||||||
mixer. But if we use two layer mixers then mux the output of
|
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
|
then we can lower the clock requirements of MDP. To use this
|
||||||
configuration we need two fill this array with <540 540>.
|
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 doesn't have to be same, but recommended, however sum of
|
||||||
both values has to be equal to the panel-width.
|
both values has to be equal to the panel-width.
|
||||||
By default two mixer streams are merged using 2D mux, however if
|
By default two mixer streams are merged using 2D mux, however if
|
||||||
2 DSC encoders are used then merge is performed within compression
|
2 DSC encoders are used then merge is performed within compression
|
||||||
engine.
|
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
|
- qcom,mdss-dsc-encoders: An integer value indicating how many DSC encoders should be used
|
||||||
to drive data stream to DSI.
|
to drive data stream to DSI.
|
||||||
Default value is 1 and max value is 2.
|
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-height: An integer value indicates the dsc slice height.
|
||||||
- qcom,mdss-dsc-slice-width: An integer value indicates the dsc slice width.
|
- qcom,mdss-dsc-slice-width: An integer value indicates the dsc slice width.
|
||||||
Multiple of slice width should be equal to panel-width.
|
Multiple of slice width should be equal to panel-width.
|
||||||
|
@ -690,5 +692,12 @@ Example:
|
||||||
qcom,mdss-dsc-config-by-manufacture-cmd;
|
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.
|
clients.
|
||||||
- qcom,mdss-dram-channels: This represents the number of channels in the
|
- qcom,mdss-dram-channels: This represents the number of channels in the
|
||||||
Bus memory controller.
|
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
|
- qcom,regs-dump-mdp: This array represents the registers offsets that
|
||||||
will be dumped from the mdp when the debug logging
|
will be dumped from the mdp when the debug logging
|
||||||
is enabled; each entry in the table is an start and
|
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.
|
configuration, second element for robust.
|
||||||
- qcom,mdss-has-pingpong-split: Boolean property to indicate if destination
|
- qcom,mdss-has-pingpong-split: Boolean property to indicate if destination
|
||||||
split feature is available or not in the target.
|
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
|
- qcom,mdss-cdm-off: Array of offset addresses for the available
|
||||||
chroma down modules that can convert RGB data
|
chroma down modules that can convert RGB data
|
||||||
to YUV before sending it to the interface
|
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
|
- qcom,max-pipe-width: This value specifies the maximum MDP SSPP width
|
||||||
the device supports. If not specified, a default value
|
the device supports. If not specified, a default value
|
||||||
of 2048 will be applied.
|
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:
|
Optional subnodes:
|
||||||
- mdss_fb: Child nodes representing the frame buffer virtual devices.
|
- mdss_fb: Child nodes representing the frame buffer virtual devices.
|
||||||
|
|
|
@ -1475,7 +1475,7 @@ end:
|
||||||
return rc;
|
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)
|
struct dsi_panel_timing *pt, struct mdss_panel_data *panel_data)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -1483,11 +1483,13 @@ static int mdss_dsi_parse_compression_params(struct device_node *np,
|
||||||
const char *data;
|
const char *data;
|
||||||
struct mdss_panel_timing *timing = &pt->timing;
|
struct mdss_panel_timing *timing = &pt->timing;
|
||||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
|
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
|
||||||
|
struct mdss_panel_info *pinfo;
|
||||||
struct device_node *cfg_np;
|
struct device_node *cfg_np;
|
||||||
|
|
||||||
ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
|
ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
|
||||||
panel_data);
|
panel_data);
|
||||||
cfg_np = ctrl_pdata->panel_data.cfg_np;
|
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)) {
|
if (!cfg_np && of_find_property(np, "qcom,config-select", NULL)) {
|
||||||
cfg_np = of_parse_phandle(np, "qcom,config-select", 0);
|
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;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pr_info("%s: cfg_node name %s lm_split:%dx%d\n", __func__,
|
rc = of_property_read_string(cfg_np, "qcom,split-mode", &data);
|
||||||
cfg_np->name,
|
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]);
|
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))
|
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",
|
||||||
"qcom,mdss-dsi-timing-switch-command-state");
|
"qcom,mdss-dsi-timing-switch-command-state");
|
||||||
|
|
||||||
rc = mdss_dsi_parse_compression_params(np, pt,
|
rc = mdss_dsi_parse_topology_config(np, pt, panel_data);
|
||||||
panel_data);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: parsing compression params failed. rc:%d\n",
|
pr_err("%s: parsing compression params failed. rc:%d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
|
|
|
@ -1065,14 +1065,13 @@ static int mdss_fb_probe(struct platform_device *pdev)
|
||||||
if (pdata->panel_info.is_split_display) {
|
if (pdata->panel_info.is_split_display) {
|
||||||
struct mdss_panel_data *pnext = pdata->next;
|
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];
|
mfd->split_fb_left = pdata->panel_info.lm_widths[0];
|
||||||
if (pnext)
|
if (pnext)
|
||||||
mfd->split_fb_right = pnext->panel_info.lm_widths[0];
|
mfd->split_fb_right = pnext->panel_info.lm_widths[0];
|
||||||
|
|
||||||
|
if (pdata->panel_info.use_pingpong_split)
|
||||||
|
mfd->split_mode = MDP_PINGPONG_SPLIT;
|
||||||
|
else
|
||||||
mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY;
|
mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY;
|
||||||
} else if ((pdata->panel_info.lm_widths[0] != 0) &&
|
} else if ((pdata->panel_info.lm_widths[0] != 0) &&
|
||||||
(pdata->panel_info.lm_widths[1] != 0)) {
|
(pdata->panel_info.lm_widths[1] != 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 */
|
/* Function returns true for either any kind of dual display */
|
||||||
static inline bool is_panel_split(struct msm_fb_data_type *mfd)
|
static inline bool is_panel_split(struct msm_fb_data_type *mfd)
|
||||||
{
|
{
|
||||||
return mfd &&
|
return mfd && mfd->panel_info && mfd->panel_info->is_split_display;
|
||||||
(mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY ||
|
|
||||||
mfd->split_mode == MDP_PINGPONG_SPLIT);
|
|
||||||
}
|
}
|
||||||
/* Function returns true, if Layer Mixer split is Set */
|
/* Function returns true, if Layer Mixer split is Set */
|
||||||
static inline bool is_split_lm(struct msm_fb_data_type *mfd)
|
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;
|
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);
|
rc = mdss_mdp_parse_dt_cdm(pdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_debug("CDM offset not found in device tree\n");
|
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 +
|
mdata->slave_pingpong_base = mdata->mdss_io.base +
|
||||||
slave_pingpong_off;
|
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
|
else
|
||||||
offset = MDSS_MDP_CTL0;
|
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);
|
ctl = mdss_mdp_ctl_alloc(mdata, offset);
|
||||||
if (!ctl) {
|
if (!ctl) {
|
||||||
pr_err("unable to allocate ctl\n");
|
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->mdp.private1 = mdp5_data;
|
||||||
mfd->wait_for_kickoff = true;
|
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);
|
rc = mdss_mdp_overlay_fb_parse_dt(mfd);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
|
@ -582,6 +582,7 @@ struct mdss_panel_info {
|
||||||
bool dynamic_switch_pending;
|
bool dynamic_switch_pending;
|
||||||
bool is_lpm_mode;
|
bool is_lpm_mode;
|
||||||
bool is_split_display; /* two DSIs in one display, pp split or not */
|
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
|
* index[0] = left layer mixer, value of 0 not valid
|
||||||
|
|
Loading…
Add table
Reference in a new issue