Now that the rcar-csi2 subdevice supports internal routing, add an has_route() operation used during graph traversal. The internal routing between the sink and the source pads depends on the virtual channel used to transmit the video stream from the remote subdevice to the R-Car CSI-2 receiver. Signed-off-by: Jacopo Mondi <jacopo+renesas@xxxxxxxxxx> --- drivers/media/platform/rcar-vin/rcar-csi2.c | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index cc7077b40f18..6c46bcc0ee83 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -1028,7 +1028,42 @@ static int rcsi2_confirm_start_v3m_e3(struct rcar_csi2 *priv) * Platform Device Driver. */ +static bool rcar_csi2_has_route(struct media_entity *entity, + unsigned int pad0, unsigned int pad1) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct rcar_csi2 *priv = sd_to_csi2(sd); + struct v4l2_mbus_frame_desc fd; + unsigned int i; + int ret; + + /* Support only direct sink->source routes. */ + if (pad0 != RCAR_CSI2_SINK) + return false; + + /* Get the frame description: from CSI-2 VC to source pad number. */ + ret = rcsi2_get_remote_frame_desc(priv, &fd); + if (ret) + return ret; + + for (i = 0; i < fd.num_entries; i++) { + struct v4l2_mbus_frame_desc_entry *entry = &fd.entry[i]; + int 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; + } + + if (source_pad == pad1) + return true; + } + + return false; +} + static const struct media_entity_operations rcar_csi2_entity_ops = { + .has_route = rcar_csi2_has_route, .link_validate = v4l2_subdev_link_validate, }; -- 2.20.1