struct mtk_disp_color {
        struct mtk_ddp_comp                     ddp_comp;
        struct drm_crtc                         *crtc;
+       struct clk                              *clk;
        const struct mtk_disp_color_data        *data;
 };
 
        return container_of(comp, struct mtk_disp_color, ddp_comp);
 }
 
+static int mtk_color_clk_enable(struct device *dev)
+{
+       struct mtk_disp_color *color = dev_get_drvdata(dev);
+
+       return clk_prepare_enable(color->clk);
+}
+
+static void mtk_color_clk_disable(struct device *dev)
+{
+       struct mtk_disp_color *color = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(color->clk);
+}
+
 static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
                             unsigned int h, unsigned int vrefresh,
                             unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
 }
 
 static const struct mtk_ddp_comp_funcs mtk_disp_color_funcs = {
+       .clk_enable = mtk_color_clk_enable,
+       .clk_disable = mtk_color_clk_disable,
        .config = mtk_color_config,
        .start = mtk_color_start,
 };
        if (!priv)
                return -ENOMEM;
 
+       priv->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(priv->clk)) {
+               dev_err(dev, "failed to get color clk\n");
+               return PTR_ERR(priv->clk);
+       }
+
        comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_COLOR);
        if (comp_id < 0) {
                dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
 
 struct mtk_disp_ovl {
        struct mtk_ddp_comp             ddp_comp;
        struct drm_crtc                 *crtc;
+       struct clk                      *clk;
        const struct mtk_disp_ovl_data  *data;
 };
 
        writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN);
 }
 
+static int mtk_ovl_clk_enable(struct device *dev)
+{
+       struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+       return clk_prepare_enable(ovl->clk);
+}
+
+static void mtk_ovl_clk_disable(struct device *dev)
+{
+       struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(ovl->clk);
+}
+
 static void mtk_ovl_start(struct mtk_ddp_comp *comp)
 {
        writel_relaxed(0x1, comp->regs + DISP_REG_OVL_EN);
 }
 
 static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
+       .clk_enable = mtk_ovl_clk_enable,
+       .clk_disable = mtk_ovl_clk_disable,
        .config = mtk_ovl_config,
        .start = mtk_ovl_start,
        .stop = mtk_ovl_stop,
        if (irq < 0)
                return irq;
 
+       priv->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(priv->clk)) {
+               dev_err(dev, "failed to get ovl clk\n");
+               return PTR_ERR(priv->clk);
+       }
+
        priv->data = of_device_get_match_data(dev);
 
        comp_id = mtk_ddp_comp_get_id(dev->of_node,
 
 struct mtk_disp_rdma {
        struct mtk_ddp_comp             ddp_comp;
        struct drm_crtc                 *crtc;
+       struct clk                      *clk;
        const struct mtk_disp_rdma_data *data;
 };
 
        rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
 }
 
+static int mtk_rdma_clk_enable(struct device *dev)
+{
+       struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
+
+       return clk_prepare_enable(rdma->clk);
+}
+
+static void mtk_rdma_clk_disable(struct device *dev)
+{
+       struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(rdma->clk);
+}
+
 static void mtk_rdma_start(struct mtk_ddp_comp *comp)
 {
        rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
 }
 
 static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = {
+       .clk_enable = mtk_rdma_clk_enable,
+       .clk_disable = mtk_rdma_clk_disable,
        .config = mtk_rdma_config,
        .start = mtk_rdma_start,
        .stop = mtk_rdma_stop,
        if (irq < 0)
                return irq;
 
+       priv->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(priv->clk)) {
+               dev_err(dev, "failed to get rdma clk\n");
+               return PTR_ERR(priv->clk);
+       }
+
        comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_RDMA);
        if (comp_id < 0) {
                dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
 
        int i;
 
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
-               ret = clk_prepare_enable(mtk_crtc->ddp_comp[i]->clk);
+               ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
                if (ret) {
                        DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
                        goto err;
        return 0;
 err:
        while (--i >= 0)
-               clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
+               mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
        return ret;
 }
 
        int i;
 
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
-               clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
+               mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
 }
 
 static
 
 #define DITHER_ADD_LSHIFT_G(x)                 (((x) & 0x7) << 4)
 #define DITHER_ADD_RSHIFT_G(x)                 (((x) & 0x7) << 0)
 
+struct mtk_ddp_comp_dev {
+       struct clk *clk;
+};
+
 void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
                   struct mtk_ddp_comp *comp, unsigned int offset)
 {
 #endif
 }
 
+static int mtk_ddp_clk_enable(struct device *dev)
+{
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
+
+       return clk_prepare_enable(priv->clk);
+}
+
+static void mtk_ddp_clk_disable(struct device *dev)
+{
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(priv->clk);
+}
+
 void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
                    unsigned int CFG, struct cmdq_pkt *cmdq_pkt)
 {
 }
 
 static const struct mtk_ddp_comp_funcs ddp_aal = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .gamma_set = mtk_gamma_set,
        .config = mtk_aal_config,
        .start = mtk_aal_start,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_ccorr = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .config = mtk_ccorr_config,
        .start = mtk_ccorr_start,
        .stop = mtk_ccorr_stop,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_dither = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .config = mtk_dither_config,
        .start = mtk_dither_start,
        .stop = mtk_dither_stop,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_gamma = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .gamma_set = mtk_gamma_set,
        .config = mtk_gamma_config,
        .start = mtk_gamma_start,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_od = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .config = mtk_od_config,
        .start = mtk_od_start,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_ufoe = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .start = mtk_ufoe_start,
 };
 
                      enum mtk_ddp_comp_id comp_id, const struct mtk_ddp_comp_funcs *funcs)
 {
        struct platform_device *comp_pdev;
-       struct device *dev;
        enum mtk_ddp_comp_type type;
+       struct mtk_ddp_comp_dev *priv;
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        struct resource res;
        struct cmdq_client_reg cmdq_reg;
            comp_id == DDP_COMPONENT_DSI3 ||
            comp_id == DDP_COMPONENT_PWM0) {
                comp->regs = NULL;
-               comp->clk = NULL;
                comp->irq = 0;
                return 0;
        }
 
        comp->regs = of_iomap(node, 0);
        comp->irq = of_irq_get(node, 0);
-       comp->clk = of_clk_get(node, 0);
-       if (IS_ERR(comp->clk))
-               return PTR_ERR(comp->clk);
-
        comp_pdev = of_find_device_by_node(node);
        if (!comp_pdev) {
                DRM_INFO("Waiting for device %s\n", node->full_name);
                return -EPROBE_DEFER;
        }
-       dev = &comp_pdev->dev;
+       comp->dev = &comp_pdev->dev;
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (of_address_to_resource(node, 0, &res) != 0) {
-               dev_err(dev, "Missing reg in %s node\n", node->full_name);
+               dev_err(comp->dev, "Missing reg in %s node\n", node->full_name);
                return -EINVAL;
        }
        comp->regs_pa = res.start;
 
-       ret = cmdq_dev_get_client_reg(dev, &cmdq_reg, 0);
+       ret = cmdq_dev_get_client_reg(comp->dev, &cmdq_reg, 0);
        if (ret)
-               dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
+               dev_dbg(comp->dev, "get mediatek,gce-client-reg fail!\n");
        else
                comp->subsys = cmdq_reg.subsys;
 #endif
            type == MTK_DISP_OVL_2L ||
            type == MTK_DISP_RDMA ||
            type == MTK_DISP_WDMA) {
-               ret = mtk_ddp_get_larb_dev(node, comp, dev);
+               ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
                if (ret)
                        return ret;
        }
 
+       if (type == MTK_DISP_COLOR ||
+           type == MTK_DISP_OVL ||
+           type == MTK_DISP_OVL_2L ||
+           type == MTK_DISP_RDMA)
+               return 0;
+
+       priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->clk = of_clk_get(node, 0);
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
+
+       platform_set_drvdata(comp_pdev, priv);
+
        return 0;
 }
 
 
 struct mtk_ddp_comp;
 struct cmdq_pkt;
 struct mtk_ddp_comp_funcs {
+       int (*clk_enable)(struct device *dev);
+       void (*clk_disable)(struct device *dev);
        void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
                       unsigned int h, unsigned int vrefresh,
                       unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
 };
 
 struct mtk_ddp_comp {
-       struct clk *clk;
+       struct device *dev;
        void __iomem *regs;
        int irq;
        struct device *larb_dev;
        u8 subsys;
 };
 
+static inline int mtk_ddp_comp_clk_enable(struct mtk_ddp_comp *comp)
+{
+       if (comp->funcs && comp->funcs->clk_enable)
+               return comp->funcs->clk_enable(comp->dev);
+
+       return 0;
+}
+
+static inline void mtk_ddp_comp_clk_disable(struct mtk_ddp_comp *comp)
+{
+       if (comp->funcs && comp->funcs->clk_disable)
+               comp->funcs->clk_disable(comp->dev);
+}
+
 static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
                                       unsigned int w, unsigned int h,
                                       unsigned int vrefresh, unsigned int bpc,