diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index b85b7a690546..d65f9622d177 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -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"; + }; }; }; diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt index 611c643f1984..7daade083c44 100644 --- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt +++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt @@ -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. diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index da8abaabc3b5..1d070acc9cf4 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -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); diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index d3f3d22d89c8..68f53cb202a4 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -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]; diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index 01ba5ea5ecb3..b1728b43d3cf 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -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) diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 0ea46dbefc24..57033cb004ff 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -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; + } } /* diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index a1299ce2ffd8..a19daa4e1837 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -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"); diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 052ddd821388..0a67cb9208de 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -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) diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index f6f3e56f4e99..f6589fdd3b4d 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -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