void __iomem                    *regs;
        struct cmdq_client_reg          cmdq_reg;
        const struct mtk_disp_ovl_data  *data;
+       void                            (*vblank_cb)(void *data);
+       void                            *vblank_cb_data;
 };
 
 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
 {
        struct mtk_disp_ovl *priv = dev_id;
-       struct mtk_ddp_comp *ovl = &priv->ddp_comp;
 
        /* Clear frame completion interrupt */
        writel(0x0, priv->regs + DISP_REG_OVL_INTSTA);
 
-       if (!priv->crtc)
+       if (!priv->vblank_cb)
                return IRQ_NONE;
 
-       mtk_crtc_ddp_irq(priv->crtc, ovl);
+       priv->vblank_cb(priv->vblank_cb_data);
 
        return IRQ_HANDLED;
 }
 
 static void mtk_ovl_enable_vblank(struct device *dev,
-                                 struct drm_crtc *crtc)
+                                 void (*vblank_cb)(void *),
+                                 void *vblank_cb_data)
 {
        struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
 
-       ovl->crtc = crtc;
+       ovl->vblank_cb = vblank_cb;
+       ovl->vblank_cb_data = vblank_cb_data;
        writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA);
        writel_relaxed(OVL_FME_CPL_INT, ovl->regs + DISP_REG_OVL_INTEN);
 }
 {
        struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
 
-       ovl->crtc = NULL;
+       ovl->vblank_cb = NULL;
+       ovl->vblank_cb_data = NULL;
        writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
 }
 
 
  */
 struct mtk_disp_rdma {
        struct mtk_ddp_comp             ddp_comp;
-       struct drm_crtc                 *crtc;
        struct clk                      *clk;
        void __iomem                    *regs;
        struct cmdq_client_reg          cmdq_reg;
        const struct mtk_disp_rdma_data *data;
+       void                            (*vblank_cb)(void *data);
+       void                            *vblank_cb_data;
 };
 
 static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
 {
        struct mtk_disp_rdma *priv = dev_id;
-       struct mtk_ddp_comp *rdma = &priv->ddp_comp;
 
        /* Clear frame completion interrupt */
        writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
 
-       if (!priv->crtc)
+       if (!priv->vblank_cb)
                return IRQ_NONE;
 
-       mtk_crtc_ddp_irq(priv->crtc, rdma);
+       priv->vblank_cb(priv->vblank_cb_data);
 
        return IRQ_HANDLED;
 }
 }
 
 static void mtk_rdma_enable_vblank(struct device *dev,
-                                  struct drm_crtc *crtc)
+                                  void (*vblank_cb)(void *),
+                                  void *vblank_cb_data)
 {
        struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
 
-       rdma->crtc = crtc;
+       rdma->vblank_cb = vblank_cb;
+       rdma->vblank_cb_data = vblank_cb_data;
        rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
                         RDMA_FRAME_END_INT);
 }
 {
        struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
 
-       rdma->crtc = NULL;
+       rdma->vblank_cb = NULL;
+       rdma->vblank_cb_data = NULL;
        rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
 }
 
 
        state->pending_config = true;
 }
 
-static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
-{
-       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-       struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-
-       mtk_ddp_comp_enable_vblank(comp, &mtk_crtc->base);
-
-       return 0;
-}
-
-static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
-{
-       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-       struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-
-       mtk_ddp_comp_disable_vblank(comp);
-}
-
 static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
 {
        int ret;
        mutex_unlock(&mtk_crtc->hw_lock);
 }
 
+static void mtk_crtc_ddp_irq(void *data)
+{
+       struct drm_crtc *crtc = data;
+       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       struct mtk_drm_private *priv = crtc->dev->dev_private;
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
+#else
+       if (!priv->data->shadow_register)
+#endif
+               mtk_crtc_ddp_config(crtc, NULL);
+
+       mtk_drm_finish_page_flip(mtk_crtc);
+}
+
+static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
+
+       mtk_ddp_comp_enable_vblank(comp, mtk_crtc_ddp_irq, &mtk_crtc->base);
+
+       return 0;
+}
+
+static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
+
+       mtk_ddp_comp_disable_vblank(comp);
+}
+
 int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
                             struct mtk_plane_state *state)
 {
        return ret;
 }
 
-void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp)
-{
-       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-       struct mtk_drm_private *priv = crtc->dev->dev_private;
-
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
-#else
-       if (!priv->data->shadow_register)
-#endif
-               mtk_crtc_ddp_config(crtc, NULL);
-
-       mtk_drm_finish_page_flip(mtk_crtc);
-}
-
 static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc,
                                        int comp_idx)
 {
 
 #define MTK_MIN_BPC    3
 
 void mtk_drm_crtc_commit(struct drm_crtc *crtc);
-void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp);
 int mtk_drm_crtc_create(struct drm_device *drm_dev,
                        const enum mtk_ddp_comp_id *path,
                        unsigned int path_len);
 
                       unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
        void (*start)(struct device *dev);
        void (*stop)(struct device *dev);
-       void (*enable_vblank)(struct device *dev, struct drm_crtc *crtc);
+       void (*enable_vblank)(struct device *dev,
+                             void (*vblank_cb)(void *),
+                             void *vblank_cb_data);
        void (*disable_vblank)(struct device *dev);
        unsigned int (*supported_rotations)(struct device *dev);
        unsigned int (*layer_nr)(struct device *dev);
 }
 
 static inline void mtk_ddp_comp_enable_vblank(struct mtk_ddp_comp *comp,
-                                             struct drm_crtc *crtc)
+                                             void (*vblank_cb)(void *),
+                                             void *vblank_cb_data)
 {
        if (comp->funcs && comp->funcs->enable_vblank)
-               comp->funcs->enable_vblank(comp->dev, crtc);
+               comp->funcs->enable_vblank(comp->dev, vblank_cb, vblank_cb_data);
 }
 
 static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp)