[PATCH 13/20] rcar-csi2: implement get_frame_desc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The frame descriptor of the CSI-2 receiver mirrors that of the
transmitter in all aspects but the routing from the multiplexed sink pad
to the 'normal' source pads. Simply fetch the frame descriptor of the
transmitter and update the routing.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx>
---
 drivers/media/platform/rcar-vin/rcar-csi2.c | 56 +++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index 034d37bc66e93ac7..e01f334364d50754 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -677,6 +677,61 @@ static int rcar_csi2_get_pad_format(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int rcar_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				    struct v4l2_mbus_frame_desc *fd)
+{
+	struct rcar_csi2 *priv = sd_to_csi2(sd);
+	struct v4l2_subdev *nextsd;
+	struct media_pad *nextpad;
+	unsigned int i;
+
+	/* Only valid for sink pad */
+	if (pad != RCAR_CSI2_SINK || fd == NULL)
+		return -EINVAL;
+
+	/* Figoure out remote subdev and pad */
+	nextpad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]);
+	if (!nextpad) {
+		dev_err(priv->dev, "Could not find remote pad\n");
+		return -EPIPE;
+	}
+
+	nextsd = media_entity_to_v4l2_subdev(nextpad->entity);
+	if (!nextsd) {
+		dev_err(priv->dev, "Could not find remote subdevice\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Our frame descriptor will mirror that of the remote device
+	 * in all aspects but which of our source pads are routed to
+	 * which muxed channel. So start with a copy of the remote
+	 * description and then update the pads
+	 */
+
+	if (v4l2_subdev_call(nextsd, pad, get_frame_desc, nextpad->index, fd)) {
+		dev_err(priv->dev, "Could not read frame desc\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < fd->num_entries; i++) {
+		/* Make sure it's a muxed CSI2 bus */
+		if ((fd->entry[i].flags & V4L2_MBUS_FRAME_DESC_FL_CSI2) == 0)
+			return -EINVAL;
+
+		if (fd->entry[i].csi2.channel >= 4) {
+			dev_err(priv->dev, "CSI-2 channel value to large: %u\n",
+				fd->entry[i].csi2.channel);
+			return -EINVAL;
+		}
+
+		/* Figure out pad from CSI-2 channel. First source pad is 1 */
+		fd->entry[i].csi2.pad = fd->entry[i].csi2.channel + 1;
+	}
+
+	return 0;
+}
+
 static const struct v4l2_subdev_core_ops rcar_csi2_subdev_core_ops = {
 	.s_power = rcar_csi2_s_power,
 };
@@ -684,6 +739,7 @@ static const struct v4l2_subdev_core_ops rcar_csi2_subdev_core_ops = {
 static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = {
 	.set_fmt = rcar_csi2_set_pad_format,
 	.get_fmt = rcar_csi2_get_pad_format,
+	.get_frame_desc = rcar_csi2_get_frame_desc,
 	.s_stream = rcar_csi2_s_stream,
 };
 
-- 
2.13.3




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux