diff options
| author | Padmanabhan Komanduru <pkomandu@codeaurora.org> | 2015-05-06 00:39:44 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:42:14 -0700 |
| commit | 31f25a7aee3045066734ec9414ecb163b213d16b (patch) | |
| tree | 1caf48e0dc581ef0ea9270672b35e99328b22f0d | |
| parent | 411d694bc12b7bab3f855a831bd31bba27525ab7 (diff) | |
msm: mdss: add support for DSI shared data in the master DSI node
Some of the properties of the individual DSI controller nodes are
common between them. Instead of having duplicate entries, they can
actually be shared via. a common data structure which can be part
of the root DSI node. Add changes in the MDSS dtsi file and the DSI
drivers to support this.
Change-Id: I22dbc1d81678fea191b3f58bd8dcc667fafdfe6a
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
[cip@codeaurora.org: Removed .dtsi file updates]
Signed-off-by: Clarence Ip <cip@codeaurora.org>
| -rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-dsi.txt | 172 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 251 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 89 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_host.c | 31 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 7 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 274 |
6 files changed, 484 insertions, 340 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt index 2c520a7f72e0..0e23a0f607f8 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt @@ -11,6 +11,30 @@ Required properties: "hw-config" = "split_dsi" - ranges: The standard property which specifies the child address space, parent address space and the length. +- vdda-supply: Phandle for vreg regulator device node. + +Optional properties: +- vcca-supply: Phandle for vcca regulator device node. +- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the + a particular "type" of DSI modulee. The module "types" + can be "core", "ctrl", and "phy". Within the same type, + there can be more than one instance of this binding, + in which case the entry would be appended with the + supply entry index. + e.g. qcom,ctrl-supply-entry@0 + -- qcom,supply-name: name of the supply (vdd/vdda/vddio) + -- qcom,supply-min-voltage: minimum voltage level (uV) + -- qcom,supply-max-voltage: maximum voltage level (uV) + -- qcom,supply-enable-load: load drawn (uA) from enabled supply + -- qcom,supply-disable-load: load drawn (uA) from disabled supply + -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on + -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on + -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off + -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off +- qcom,mmss-ulp-clamp-ctrl-offset: Specifies the offset for dsi ulps clamp control register. +- qcom,mmss-phyreset-ctrl-offset: Specifies the offset for dsi phy reset control register. +- qcom,timing-db-mode: Boolean specifies dsi timing mode registers are supported or not. +- qcom,dsi-clk-ln-recovery: Boolean which enables the clk lane recovery mdss-dsi-ctrl is a dsi controller device which is treated as a subnode of the mdss-dsi device. @@ -22,10 +46,10 @@ Required properties: - reg-names: A list of strings that map in order to the list of regs. "dsi_ctrl" - MDSS DSI controller register region "dsi_phy" - MDSS DSI PHY register region + "dsi_phy_regulator" - MDSS DSI PHY REGULATOR region "mmss_misc_phys" - Register region for MMSS DSI clamps - vdd-supply: Phandle for vdd regulator device node. - vddio-supply: Phandle for vdd-io regulator device node. -- vdda-supply: Phandle for vreg regulator device node. - qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the interface is mapped. - qcom,mdss-mdp: pHandle that specifies the mdss-mdp device. @@ -35,33 +59,13 @@ Required properties: strengthCtrl settings. It use 10 bytes for 8996 pll. - qcom,platform-lane-config: An array of length 45 or 20 that specifies the PHY lane configuration settings. It use 20 bytes for 8996 pll. +- qcom,platform-bist-ctrl: An array of length 6 that specifies the PHY + BIST ctrl settings. - qcom,dsi-pref-prim-pan: phandle that specifies the primary panel to be used with the controller. Optional properties: - label: A string used to describe the controller used. - -- reg-names: A list of strings that map in order to the list of regs. - "dsi_phy_regulator" - MDSS DSI PHY REGULATOR region -- qcom,platform-bist-ctrl: An array of length 6 that specifies the PHY - BIST ctrl settings. -- vcca-supply: Phandle for vcca regulator device node. -- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the - a particular "type" of DSI modulee. The module "types" - can be "core", "ctrl", and "phy". Within the same type, - there can be more than one instance of this binding, - in which case the entry would be appended with the - supply entry index. - e.g. qcom,ctrl-supply-entry@0 - -- qcom,supply-name: name of the supply (vdd/vdda/vddio) - -- qcom,supply-min-voltage: minimum voltage level (uV) - -- qcom,supply-max-voltage: maximum voltage level (uV) - -- qcom,supply-enable-load: load drawn (uA) from enabled supply - -- qcom,supply-disable-load: load drawn (uA) from disabled supply - -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on - -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on - -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off - -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off - qcom,platform-enable-gpio: Specifies the panel lcd/display enable gpio. - qcom,platform-reset-gpio: Specifies the panel reset gpio. - qcom,platform-te-gpio: Specifies the gpio used for TE. @@ -74,11 +78,7 @@ Optional properties: controller. These pin configurations are installed in the pinctrl device node. Refer to pinctrl-bindings.txt - qcom,regulator-ldo-mode: Boolean to enable ldo mode for the dsi phy regulator -- qcom,mmss-ulp-clamp-ctrl-offset: Specifies the offset for dsi ulps clamp control register. -- qcom,mmss-phyreset-ctrl-offset: Specifies the offset for dsi phy reset control register. - qcom,dsi-irq-line: Boolean specifies if DSI has a different irq line than mdp. -- qcom,timing-db-mode: Boolean specifies dsi timing mode registers are supported or not. -- qcom,dsi-clk-ln-recovery: Boolean which enables the clk lane recovery - qcom,lane-map: Specifies the data lane swap configuration. "lane_map_0123" = <0 1 2 3> (default value) "lane_map_3012" = <3 0 1 2> @@ -95,11 +95,70 @@ Example: hw-config = "single_dsi"; #address-cells = <1>; #size-cells = <1>; + vdda-supply = <&pm8226_l4>; + vcca-supply = <&pm8226_l28>; reg = <0x1a98000 0x1a98000 0x25c 0x1a98500 0x1a98500 0x280 0x1a98780 0x1a98780 0x30 0x193e000 0x193e000 0x30>; + qcom,timing-db-mode; + qcom,dsi-clk-ln-recovery; + + qcom,core-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,core-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + qcom,supply-pre-on-sleep = <0>; + qcom,supply-post-on-sleep = <0>; + qcom,supply-pre-off-sleep = <0>; + qcom,supply-post-off-sleep = <0>; + }; + }; + + qcom,phy-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,phy-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vddio"; + qcom,supply-min-voltage = <1800000>; + qcom,supply-max-voltage = <1800000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-pre-on-sleep = <0>; + qcom,supply-post-on-sleep = <20>; + qcom,supply-pre-off-sleep = <0>; + qcom,supply-post-off-sleep = <0>; + }; + }; + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda"; + qcom,supply-min-voltage = <1200000>; + qcom,supply-max-voltage = <1200000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-pre-on-sleep = <0>; + qcom,supply-post-on-sleep = <20>; + qcom,supply-pre-off-sleep = <0>; + qcom,supply-post-off-sleep = <0>; + }; + }; + mdss_dsi0: mdss_dsi_ctrl0@fd922800 { compatible = "qcom,mdss-dsi-ctrl"; label = "MDSS DSI CTRL->0"; @@ -113,8 +172,6 @@ Example: vdd-supply = <&pm8226_l15>; vddio-supply = <&pm8226_l8>; - vdda-supply = <&pm8226_l4>; - vcca-supply = <&pm8226_l28>; qcom,mdss-fb-map = <&mdss_fb0>; qcom,mdss-mdp = <&mdss_mdp>; @@ -142,63 +199,6 @@ Example: qcom,platform-bklight-en-gpio = <&msmgpio 86 0>; qcom,platform-mode-gpio = <&msmgpio 7 0>; qcom,dsi-irq-line; - qcom,timing-db-mode; - qcom,dsi-clk-ln-recovery; qcom,lane-map = "lane_map_3012"; - - qcom,core-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,core-supply-entry@0 { - reg = <0>; - qcom,supply-name = "gdsc"; - qcom,supply-min-voltage = <0>; - qcom,supply-max-voltage = <0>; - qcom,supply-enable-load = <0>; - qcom,supply-disable-load = <0>; - qcom,supply-pre-on-sleep = <0>; - qcom,supply-post-on-sleep = <0>; - qcom,supply-pre-off-sleep = <0>; - qcom,supply-post-off-sleep = <0>; - }; - }; - - qcom,phy-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,phy-supply-entry@0 { - reg = <0>; - qcom,supply-name = "vddio"; - qcom,supply-min-voltage = <1800000>; - qcom,supply-max-voltage = <1800000>; - qcom,supply-enable-load = <100000>; - qcom,supply-disable-load = <100>; - qcom,supply-pre-on-sleep = <0>; - qcom,supply-post-on-sleep = <20>; - qcom,supply-pre-off-sleep = <0>; - qcom,supply-post-off-sleep = <0>; - }; - }; - - qcom,ctrl-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,ctrl-supply-entry@0 { - reg = <0>; - qcom,supply-name = "vdda"; - qcom,supply-min-voltage = <1200000>; - qcom,supply-max-voltage = <1200000>; - qcom,supply-enable-load = <100000>; - qcom,supply-disable-load = <100>; - qcom,supply-pre-on-sleep = <0>; - qcom,supply-post-on-sleep = <20>; - qcom,supply-pre-off-sleep = <0>; - qcom,supply-post-off-sleep = <0>; - }; - }; - }; }; diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index aa7d870fd4a7..8f04dc4786d7 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -48,31 +48,29 @@ static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl(u32 ctrl_id) return mdss_dsi_res->ctrl_pdata[ctrl_id]; } -static int mdss_dsi_regulator_init(struct platform_device *pdev) +static int mdss_dsi_regulator_init(struct platform_device *pdev, + struct dsi_shared_data *sdata) { - int rc = 0; - - struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; - int i = 0; + int rc = 0, i = 0, j = 0; - if (!pdev) { + if (!pdev || !sdata) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } - ctrl_pdata = platform_get_drvdata(pdev); - if (!ctrl_pdata) { - pr_err("%s: invalid driver data\n", __func__); - return -EINVAL; - } - - for (i = 0; !rc && (i < DSI_MAX_PM); i++) { + for (i = DSI_CORE_PM; !rc && (i < DSI_MAX_PM); i++) { rc = msm_dss_config_vreg(&pdev->dev, - ctrl_pdata->power_data[i].vreg_config, - ctrl_pdata->power_data[i].num_vreg, 1); - if (rc) + sdata->power_data[i].vreg_config, + sdata->power_data[i].num_vreg, 1); + if (rc) { pr_err("%s: failed to init vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); + for (j = i-1; j >= DSI_CORE_PM; j--) { + msm_dss_config_vreg(&pdev->dev, + sdata->power_data[j].vreg_config, + sdata->power_data[j].num_vreg, 0); + } + } } return rc; @@ -102,8 +100,8 @@ static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) pr_debug("reset disable: pinctrl not enabled\n"); ret = msm_dss_enable_vreg( - ctrl_pdata->power_data[DSI_PANEL_PM].vreg_config, - ctrl_pdata->power_data[DSI_PANEL_PM].num_vreg, 0); + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 0); if (ret) pr_err("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); @@ -126,8 +124,8 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) panel_data); ret = msm_dss_enable_vreg( - ctrl_pdata->power_data[DSI_PANEL_PM].vreg_config, - ctrl_pdata->power_data[DSI_PANEL_PM].num_vreg, 1); + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 1); if (ret) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); @@ -1138,6 +1136,13 @@ static int mdss_dsi_pinctrl_set_state( if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.pinctrl)) return PTR_ERR(ctrl_pdata->pin_res.pinctrl); + if (mdss_dsi_is_right_ctrl(ctrl_pdata) && + mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { + pr_debug("%s:%d, right ctrl pinctrl config not needed\n", + __func__, __LINE__); + return 0; + } + pin_state = active ? ctrl_pdata->pin_res.gpio_state_active : ctrl_pdata->pin_res.gpio_state_suspend; if (!IS_ERR_OR_NULL(pin_state)) { @@ -1412,7 +1417,7 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata, } ctrl_rev = MIPI_INP(ctrl_pdata->ctrl_base); /* Flush DSI TIMING registers for 8916/8939 */ - if (ctrl_pdata->timing_db_mode) + if (ctrl_pdata->shared_data->timing_db_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e4, 0x1); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; @@ -1615,7 +1620,7 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) * reguest. */ pinfo = &pdata->panel_info; - if (pinfo->is_split_display) { + if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { if (mdss_dsi_is_right_ctrl(ctrl_pdata)) { pr_debug("%s DFPS already updated.\n", __func__); return rc; @@ -2060,7 +2065,7 @@ static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev) static int mdss_dsi_ctrl_probe(struct platform_device *pdev) { - int rc = 0, i = 0; + int rc = 0; u32 index; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct device_node *dsi_pan_node = NULL; @@ -2113,19 +2118,6 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) if (rc) pr_warn("%s: failed to get pin resources\n", __func__); - /* Parse the regulator information */ - for (i = 0; i < DSI_MAX_PM; i++) { - if (DSI_PANEL_PM == i) - continue; - rc = mdss_dsi_get_dt_vreg_data(&pdev->dev, pdev->dev.of_node, - &ctrl_pdata->power_data[i], i); - if (rc) { - DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", - __func__, __mdss_dsi_pm_name(i), rc); - goto error_vreg; - } - } - if (index == 0) ctrl_pdata->panel_data.panel_info.pdest = DISPLAY_1; else @@ -2134,13 +2126,11 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) dsi_pan_node = mdss_dsi_config_panel(pdev); if (!dsi_pan_node) { pr_err("%s: panel configuration failed\n", __func__); - i--; - rc = -EINVAL; - goto error_vreg; + return -EINVAL; } - if ((mdss_dsi_res->hw_config != SPLIT_DSI) || - ((mdss_dsi_res->hw_config == SPLIT_DSI) && + if (!mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) || + (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1))) { rc = mdss_panel_parse_bl_settings(dsi_pan_node, ctrl_pdata); if (rc) { @@ -2173,18 +2163,38 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) error_pan_node: of_node_put(dsi_pan_node); - i--; -error_vreg: - for (; i >= 0; i--) - mdss_dsi_put_dt_vreg_data(&pdev->dev, - &ctrl_pdata->power_data[i]); return rc; } +static int mdss_dsi_parse_dt_params(struct platform_device *pdev, + struct dsi_shared_data *sdata) +{ + int rc = 0; + + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,mmss-ulp-clamp-ctrl-offset", + &sdata->ulps_clamp_ctrl_off); + if (!rc) { + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,mmss-phyreset-ctrl-offset", + &sdata->ulps_phyrst_ctrl_off); + } + + sdata->timing_db_mode = of_property_read_bool( + pdev->dev.of_node, "qcom,timing-db-mode"); + + sdata->cmd_clk_ln_recovery_en = + of_property_read_bool(pdev->dev.of_node, + "qcom,dsi-clk-ln-recovery"); + + return 0; +} + static void mdss_dsi_res_deinit(struct platform_device *pdev) { int i; struct mdss_dsi_data *dsi_res = platform_get_drvdata(pdev); + struct dsi_shared_data *sdata; if (!dsi_res) { pr_err("%s: DSI root device drvdata not found\n", __func__); @@ -2196,6 +2206,26 @@ static void mdss_dsi_res_deinit(struct platform_device *pdev) devm_kfree(&pdev->dev, dsi_res->ctrl_pdata[i]); } + sdata = dsi_res->shared_data; + if (!sdata) + goto res_release; + + for (i = (DSI_MAX_PM - 1); i >= DSI_CORE_PM; i--) { + if (msm_dss_config_vreg(&pdev->dev, + sdata->power_data[i].vreg_config, + sdata->power_data[i].num_vreg, 1) < 0) + pr_err("%s: failed to de-init vregs for %s\n", + __func__, __mdss_dsi_pm_name(i)); + mdss_dsi_put_dt_vreg_data(&pdev->dev, + &sdata->power_data[i]); + } + + mdss_dsi_bus_clk_deinit(&pdev->dev, sdata); + + if (sdata) + devm_kfree(&pdev->dev, sdata); + +res_release: if (dsi_res) devm_kfree(&pdev->dev, dsi_res); @@ -2205,6 +2235,7 @@ static void mdss_dsi_res_deinit(struct platform_device *pdev) static int mdss_dsi_res_init(struct platform_device *pdev) { int rc = 0, i; + struct dsi_shared_data *sdata; mdss_dsi_res = platform_get_drvdata(pdev); if (!mdss_dsi_res) { @@ -2218,18 +2249,69 @@ static int mdss_dsi_res_init(struct platform_device *pdev) goto mem_fail; } + mdss_dsi_res->shared_data = devm_kzalloc(&pdev->dev, + sizeof(struct dsi_shared_data), + GFP_KERNEL); + pr_debug("%s Allocated shared_data=%p\n", __func__, + mdss_dsi_res->shared_data); + if (!mdss_dsi_res->shared_data) { + pr_err("%s Unable to alloc mem for shared_data\n", + __func__); + rc = -ENOMEM; + goto mem_fail; + } + + sdata = mdss_dsi_res->shared_data; + + rc = mdss_dsi_parse_dt_params(pdev, sdata); + if (rc) { + pr_err("%s: failed to parse mdss dsi DT params\n", + __func__); + goto mem_fail; + } + + rc = mdss_dsi_bus_clk_init(pdev, sdata); + if (rc) { + pr_err("%s: failed to initialize DSI Bus clocks\n", + __func__); + goto mem_fail; + } + + /* Parse the regulator information */ + for (i = DSI_CORE_PM; i < DSI_MAX_PM; i++) { + rc = mdss_dsi_get_dt_vreg_data(&pdev->dev, + pdev->dev.of_node, &sdata->power_data[i], i); + if (rc) { + pr_err("%s: '%s' get_dt_vreg_data failed.rc=%d\n", + __func__, __mdss_dsi_pm_name(i), rc); + i--; + for (; i >= DSI_CORE_PM; i--) + mdss_dsi_put_dt_vreg_data(&pdev->dev, + &sdata->power_data[i]); + goto mem_fail; + } + } + rc = mdss_dsi_regulator_init(pdev, sdata); + if (rc) { + pr_err("%s: failed to init regulator, rc=%d\n", + __func__, rc); + goto mem_fail; + } + for (i = 0; i < DSI_CTRL_MAX; i++) { mdss_dsi_res->ctrl_pdata[i] = devm_kzalloc(&pdev->dev, sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL); - pr_debug("%s Allocated ctrl_pdata[%d]=%p\n", - __func__, i, mdss_dsi_res->ctrl_pdata[i]); if (!mdss_dsi_res->ctrl_pdata[i]) { pr_err("%s Unable to alloc mem for ctrl=%d\n", __func__, i); rc = -ENOMEM; goto mem_fail; } + pr_debug("%s Allocated ctrl_pdata[%d]=%p\n", + __func__, i, mdss_dsi_res->ctrl_pdata[i]); + mdss_dsi_res->ctrl_pdata[i]->shared_data = + mdss_dsi_res->shared_data; } platform_set_drvdata(pdev, mdss_dsi_res); @@ -2249,22 +2331,29 @@ static int mdss_dsi_parse_hw_cfg(struct platform_device *pdev) { const char *data; struct mdss_dsi_data *dsi_res = platform_get_drvdata(pdev); + struct dsi_shared_data *sdata; if (!dsi_res) { pr_err("%s: DSI root device drvdata not found\n", __func__); return -EINVAL; } - dsi_res->hw_config = SINGLE_DSI; + sdata = mdss_dsi_res->shared_data; + if (!sdata) { + pr_err("%s: DSI shared data not found\n", __func__); + return -EINVAL; + } + + sdata->hw_config = SINGLE_DSI; data = of_get_property(pdev->dev.of_node, "hw-config", NULL); if (data) { if (!strcmp(data, "dual_dsi")) - dsi_res->hw_config = DUAL_DSI; + sdata->hw_config = DUAL_DSI; else if (!strcmp(data, "split_dsi")) - dsi_res->hw_config = SPLIT_DSI; + sdata->hw_config = SPLIT_DSI; else if (!strcmp(data, "single_dsi")) - dsi_res->hw_config = SINGLE_DSI; + sdata->hw_config = SINGLE_DSI; else pr_err("%s: Incorrect string for DSI config:%s. Setting default as SINGLE_DSI\n", __func__, data); @@ -2275,7 +2364,7 @@ static int mdss_dsi_parse_hw_cfg(struct platform_device *pdev) } pr_debug("%s: DSI h/w configuration is %d\n", __func__, - dsi_res->hw_config); + sdata->hw_config); return 0; } @@ -2346,22 +2435,18 @@ static int mdss_dsi_ctrl_remove(struct platform_device *pdev) { struct msm_fb_data_type *mfd; struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev); - int i = 0; if (!ctrl_pdata) { pr_err("%s: no driver data\n", __func__); return -ENODEV; } - for (i = DSI_MAX_PM - 1; i >= 0; i--) { - if (msm_dss_config_vreg(&pdev->dev, - ctrl_pdata->power_data[i].vreg_config, - ctrl_pdata->power_data[i].num_vreg, 1) < 0) - pr_err("%s: failed to de-init vregs for %s\n", - __func__, __mdss_dsi_pm_name(i)); - mdss_dsi_put_dt_vreg_data(&pdev->dev, - &ctrl_pdata->power_data[i]); - } + if (msm_dss_config_vreg(&pdev->dev, + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 1) < 0) + pr_err("%s: failed to de-init vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->panel_power_data); mfd = platform_get_drvdata(pdev); msm_dss_iounmap(&ctrl_pdata->mmss_misc_io); @@ -2500,7 +2585,7 @@ static void mdss_dsi_parse_lane_swap(struct device_node *np, char *dlane_swap) static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { - int rc, i, len; + int i, len; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); const char *data; @@ -2552,26 +2637,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i]; } - rc = of_property_read_u32(ctrl_pdev->dev.of_node, - "qcom,mmss-ulp-clamp-ctrl-offset", - &ctrl_pdata->ulps_clamp_ctrl_off); - if (rc && pinfo->mipi.mode == DSI_CMD_MODE) { - pr_err("%s: dsi clamp register settings missing\n", - __func__); - return -EINVAL; - } - rc = of_property_read_u32(ctrl_pdev->dev.of_node, - "qcom,mmss-phyreset-ctrl-offset", - &ctrl_pdata->ulps_phyrst_ctrl_off); - if (rc && pinfo->mipi.mode == DSI_CMD_MODE) - pr_debug("%s: dsi phyreset register settings missing\n", - __func__); - ctrl_pdata->cmd_sync_wait_broadcast = of_property_read_bool( pan_node, "qcom,cmd-sync-wait-broadcast"); if (ctrl_pdata->cmd_sync_wait_broadcast && - (mdss_dsi_res->hw_config == SPLIT_DSI) && + mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && (pinfo->pdest == DISPLAY_2)) ctrl_pdata->cmd_sync_wait_trigger = true; @@ -2579,12 +2649,6 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, ctrl_pdata->cmd_sync_wait_broadcast, ctrl_pdata->cmd_sync_wait_trigger); - ctrl_pdata->timing_db_mode = of_property_read_bool( - ctrl_pdev->dev.of_node, "qcom,timing-db-mode"); - - ctrl_pdata->cmd_clk_ln_recovery_en = of_property_read_bool( - ctrl_pdev->dev.of_node, "qcom,dsi-clk-ln-recovery"); - mdss_dsi_parse_lane_swap(ctrl_pdev->dev.of_node, &(ctrl_pdata->dlane_swap)); @@ -2650,6 +2714,7 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, { struct mipi_panel_info *mipi; int rc; + struct dsi_shared_data *sdata; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); struct resource *res; u64 clk_rate; @@ -2667,14 +2732,16 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, } rc = mdss_dsi_get_dt_vreg_data(&ctrl_pdev->dev, pan_node, - &ctrl_pdata->power_data[DSI_PANEL_PM], DSI_PANEL_PM); + &ctrl_pdata->panel_power_data, DSI_PANEL_PM); if (rc) { DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n", __func__, __mdss_dsi_pm_name(DSI_PANEL_PM), rc); return rc; } - rc = mdss_dsi_regulator_init(ctrl_pdev); + rc = msm_dss_config_vreg(&ctrl_pdev->dev, + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 1); if (rc) { pr_err("%s: failed to init regulator, rc=%d\n", __func__, rc); @@ -2698,7 +2765,7 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, return rc; } - if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) { + if (mdss_dsi_link_clk_init(ctrl_pdev, ctrl_pdata)) { pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__); return -EPERM; } @@ -2773,10 +2840,12 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, * This is needed for the DSI PHY to maintain ULPS state during * suspend also. */ + sdata = ctrl_pdata->shared_data; + 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); + sdata->power_data[DSI_PHY_PM].vreg_config, + sdata->power_data[DSI_PHY_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for DSI_CTRL_PM\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index a8076b6cac91..e6963c1426ae 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -120,10 +120,11 @@ enum dsi_lane_map_type { }; enum dsi_pm_type { + /* PANEL_PM not used as part of power_data in dsi_shared_data */ + DSI_PANEL_PM, DSI_CORE_PM, DSI_CTRL_PM, DSI_PHY_PM, - DSI_PANEL_PM, DSI_MAX_PM }; @@ -210,12 +211,43 @@ enum { DSI_CTRL_MAX, }; -struct mdss_dsi_data { +/* + * Common DSI properties for each controller. The DSI root probe will create the + * shared_data struct which should be accessible to each controller. The goal is + * to only access ctrl_pdata and ctrl_pdata->shared_data during the lifetime of + * each controller i.e. mdss_dsi_res should not be used directly. + */ +struct dsi_shared_data { u32 hw_config; /* DSI setup configuration i.e. single/dual/split */ + u32 hw_rev; /* DSI h/w revision */ + + /* DSI ULPS clamp register offsets */ + u32 ulps_clamp_ctrl_off; + u32 ulps_phyrst_ctrl_off; + + bool timing_db_mode; + bool cmd_clk_ln_recovery_en; + + /* DSI bus clocks */ + struct clk *mdp_core_clk; + struct clk *ahb_clk; + struct clk *axi_clk; + struct clk *mmss_misc_ahb_clk; + + /* DSI core regulators */ + struct dss_module_power power_data[DSI_MAX_PM]; +}; + +struct mdss_dsi_data { bool res_init; struct platform_device *pdev; /* List of controller specific struct data */ struct mdss_dsi_ctrl_pdata *ctrl_pdata[DSI_CTRL_MAX]; + /* + * This structure should hold common data structures like + * mutex, clocks, regulator information, setup information + */ + struct dsi_shared_data *shared_data; }; /* @@ -298,7 +330,6 @@ struct mdss_dsi_ctrl_pdata { void (*switch_mode) (struct mdss_panel_data *pdata, int mode); struct mdss_panel_data panel_data; unsigned char *ctrl_base; - u32 hw_rev; struct dss_io_data ctrl_io; struct dss_io_data mmss_misc_io; struct dss_io_data phy_io; @@ -306,10 +337,6 @@ struct mdss_dsi_ctrl_pdata { u32 bus_clk_cnt; u32 link_clk_cnt; u32 flags; - struct clk *mdp_core_clk; - struct clk *ahb_clk; - struct clk *axi_clk; - struct clk *mmss_misc_ahb_clk; struct clk *byte_clk; struct clk *esc_clk; struct clk *pixel_clk; @@ -342,7 +369,6 @@ struct mdss_dsi_ctrl_pdata { bool dcs_cmd_insert; atomic_t te_irq_ready; - bool cmd_clk_ln_recovery_en; bool cmd_sync_wait_broadcast; bool cmd_sync_wait_trigger; @@ -352,7 +378,8 @@ struct mdss_dsi_ctrl_pdata { u32 pclk_rate; u32 byte_clk_rate; bool refresh_clk_rate; /* flag to recalculate clk_rate */ - struct dss_module_power power_data[DSI_MAX_PM]; + struct dss_module_power panel_power_data; + struct dss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */ u32 dsi_irq_mask; struct mdss_hw *dsi_hw; struct mdss_intf_recovery *recovery; @@ -385,12 +412,9 @@ struct mdss_dsi_ctrl_pdata { struct regulator *ibb; /* vreg handle */ struct mutex clk_lane_mutex; - u32 ulps_clamp_ctrl_off; - u32 ulps_phyrst_ctrl_off; bool ulps; bool core_power; bool mmss_clamp; - bool timing_db_mode; char dlane_swap; /* data lane swap */ struct dsi_buf tx_buf; @@ -409,6 +433,7 @@ struct mdss_dsi_ctrl_pdata { int horizontal_idle_cnt; struct panel_horizontal_idle *line_idle; struct mdss_util_intf *mdss_util; + struct dsi_shared_data *shared_data; /* debugfs structure */ struct mdss_dsi_debugfs_info *debugfs_info; @@ -454,14 +479,20 @@ void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata); int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, int frame_rate); -int mdss_dsi_clk_init(struct platform_device *pdev, +int mdss_dsi_link_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); +void mdss_dsi_link_clk_deinit(struct device *dev, + struct mdss_dsi_ctrl_pdata *ctrl_pdata); +int mdss_dsi_bus_clk_init(struct platform_device *pdev, + struct dsi_shared_data *sdata); +void mdss_dsi_bus_clk_deinit(struct device *dev, + struct dsi_shared_data *sdata); int mdss_dsi_shadow_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); +void mdss_dsi_shadow_clk_deinit(struct device *dev, + struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_pll_1_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); -void mdss_dsi_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl_pdata); -void mdss_dsi_shadow_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_enable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_disable_bus_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable); @@ -521,14 +552,24 @@ static inline const char *__mdss_dsi_pm_supply_node_name( } } -static inline bool mdss_dsi_split_display_enabled(void) +static inline u32 mdss_dsi_get_hw_config(struct dsi_shared_data *sdata) { - /* - * currently the only supported mode is split display. - * So, if both controllers are initialized, then assume that - * split display mode is enabled. - */ - return ctrl_list[DSI_CTRL_LEFT] && ctrl_list[DSI_CTRL_RIGHT]; + return sdata->hw_config; +} + +static inline bool mdss_dsi_is_hw_config_single(struct dsi_shared_data *sdata) +{ + return mdss_dsi_get_hw_config(sdata) == SINGLE_DSI; +} + +static inline bool mdss_dsi_is_hw_config_split(struct dsi_shared_data *sdata) +{ + return mdss_dsi_get_hw_config(sdata) == SPLIT_DSI; +} + +static inline bool mdss_dsi_is_hw_config_dual(struct dsi_shared_data *sdata) +{ + return mdss_dsi_get_hw_config(sdata) == DUAL_DSI; } static inline bool mdss_dsi_sync_wait_enable(struct mdss_dsi_ctrl_pdata *ctrl) @@ -571,13 +612,13 @@ static inline struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl_by_index(int ndx) static inline bool mdss_dsi_is_ctrl_clk_master(struct mdss_dsi_ctrl_pdata *ctrl) { - return mdss_dsi_split_display_enabled() && + return mdss_dsi_is_hw_config_split(ctrl->shared_data) && (ctrl->ndx == DSI_CTRL_CLK_MASTER); } static inline bool mdss_dsi_is_ctrl_clk_slave(struct mdss_dsi_ctrl_pdata *ctrl) { - return mdss_dsi_split_display_enabled() && + return mdss_dsi_is_hw_config_split(ctrl->shared_data) && (ctrl->ndx == DSI_CTRL_CLK_SLAVE); } diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 530d69d03a81..1f2257064866 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -260,17 +260,17 @@ void mdss_dsi_cmd_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl) void mdss_dsi_read_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl) { /* clock must be on */ - ctrl->hw_rev = MIPI_INP(ctrl->ctrl_base); + ctrl->shared_data->hw_rev = MIPI_INP(ctrl->ctrl_base); } void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl) { mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); - ctrl->hw_rev = MIPI_INP(ctrl->ctrl_base); + ctrl->shared_data->hw_rev = MIPI_INP(ctrl->ctrl_base); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); pr_debug("%s: ndx=%d hw_rev=%x\n", __func__, - ctrl->ndx, ctrl->hw_rev); + ctrl->ndx, ctrl->shared_data->hw_rev); } void mdss_dsi_host_init(struct mdss_panel_data *pdata) @@ -636,7 +636,7 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl) pr_debug("%s: MDSS DSI CTRL and PHY reset. ctrl-num = %d\n", __func__, ctrl->ndx); - if (ctrl->panel_data.panel_info.is_split_display) { + if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) { pr_debug("%s: Split display enabled\n", __func__); ctrl0 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0); ctrl1 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_1); @@ -1106,7 +1106,7 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { - if (ctrl_pdata->timing_db_mode) + if (ctrl_pdata->shared_data->timing_db_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e8, 0x1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24, ((hspw + hbp + width + dummy_xres) << 16 | @@ -1121,7 +1121,7 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16)); - if (ctrl_pdata->timing_db_mode) + if (ctrl_pdata->shared_data->timing_db_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e4, 0x1); } else { /* command mode */ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888) @@ -1526,7 +1526,7 @@ do_send: goto end; } - if (ctrl->hw_rev >= MDSS_DSI_HW_REV_101) { + if (ctrl->shared_data->hw_rev >= MDSS_DSI_HW_REV_101) { /* clear the RDBK_DATA registers */ MIPI_OUTP(ctrl->ctrl_base + 0x01d4, 0x1); wmb(); /* make sure the RDBK registers are cleared */ @@ -1767,7 +1767,7 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl, if (cnt > 4) cnt = 4; /* 4 x 32 bits registers only */ - if (ctrl->hw_rev >= MDSS_DSI_HW_REV_101) { + if (ctrl->shared_data->hw_rev >= MDSS_DSI_HW_REV_101) { rp->read_cnt = (MIPI_INP((ctrl->ctrl_base) + 0x01d4) >> 16); pr_debug("%s: bytes read:%d\n", __func__, rp->read_cnt); @@ -1949,7 +1949,7 @@ static int mdss_dsi_mdp_busy_tout_check(struct mdss_dsi_ctrl_pdata *ctrl) MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr); mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); ctrl->mdp_busy = false; - if (ctrl->cmd_clk_ln_recovery_en && + if (ctrl->shared_data->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* has hs_lane_recovery do the work */ stop_hs_clk = true; @@ -2087,12 +2087,12 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) * will followed. */ if (!roi || (roi->w != 0 || roi->h != 0)) { - if (ctrl->cmd_clk_ln_recovery_en && + if (ctrl->shared_data->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) mdss_dsi_start_hs_clk_lane(ctrl); } } else { /* from dcs send */ - if (ctrl->cmd_clk_ln_recovery_en && + if (ctrl->shared_data->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE && (req->flags & CMD_REQ_HS_MODE)) mdss_dsi_cmd_start_hs_clk_lane(ctrl); @@ -2163,7 +2163,7 @@ need_lock: mutex_unlock(&ctrl->cmd_mutex); } else { /* from dcs send */ - if (ctrl->cmd_clk_ln_recovery_en && + if (ctrl->shared_data->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE && (req && (req->flags & CMD_REQ_HS_MODE))) mdss_dsi_cmd_stop_hs_clk_lane(ctrl); @@ -2262,7 +2262,8 @@ static int dsi_event_thread(void *data) pr_debug("%s: lane_status: 0x%x\n", __func__, ln_status); if (ctrl->recovery - && (ctrl->hw_rev != MDSS_DSI_HW_REV_103) + && (ctrl->shared_data->hw_rev + != MDSS_DSI_HW_REV_103) && !(force_clk_ln_hs) && (ln_status & DSI_DATA_LANES_STOP_STATE) @@ -2276,7 +2277,7 @@ static int dsi_event_thread(void *data) DSI_INTR_ERROR_MASK, 1); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); } else if (ctrl->recovery - && (ctrl->hw_rev + && (ctrl->shared_data->hw_rev == MDSS_DSI_HW_REV_103)) { pr_debug("%s: Handle overflow->Rev_103\n", __func__); @@ -2511,7 +2512,7 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x99); spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); - if (ctrl->cmd_clk_ln_recovery_en && + if (ctrl->shared_data->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* stop force clk lane hs */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 0); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index b05689da9ec5..d6ad191cdf67 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -293,6 +293,13 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); + if (mdss_dsi_is_right_ctrl(ctrl_pdata) && + mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { + pr_debug("%s:%d, right ctrl gpio configuration not needed\n", + __func__, __LINE__); + return rc; + } + if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) { pr_debug("%s:%d, reset line not configured\n", __func__, __LINE__); diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 6d2c28acb3a1..9f616789f7a1 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -72,7 +72,8 @@ static void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) return; } - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, MDSS_DSI_HW_REV_104)) { + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, + MDSS_DSI_HW_REV_104)) { if (mdss_dsi_is_ctrl_clk_master(ctrl)) sctrl = mdss_dsi_get_ctrl_clk_slave(); else @@ -89,7 +90,7 @@ static void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) * Need to turn off the PLL1 to avoid current leakage issues */ if (ctrl->ndx == DSI_CTRL_1) { - if (ctrl->hw_rev == MDSS_DSI_HW_REV_103) { + if (ctrl->shared_data->hw_rev == MDSS_DSI_HW_REV_103) { pr_debug("Turn off PLL 1 registers\n"); clk_set_rate(ctrl->vco_clk, 1); } @@ -103,7 +104,8 @@ static void mdss_dsi_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl) return; } - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, MDSS_DSI_HW_REV_104)) + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, + MDSS_DSI_HW_REV_104)) return; MIPI_OUTP(ctrl->shared_ctrl_data->phy_regulator_io.base @@ -117,7 +119,8 @@ static void mdss_dsi_phy_lane_shutdown(struct mdss_dsi_ctrl_pdata *ctrl) return; } - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, MDSS_DSI_HW_REV_104)) + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, + MDSS_DSI_HW_REV_104)) MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, ~0x1F); else MIPI_OUTP(ctrl->phy_io.base + MDSS_DSI_DSIPHY_CTRL_0, 0x000); @@ -135,11 +138,11 @@ void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl) ctrl->shared_ctrl_data->phy_disable_refcount++; /* - * In dual-dsi configuration, the phy should be disabled for the + * In split-dsi configuration, the phy should be disabled for the * first controller only when the second controller is disabled. * This is true regardless of whether broadcast mode is enabled. */ - if (!mdss_dsi_split_display_enabled() || + if (!mdss_dsi_is_hw_config_split(ctrl->shared_data) || ctrl->shared_ctrl_data->phy_disable_refcount == 2) { other_ctrl = mdss_dsi_get_other_ctrl(ctrl); @@ -175,7 +178,8 @@ void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl) return; } - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, MDSS_DSI_HW_REV_104)) + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, + MDSS_DSI_HW_REV_104)) return; pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db); @@ -298,7 +302,7 @@ static void mdss_dsi_28nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */ if (((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) || - (ctrl_pdata->hw_rev == MDSS_DSI_HW_REV_103_1)) + (ctrl_pdata->shared_data->hw_rev == MDSS_DSI_HW_REV_103_1)) MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01); else MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00); @@ -530,7 +534,7 @@ static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl) udelay(100); MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_CTRL_1, 0x00); - if (mdss_dsi_split_display_enabled()) { + if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) { if (mdss_dsi_is_left_ctrl(ctrl)) mdss_dsi_8996_pll_source_from_left(ctrl); else @@ -571,7 +575,7 @@ static void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) return; } - switch (ctrl->hw_rev) { + switch (ctrl->shared_data->hw_rev) { case MDSS_DSI_HW_REV_104: case MDSS_DSI_HW_REV_104_1: mdss_dsi_8996_phy_init(ctrl); @@ -585,83 +589,121 @@ static void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) } } -int mdss_dsi_clk_init(struct platform_device *pdev, - struct mdss_dsi_ctrl_pdata *ctrl) +void mdss_dsi_bus_clk_deinit(struct device *dev, + struct dsi_shared_data *sdata) +{ + if (sdata->mmss_misc_ahb_clk) + devm_clk_put(dev, sdata->mmss_misc_ahb_clk); + if (sdata->axi_clk) + devm_clk_put(dev, sdata->axi_clk); + if (sdata->ahb_clk) + devm_clk_put(dev, sdata->ahb_clk); + if (sdata->mdp_core_clk) + devm_clk_put(dev, sdata->mdp_core_clk); +} + +int mdss_dsi_bus_clk_init(struct platform_device *pdev, + struct dsi_shared_data *sdata) { struct device *dev = NULL; int rc = 0; if (!pdev) { pr_err("%s: Invalid pdev\n", __func__); - goto mdss_dsi_clk_err; + goto clk_err; } dev = &pdev->dev; - ctrl->mdp_core_clk = clk_get(dev, "mdp_core_clk"); - if (IS_ERR(ctrl->mdp_core_clk)) { - rc = PTR_ERR(ctrl->mdp_core_clk); + sdata->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk"); + if (IS_ERR(sdata->mdp_core_clk)) { + rc = PTR_ERR(sdata->mdp_core_clk); pr_err("%s: Unable to get mdp core clk. rc=%d\n", __func__, rc); - goto mdss_dsi_clk_err; + goto clk_err; } - ctrl->ahb_clk = clk_get(dev, "iface_clk"); - if (IS_ERR(ctrl->ahb_clk)) { - rc = PTR_ERR(ctrl->ahb_clk); + sdata->ahb_clk = devm_clk_get(dev, "iface_clk"); + if (IS_ERR(sdata->ahb_clk)) { + rc = PTR_ERR(sdata->ahb_clk); pr_err("%s: Unable to get mdss ahb clk. rc=%d\n", __func__, rc); - goto mdss_dsi_clk_err; + goto clk_err; } - ctrl->axi_clk = clk_get(dev, "bus_clk"); - if (IS_ERR(ctrl->axi_clk)) { - rc = PTR_ERR(ctrl->axi_clk); + sdata->axi_clk = devm_clk_get(dev, "bus_clk"); + if (IS_ERR(sdata->axi_clk)) { + rc = PTR_ERR(sdata->axi_clk); pr_err("%s: Unable to get axi bus clk. rc=%d\n", __func__, rc); - goto mdss_dsi_clk_err; + goto clk_err; } - if ((ctrl->panel_data.panel_info.type == MIPI_CMD_PANEL) || - ctrl->panel_data.panel_info.mipi.dms_mode || - 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; - pr_info("%s: Unable to get mmss misc ahb clk\n", - __func__); - } + sdata->mmss_misc_ahb_clk = devm_clk_get(dev, "core_mmss_clk"); + if (IS_ERR(sdata->mmss_misc_ahb_clk)) { + sdata->mmss_misc_ahb_clk = NULL; + pr_info("%s: Unable to get mmss misc ahb clk\n", + __func__); } - ctrl->byte_clk = clk_get(dev, "byte_clk"); +clk_err: + if (rc) + mdss_dsi_bus_clk_deinit(dev, sdata); + return rc; +} + +void mdss_dsi_link_clk_deinit(struct device *dev, + struct mdss_dsi_ctrl_pdata *ctrl) +{ + if (ctrl->byte_clk) + devm_clk_put(dev, ctrl->byte_clk); + if (ctrl->esc_clk) + devm_clk_put(dev, ctrl->esc_clk); + if (ctrl->pixel_clk) + devm_clk_put(dev, ctrl->pixel_clk); +} + +int mdss_dsi_link_clk_init(struct platform_device *pdev, + struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct device *dev = NULL; + int rc = 0; + + if (!pdev) { + pr_err("%s: Invalid pdev\n", __func__); + goto error; + } + + dev = &pdev->dev; + ctrl->byte_clk = devm_clk_get(dev, "byte_clk"); if (IS_ERR(ctrl->byte_clk)) { rc = PTR_ERR(ctrl->byte_clk); pr_err("%s: can't find dsi_byte_clk. rc=%d\n", __func__, rc); ctrl->byte_clk = NULL; - goto mdss_dsi_clk_err; + goto error; } - ctrl->pixel_clk = clk_get(dev, "pixel_clk"); + ctrl->pixel_clk = devm_clk_get(dev, "pixel_clk"); if (IS_ERR(ctrl->pixel_clk)) { rc = PTR_ERR(ctrl->pixel_clk); pr_err("%s: can't find dsi_pixel_clk. rc=%d\n", __func__, rc); ctrl->pixel_clk = NULL; - goto mdss_dsi_clk_err; + goto error; } - ctrl->esc_clk = clk_get(dev, "core_clk"); + ctrl->esc_clk = devm_clk_get(dev, "core_clk"); if (IS_ERR(ctrl->esc_clk)) { rc = PTR_ERR(ctrl->esc_clk); pr_err("%s: can't find dsi_esc_clk. rc=%d\n", __func__, rc); ctrl->esc_clk = NULL; - goto mdss_dsi_clk_err; + goto error; } -mdss_dsi_clk_err: +error: if (rc) - mdss_dsi_clk_deinit(ctrl); + mdss_dsi_link_clk_deinit(dev, ctrl); return rc; } @@ -688,6 +730,23 @@ int mdss_dsi_pll_1_clk_init(struct platform_device *pdev, return rc; } +void mdss_dsi_shadow_clk_deinit(struct device *dev, + struct mdss_dsi_ctrl_pdata *ctrl) +{ + if (ctrl->mux_byte_clk) + devm_clk_put(dev, ctrl->mux_byte_clk); + if (ctrl->mux_pixel_clk) + devm_clk_put(dev, ctrl->mux_pixel_clk); + if (ctrl->pll_byte_clk) + devm_clk_put(dev, ctrl->pll_byte_clk); + if (ctrl->pll_pixel_clk) + devm_clk_put(dev, ctrl->pll_pixel_clk); + if (ctrl->shadow_byte_clk) + devm_clk_put(dev, ctrl->shadow_byte_clk); + if (ctrl->shadow_pixel_clk) + devm_clk_put(dev, ctrl->shadow_pixel_clk); +} + int mdss_dsi_shadow_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl) { @@ -700,101 +759,66 @@ int mdss_dsi_shadow_clk_init(struct platform_device *pdev, } dev = &pdev->dev; - ctrl->mux_byte_clk = clk_get(dev, "mdss_byte_clk_mux"); + ctrl->mux_byte_clk = devm_clk_get(dev, "mdss_byte_clk_mux"); if (IS_ERR(ctrl->mux_byte_clk)) { rc = PTR_ERR(ctrl->mux_byte_clk); pr_err("%s: can't find mux_byte_clk. rc=%d\n", __func__, rc); ctrl->mux_byte_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } - ctrl->mux_pixel_clk = clk_get(dev, "mdss_pixel_clk_mux"); + ctrl->mux_pixel_clk = devm_clk_get(dev, "mdss_pixel_clk_mux"); if (IS_ERR(ctrl->mux_pixel_clk)) { rc = PTR_ERR(ctrl->mux_pixel_clk); pr_err("%s: can't find mdss_mux_pixel_clk. rc=%d\n", __func__, rc); ctrl->mux_pixel_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } - ctrl->pll_byte_clk = clk_get(dev, "byte_clk_src"); + ctrl->pll_byte_clk = devm_clk_get(dev, "byte_clk_src"); if (IS_ERR(ctrl->pll_byte_clk)) { rc = PTR_ERR(ctrl->pll_byte_clk); pr_err("%s: can't find pll_byte_clk. rc=%d\n", __func__, rc); ctrl->pll_byte_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } - ctrl->pll_pixel_clk = clk_get(dev, "pixel_clk_src"); + ctrl->pll_pixel_clk = devm_clk_get(dev, "pixel_clk_src"); if (IS_ERR(ctrl->pll_pixel_clk)) { rc = PTR_ERR(ctrl->pll_pixel_clk); pr_err("%s: can't find pll_pixel_clk. rc=%d\n", __func__, rc); ctrl->pll_pixel_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } - ctrl->shadow_byte_clk = clk_get(dev, "shadow_byte_clk_src"); + ctrl->shadow_byte_clk = devm_clk_get(dev, "shadow_byte_clk_src"); if (IS_ERR(ctrl->shadow_byte_clk)) { rc = PTR_ERR(ctrl->shadow_byte_clk); pr_err("%s: can't find shadow_byte_clk. rc=%d\n", __func__, rc); ctrl->shadow_byte_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } - ctrl->shadow_pixel_clk = clk_get(dev, "shadow_pixel_clk_src"); + ctrl->shadow_pixel_clk = devm_clk_get(dev, "shadow_pixel_clk_src"); if (IS_ERR(ctrl->shadow_pixel_clk)) { rc = PTR_ERR(ctrl->shadow_pixel_clk); pr_err("%s: can't find shadow_pixel_clk. rc=%d\n", __func__, rc); ctrl->shadow_pixel_clk = NULL; - goto mdss_dsi_shadow_clk_err; + goto error; } -mdss_dsi_shadow_clk_err: +error: if (rc) - mdss_dsi_shadow_clk_deinit(ctrl); + mdss_dsi_shadow_clk_deinit(dev, ctrl); return rc; } -void mdss_dsi_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl) -{ - if (ctrl->byte_clk) - clk_put(ctrl->byte_clk); - if (ctrl->esc_clk) - clk_put(ctrl->esc_clk); - if (ctrl->pixel_clk) - clk_put(ctrl->pixel_clk); - if (ctrl->mmss_misc_ahb_clk) - clk_put(ctrl->mmss_misc_ahb_clk); - if (ctrl->axi_clk) - clk_put(ctrl->axi_clk); - if (ctrl->ahb_clk) - clk_put(ctrl->ahb_clk); - if (ctrl->mdp_core_clk) - clk_put(ctrl->mdp_core_clk); -} - -void mdss_dsi_shadow_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl) -{ - if (ctrl->mux_byte_clk) - clk_put(ctrl->mux_byte_clk); - if (ctrl->mux_pixel_clk) - clk_put(ctrl->mux_pixel_clk); - if (ctrl->pll_byte_clk) - clk_put(ctrl->pll_byte_clk); - if (ctrl->pll_pixel_clk) - clk_put(ctrl->pll_pixel_clk); - if (ctrl->shadow_byte_clk) - clk_put(ctrl->shadow_byte_clk); - if (ctrl->shadow_pixel_clk) - clk_put(ctrl->shadow_pixel_clk); -} - - int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, int frame_rate) { @@ -864,10 +888,11 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, static int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int rc = 0; + struct dsi_shared_data *sdata = ctrl_pdata->shared_data; pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx); - rc = clk_prepare_enable(ctrl_pdata->mdp_core_clk); + rc = clk_prepare_enable(sdata->mdp_core_clk); if (rc) { pr_err("%s: failed to enable mdp_core_clock. rc=%d\n", __func__, rc); @@ -875,20 +900,20 @@ static int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata) } mdss_update_reg_bus_vote(VOTE_INDEX_19_MHZ); - rc = clk_prepare_enable(ctrl_pdata->ahb_clk); + rc = clk_prepare_enable(sdata->ahb_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); goto disable_core_clk; } - rc = clk_prepare_enable(ctrl_pdata->axi_clk); + rc = clk_prepare_enable(sdata->axi_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); goto disable_ahb_clk; } - if (ctrl_pdata->mmss_misc_ahb_clk) { - rc = clk_prepare_enable(ctrl_pdata->mmss_misc_ahb_clk); + if (sdata->mmss_misc_ahb_clk) { + rc = clk_prepare_enable(sdata->mmss_misc_ahb_clk); if (rc) { pr_err("%s: failed to enable mmss misc ahb clk.rc=%d\n", __func__, rc); @@ -898,24 +923,25 @@ static int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return rc; disable_axi_clk: - clk_disable_unprepare(ctrl_pdata->axi_clk); + clk_disable_unprepare(sdata->axi_clk); disable_ahb_clk: - clk_disable_unprepare(ctrl_pdata->ahb_clk); + clk_disable_unprepare(sdata->ahb_clk); disable_core_clk: mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE); - clk_disable_unprepare(ctrl_pdata->mdp_core_clk); + clk_disable_unprepare(sdata->mdp_core_clk); error: return rc; } static void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { - if (ctrl_pdata->mmss_misc_ahb_clk) - clk_disable_unprepare(ctrl_pdata->mmss_misc_ahb_clk); - clk_disable_unprepare(ctrl_pdata->axi_clk); - clk_disable_unprepare(ctrl_pdata->ahb_clk); + struct dsi_shared_data *sdata = ctrl_pdata->shared_data; + if (sdata->mmss_misc_ahb_clk) + clk_disable_unprepare(sdata->mmss_misc_ahb_clk); + clk_disable_unprepare(sdata->axi_clk); + clk_disable_unprepare(sdata->ahb_clk); mdss_update_reg_bus_vote(VOTE_INDEX_DISABLE); - clk_disable_unprepare(ctrl_pdata->mdp_core_clk); + clk_disable_unprepare(sdata->mdp_core_clk); } static int mdss_dsi_link_clk_prepare(struct mdss_dsi_ctrl_pdata *ctrl_pdata) @@ -1255,13 +1281,14 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) return -EINVAL; } - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, MDSS_DSI_HW_REV_104)) { + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, + MDSS_DSI_HW_REV_104)) { pr_debug("%s: clamp ctrl configuration is skipped\n", __func__); return 0; } - clamp_reg_off = ctrl->ulps_clamp_ctrl_off; - phyrst_reg_off = ctrl->ulps_phyrst_ctrl_off; + clamp_reg_off = ctrl->shared_data->ulps_clamp_ctrl_off; + phyrst_reg_off = ctrl->shared_data->ulps_phyrst_ctrl_off; mipi = &ctrl->panel_data.panel_info.mipi; /* clock lane will always be clamped */ @@ -1313,7 +1340,7 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) * reset when mdss ahb clock reset is asserted while coming * out of power collapse */ - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, MDSS_DSI_HW_REV_104)) { regval = MIPI_INP(ctrl->mmss_misc_io.base + @@ -1328,7 +1355,7 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) wmb(); ctrl->mmss_clamp = true; } else if (!enable && ctrl->mmss_clamp) { - if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->hw_rev, + if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev, MDSS_DSI_HW_REV_104)) { regval = MIPI_INP(ctrl->mmss_misc_io.base + @@ -1379,12 +1406,14 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int rc = 0; int i = 0; struct mdss_panel_data *pdata = NULL; + struct dsi_shared_data *sdata; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } + sdata = ctrl->shared_data; pdata = &ctrl->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); @@ -1402,16 +1431,15 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, * not be changed during static screen. */ pr_debug("%s: Enable DSI core power\n", __func__); - for (i = 0; i < DSI_MAX_PM; i++) { - if ((DSI_PANEL_PM == i) || - ((DSI_CORE_PM != i) && + for (i = DSI_CORE_PM; i < DSI_MAX_PM; i++) { + if (((DSI_CORE_PM != i) && (pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) && !pdata->panel_info.cont_splash_enabled)) continue; rc = msm_dss_enable_vreg( - ctrl->power_data[i].vreg_config, - ctrl->power_data[i].num_vreg, 1); + sdata->power_data[i].vreg_config, + sdata->power_data[i].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, @@ -1508,15 +1536,14 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, pr_debug("%s: leaving DSI core power on\n", __func__); } else { pr_debug("%s: Disable DSI core power\n", __func__); - for (i = DSI_MAX_PM - 1; i >= 0; i--) { - if ((DSI_PANEL_PM == i) || - ((DSI_CORE_PM != i) && + for (i = DSI_MAX_PM - 1; i >= DSI_CORE_PM; i--) { + if (((DSI_CORE_PM != i) && (pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK))) continue; rc = msm_dss_enable_vreg( - ctrl->power_data[i].vreg_config, - ctrl->power_data[i].num_vreg, 0); + sdata->power_data[i].vreg_config, + sdata->power_data[i].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, @@ -1533,13 +1560,12 @@ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, error_ulps: mdss_dsi_bus_clk_stop(ctrl); error_bus_clk_start: - for (i = DSI_MAX_PM - 1; i >= 0; i--) { - if ((DSI_PANEL_PM == i) || ((DSI_CORE_PM != i) && - (pdata->panel_info.blank_state != + for (i = DSI_MAX_PM - 1; i >= DSI_CORE_PM; i--) { + if (((DSI_CORE_PM != i) && (pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK))) continue; - rc = msm_dss_enable_vreg(ctrl->power_data[i].vreg_config, - ctrl->power_data[i].num_vreg, 0); + rc = msm_dss_enable_vreg(sdata->power_data[i].vreg_config, + sdata->power_data[i].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); |
