@@ -14,6 +14,8 @@
#include "adv748x.h"
+#define ADV748X_CSI2_ROUTES_MAX 4
+
struct adv748x_csi2_format {
unsigned int code;
unsigned int datatype;
@@ -253,10 +255,73 @@ static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
return 0;
}
+static int adv748x_csi2_get_routing(struct v4l2_subdev *sd,
+ struct v4l2_subdev_krouting *routing)
+{
+ struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
+ struct v4l2_subdev_route *r = routing->routes;
+ unsigned int vc;
+
+ if (routing->num_routes < ADV748X_CSI2_ROUTES_MAX) {
+ routing->num_routes = ADV748X_CSI2_ROUTES_MAX;
+ return -ENOSPC;
+ }
+
+ routing->num_routes = ADV748X_CSI2_ROUTES_MAX;
+
+ for (vc = 0; vc < ADV748X_CSI2_ROUTES_MAX; vc++) {
+ r->sink_pad = ADV748X_CSI2_SINK;
+ r->sink_stream = 0;
+ r->source_pad = ADV748X_CSI2_SOURCE;
+ r->source_stream = vc;
+ r->flags = vc == tx->vc ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0;
+ r++;
+ }
+
+ return 0;
+}
+
+static int adv748x_csi2_set_routing(struct v4l2_subdev *sd,
+ struct v4l2_subdev_krouting *routing)
+{
+ struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
+ struct v4l2_subdev_route *r = routing->routes;
+ unsigned int i;
+ int vc = -1;
+
+ if (routing->num_routes > ADV748X_CSI2_ROUTES_MAX)
+ return -ENOSPC;
+
+ for (i = 0; i < routing->num_routes; i++) {
+ if (r->sink_pad != ADV748X_CSI2_SINK ||
+ r->sink_stream != 0 ||
+ r->source_pad != ADV748X_CSI2_SOURCE ||
+ r->source_stream >= ADV748X_CSI2_ROUTES_MAX)
+ return -EINVAL;
+
+ if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) {
+ if (vc != -1)
+ return -EMLINK;
+
+ vc = r->source_stream;
+ }
+ r++;
+ }
+
+ if (vc != -1)
+ tx->vc = vc;
+
+ adv748x_csi2_set_virtual_channel(tx, tx->vc);
+
+ return 0;
+}
+
static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
.get_fmt = adv748x_csi2_get_format,
.set_fmt = adv748x_csi2_set_format,
.get_frame_desc = adv748x_csi2_get_frame_desc,
+ .get_routing = adv748x_csi2_get_routing,
+ .set_routing = adv748x_csi2_set_routing,
};
/* -----------------------------------------------------------------------------