diff mbox series

[4/4] media: i2c: st-vgxy61: Implement set_routing callback

Message ID 20240315085158.1213159-5-julien.massot@collabora.com (mailing list archive)
State New, archived
Headers show
Series media: i2c: st-vgxy61 Add support for embedded metadata | expand

Commit Message

Julien Massot March 15, 2024, 8:51 a.m. UTC
It's possible to bypass the Intelligent Status Line, through the
bypass register. Allows to remove the internal route from the meta
pad to the source pad.

Signed-off-by: Julien Massot <julien.massot@collabora.com>
---
 drivers/media/i2c/st-vgxy61.c | 41 +++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
diff mbox series

Patch

diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c
index 754853378ee6..f931c51fddbb 100644
--- a/drivers/media/i2c/st-vgxy61.c
+++ b/drivers/media/i2c/st-vgxy61.c
@@ -1221,6 +1221,46 @@  static int vgxy61_disable_streams(struct v4l2_subdev *sd,
 	return ret;
 }
 
+static int vgxy61_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      enum v4l2_subdev_format_whence which,
+			      struct v4l2_subdev_krouting *routing)
+{
+	struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
+	struct device *dev = &sensor->i2c_client->dev;
+	unsigned int isl_bypass = VGXY61_ISL_BYPASS;
+	struct v4l2_subdev_route *route;
+	int ret;
+
+	if (sensor->streaming)
+		return -EBUSY;
+
+	if (routing->num_routes != 1 && routing->num_routes != 2)
+		return -EINVAL;
+
+	route = &routing->routes[0];
+	if (route->sink_pad != VGXY61_PAD_PIXEL ||
+	    route->source_stream != VGXY61_STREAM_PIXEL) {
+		dev_warn(dev, "Can't disable pixel route\n");
+		return -EINVAL;
+	}
+
+	if (routing->num_routes == 2) {
+		route = &routing->routes[1];
+		if (route->sink_pad != VGXY61_PAD_META  ||
+		    route->source_stream != VGXY61_STREAM_META)
+			return -EINVAL;
+		isl_bypass = 0;
+	}
+
+	ret = cci_update_bits(sensor->regmap, VGXY61_REG_BYPASS_CTRL,
+			      VGXY61_ISL_BYPASS, isl_bypass, NULL);
+	if (ret)
+		return ret;
+
+	return v4l2_subdev_set_routing(sd, state, routing);
+}
+
 static int __vgxy61_set_fmt(struct v4l2_subdev *sd,
 			    struct v4l2_subdev_state *sd_state,
 			    struct v4l2_mbus_framefmt *format,
@@ -1518,6 +1558,7 @@  static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = {
 	.enum_mbus_code = vgxy61_enum_mbus_code,
 	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = vgxy61_set_fmt,
+	.set_routing = vgxy61_set_routing,
 	.get_frame_desc = vgxy61_get_frame_desc,
 	.get_selection = vgxy61_get_selection,
 	.enum_frame_size = vgxy61_enum_frame_size,