VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   30 Branches   50 Tags
author: Changhuang Liang <changhuang.liang@starfivetech.com> 2023-06-01 17:06:22 +0800 committer: Andy Hu <andy.hu@starfivetech.com> 2023-11-01 15:04:53 +0800 commit: 9dc2c2d8b769a8703d5c37f0cab80346304bce5c parent: 4c0e9158bf1c177a02d201406a33243611a18de4
Commit Summary:
media: starfive: Add isp frame sync event
Diffstat:
1 file changed, 25 insertions, 1 deletion
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
index 5758ab77d7ea..a96199a161fe 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <media/v4l2-event.h>
 
 #include "stfcamss.h"
 
@@ -1133,6 +1134,9 @@ static void vin_buffer_done(struct vin_line *line, struct vin_params *params)
 	struct vin_output *output = &line->output;
 	unsigned long flags;
 	u64 ts = ktime_get_ns();
+	struct v4l2_event event = {
+		.type = V4L2_EVENT_FRAME_SYNC,
+	};
 
 	if (output->state == VIN_OUTPUT_OFF
 		|| output->state == VIN_OUTPUT_RESERVED)
@@ -1141,6 +1145,11 @@ static void vin_buffer_done(struct vin_line *line, struct vin_params *params)
 	spin_lock_irqsave(&line->output_lock, flags);
 
 	while ((ready_buf = vin_buf_get_ready(output))) {
+		if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
+			event.u.frame_sync.frame_sequence = output->sequence;
+			v4l2_event_queue(line->subdev.devnode, &event);
+		}
+
 		ready_buf->vb.vb2_buf.timestamp = ts;
 		ready_buf->vb.sequence = output->sequence++;
 
@@ -1331,8 +1340,23 @@ static int vin_link_setup(struct media_entity *entity,
 	return 0;
 }
 
+static int stf_vin_subscribe_event(struct v4l2_subdev *sd,
+				   struct v4l2_fh *fh,
+				   struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_FRAME_SYNC:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	default:
+		st_debug(ST_VIN, "unsupport subscribe_event\n");
+		return -EINVAL;
+	}
+}
+
 static const struct v4l2_subdev_core_ops vin_core_ops = {
 	.s_power = vin_set_power,
+	.subscribe_event = stf_vin_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
 };
 
 static const struct v4l2_subdev_video_ops vin_video_ops = {
@@ -1393,7 +1417,7 @@ int stf_vin_register(struct stf_vin2_dev *vin_dev, struct v4l2_device *v4l2_dev)
 
 		v4l2_subdev_init(sd, &vin_v4l2_ops);
 		sd->internal_ops = &vin_v4l2_internal_ops;
-		sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+		sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
 		snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
 			STF_VIN_NAME, 0, sub_name);
 		v4l2_set_subdevdata(sd, &vin_dev->line[i]);