[PATCH 11/20] rcar-csi2: when starting CSI-2 receiver use frame descriptor information

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

 



The driver now have access to frame descriptor information, use it. Only
enable the virtual channels which are described in the frame descriptor
and calculate the PHY PLL based on all streams described.

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

diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index 12a8ea7a219ac7d3..b8ec03d595ba8ac4 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -242,24 +242,22 @@ static const struct phypll_hsfreqrange hsfreqrange_m3w_h3es1[] = {
 #define CSI0CLKFREQRANGE(n)		((n & 0x3f) << 16)
 
 struct rcar_csi2_format {
-	unsigned int code;
 	unsigned int datatype;
 	unsigned int bpp;
 };
 
 static const struct rcar_csi2_format rcar_csi2_formats[] = {
-	{ .code = MEDIA_BUS_FMT_RGB888_1X24,	.datatype = 0x24, .bpp = 24 },
-	{ .code = MEDIA_BUS_FMT_UYVY8_1X16,	.datatype = 0x1e, .bpp = 16 },
-	{ .code = MEDIA_BUS_FMT_UYVY8_2X8,	.datatype = 0x1e, .bpp = 16 },
-	{ .code = MEDIA_BUS_FMT_YUYV10_2X10,	.datatype = 0x1e, .bpp = 16 },
+	{ .datatype = 0x1e, .bpp = 16 },
+	{ .datatype = 0x24, .bpp = 24 },
 };
 
-static const struct rcar_csi2_format *rcar_csi2_code_to_fmt(unsigned int code)
+static const struct rcar_csi2_format
+*rcar_csi2_datatype_to_fmt(unsigned int datatype)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++)
-		if (rcar_csi2_formats[i].code == code)
+		if (rcar_csi2_formats[i].datatype == datatype)
 			return rcar_csi2_formats + i;
 	return NULL;
 }
@@ -348,12 +346,14 @@ static int rcar_csi2_wait_phy_start(struct rcar_csi2 *priv)
 
 static int rcar_csi2_calc_phypll(struct rcar_csi2 *priv,
 				 struct v4l2_subdev *source,
-				 struct v4l2_mbus_framefmt *mf,
+				 struct v4l2_mbus_frame_desc *fd,
 				 u32 *phypll)
 {
+	struct v4l2_mbus_frame_desc_entry *entry;
 	const struct phypll_hsfreqrange *hsfreq;
 	const struct rcar_csi2_format *format;
 	struct v4l2_ctrl *ctrl;
+	unsigned int i, bpp = 0;
 	u64 mbps;
 
 	ctrl = v4l2_ctrl_find(source->ctrl_handler, V4L2_CID_PIXEL_RATE);
@@ -363,13 +363,20 @@ static int rcar_csi2_calc_phypll(struct rcar_csi2 *priv,
 		return -EINVAL;
 	}
 
-	format = rcar_csi2_code_to_fmt(mf->code);
-	if (!format) {
-		dev_err(priv->dev, "Unknown format: %d\n", mf->code);
-		return -EINVAL;
+	for (i = 0; i < fd->num_entries; i++) {
+		entry = &fd->entry[i];
+
+		format = rcar_csi2_datatype_to_fmt(entry->csi2.datatype);
+		if (!format) {
+			dev_err(priv->dev, "Unknown datatype: %d\n",
+				entry->csi2.datatype);
+			return -EINVAL;
+		}
+
+		bpp += format->bpp;
 	}
 
-	mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * format->bpp;
+	mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;
 	do_div(mbps, priv->lanes * 1000000);
 
 	for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++)
@@ -391,11 +398,10 @@ static int rcar_csi2_calc_phypll(struct rcar_csi2 *priv,
 
 static int rcar_csi2_start(struct rcar_csi2 *priv)
 {
-	const struct rcar_csi2_format *format;
-	struct v4l2_subdev_format fmt;
+	struct v4l2_mbus_frame_desc_entry *entry;
 	struct media_pad *pad, *source_pad;
 	struct v4l2_subdev *source = NULL;
-	struct v4l2_mbus_framefmt *mf = &fmt.format;
+	struct v4l2_mbus_frame_desc fd;
 	u32 phycnt, phypll, tmp;
 	u32 vcdt = 0, vcdt2 = 0;
 	unsigned int i;
@@ -417,40 +423,33 @@ static int rcar_csi2_start(struct rcar_csi2 *priv)
 	dev_dbg(priv->dev, "Using source %s pad: %u\n", source->name,
 		source_pad->index);
 
-	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	fmt.pad = source_pad->index;
-	ret = v4l2_subdev_call(source, pad, get_fmt, NULL, &fmt);
-	if (ret)
-		return ret;
+	if (v4l2_subdev_call(source, pad, get_frame_desc, source_pad->index,
+			     &fd)) {
+		dev_err(priv->dev, "Could not read frame desc\n");
+		return -EINVAL;
+	}
 
-	dev_dbg(priv->dev, "Input size (%dx%d%c)\n", mf->width,
-		mf->height, mf->field == V4L2_FIELD_NONE ? 'p' : 'i');
-
-	/*
-	 * Enable all Virtual Channels
-	 *
-	 * NOTE: It's not possible to get individual format for each
-	 *       source virtual channel. Once this is possible in V4L2
-	 *       it should be used here.
-	 */
-	for (i = 0; i < 4; i++) {
-		format = rcar_csi2_code_to_fmt(mf->code);
-		if (!format) {
-			dev_err(priv->dev, "Unsupported media bus format: %d\n",
-				mf->code);
+	for (i = 0; i < fd.num_entries; i++) {
+		entry = &fd.entry[i];
+
+		if ((entry->flags & V4L2_MBUS_FRAME_DESC_FL_CSI2) == 0)
 			return -EINVAL;
-		}
 
-		tmp = VCDT_SEL_VC(i) | VCDT_VCDTN_EN | VCDT_SEL_DTN_ON |
-			VCDT_SEL_DT(format->datatype);
+		tmp = VCDT_SEL_VC(entry->csi2.channel) | VCDT_VCDTN_EN |
+			VCDT_SEL_DTN_ON | VCDT_SEL_DT(entry->csi2.datatype);
 
 		/* Store in correct reg and offset */
-		if (i < 2)
-			vcdt |= tmp << ((i % 2) * 16);
+		if (entry->csi2.channel < 2)
+			vcdt |= tmp << ((entry->csi2.channel % 2) * 16);
 		else
-			vcdt2 |= tmp << ((i % 2) * 16);
+			vcdt2 |= tmp << ((entry->csi2.channel % 2) * 16);
+
+		dev_dbg(priv->dev, "VC%d datatype: 0x%x\n",
+			entry->csi2.channel, entry->csi2.datatype);
 	}
 
+	dev_dbg(priv->dev, "VCDT: 0x%08x VCDT2: 0x%08x\n", vcdt, vcdt2);
+
 	switch (priv->lanes) {
 	case 1:
 		phycnt = PHYCNT_ENABLECLK | PHYCNT_ENABLE_0;
@@ -466,7 +465,7 @@ static int rcar_csi2_start(struct rcar_csi2 *priv)
 		return -EINVAL;
 	}
 
-	ret = rcar_csi2_calc_phypll(priv, source, mf, &phypll);
+	ret = rcar_csi2_calc_phypll(priv, source, &fd, &phypll);
 	if (ret)
 		return ret;
 
-- 
2.13.3




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux