diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index 476d1e57703c..d6e2cb3f7468 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -320,6 +320,7 @@ Optional properties: - qcom,mdss-dsi-rx-eot-ignore: Boolean used to enable ignoring end of transmission packets. - qcom,mdss-dsi-tx-eot-append: Boolean used to enable appending end of transmission packets. - qcom,ulps-enabled: Boolean to enable support for Ultra Low Power State (ULPS) mode. +- qcom,suspend-ulps-enabled: Boolean to enable support for ULPS mode for panels during suspend state. - qcom,panel-roi-alignment: Specifies the panel ROI alignment restrictions on its left, top, width, height alignments and minimum width and height values @@ -470,6 +471,7 @@ Example: mdss-dsi-rx-eot-ignore; mdss-dsi-tx-eot-append; qcom,ulps-enabled; + qcom,suspend-ulps-enabled; qcom,panel-roi-alignment = <4 4 2 2 20 20>; qcom,esd-check-enabled; qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 02 0A 08]; diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 54717793771b..06738899e837 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -480,11 +480,13 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state) if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); - /* disable DSI controller */ - mdss_dsi_controller_cfg(0, pdata); + if (!pdata->panel_info.ulps_suspend_enabled) { + /* disable DSI controller */ + mdss_dsi_controller_cfg(0, pdata); - /* disable DSI phy */ - mdss_dsi_phy_disable(ctrl_pdata); + /* disable DSI phy */ + mdss_dsi_phy_disable(ctrl_pdata); + } mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); @@ -1834,6 +1836,23 @@ int dsi_panel_device_register(struct device_node *pan_node, ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN; + /* + * If ULPS during suspend is enabled, add an extra vote for the + * DSI CTRL power module. This keeps the regulator always enabled. + * This is needed for the DSI PHY to maintain ULPS state during + * suspend also. + */ + if (pinfo->ulps_suspend_enabled) { + rc = msm_dss_enable_vreg( + ctrl_pdata->power_data[DSI_CTRL_PM].vreg_config, + ctrl_pdata->power_data[DSI_CTRL_PM].num_vreg, 1); + if (rc) { + pr_err("%s: failed to enable vregs for DSI_CTRL_PM\n", + __func__); + return rc; + } + } + if (pinfo->cont_splash_enabled) { rc = mdss_dsi_panel_power_ctrl(&(ctrl_pdata->panel_data), MDSS_PANEL_POWER_ON); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 2dbdf77f7683..6b46eef793af 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1084,6 +1084,11 @@ static int mdss_dsi_parse_panel_features(struct device_node *np, pinfo->esd_check_enabled = of_property_read_bool(np, "qcom,esd-check-enabled"); + pinfo->ulps_suspend_enabled = of_property_read_bool(np, + "qcom,suspend-ulps-enabled"); + pr_info("%s: ulps during suspend feature %s", __func__, + (pinfo->ulps_suspend_enabled ? "enabled" : "disabled")); + pinfo->mipi.dynamic_switch_enabled = of_property_read_bool(np, "qcom,dynamic-mode-switch-enabled"); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index e3bc5e78b5b1..b6b6f6d12481 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -365,6 +365,7 @@ struct mdss_panel_info { int pwm_period; bool dynamic_fps; bool ulps_feature_enabled; + bool ulps_suspend_enabled; bool panel_ack_disabled; bool esd_check_enabled; char dfps_update; diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 29faeb010bce..17980bdadd95 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -394,7 +394,8 @@ int mdss_dsi_clk_init(struct platform_device *pdev, } if ((ctrl->panel_data.panel_info.type == MIPI_CMD_PANEL) || - ctrl->panel_data.panel_info.mipi.dynamic_switch_enabled) { + ctrl->panel_data.panel_info.mipi.dynamic_switch_enabled || + ctrl->panel_data.panel_info.ulps_suspend_enabled) { ctrl->mmss_misc_ahb_clk = clk_get(dev, "core_mmss_clk"); if (IS_ERR(ctrl->mmss_misc_ahb_clk)) { ctrl->mmss_misc_ahb_clk = NULL; @@ -958,7 +959,8 @@ static int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl, pinfo = &pdata->panel_info; mipi = &pinfo->mipi; - if (!mdss_dsi_ulps_feature_enabled(pdata)) { + if (!mdss_dsi_ulps_feature_enabled(pdata) && + !pinfo->ulps_suspend_enabled) { pr_debug("%s: ULPS feature not supported. enable=%d\n", __func__, enable); return -ENOTSUPP; @@ -1219,11 +1221,13 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, } /* - * Phy software reset should not be done for idle screen power - * collapse use-case. Issue a phy software reset only when - * unblanking the panel. + * Phy software reset should not be done for: + * 1.) Idle screen power collapse use-case. Issue a phy software + * reset only when unblanking the panel in this case. + * 2.) When ULPS during suspend is enabled. */ - if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_BLANK) + if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_BLANK && + !pdata->panel_info.ulps_suspend_enabled) mdss_dsi_phy_sw_reset(ctrl); /* @@ -1266,8 +1270,12 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, goto error_ulps; } } else { - /* Enable DSI clamps only if entering idle power collapse */ - if (pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) { + /* + * Enable DSI clamps only if entering idle power collapse or + * when ULPS during suspend is enabled. + */ + if ((pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) || + pdata->panel_info.ulps_suspend_enabled) { rc = mdss_dsi_clamp_ctrl(ctrl, 1); if (rc) pr_err("%s: Failed to enable dsi clamps. rc=%d\n", @@ -1380,13 +1388,16 @@ static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, if (clk_type & DSI_LINK_CLKS) { /* * If ULPS feature is enabled, enter ULPS first. - * No need to enable ULPS when turning off clocks + * If ULPS during suspend is not enabled, no need + * to enable ULPS when turning off the clocks * while blanking the panel. */ - if ((mdss_dsi_ulps_feature_enabled(pdata)) && + if (((mdss_dsi_ulps_feature_enabled(pdata)) && (pdata->panel_info.blank_state != - MDSS_PANEL_BLANK_BLANK)) + MDSS_PANEL_BLANK_BLANK)) || + (pdata->panel_info.ulps_suspend_enabled)) mdss_dsi_ulps_config(ctrl, 1); + mdss_dsi_link_clk_stop(ctrl); } if (clk_type & DSI_BUS_CLKS) {