Kaanapali (SM8750) and Glymur use two display power domains.
CORE_GDSC powers the main display hardware while INT2_GDSC powers
a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6).

The MDSS driver currently relies on the default runtime PM handling
and does not enable the secondary INT2_GDSC. As a result, display
pipes backed by INT2_GDSC remain inaccessible.

Attach and manage both power domains explicitly and enable them
during MDSS runtime PM activation.

Signed-off-by: Yongxing Mou <[email protected]>
---
 drivers/gpu/drm/msm/msm_mdss.c | 53 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 9087c4b290db..63ece55c4f2e 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -13,6 +13,7 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
 
@@ -44,6 +45,7 @@ struct msm_mdss {
        struct icc_path *mdp_path[2];
        u32 num_mdp_paths;
        struct icc_path *reg_bus_path;
+       struct dev_pm_domain_list *pd_list;
 };
 
 static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
@@ -233,6 +235,21 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
        int ret, i;
        u32 hw_rev;
 
+       /*
+        * Platforms with two power domains (e.g. Kaanapali, Glymur) need both
+        * GDSCs enabled explicitly; the core framework only auto-attaches a
+        * single power domain.
+        */
+       if (msm_mdss->pd_list) {
+               ret = pm_runtime_resume_and_get(msm_mdss->pd_list->pd_devs[0]);
+               if (ret < 0)
+                       return ret;
+
+               ret = pm_runtime_resume_and_get(msm_mdss->pd_list->pd_devs[1]);
+               if (ret < 0)
+                       goto err_put_core;
+       }
+
        /*
         * Several components have AXI clocks that can only be turned on if
         * the interconnect is enabled (non-zero bandwidth). Let's make sure
@@ -255,7 +272,7 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
        ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks);
        if (ret) {
                dev_err(msm_mdss->dev, "clock enable failed, ret:%d\n", ret);
-               return ret;
+               goto err_put_int2;
        }
 
        /*
@@ -276,6 +293,14 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
        /* else UBWC 1.0 or none, no params to program */
 
        return ret;
+
+err_put_int2:
+       if (msm_mdss->pd_list)
+               pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[1]);
+err_put_core:
+       if (msm_mdss->pd_list)
+               pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[0]);
+       return ret;
 }
 
 static int msm_mdss_disable(struct msm_mdss *msm_mdss)
@@ -290,6 +315,11 @@ static int msm_mdss_disable(struct msm_mdss *msm_mdss)
        if (msm_mdss->reg_bus_path)
                icc_set_bw(msm_mdss->reg_bus_path, 0, 0);
 
+       if (msm_mdss->pd_list) {
+               pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[1]);
+               pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[0]);
+       }
+
        return 0;
 }
 
@@ -421,6 +451,27 @@ static struct msm_mdss *msm_mdss_init(struct 
platform_device *pdev, bool is_mdp5
        irq_set_chained_handler_and_data(irq, msm_mdss_irq,
                                         msm_mdss);
 
+       /*
+        * When two power domains are listed in DT, the core framework does not
+        * auto-attach either of them.  Attach and manage both explicitly so
+        * that INT2_GDSC (needed for VIG2/VIG3) is enabled alongside the main
+        * CORE_GDSC.  Single-domain platforms are unaffected.
+        */
+       if (of_count_phandle_with_args(pdev->dev.of_node, "power-domains",
+                                      "#power-domain-cells") > 1) {
+               static const char * const mdss_pd_names[] = { "core", "int2" };
+               static const struct dev_pm_domain_attach_data pd_data = {
+                       .pd_names = mdss_pd_names,
+                       .num_pd_names = ARRAY_SIZE(mdss_pd_names),
+                       .pd_flags = PD_FLAG_NO_DEV_LINK,
+               };
+
+               ret = devm_pm_domain_attach_list(&pdev->dev, &pd_data,
+                                                &msm_mdss->pd_list);
+               if (ret < 0)
+                       return ERR_PTR(ret);
+       }
+
        pm_runtime_enable(&pdev->dev);
 
        return msm_mdss;

-- 
2.43.0

Reply via email to