unsigned int next);
 void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
                                unsigned int next);
+int mtk_ovl_adaptor_power_on(struct device *dev);
+void mtk_ovl_adaptor_power_off(struct device *dev);
 int mtk_ovl_adaptor_clk_enable(struct device *dev);
 void mtk_ovl_adaptor_clk_disable(struct device *dev);
 void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
 const u32 *mtk_rdma_get_formats(struct device *dev);
 size_t mtk_rdma_get_num_formats(struct device *dev);
 
+int mtk_mdp_rdma_power_on(struct device *dev);
+void mtk_mdp_rdma_power_off(struct device *dev);
 int mtk_mdp_rdma_clk_enable(struct device *dev);
 void mtk_mdp_rdma_clk_disable(struct device *dev);
 void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
 
 };
 
 static const struct mtk_ddp_comp_funcs rdma = {
+       .power_on = mtk_mdp_rdma_power_on,
+       .power_off = mtk_mdp_rdma_power_off,
        .clk_enable = mtk_mdp_rdma_clk_enable,
        .clk_disable = mtk_mdp_rdma_clk_disable,
 };
        mtk_ethdr_stop(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
 }
 
-int mtk_ovl_adaptor_clk_enable(struct device *dev)
+/**
+ * power_off - Power off the devices in OVL adaptor
+ * @dev: Device to be powered off
+ * @num: Number of the devices to be powered off
+ *
+ * Calls the .power_off() ovl_adaptor component callback if it is present.
+ */
+static inline void power_off(struct device *dev, int num)
 {
        struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
-       struct device *comp;
-       int ret;
        int i;
 
-       for (i = 0; i < OVL_ADAPTOR_MERGE0; i++) {
-               comp = ovl_adaptor->ovl_adaptor_comp[i];
-               ret = pm_runtime_get_sync(comp);
+       if (num > OVL_ADAPTOR_ID_MAX)
+               num = OVL_ADAPTOR_ID_MAX;
+
+       for (i = num - 1; i >= 0; i--) {
+               if (!ovl_adaptor->ovl_adaptor_comp[i] ||
+                   !comp_matches[i].funcs->power_off)
+                       continue;
+
+               comp_matches[i].funcs->power_off(ovl_adaptor->ovl_adaptor_comp[i]);
+       }
+}
+
+/**
+ * mtk_ovl_adaptor_power_on - Power on the devices in OVL adaptor
+ * @dev: Device to be powered on
+ *
+ * Different from OVL, OVL adaptor is a pseudo device so
+ * we didn't define it in the device tree, pm_runtime_resume_and_get()
+ * called by .atomic_enable() power on no device in OVL adaptor,
+ * we have to implement a function to do the job instead.
+ *
+ * Return: Zero for success or negative number for failure.
+ */
+int mtk_ovl_adaptor_power_on(struct device *dev)
+{
+       struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+       int i, ret;
+
+       for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
+               if (!ovl_adaptor->ovl_adaptor_comp[i] ||
+                   !comp_matches[i].funcs->power_on)
+                       continue;
+
+               ret = comp_matches[i].funcs->power_on(ovl_adaptor->ovl_adaptor_comp[i]);
                if (ret < 0) {
                        dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
-                       goto error;
+                       power_off(dev, i);
+                       return ret;
                }
        }
+       return 0;
+}
+
+void mtk_ovl_adaptor_power_off(struct device *dev)
+{
+       power_off(dev, OVL_ADAPTOR_ID_MAX);
+}
+
+int mtk_ovl_adaptor_clk_enable(struct device *dev)
+{
+       struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+       struct device *comp;
+       int ret;
+       int i;
 
        for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
                comp = ovl_adaptor->ovl_adaptor_comp[i];
                        dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
                        while (--i >= 0)
                                comp_matches[i].funcs->clk_disable(comp);
-                       i = OVL_ADAPTOR_MERGE0;
-                       goto error;
+                       return ret;
                }
        }
        return 0;
-error:
-       while (--i >= 0)
-               pm_runtime_put(ovl_adaptor->ovl_adaptor_comp[i]);
-
-       return ret;
 }
 
 void mtk_ovl_adaptor_clk_disable(struct device *dev)
 
 
        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
-       ret = pm_runtime_resume_and_get(comp->dev);
+       ret = mtk_ddp_comp_power_on(comp);
        if (ret < 0) {
                DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
                return;
 
        ret = mtk_crtc_ddp_hw_init(mtk_crtc);
        if (ret) {
-               pm_runtime_put(comp->dev);
+               mtk_ddp_comp_power_off(comp);
                return;
        }
 
 {
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
        struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-       int i, ret;
+       int i;
 
        DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
        if (!mtk_crtc->enabled)
 
        drm_crtc_vblank_off(crtc);
        mtk_crtc_ddp_hw_fini(mtk_crtc);
-       ret = pm_runtime_put(comp->dev);
-       if (ret < 0)
-               DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret);
+       mtk_ddp_comp_power_off(comp);
 
        mtk_crtc->enabled = false;
 }
 
 };
 
 static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
+       .power_on = mtk_ovl_adaptor_power_on,
+       .power_off = mtk_ovl_adaptor_power_off,
        .clk_enable = mtk_ovl_adaptor_clk_enable,
        .clk_disable = mtk_ovl_adaptor_clk_disable,
        .config = mtk_ovl_adaptor_config,
 
 #define MTK_DRM_DDP_COMP_H
 
 #include <linux/io.h>
+#include <linux/pm_runtime.h>
 #include <linux/soc/mediatek/mtk-cmdq.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 #include <linux/soc/mediatek/mtk-mutex.h>
 struct mtk_ddp_comp;
 struct cmdq_pkt;
 struct mtk_ddp_comp_funcs {
+       int (*power_on)(struct device *dev);
+       void (*power_off)(struct device *dev);
        int (*clk_enable)(struct device *dev);
        void (*clk_disable)(struct device *dev);
        void (*config)(struct device *dev, unsigned int w,
        const struct mtk_ddp_comp_funcs *funcs;
 };
 
+static inline int mtk_ddp_comp_power_on(struct mtk_ddp_comp *comp)
+{
+       if (comp->funcs && comp->funcs->power_on)
+               return comp->funcs->power_on(comp->dev);
+       else
+               return pm_runtime_resume_and_get(comp->dev);
+       return 0;
+}
+
+static inline void mtk_ddp_comp_power_off(struct mtk_ddp_comp *comp)
+{
+       if (comp->funcs && comp->funcs->power_off)
+               comp->funcs->power_off(comp->dev);
+       else
+               pm_runtime_put(comp->dev);
+}
+
 static inline int mtk_ddp_comp_clk_enable(struct mtk_ddp_comp *comp)
 {
        if (comp->funcs && comp->funcs->clk_enable)
 
        return ARRAY_SIZE(formats);
 }
 
+int mtk_mdp_rdma_power_on(struct device *dev)
+{
+       int ret = pm_runtime_resume_and_get(dev);
+
+       if (ret < 0) {
+               dev_err(dev, "Failed to power on: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+void mtk_mdp_rdma_power_off(struct device *dev)
+{
+       pm_runtime_put(dev);
+}
+
 int mtk_mdp_rdma_clk_enable(struct device *dev)
 {
        struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);