From: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> Expose the subdevice internal routing from the single multiplexed sink pad to its source pads by implementing .get_routing(). This information is used to do link validation at stream start and allows user-space to view the route configuration. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> Signed-off-by: Jacopo Mondi <jacopo+renesas@xxxxxxxxxx> --- drivers/media/platform/rcar-vin/rcar-csi2.c | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index f9cc99ba00bc..cc7077b40f18 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -341,6 +341,14 @@ static int rcsi2_pad_to_vc(unsigned int pad) return pad - RCAR_CSI2_SOURCE_VC0; } +static int rcsi2_vc_to_pad(unsigned int vc) +{ + if (vc > 3) + return -EINVAL; + + return vc + RCAR_CSI2_SOURCE_VC0; +} + struct rcar_csi2_info { int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps); int (*confirm_start)(struct rcar_csi2 *priv); @@ -705,9 +713,54 @@ static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { .s_stream = rcsi2_s_stream, }; +static int rcsi2_get_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_krouting *routing) +{ + struct v4l2_subdev_route *r = routing->routes; + struct rcar_csi2 *priv = sd_to_csi2(sd); + struct v4l2_mbus_frame_desc fd; + unsigned int i; + int ret; + + /* Get information about multiplexed link */ + ret = rcsi2_get_remote_frame_desc(priv, &fd); + if (ret) + return ret; + + if (routing->num_routes < fd.num_entries) { + routing->num_routes = fd.num_entries; + return -ENOSPC; + } + + routing->num_routes = fd.num_entries; + + for (i = 0; i < fd.num_entries; i++) { + struct v4l2_mbus_frame_desc_entry *entry = &fd.entry[i]; + int source_pad; + + source_pad = rcsi2_vc_to_pad(entry->bus.csi2.channel); + if (source_pad < 0) { + dev_err(priv->dev, "Virtual Channel out of range: %u\n", + entry->bus.csi2.channel); + return -EINVAL; + } + + r->sink_pad = RCAR_CSI2_SINK; + r->sink_stream = entry->stream; + r->source_pad = source_pad; + r->source_stream = 0; + r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE | + V4L2_SUBDEV_ROUTE_FL_IMMUTABLE; + r++; + } + + return 0; +} + static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { .set_fmt = rcsi2_set_pad_format, .get_fmt = rcsi2_get_pad_format, + .get_routing = rcsi2_get_routing, }; static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { -- 2.20.1