diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 2031c8c5e70b4a8961a004c52b80a7e35715ddd2..b2df8f0cc614be1728d457d913425260500f6b2e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -33,6 +33,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/iopoll.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
@@ -580,6 +581,7 @@ struct vop2_video_port {
 	bool need_reset_p2i_flag;
 	atomic_t post_buf_empty_flag;
 	const struct vop2_video_port_regs *regs;
+	struct gpio_desc *vsync_gpio;
 
 	struct completion dsp_hold_completion;
 	struct completion line_flag_completion;
@@ -12778,6 +12780,7 @@ static irqreturn_t vop3_vp_isr(int irq, void *data)
 
 	if (active_irqs & FS_FIELD_INTR) {
 		rockchip_drm_dbg(vop2->dev, VOP_DEBUG_VSYNC, "vsync_vp%d\n", vp->id);
+		gpiod_set_value(vp->vsync_gpio, !gpiod_get_value(vp->vsync_gpio));
 		vop2_wb_handler(vp);
 		drm_crtc_handle_vblank(crtc);
 		vop2_handle_vblank(vop2, crtc);
@@ -14473,6 +14476,14 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
 
 			vop2->vps[vp_id].xmirror_en = of_property_read_bool(child, "xmirror-enable");
 
+			vop2->vps[vp_id].vsync_gpio = devm_fwnode_gpiod_get(dev, of_node_to_fwnode(child), "vsync-notify", GPIOD_OUT_LOW, fwnode_get_name(of_node_to_fwnode(child)));
+			if (IS_ERR(vop2->vps[vp_id].vsync_gpio)) {
+				if (PTR_ERR(vop2->vps[vp_id].vsync_gpio))
+					vop2->vps[vp_id].vsync_gpio = NULL;
+				else
+					return dev_err_probe(dev, PTR_ERR(vop2->vps[vp_id].vsync_gpio), "failed to get vsync notify GPIO");
+			}
+
 			ret = of_clk_set_defaults(child, false);
 			if (ret) {
 				DRM_DEV_ERROR(dev, "Failed to set clock defaults %d\n", ret);