linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] R-Car DU: Support CRC calculation
@ 2017-12-03 10:57 Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs Laurent Pinchart
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

Hello,

This patch series adds support for CRC calculation to the rcar-du-drm driver.

CRC calculation is supported starting at the Renesas R-Car Gen3 SoCs, as
earlier versions don't have the necessary hardware. On Gen3 SoCs, the CRC is
computed by the DISCOM module part of the VSP-D and VSP-DL.

The DISCOM is interfaced to the VSP through the UIF glue and appears as a VSP
entity with a sink pad and a source pad.

The series starts with two fixes. Patch 1/9 fixes a display stall when
requesting more than two planes from the VGA output. It is a temporary fix to
avoid complete stalls during unit testing, and a better fix will follow but
will take longer to develop. Patch 2/9 then fixes debug messages that confused
me when I was debugging the rest of this patch series.

The series then continues with cleanup and refactoring. Patches 3/9 and 4/9
prepare for DISCOM and UIF support by extending generic code to make it usable
for the UIF. Patch 5/9 documents a structure that will receive new fields.

Patch 6/9 then extends the API exposed by the VSP driver to the DU driver to
support CRC computation configuration and reporting. The patch unfortunately
needs to touch both the VSP and DU drivers. The whole series will need to be
merged through a single tree, I will check when it will be time to submit a
pull request which option would generate the least conflicts.

Patch 7/9 adds support for the DISCOM and UIF in the VSP driver, patch 8/9
integrates it in the DRM pipeline, and patch 9/9 finally implements the CRC
API in the DU driver to expose CRC computation to userspace.

The hardware supports computing the CRC at any arbitrary point in the
pipeline on a configurable window of the frame. This patch series supports CRC
computation on input planes or pipeline output, but on the full frame only.
Support for CRC window configuration can be added later if needed but will
require extending the userspace API, as the DRM/KMS CRC API doesn't support
this feature.

Note that exposing the DISCOM and UIF though the V4L2 API isn't supported as
the module is only found in VSP-D and VSP-DL instances that are not exposed
through V4L2. It is possible to expose those instances through V4L2 with a
small modification to the driver for testing purpose. If the need arises to
test DISCOM and UIF with such an out-of-tree patch, support for CRC reporting
through a V4L2 control can be added later without affecting how CRC is exposed
through the DRM/KMS API.

The patches are based on top of a merge of the Linux media master branch and
the pending DU patches. For convenience they are available at

	git://linuxtv.org/pinchartl/media.git vsp1-discom-v1-20171203

The code has been tested through the kms-test-crc.py script part of the DU
test suite available at

	git://git.ideasonboard.com/renesas/kms-tests.git discom


Laurent Pinchart (9):
  v4l: vsp1: Fix display stalls when requesting too many inputs
  v4l: vsp1: Print the correct blending unit name in debug messages
  v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code
  v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper
  v4l: vsp1: Document the vsp1_du_atomic_config structure
  v4l: vsp1: Extend the DU API to support CRC computation
  v4l: vsp1: Add support for the DISCOM entity
  v4l: vsp1: Integrate DISCOM in display pipeline
  drm: rcar-du: Add support for CRC computation

 drivers/gpu/drm/rcar-du/rcar_du_crtc.c    | 148 +++++++++++++++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h    |  19 +++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c     |  13 +-
 drivers/media/platform/vsp1/Makefile      |   2 +-
 drivers/media/platform/vsp1/vsp1.h        |   4 +
 drivers/media/platform/vsp1/vsp1_clu.c    |  65 ++-----
 drivers/media/platform/vsp1/vsp1_drm.c    | 138 +++++++++++++--
 drivers/media/platform/vsp1/vsp1_drm.h    |  14 +-
 drivers/media/platform/vsp1/vsp1_drv.c    |  20 +++
 drivers/media/platform/vsp1/vsp1_entity.c |  97 +++++++++++
 drivers/media/platform/vsp1/vsp1_entity.h |   7 +
 drivers/media/platform/vsp1/vsp1_histo.c  |  59 +------
 drivers/media/platform/vsp1/vsp1_lif.c    |  65 ++-----
 drivers/media/platform/vsp1/vsp1_lut.c    |  65 ++-----
 drivers/media/platform/vsp1/vsp1_regs.h   |  41 +++++
 drivers/media/platform/vsp1/vsp1_uif.c    | 275 ++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_uif.h    |  36 ++++
 include/media/vsp1.h                      |  39 ++++-
 18 files changed, 870 insertions(+), 237 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-15 10:11   ` Kieran Bingham
  2017-12-03 10:57 ` [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages Laurent Pinchart
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

Make sure we don't accept more inputs than the hardware can handle. This
is a temporary fix to avoid display stall, we need to instead allocate
the BRU or BRS to display pipelines dynamically based on the number of
planes they each use.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 7ce69f23f50a..ac85942162c1 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -530,6 +530,15 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 		unsigned int j;
 
+		/*
+		 * Make sure we don't accept more inputs than the hardware can
+		 * handle. This is a temporary fix to avoid display stall, we
+		 * need to instead allocate the BRU or BRS to display pipelines
+		 * dynamically based on the number of planes they each use.
+		 */
+		if (pipe->num_inputs >= pipe->bru->source_pad)
+			pipe->inputs[i] = NULL;
+
 		if (!pipe->inputs[i])
 			continue;
 
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-15 10:13   ` Kieran Bingham
  2017-12-03 10:57 ` [PATCH 3/9] v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code Laurent Pinchart
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

The DRM pipelines can use either the BRU or the BRS for blending. Make
sure the right name is used in debugging messages to avoid confusion.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index ac85942162c1..0fe541084f5c 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -400,8 +400,11 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
 	struct v4l2_subdev_selection sel;
 	struct v4l2_subdev_format format;
 	const struct v4l2_rect *crop;
+	const char *bru_name;
 	int ret;
 
+	bru_name = pipe->bru->type == VSP1_ENTITY_BRU ? "BRU" : "BRS";
+
 	/*
 	 * Configure the format on the RPF sink pad and propagate it up to the
 	 * BRU sink pad.
@@ -473,9 +476,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n",
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
 		__func__, format.format.width, format.format.height,
-		format.format.code, format.pad);
+		format.format.code, bru_name, format.pad);
 
 	sel.pad = bru_input;
 	sel.target = V4L2_SEL_TGT_COMPOSE;
@@ -486,10 +489,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(vsp1->dev,
-		"%s: set selection (%u,%u)/%ux%u on BRU pad %u\n",
+	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
 		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
-		sel.pad);
+		bru_name, sel.pad);
 
 	return 0;
 }
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/9] v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 4/9] v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper Laurent Pinchart
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

The implementation of the set_fmt pad operation is identical in the
three modules. Move it to a generic helper function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_clu.c    | 65 +++++----------------------
 drivers/media/platform/vsp1/vsp1_entity.c | 75 +++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_entity.h |  6 +++
 drivers/media/platform/vsp1/vsp1_lif.c    | 65 +++++----------------------
 drivers/media/platform/vsp1/vsp1_lut.c    | 65 +++++----------------------
 5 files changed, 116 insertions(+), 160 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c
index f2fb26e5ab4e..bc931a3ab498 100644
--- a/drivers/media/platform/vsp1/vsp1_clu.c
+++ b/drivers/media/platform/vsp1/vsp1_clu.c
@@ -118,18 +118,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {
  * V4L2 Subdevice Pad Operations
  */
 
+static const unsigned int clu_codes[] = {
+	MEDIA_BUS_FMT_ARGB8888_1X32,
+	MEDIA_BUS_FMT_AHSV8888_1X32,
+	MEDIA_BUS_FMT_AYUV8_1X32,
+};
+
 static int clu_enum_mbus_code(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_pad_config *cfg,
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
-	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AHSV8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
-	};
-
-	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
-					  ARRAY_SIZE(codes));
+	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
+					  ARRAY_SIZE(clu_codes));
 }
 
 static int clu_enum_frame_size(struct v4l2_subdev *subdev,
@@ -145,51 +145,10 @@ static int clu_set_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_pad_config *cfg,
 			  struct v4l2_subdev_format *fmt)
 {
-	struct vsp1_clu *clu = to_clu(subdev);
-	struct v4l2_subdev_pad_config *config;
-	struct v4l2_mbus_framefmt *format;
-	int ret = 0;
-
-	mutex_lock(&clu->entity.lock);
-
-	config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
-	if (!config) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
-
-	format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
-
-	if (fmt->pad == CLU_PAD_SOURCE) {
-		/* The CLU output format can't be modified. */
-		fmt->format = *format;
-		goto done;
-	}
-
-	format->code = fmt->format.code;
-	format->width = clamp_t(unsigned int, fmt->format.width,
-				CLU_MIN_SIZE, CLU_MAX_SIZE);
-	format->height = clamp_t(unsigned int, fmt->format.height,
-				 CLU_MIN_SIZE, CLU_MAX_SIZE);
-	format->field = V4L2_FIELD_NONE;
-	format->colorspace = V4L2_COLORSPACE_SRGB;
-
-	fmt->format = *format;
-
-	/* Propagate the format to the source pad. */
-	format = vsp1_entity_get_pad_format(&clu->entity, config,
-					    CLU_PAD_SOURCE);
-	*format = fmt->format;
-
-done:
-	mutex_unlock(&clu->entity.lock);
-	return ret;
+	return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
+					  ARRAY_SIZE(clu_codes),
+					  CLU_MIN_SIZE, CLU_MIN_SIZE,
+					  CLU_MAX_SIZE, CLU_MAX_SIZE);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 54de15095709..0fa310f1a8d1 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -311,6 +311,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
 	return ret;
 }
 
+/*
+ * vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
+ * @subdev: V4L2 subdevice
+ * @cfg: V4L2 subdev pad configuration
+ * @fmt: V4L2 subdev format
+ * @codes: Array of supported media bus codes
+ * @ncodes: Number of supported media bus codes
+ * @min_width: Minimum image width
+ * @min_height: Minimum image height
+ * @max_width: Maximum image width
+ * @max_height: Maximum image height
+ *
+ * This function implements the subdev set_fmt pad operation for entities that
+ * do not support scaling or cropping. It defaults to the first supplied media
+ * bus code if the requested code isn't supported, clamps the size to the
+ * supplied minimum and maximum, and propagates the sink pad format to the
+ * source pad.
+ */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt,
+			       const unsigned int *codes, unsigned int ncodes,
+			       unsigned int min_width, unsigned int min_height,
+			       unsigned int max_width, unsigned int max_height)
+{
+	struct vsp1_entity *entity = to_vsp1_entity(subdev);
+	struct v4l2_subdev_pad_config *config;
+	struct v4l2_mbus_framefmt *format;
+	unsigned int i;
+	int ret = 0;
+
+	mutex_lock(&entity->lock);
+
+	config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
+	if (!config) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
+
+	if (fmt->pad != 0) {
+		/* The output format can't be modified. */
+		fmt->format = *format;
+		goto done;
+	}
+
+	/*
+	 * Default to the first media bus code if the requested format is not
+	 * supported.
+	 */
+	for (i = 0; i < ncodes; ++i) {
+		if (fmt->format.code == codes[i])
+			break;
+	}
+
+	format->code = i < ncodes ? codes[i] : codes[0];
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				min_width, max_width);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 min_height, max_height);
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad. */
+	format = vsp1_entity_get_pad_format(entity, config, 1);
+	*format = fmt->format;
+
+done:
+	mutex_unlock(&entity->lock);
+	return ret;
+}
+
 /* -----------------------------------------------------------------------------
  * Media Operations
  */
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 408602ebeb97..319e053737fd 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -162,6 +162,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);
 int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
 			       struct v4l2_subdev_pad_config *cfg,
 			       struct v4l2_subdev_format *fmt);
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt,
+			       const unsigned int *codes, unsigned int ncodes,
+			       unsigned int min_width, unsigned int min_height,
+			       unsigned int max_width, unsigned int max_height);
 int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
 			       struct v4l2_subdev_pad_config *cfg,
 			       struct v4l2_subdev_mbus_code_enum *code,
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index e6fa16d7fda8..ad56629450ec 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -37,17 +37,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
  * V4L2 Subdevice Operations
  */
 
+static const unsigned int lif_codes[] = {
+	MEDIA_BUS_FMT_ARGB8888_1X32,
+	MEDIA_BUS_FMT_AYUV8_1X32,
+};
+
 static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_pad_config *cfg,
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
-	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
-	};
-
-	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
-					  ARRAY_SIZE(codes));
+	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
+					  ARRAY_SIZE(lif_codes));
 }
 
 static int lif_enum_frame_size(struct v4l2_subdev *subdev,
@@ -63,53 +63,10 @@ static int lif_set_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_pad_config *cfg,
 			  struct v4l2_subdev_format *fmt)
 {
-	struct vsp1_lif *lif = to_lif(subdev);
-	struct v4l2_subdev_pad_config *config;
-	struct v4l2_mbus_framefmt *format;
-	int ret = 0;
-
-	mutex_lock(&lif->entity.lock);
-
-	config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
-	if (!config) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
-
-	format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
-
-	if (fmt->pad == LIF_PAD_SOURCE) {
-		/*
-		 * The LIF source format is always identical to its sink
-		 * format.
-		 */
-		fmt->format = *format;
-		goto done;
-	}
-
-	format->code = fmt->format.code;
-	format->width = clamp_t(unsigned int, fmt->format.width,
-				LIF_MIN_SIZE, LIF_MAX_SIZE);
-	format->height = clamp_t(unsigned int, fmt->format.height,
-				 LIF_MIN_SIZE, LIF_MAX_SIZE);
-	format->field = V4L2_FIELD_NONE;
-	format->colorspace = V4L2_COLORSPACE_SRGB;
-
-	fmt->format = *format;
-
-	/* Propagate the format to the source pad. */
-	format = vsp1_entity_get_pad_format(&lif->entity, config,
-					    LIF_PAD_SOURCE);
-	*format = fmt->format;
-
-done:
-	mutex_unlock(&lif->entity.lock);
-	return ret;
+	return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
+					  ARRAY_SIZE(lif_codes),
+					  LIF_MIN_SIZE, LIF_MIN_SIZE,
+					  LIF_MAX_SIZE, LIF_MAX_SIZE);
 }
 
 static const struct v4l2_subdev_pad_ops lif_pad_ops = {
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index c67cc60db0db..63f8127a65a4 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -94,18 +94,18 @@ static const struct v4l2_ctrl_config lut_table_control = {
  * V4L2 Subdevice Pad Operations
  */
 
+static const unsigned int lut_codes[] = {
+	MEDIA_BUS_FMT_ARGB8888_1X32,
+	MEDIA_BUS_FMT_AHSV8888_1X32,
+	MEDIA_BUS_FMT_AYUV8_1X32,
+};
+
 static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_pad_config *cfg,
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
-	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AHSV8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
-	};
-
-	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
-					  ARRAY_SIZE(codes));
+	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
+					  ARRAY_SIZE(lut_codes));
 }
 
 static int lut_enum_frame_size(struct v4l2_subdev *subdev,
@@ -121,51 +121,10 @@ static int lut_set_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_pad_config *cfg,
 			  struct v4l2_subdev_format *fmt)
 {
-	struct vsp1_lut *lut = to_lut(subdev);
-	struct v4l2_subdev_pad_config *config;
-	struct v4l2_mbus_framefmt *format;
-	int ret = 0;
-
-	mutex_lock(&lut->entity.lock);
-
-	config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
-	if (!config) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
-
-	format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
-
-	if (fmt->pad == LUT_PAD_SOURCE) {
-		/* The LUT output format can't be modified. */
-		fmt->format = *format;
-		goto done;
-	}
-
-	format->code = fmt->format.code;
-	format->width = clamp_t(unsigned int, fmt->format.width,
-				LUT_MIN_SIZE, LUT_MAX_SIZE);
-	format->height = clamp_t(unsigned int, fmt->format.height,
-				 LUT_MIN_SIZE, LUT_MAX_SIZE);
-	format->field = V4L2_FIELD_NONE;
-	format->colorspace = V4L2_COLORSPACE_SRGB;
-
-	fmt->format = *format;
-
-	/* Propagate the format to the source pad. */
-	format = vsp1_entity_get_pad_format(&lut->entity, config,
-					    LUT_PAD_SOURCE);
-	*format = fmt->format;
-
-done:
-	mutex_unlock(&lut->entity.lock);
-	return ret;
+	return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
+					  ARRAY_SIZE(lut_codes),
+					  LUT_MIN_SIZE, LUT_MIN_SIZE,
+					  LUT_MAX_SIZE, LUT_MAX_SIZE);
 }
 
 /* -----------------------------------------------------------------------------
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/9] v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (2 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 3/9] v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure Laurent Pinchart
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

To make vsp1_subdev_set_pad_format() usable by entities that support
selection rectangles, we need to reset the crop and compose rectangles
when setting the format on the sink pad. Do so and replace the custom
set_fmt implementation of the histogram code by a call to
vsp1_subdev_set_pad_format().

Resetting the crop and compose rectangles for entities that don't
support crop and compose has no adverse effect as the rectangles are
ignored anyway.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_entity.c | 16 +++++++++
 drivers/media/platform/vsp1/vsp1_histo.c  | 59 +++----------------------------
 2 files changed, 20 insertions(+), 55 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 0fa310f1a8d1..b92d3985ae47 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -339,6 +339,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
 	struct vsp1_entity *entity = to_vsp1_entity(subdev);
 	struct v4l2_subdev_pad_config *config;
 	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *selection;
 	unsigned int i;
 	int ret = 0;
 
@@ -381,6 +382,21 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
 	format = vsp1_entity_get_pad_format(entity, config, 1);
 	*format = fmt->format;
 
+	/* Reset the crop and compose rectangles */
+	selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
+						  V4L2_SEL_TGT_CROP);
+	selection->left = 0;
+	selection->top = 0;
+	selection->width = format->width;
+	selection->height = format->height;
+
+	selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
+						  V4L2_SEL_TGT_COMPOSE);
+	selection->left = 0;
+	selection->top = 0;
+	selection->width = format->width;
+	selection->height = format->height;
+
 done:
 	mutex_unlock(&entity->lock);
 	return ret;
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
index afab77cf4fa5..f470626cb601 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -393,65 +393,14 @@ static int histo_set_format(struct v4l2_subdev *subdev,
 			    struct v4l2_subdev_format *fmt)
 {
 	struct vsp1_histogram *histo = subdev_to_histo(subdev);
-	struct v4l2_subdev_pad_config *config;
-	struct v4l2_mbus_framefmt *format;
-	struct v4l2_rect *selection;
-	unsigned int i;
-	int ret = 0;
 
 	if (fmt->pad != HISTO_PAD_SINK)
 		return histo_get_format(subdev, cfg, fmt);
 
-	mutex_lock(&histo->entity.lock);
-
-	config = vsp1_entity_get_pad_config(&histo->entity, cfg, fmt->which);
-	if (!config) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 * Default to the first format if the requested format is not
-	 * supported.
-	 */
-	for (i = 0; i < histo->num_formats; ++i) {
-		if (fmt->format.code == histo->formats[i])
-			break;
-	}
-	if (i == histo->num_formats)
-		fmt->format.code = histo->formats[0];
-
-	format = vsp1_entity_get_pad_format(&histo->entity, config, fmt->pad);
-
-	format->code = fmt->format.code;
-	format->width = clamp_t(unsigned int, fmt->format.width,
-				HISTO_MIN_SIZE, HISTO_MAX_SIZE);
-	format->height = clamp_t(unsigned int, fmt->format.height,
-				 HISTO_MIN_SIZE, HISTO_MAX_SIZE);
-	format->field = V4L2_FIELD_NONE;
-	format->colorspace = V4L2_COLORSPACE_SRGB;
-
-	fmt->format = *format;
-
-	/* Reset the crop and compose rectangles */
-	selection = vsp1_entity_get_pad_selection(&histo->entity, config,
-						  fmt->pad, V4L2_SEL_TGT_CROP);
-	selection->left = 0;
-	selection->top = 0;
-	selection->width = format->width;
-	selection->height = format->height;
-
-	selection = vsp1_entity_get_pad_selection(&histo->entity, config,
-						  fmt->pad,
-						  V4L2_SEL_TGT_COMPOSE);
-	selection->left = 0;
-	selection->top = 0;
-	selection->width = format->width;
-	selection->height = format->height;
-
-done:
-	mutex_unlock(&histo->entity.lock);
-	return ret;
+	return vsp1_subdev_set_pad_format(subdev, cfg, fmt,
+					  histo->formats, histo->num_formats,
+					  HISTO_MIN_SIZE, HISTO_MIN_SIZE,
+					  HISTO_MAX_SIZE, HISTO_MAX_SIZE);
 }
 
 static const struct v4l2_subdev_pad_ops histo_pad_ops = {
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (3 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 4/9] v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-04  9:31   ` Sergei Shtylyov
  2017-12-03 10:57 ` [PATCH 6/9] v4l: vsp1: Extend the DU API to support CRC computation Laurent Pinchart
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

The structure is used in the API that the VSP1 driver exposes to the DU
driver. Documenting it is thus important.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 include/media/vsp1.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/media/vsp1.h b/include/media/vsp1.h
index 68a8abe4fac5..7850f96fb708 100644
--- a/include/media/vsp1.h
+++ b/include/media/vsp1.h
@@ -41,6 +41,16 @@ struct vsp1_du_lif_config {
 int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		      const struct vsp1_du_lif_config *cfg);
 
+/**
+ * struct vsp1_du_atomic_config - VSP atomic configuration parameters
+ * @pixelformat: plan pixel format (V4L2 4CC)
+ * @pitch: line pitch in bytes, for all planes
+ * @mem: DMA memory address for each plane of the frame buffer
+ * @src: source rectangle in the frame buffer (integer coordinates)
+ * @dst: destination rectangle on the display (integer coordinates)
+ * @alpha: alpha value (0: fully transparent, 255: fully opaque)
+ * @zpos: Z position of the plane (from 0 to number of planes minus 1)
+ */
 struct vsp1_du_atomic_config {
 	u32 pixelformat;
 	unsigned int pitch;
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/9] v4l: vsp1: Extend the DU API to support CRC computation
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (4 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 7/9] v4l: vsp1: Add support for the DISCOM entity Laurent Pinchart
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

Add a parameter (in the form of a structure to ease future API
extensions) to the VSP atomic flush handler to pass CRC source
configuration, and pass the CRC value to the completion callback.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  |  6 ++++--
 drivers/media/platform/vsp1/vsp1_drm.c |  6 ++++--
 drivers/media/platform/vsp1/vsp1_drm.h |  2 +-
 include/media/vsp1.h                   | 29 +++++++++++++++++++++++++++--
 4 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 2c260c33840b..bdcec201591f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -31,7 +31,7 @@
 #include "rcar_du_kms.h"
 #include "rcar_du_vsp.h"
 
-static void rcar_du_vsp_complete(void *private, bool completed)
+static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
 {
 	struct rcar_du_crtc *crtc = private;
 
@@ -102,7 +102,9 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
 
 void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
 {
-	vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe);
+	struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
+
+	vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
 }
 
 /* Keep the two tables in sync. */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 0fe541084f5c..97d2be3b0023 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -38,7 +38,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 
 	if (drm_pipe->du_complete)
-		drm_pipe->du_complete(drm_pipe->du_private, completed);
+		drm_pipe->du_complete(drm_pipe->du_private, completed, 0);
 }
 
 /* -----------------------------------------------------------------------------
@@ -505,8 +505,10 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
  * vsp1_du_atomic_flush - Commit an atomic update
  * @dev: the VSP device
  * @pipe_index: the DRM pipeline index
+ * @cfg: atomic pipe configuration
  */
-void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
+void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
+			  const struct vsp1_du_atomic_pipe_config *cfg)
 {
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 1cd9db785bf7..c6515272da7d 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -29,7 +29,7 @@ struct vsp1_drm_pipeline {
 	bool enabled;
 
 	/* Frame synchronisation */
-	void (*du_complete)(void *, bool);
+	void (*du_complete)(void *data, bool completed, u32 crc);
 	void *du_private;
 };
 
diff --git a/include/media/vsp1.h b/include/media/vsp1.h
index 7850f96fb708..89af1606ecb3 100644
--- a/include/media/vsp1.h
+++ b/include/media/vsp1.h
@@ -34,7 +34,7 @@ struct vsp1_du_lif_config {
 	unsigned int width;
 	unsigned int height;
 
-	void (*callback)(void *, bool);
+	void (*callback)(void *data, bool completed, u32 crc);
 	void *callback_data;
 };
 
@@ -61,11 +61,36 @@ struct vsp1_du_atomic_config {
 	unsigned int zpos;
 };
 
+/**
+ * enum vsp1_du_crc_source - Source used for CRC calculation
+ * @VSP1_DU_CRC_NONE: CRC calculation disabled
+ * @VSP_DU_CRC_PLANE: Perform CRC calculation on an input plane
+ * @VSP_DU_CRC_OUTPUT: Perform CRC calculation on the composed output
+ */
+enum vsp1_du_crc_source {
+	VSP1_DU_CRC_NONE,
+	VSP1_DU_CRC_PLANE,
+	VSP1_DU_CRC_OUTPUT,
+};
+
+/**
+ * struct vsp1_du_atomic_pipe_config - VSP atomic pipe configuration parameters
+ * @crc.source: source for CRC calculation
+ * @crc.index: index of the CRC source plane (when crc.source is set to plane)
+ */
+struct vsp1_du_atomic_pipe_config {
+	struct  {
+		enum vsp1_du_crc_source source;
+		unsigned int index;
+	} crc;
+};
+
 void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index);
 int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 			  unsigned int rpf,
 			  const struct vsp1_du_atomic_config *cfg);
-void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index);
+void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
+			  const struct vsp1_du_atomic_pipe_config *cfg);
 int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt);
 void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt);
 
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/9] v4l: vsp1: Add support for the DISCOM entity
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (5 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 6/9] v4l: vsp1: Extend the DU API to support CRC computation Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 8/9] v4l: vsp1: Integrate DISCOM in display pipeline Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 9/9] drm: rcar-du: Add support for CRC computation Laurent Pinchart
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

The DISCOM calculates a CRC on a configurable window of the frame. It
interfaces to the VSP through the UIF glue, hence the name used in the
code.

The module supports configuration of the CRC window through the crop
rectangle on the ink pad of the corresponding entity. However, unlike
the traditional V4L2 subdevice model, the crop rectangle does not
influence the format on the source pad.

Modeling the DISCOM as a sink-only entity would allow adhering to the
V4L2 subdevice model at the expense of more complex code in the driver,
as at the hardware level the UIF is handled as a sink+source entity. As
the DISCOM is only present in R-Car Gen3 VSP-D and VSP-DL instances it
is not exposed to userspace through V4L2 but controlled through the DU
driver. We can thus change this model later if needed without fear of
affecting userspace.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/Makefile      |   2 +-
 drivers/media/platform/vsp1/vsp1.h        |   4 +
 drivers/media/platform/vsp1/vsp1_drv.c    |  20 +++
 drivers/media/platform/vsp1/vsp1_entity.c |   6 +
 drivers/media/platform/vsp1/vsp1_entity.h |   1 +
 drivers/media/platform/vsp1/vsp1_regs.h   |  41 +++++
 drivers/media/platform/vsp1/vsp1_uif.c    | 275 ++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_uif.h    |  36 ++++
 8 files changed, 384 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index f5cd6f0491cb..3c73dd0cc898 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -5,6 +5,6 @@ vsp1-y					+= vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
 vsp1-y					+= vsp1_clu.o vsp1_hsit.o vsp1_lut.o
 vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
 vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
-vsp1-y					+= vsp1_lif.o
+vsp1-y					+= vsp1_lif.o vsp1_uif.o
 
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1.o
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 78ef838416b3..6f0b6baf125a 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -40,10 +40,12 @@ struct vsp1_lut;
 struct vsp1_rwpf;
 struct vsp1_sru;
 struct vsp1_uds;
+struct vsp1_uif;
 
 #define VSP1_MAX_LIF		2
 #define VSP1_MAX_RPF		5
 #define VSP1_MAX_UDS		3
+#define VSP1_MAX_UIF		2
 #define VSP1_MAX_WPF		4
 
 #define VSP1_HAS_LUT		(1 << 1)
@@ -64,6 +66,7 @@ struct vsp1_device_info {
 	unsigned int lif_count;
 	unsigned int rpf_count;
 	unsigned int uds_count;
+	unsigned int uif_count;
 	unsigned int wpf_count;
 	unsigned int num_bru_inputs;
 	bool uapi;
@@ -90,6 +93,7 @@ struct vsp1_device {
 	struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
 	struct vsp1_sru *sru;
 	struct vsp1_uds *uds[VSP1_MAX_UDS];
+	struct vsp1_uif *uif[VSP1_MAX_UIF];
 	struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
 
 	struct list_head entities;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 962e4c304076..b1e360ebb587 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -39,6 +39,7 @@
 #include "vsp1_rwpf.h"
 #include "vsp1_sru.h"
 #include "vsp1_uds.h"
+#include "vsp1_uif.h"
 #include "vsp1_video.h"
 
 /* -----------------------------------------------------------------------------
@@ -413,6 +414,19 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&uds->entity.list_dev, &vsp1->entities);
 	}
 
+	for (i = 0; i < vsp1->info->uif_count; ++i) {
+		struct vsp1_uif *uif;
+
+		uif = vsp1_uif_create(vsp1, i);
+		if (IS_ERR(uif)) {
+			ret = PTR_ERR(uif);
+			goto done;
+		}
+
+		vsp1->uif[i] = uif;
+		list_add_tail(&uif->entity.list_dev, &vsp1->entities);
+	}
+
 	for (i = 0; i < vsp1->info->wpf_count; ++i) {
 		struct vsp1_rwpf *wpf;
 
@@ -517,6 +531,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
 	for (i = 0; i < vsp1->info->uds_count; ++i)
 		vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
 
+	for (i = 0; i < vsp1->info->uif_count; ++i)
+		vsp1_write(vsp1, VI6_DPR_UIF_ROUTE(i), VI6_DPR_NODE_UNUSED);
+
 	vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED);
 	vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED);
 	vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED);
@@ -732,6 +749,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 		.features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
 		.lif_count = 1,
 		.rpf_count = 5,
+		.uif_count = 1,
 		.wpf_count = 2,
 		.num_bru_inputs = 5,
 	}, {
@@ -741,6 +759,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 		.features = VSP1_HAS_BRS | VSP1_HAS_BRU,
 		.lif_count = 1,
 		.rpf_count = 5,
+		.uif_count = 1,
 		.wpf_count = 1,
 		.num_bru_inputs = 5,
 	}, {
@@ -750,6 +769,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 		.features = VSP1_HAS_BRS | VSP1_HAS_BRU,
 		.lif_count = 2,
 		.rpf_count = 5,
+		.uif_count = 2,
 		.wpf_count = 2,
 		.num_bru_inputs = 5,
 	},
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index b92d3985ae47..95a5db6d378d 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -543,6 +543,10 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad)
 	{ VSP1_ENTITY_UDS, idx, VI6_DPR_UDS_ROUTE(idx),			\
 	  { VI6_DPR_NODE_UDS(idx) }, VI6_DPR_NODE_UDS(idx) }
 
+#define VSP1_ENTITY_ROUTE_UIF(idx)					\
+	{ VSP1_ENTITY_UIF, idx, VI6_DPR_UIF_ROUTE(idx),			\
+	  { VI6_DPR_NODE_UIF(idx) }, VI6_DPR_NODE_UIF(idx) }
+
 #define VSP1_ENTITY_ROUTE_WPF(idx)					\
 	{ VSP1_ENTITY_WPF, idx, 0,					\
 	  { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) }
@@ -571,6 +575,8 @@ static const struct vsp1_route vsp1_routes[] = {
 	VSP1_ENTITY_ROUTE_UDS(0),
 	VSP1_ENTITY_ROUTE_UDS(1),
 	VSP1_ENTITY_ROUTE_UDS(2),
+	VSP1_ENTITY_ROUTE_UIF(0),	/* Named UIF4 in the documentation */
+	VSP1_ENTITY_ROUTE_UIF(1),	/* Named UIF5 in the documentation */
 	VSP1_ENTITY_ROUTE_WPF(0),
 	VSP1_ENTITY_ROUTE_WPF(1),
 	VSP1_ENTITY_ROUTE_WPF(2),
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 319e053737fd..b80798eb7696 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -37,6 +37,7 @@ enum vsp1_entity_type {
 	VSP1_ENTITY_RPF,
 	VSP1_ENTITY_SRU,
 	VSP1_ENTITY_UDS,
+	VSP1_ENTITY_UIF,
 	VSP1_ENTITY_WPF,
 };
 
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 26c4ffad2f46..0e968eb5cb8e 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -311,6 +311,44 @@
 #define VI6_WPF_WRBCK_CTRL_WBMD		(1 << 0)
 
 /* -----------------------------------------------------------------------------
+ * UIF Control Registers
+ */
+
+#define VI6_UIF_OFFSET			0x100
+
+#define VI6_UIF_DISCOM_DOCMCR		0x1c00
+#define VI6_UIF_DISCOM_DOCMCR_CMPRU	(1 << 16)
+#define VI6_UIF_DISCOM_DOCMCR_CMPR	(1 << 0)
+
+#define VI6_UIF_DISCOM_DOCMSTR		0x1c04
+#define VI6_UIF_DISCOM_DOCMSTR_CMPPRE	(1 << 1)
+#define VI6_UIF_DISCOM_DOCMSTR_CMPST	(1 << 0)
+
+#define VI6_UIF_DISCOM_DOCMCLSTR	0x1c08
+#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLPRE	(1 << 1)
+#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLST	(1 << 0)
+
+#define VI6_UIF_DISCOM_DOCMIENR		0x1c0c
+#define VI6_UIF_DISCOM_DOCMIENR_CMPPREIEN	(1 << 1)
+#define VI6_UIF_DISCOM_DOCMIENR_CMPIEN		(1 << 0)
+
+#define VI6_UIF_DISCOM_DOCMMDR		0x1c10
+#define VI6_UIF_DISCOM_DOCMMDR_INTHRH(n)	((n) << 16)
+
+#define VI6_UIF_DISCOM_DOCMPMR		0x1c14
+#define VI6_UIF_DISCOM_DOCMPMR_CMPDFF(n)	((n) << 17)
+#define VI6_UIF_DISCOM_DOCMPMR_CMPDFA(n)	((n) << 8)
+#define VI6_UIF_DISCOM_DOCMPMR_CMPDAUF		(1 << 7)
+#define VI6_UIF_DISCOM_DOCMPMR_SEL(n)		((n) << 0)
+
+#define VI6_UIF_DISCOM_DOCMECRCR	0x1c18
+#define VI6_UIF_DISCOM_DOCMCCRCR	0x1c1c
+#define VI6_UIF_DISCOM_DOCMSPXR		0x1c20
+#define VI6_UIF_DISCOM_DOCMSPYR		0x1c24
+#define VI6_UIF_DISCOM_DOCMSZXR		0x1c28
+#define VI6_UIF_DISCOM_DOCMSZYR		0x1c2c
+
+/* -----------------------------------------------------------------------------
  * DPR Control Registers
  */
 
@@ -342,7 +380,10 @@
 #define VI6_DPR_SMPPT_PT_MASK		(0x3f << 0)
 #define VI6_DPR_SMPPT_PT_SHIFT		0
 
+#define VI6_DPR_UIF_ROUTE(n)		(0x2074 + (n) * 4)
+
 #define VI6_DPR_NODE_RPF(n)		(n)
+#define VI6_DPR_NODE_UIF(n)		(12 + (n))
 #define VI6_DPR_NODE_SRU		16
 #define VI6_DPR_NODE_UDS(n)		(17 + (n))
 #define VI6_DPR_NODE_LUT		22
diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c
new file mode 100644
index 000000000000..60c482747d66
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_uif.c
@@ -0,0 +1,275 @@
+/*
+ * vsp1_uif.c  --  R-Car VSP1 User Logic Interface
+ *
+ * Copyright (C) 2017 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/gfp.h>
+#include <linux/sys_soc.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
+
+#include "vsp1.h"
+#include "vsp1_dl.h"
+#include "vsp1_entity.h"
+#include "vsp1_uif.h"
+
+#define UIF_MIN_SIZE				4U
+#define UIF_MAX_SIZE				8190U
+
+/* -----------------------------------------------------------------------------
+ * Device Access
+ */
+
+static inline u32 vsp1_uif_read(struct vsp1_uif *uif, u32 reg)
+{
+	return vsp1_read(uif->entity.vsp1,
+			 uif->entity.index * VI6_UIF_OFFSET + reg);
+}
+static inline void vsp1_uif_write(struct vsp1_uif *uif, struct vsp1_dl_list *dl,
+				  u32 reg, u32 data)
+{
+	vsp1_dl_list_write(dl, reg + uif->entity.index * VI6_UIF_OFFSET, data);
+}
+
+u32 vsp1_uif_get_crc(struct vsp1_uif *uif)
+{
+	return vsp1_uif_read(uif, VI6_UIF_DISCOM_DOCMCCRCR);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static const unsigned int uif_codes[] = {
+	MEDIA_BUS_FMT_ARGB8888_1X32,
+	MEDIA_BUS_FMT_AHSV8888_1X32,
+	MEDIA_BUS_FMT_AYUV8_1X32,
+};
+
+static int uif_enum_mbus_code(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_pad_config *cfg,
+			      struct v4l2_subdev_mbus_code_enum *code)
+{
+	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, uif_codes,
+					  ARRAY_SIZE(uif_codes));
+}
+
+static int uif_enum_frame_size(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_frame_size_enum *fse)
+{
+	return vsp1_subdev_enum_frame_size(subdev, cfg, fse, UIF_MIN_SIZE,
+					   UIF_MIN_SIZE, UIF_MAX_SIZE,
+					   UIF_MAX_SIZE);
+}
+
+static int uif_set_format(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_pad_config *cfg,
+			    struct v4l2_subdev_format *fmt)
+{
+	return vsp1_subdev_set_pad_format(subdev, cfg, fmt, uif_codes,
+					  ARRAY_SIZE(uif_codes),
+					  UIF_MIN_SIZE, UIF_MIN_SIZE,
+					  UIF_MAX_SIZE, UIF_MAX_SIZE);
+}
+
+static int uif_get_selection(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_uif *uif = to_uif(subdev);
+	struct v4l2_subdev_pad_config *config;
+	struct v4l2_mbus_framefmt *format;
+	int ret = 0;
+
+	if (sel->pad != UIF_PAD_SINK)
+		return -EINVAL;
+
+	mutex_lock(&uif->entity.lock);
+
+	config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
+	if (!config) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		format = vsp1_entity_get_pad_format(&uif->entity, config,
+						    UIF_PAD_SINK);
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = format->width;
+		sel->r.height = format->height;
+		break;
+
+	case V4L2_SEL_TGT_CROP:
+		sel->r = *vsp1_entity_get_pad_selection(&uif->entity, config,
+							sel->pad, sel->target);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+done:
+	mutex_unlock(&uif->entity.lock);
+	return ret;
+}
+
+static int uif_set_selection(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_uif *uif = to_uif(subdev);
+	struct v4l2_subdev_pad_config *config;
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *selection;
+	int ret;
+
+	if (sel->pad != UIF_PAD_SINK ||
+	    sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	mutex_lock(&uif->entity.lock);
+
+	config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
+	if (!config) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* The crop rectangle must be inside the input frame. */
+	format = vsp1_entity_get_pad_format(&uif->entity, config, UIF_PAD_SINK);
+
+	sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
+	sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
+	sel->r.width = clamp_t(unsigned int, sel->r.width, UIF_MIN_SIZE,
+			       format->width - sel->r.left);
+	sel->r.height = clamp_t(unsigned int, sel->r.height, UIF_MIN_SIZE,
+				format->height - sel->r.top);
+
+	/* Store the crop rectangle. */
+	selection = vsp1_entity_get_pad_selection(&uif->entity, config,
+						  sel->pad, V4L2_SEL_TGT_CROP);
+	*selection = sel->r;
+
+done:
+	mutex_unlock(&uif->entity.lock);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static const struct v4l2_subdev_pad_ops uif_pad_ops = {
+	.init_cfg = vsp1_entity_init_cfg,
+	.enum_mbus_code = uif_enum_mbus_code,
+	.enum_frame_size = uif_enum_frame_size,
+	.get_fmt = vsp1_subdev_get_pad_format,
+	.set_fmt = uif_set_format,
+	.get_selection = uif_get_selection,
+	.set_selection = uif_set_selection,
+};
+
+static const struct v4l2_subdev_ops uif_ops = {
+	.pad    = &uif_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * VSP1 Entity Operations
+ */
+
+static void uif_configure(struct vsp1_entity *entity,
+			  struct vsp1_pipeline *pipe,
+			  struct vsp1_dl_list *dl,
+			  enum vsp1_entity_params params)
+{
+	struct vsp1_uif *uif = to_uif(&entity->subdev);
+	const struct v4l2_rect *crop;
+	unsigned int left;
+	unsigned int width;
+
+	/*
+	 * Per-partition configuration isn't needed as the DISCOM is used in
+	 * display pipelines only.
+	 */
+	if (params != VSP1_ENTITY_PARAMS_INIT)
+		return;
+
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR,
+		       VI6_UIF_DISCOM_DOCMPMR_SEL(9));
+
+	crop = vsp1_entity_get_pad_selection(entity, entity->config,
+					     UIF_PAD_SINK, V4L2_SEL_TGT_CROP);
+
+	/* On M3-W the horizontal coordinates are twice the register value. */
+	if (uif->m3w_quirk) {
+		left = crop->left / 2;
+		width = crop->width / 2;
+	} else {
+		left = crop->left;
+		width = crop->width;
+	}
+
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPXR, left);
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPYR, crop->top);
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZXR, width);
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZYR, crop->height);
+
+	vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMCR,
+		       VI6_UIF_DISCOM_DOCMCR_CMPR);
+}
+
+static const struct vsp1_entity_operations uif_entity_ops = {
+	.configure = uif_configure,
+};
+
+/* -----------------------------------------------------------------------------
+ * Initialization and Cleanup
+ */
+
+static const struct soc_device_attribute vsp1_r8a7796[] = {
+	{ .soc_id = "r8a7796" },
+	{ /* sentinel */ }
+};
+
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index)
+{
+	struct vsp1_uif *uif;
+	char name[6];
+	int ret;
+
+	uif = devm_kzalloc(vsp1->dev, sizeof(*uif), GFP_KERNEL);
+	if (uif == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (soc_device_match(vsp1_r8a7796))
+		uif->m3w_quirk = true;
+
+	uif->entity.ops = &uif_entity_ops;
+	uif->entity.type = VSP1_ENTITY_UIF;
+	uif->entity.index = index;
+
+	/* The datasheet names the two UIF instances UIF4 and UIF5. */
+	sprintf(name, "uif.%u", index + 4);
+	ret = vsp1_entity_init(vsp1, &uif->entity, name, 2, &uif_ops,
+			       MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	return uif;
+}
diff --git a/drivers/media/platform/vsp1/vsp1_uif.h b/drivers/media/platform/vsp1/vsp1_uif.h
new file mode 100644
index 000000000000..4621d3cf2585
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_uif.h
@@ -0,0 +1,36 @@
+/*
+ * vsp1_uif.h  --  R-Car VSP1 User Logic Interface
+ *
+ * Copyright (C) 2017 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_UIF_H__
+#define __VSP1_UIF_H__
+
+#include "vsp1_entity.h"
+
+struct vsp1_device;
+
+#define UIF_PAD_SINK				0
+#define UIF_PAD_SOURCE				1
+
+struct vsp1_uif {
+	struct vsp1_entity entity;
+	bool m3w_quirk;
+};
+
+static inline struct vsp1_uif *to_uif(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct vsp1_uif, entity.subdev);
+}
+
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index);
+u32 vsp1_uif_get_crc(struct vsp1_uif *uif);
+
+#endif /* __VSP1_UIF_H__ */
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/9] v4l: vsp1: Integrate DISCOM in display pipeline
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (6 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 7/9] v4l: vsp1: Add support for the DISCOM entity Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  2017-12-03 10:57 ` [PATCH 9/9] drm: rcar-du: Add support for CRC computation Laurent Pinchart
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

The DISCOM is used to compute CRCs on display frames. Integrate it in
the display pipeline at the output of the blending unit to process
output frames.

Computing CRCs on input frames is possible by positioning the DISCOM at
a different point in the pipeline. This use case isn't supported at the
moment and could be implemented by extending the API between the VSP1
and DU drivers if needed.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 113 +++++++++++++++++++++++++++++++--
 drivers/media/platform/vsp1/vsp1_drm.h |  12 ++++
 2 files changed, 121 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 97d2be3b0023..bcf30c25ccb3 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -26,6 +26,7 @@
 #include "vsp1_lif.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
+#include "vsp1_uif.h"
 
 
 /* -----------------------------------------------------------------------------
@@ -36,9 +37,15 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 				       bool completed)
 {
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
+	u32 crc = 0;
 
-	if (drm_pipe->du_complete)
-		drm_pipe->du_complete(drm_pipe->du_private, completed, 0);
+	if (!drm_pipe->du_complete)
+		return;
+
+	if (drm_pipe->uif)
+		crc = vsp1_uif_get_crc(to_uif(&drm_pipe->uif->subdev));
+
+	drm_pipe->du_complete(drm_pipe->du_private, completed, crc);
 }
 
 /* -----------------------------------------------------------------------------
@@ -393,9 +400,67 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
 
+/*
+ * Insert the UIF in the pipeline between the prev and next entities. If no UIF
+ * is available connect the two entities directly.
+ */
+static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
+			      struct vsp1_pipeline *pipe,
+			      struct vsp1_entity *uif,
+			      struct vsp1_entity *prev, unsigned int prev_pad,
+			      struct vsp1_entity *next, unsigned int next_pad)
+{
+	int ret;
+
+	if (uif) {
+		struct v4l2_subdev_format format;
+
+		prev->sink = uif;
+		prev->sink_pad = UIF_PAD_SINK;
+
+		memset(&format, 0, sizeof(format));
+		format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		format.pad = prev_pad;
+
+		ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL,
+				       &format);
+		if (ret < 0)
+			return ret;
+
+		format.pad = UIF_PAD_SINK;
+
+		ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL,
+				       &format);
+		if (ret < 0)
+			return ret;
+
+		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
+			__func__, format.format.width, format.format.height,
+			format.format.code);
+
+		/*
+		 * The UIF doesn't mangle the format between its sink and
+		 * source pads, so there is no need to retrieve the format on
+		 * its source pad.
+		 */
+
+		uif->sink = next;
+		uif->sink_pad = next_pad;
+
+		list_add_tail(&uif->list_pipe, &pipe->entities);
+	} else {
+		prev->sink = next;
+		prev->sink_pad = next_pad;
+	}
+
+	return 0;
+}
+
 static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
 				  struct vsp1_pipeline *pipe,
-				  struct vsp1_rwpf *rpf, unsigned int bru_input)
+				  struct vsp1_rwpf *rpf,
+				  struct vsp1_entity *uif,
+				  unsigned int bru_input)
 {
 	struct v4l2_subdev_selection sel;
 	struct v4l2_subdev_format format;
@@ -468,6 +533,12 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
 	if (ret < 0)
 		return ret;
 
+	/* Insert and configure the UIF if available. */
+	ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE,
+				 pipe->bru, bru_input);
+	if (ret < 0)
+		return ret;
+
 	/* BRU sink, propagate the format from the RPF source. */
 	format.pad = bru_input;
 
@@ -517,6 +588,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
 	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
 	struct vsp1_entity *entity;
 	struct vsp1_entity *next;
+	struct vsp1_entity *uif;
 	struct vsp1_dl_list *dl;
 	const char *bru_name;
 	unsigned int i;
@@ -556,6 +628,12 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
 		inputs[j] = rpf;
 	}
 
+	/*
+	 * Remove the UIF from the pipeline, it will be inserted only if needed.
+	 */
+	if (drm_pipe->uif && !list_empty(&drm_pipe->uif->list_pipe))
+		list_del_init(&drm_pipe->uif->list_pipe);
+
 	/* Setup the RPF input pipeline for every enabled input. */
 	for (i = 0; i < pipe->bru->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
@@ -576,13 +654,29 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
 		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
 			__func__, rpf->entity.index, bru_name, i);
 
-		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
+		uif = cfg->crc.source == VSP1_DU_CRC_PLANE &&
+		      cfg->crc.index == i ? drm_pipe->uif : NULL;
+		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, uif, i);
 		if (ret < 0)
 			dev_err(vsp1->dev,
 				"%s: failed to setup RPF.%u\n",
 				__func__, rpf->entity.index);
 	}
 
+	/* Insert and configure the UIF at the BRU output if available. */
+	uif = cfg->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL;
+	ret = vsp1_du_insert_uif(vsp1, pipe, uif,
+				 pipe->bru, pipe->bru->source_pad,
+				 &pipe->output->entity, 0);
+	if (ret < 0)
+		dev_err(vsp1->dev, "%s: failed to setup UIF after BRU\n",
+			__func__);
+
+	/* Disconnect the UIF if it isn't present in the pipeline. */
+	if (drm_pipe->uif && cfg->crc.source == VSP1_DU_CRC_NONE)
+		vsp1_dl_list_write(dl, drm_pipe->uif->route->reg,
+				   VI6_DPR_NODE_UNUSED);
+
 	/* Configure all entities in the pipeline. */
 	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
 		/* Disconnect unused RPFs from the pipeline. */
@@ -672,6 +766,17 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
 		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
 		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
+
+		/*
+		 * CRC computation is initially disabled, don't add the UIF to
+		 * the pipeline.
+		 */
+		if (i < vsp1->info->uif_count) {
+			drm_pipe->uif = &vsp1->uif[i]->entity;
+			drm_pipe->uif->sink = &pipe->output->entity;
+			drm_pipe->uif->sink_pad = 0;
+			INIT_LIST_HEAD(&drm_pipe->uif->list_pipe);
+		}
 	}
 
 	/* Disable all RPFs initially. */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index c6515272da7d..aa07c54e6d9f 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -15,12 +15,17 @@
 
 #include <linux/videodev2.h>
 
+#include <media/vsp1.h>
+
 #include "vsp1_pipe.h"
 
 /**
  * vsp1_drm_pipeline - State for the API exposed to the DRM driver
  * @pipe: the VSP1 pipeline used for display
  * @enabled: pipeline state at the beginning of an update
+ * @uif: UIF entity if available for the pipeline
+ * @crc.source: source for CRC calculation
+ * @crc.index: index of the CRC source plane (when crc.source is set to plane)
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
@@ -28,6 +33,13 @@ struct vsp1_drm_pipeline {
 	struct vsp1_pipeline pipe;
 	bool enabled;
 
+	struct vsp1_entity *uif;
+
+	struct {
+		enum vsp1_du_crc_source source;
+		unsigned int index;
+	} crc;
+
 	/* Frame synchronisation */
 	void (*du_complete)(void *data, bool completed, u32 crc);
 	void *du_private;
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 9/9] drm: rcar-du: Add support for CRC computation
  2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
                   ` (7 preceding siblings ...)
  2017-12-03 10:57 ` [PATCH 8/9] v4l: vsp1: Integrate DISCOM in display pipeline Laurent Pinchart
@ 2017-12-03 10:57 ` Laurent Pinchart
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-03 10:57 UTC (permalink / raw)
  To: linux-media, dri-devel; +Cc: linux-renesas-soc

Implement CRC computation configuration and reporting through the DRM
debugfs-based CRC API. The CRC source can be configured to any input
plane or the pipeline output.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 148 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h |  19 +++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  |   7 ++
 3 files changed, 168 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 5685d5af6998..b65750096090 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -650,6 +650,52 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
 	.atomic_disable = rcar_du_crtc_atomic_disable,
 };
 
+static struct drm_crtc_state *
+rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+	struct rcar_du_crtc_state *state;
+	struct rcar_du_crtc_state *copy;
+
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	state = to_rcar_crtc_state(crtc->state);
+	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+	if (copy == NULL)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &copy->state);
+
+	return &copy->state;
+}
+
+static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+					      struct drm_crtc_state *state)
+{
+	__drm_atomic_helper_crtc_destroy_state(state);
+	kfree(to_rcar_crtc_state(state));
+}
+
+static void rcar_du_crtc_reset(struct drm_crtc *crtc)
+{
+	struct rcar_du_crtc_state *state;
+
+	if (crtc->state) {
+		rcar_du_crtc_atomic_destroy_state(crtc, crtc->state);
+		crtc->state = NULL;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state == NULL)
+		return;
+
+	state->crc.source = VSP1_DU_CRC_NONE;
+	state->crc.index = 0;
+
+	crtc->state = &state->state;
+	crtc->state->crtc = crtc;
+}
+
 static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
 {
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -669,15 +715,103 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc)
 	rcrtc->vblank_enable = false;
 }
 
-static const struct drm_crtc_funcs crtc_funcs = {
-	.reset = drm_atomic_helper_crtc_reset,
+static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
+				       const char *source_name,
+				       size_t *values_cnt)
+{
+	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_crtc_state *crtc_state;
+	struct drm_atomic_state *state;
+	enum vsp1_du_crc_source source;
+	unsigned int index;
+	int ret;
+
+	/*
+	 * Parse the source name. Supported values are "plane%u" to compute the
+	 * CRC on an input plane (%u is the plane index), and "auto" to compute
+	 * the CRC on the composer (VSP) output.
+	 */
+	if (!source_name) {
+		source = VSP1_DU_CRC_NONE;
+	} else if (!strcmp(source_name, "auto")) {
+		source = VSP1_DU_CRC_OUTPUT;
+	} else if (strstarts(source_name, "plane")) {
+		source = VSP1_DU_CRC_PLANE;
+
+		ret = kstrtouint(source_name + strlen("plane"), 10, &index);
+		if (ret < 0)
+			return ret;
+
+		if (index >= rcrtc->vsp->num_planes)
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	*values_cnt = 1;
+
+	/* Perform an atomic commit to set the CRC source. */
+	drm_modeset_acquire_init(&ctx, 0);
+
+	state = drm_atomic_state_alloc(crtc->dev);
+	if (!state) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	state->acquire_ctx = &ctx;
+
+retry:
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (!IS_ERR(crtc_state)) {
+		struct rcar_du_crtc_state *rcrtc_state;
+
+		rcrtc_state = to_rcar_crtc_state(crtc_state);
+		rcrtc_state->crc.source = source;
+		rcrtc_state->crc.index = index;
+
+		ret = drm_atomic_commit(state);
+	} else {
+		ret = PTR_ERR(crtc_state);
+	}
+
+	if (ret == -EDEADLK) {
+		drm_atomic_state_clear(state);
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+
+	drm_atomic_state_put(state);
+
+unlock:
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return 0;
+}
+
+static const struct drm_crtc_funcs crtc_funcs_gen2 = {
+	.reset = rcar_du_crtc_reset,
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
+	.atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
+	.enable_vblank = rcar_du_crtc_enable_vblank,
+	.disable_vblank = rcar_du_crtc_disable_vblank,
+};
+
+static const struct drm_crtc_funcs crtc_funcs_gen3 = {
+	.reset = rcar_du_crtc_reset,
 	.destroy = drm_crtc_cleanup,
 	.set_config = drm_atomic_helper_set_config,
 	.page_flip = drm_atomic_helper_page_flip,
-	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
+	.atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
 	.enable_vblank = rcar_du_crtc_enable_vblank,
 	.disable_vblank = rcar_du_crtc_disable_vblank,
+	.set_crc_source = rcar_du_crtc_set_crc_source,
 };
 
 /* -----------------------------------------------------------------------------
@@ -780,8 +914,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	else
 		primary = &rgrp->planes[index % 2].plane;
 
-	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
-					NULL, &crtc_funcs, NULL);
+	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, NULL,
+					rcdu->info->gen <= 2 ?
+					&crtc_funcs_gen2 : &crtc_funcs_gen3,
+					NULL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index fdc2bf99bda1..518ee2c60eb8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -21,6 +21,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 
+#include <media/vsp1.h>
+
 struct rcar_du_group;
 struct rcar_du_vsp;
 
@@ -69,6 +71,23 @@ struct rcar_du_crtc {
 
 #define to_rcar_crtc(c)	container_of(c, struct rcar_du_crtc, crtc)
 
+/**
+ * struct rcar_du_crtc_state - Driver-specific CRTC state
+ * @state: base DRM CRTC state
+ * @crc.source: source for CRC calculation
+ * @crc.index: index of the CRC source plane (when crc.source is set to plane)
+ */
+struct rcar_du_crtc_state {
+	struct drm_crtc_state state;
+
+	struct {
+		enum vsp1_du_crc_source source;
+		unsigned int index;
+	} crc;
+};
+
+#define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
+
 enum rcar_du_output {
 	RCAR_DU_OUTPUT_DPAD0,
 	RCAR_DU_OUTPUT_DPAD1,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index bdcec201591f..ce19b883ad16 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -40,6 +40,8 @@ static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
 
 	if (completed)
 		rcar_du_crtc_finish_page_flip(crtc);
+
+	drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc);
 }
 
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
@@ -103,6 +105,11 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
 void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
 {
 	struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
+	struct rcar_du_crtc_state *state;
+
+	state = to_rcar_crtc_state(crtc->crtc.state);
+	cfg.crc.source = state->crc.source;
+	cfg.crc.index = state->crc.index;
 
 	vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
 }
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure
  2017-12-03 10:57 ` [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure Laurent Pinchart
@ 2017-12-04  9:31   ` Sergei Shtylyov
  2017-12-04 11:14     ` Laurent Pinchart
  0 siblings, 1 reply; 14+ messages in thread
From: Sergei Shtylyov @ 2017-12-04  9:31 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media, dri-devel; +Cc: linux-renesas-soc

Hello!

On 12/3/2017 1:57 PM, Laurent Pinchart wrote:

> The structure is used in the API that the VSP1 driver exposes to the DU
> driver. Documenting it is thus important.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>   include/media/vsp1.h | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/include/media/vsp1.h b/include/media/vsp1.h
> index 68a8abe4fac5..7850f96fb708 100644
> --- a/include/media/vsp1.h
> +++ b/include/media/vsp1.h
> @@ -41,6 +41,16 @@ struct vsp1_du_lif_config {
>   int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>   		      const struct vsp1_du_lif_config *cfg);
>   
> +/**
> + * struct vsp1_du_atomic_config - VSP atomic configuration parameters
> + * @pixelformat: plan pixel format (V4L2 4CC)

    s/plan/plane/?

[...]

MBR, Sergei

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure
  2017-12-04  9:31   ` Sergei Shtylyov
@ 2017-12-04 11:14     ` Laurent Pinchart
  0 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2017-12-04 11:14 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-media, dri-devel, linux-renesas-soc

Hi Sergei,

On Monday, 4 December 2017 11:31:49 EET Sergei Shtylyov wrote:
> On 12/3/2017 1:57 PM, Laurent Pinchart wrote:
> > The structure is used in the API that the VSP1 driver exposes to the DU
> > driver. Documenting it is thus important.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >   include/media/vsp1.h | 10 ++++++++++
> >   1 file changed, 10 insertions(+)
> > 
> > diff --git a/include/media/vsp1.h b/include/media/vsp1.h
> > index 68a8abe4fac5..7850f96fb708 100644
> > --- a/include/media/vsp1.h
> > +++ b/include/media/vsp1.h
> > @@ -41,6 +41,16 @@ struct vsp1_du_lif_config {
> >   int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
> >   		      const struct vsp1_du_lif_config *cfg);
> > 
> > +/**
> > + * struct vsp1_du_atomic_config - VSP atomic configuration parameters
> > + * @pixelformat: plan pixel format (V4L2 4CC)
> 
>     s/plan/plane/?

Of course, my bad. This will be fixed in v2. Thank you for catching the typo.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs
  2017-12-03 10:57 ` [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs Laurent Pinchart
@ 2017-12-15 10:11   ` Kieran Bingham
  0 siblings, 0 replies; 14+ messages in thread
From: Kieran Bingham @ 2017-12-15 10:11 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media, dri-devel; +Cc: linux-renesas-soc

Hi Laurent,

As this is a prevents hardware hangs, and is a distinct patch on it's own - I
feel it should be on an accelerated path to integration, and should be merged
separately from the rest of the CRC feature series.

On 03/12/17 10:57, Laurent Pinchart wrote:
> Make sure we don't accept more inputs than the hardware can handle. This
> is a temporary fix to avoid display stall, we need to instead allocate
> the BRU or BRS to display pipelines dynamically based on the number of
> planes they each use.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 7ce69f23f50a..ac85942162c1 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -530,6 +530,15 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  		struct vsp1_rwpf *rpf = vsp1->rpf[i];
>  		unsigned int j;
>  
> +		/*
> +		 * Make sure we don't accept more inputs than the hardware can
> +		 * handle. This is a temporary fix to avoid display stall, we
> +		 * need to instead allocate the BRU or BRS to display pipelines
> +		 * dynamically based on the number of planes they each use.
> +		 */
> +		if (pipe->num_inputs >= pipe->bru->source_pad)
> +			pipe->inputs[i] = NULL;
> +
>  		if (!pipe->inputs[i])
>  			continue;
>  
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages
  2017-12-03 10:57 ` [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages Laurent Pinchart
@ 2017-12-15 10:13   ` Kieran Bingham
  0 siblings, 0 replies; 14+ messages in thread
From: Kieran Bingham @ 2017-12-15 10:13 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media, dri-devel; +Cc: linux-renesas-soc

Hi Laurent,

On 03/12/17 10:57, Laurent Pinchart wrote:
> The DRM pipelines can use either the BRU or the BRS for blending. Make
> sure the right name is used in debugging messages to avoid confusion.

This could likely tag along with the preceding [PATCH 1/9] on it's short cut to
mainline before the rest of the CRC series is reviewed.

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index ac85942162c1..0fe541084f5c 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -400,8 +400,11 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
>  	struct v4l2_subdev_selection sel;
>  	struct v4l2_subdev_format format;
>  	const struct v4l2_rect *crop;
> +	const char *bru_name;
>  	int ret;
>  
> +	bru_name = pipe->bru->type == VSP1_ENTITY_BRU ? "BRU" : "BRS";
> +
>  	/*
>  	 * Configure the format on the RPF sink pad and propagate it up to the
>  	 * BRU sink pad.
> @@ -473,9 +476,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
>  	if (ret < 0)
>  		return ret;
>  
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n",
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
>  		__func__, format.format.width, format.format.height,
> -		format.format.code, format.pad);
> +		format.format.code, bru_name, format.pad);
>  
>  	sel.pad = bru_input;
>  	sel.target = V4L2_SEL_TGT_COMPOSE;
> @@ -486,10 +489,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
>  	if (ret < 0)
>  		return ret;
>  
> -	dev_dbg(vsp1->dev,
> -		"%s: set selection (%u,%u)/%ux%u on BRU pad %u\n",
> +	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
>  		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> -		sel.pad);
> +		bru_name, sel.pad);
>  
>  	return 0;
>  }
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-12-15 10:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-03 10:57 [PATCH 0/9] R-Car DU: Support CRC calculation Laurent Pinchart
2017-12-03 10:57 ` [PATCH 1/9] v4l: vsp1: Fix display stalls when requesting too many inputs Laurent Pinchart
2017-12-15 10:11   ` Kieran Bingham
2017-12-03 10:57 ` [PATCH 2/9] v4l: vsp1: Print the correct blending unit name in debug messages Laurent Pinchart
2017-12-15 10:13   ` Kieran Bingham
2017-12-03 10:57 ` [PATCH 3/9] v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code Laurent Pinchart
2017-12-03 10:57 ` [PATCH 4/9] v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper Laurent Pinchart
2017-12-03 10:57 ` [PATCH 5/9] v4l: vsp1: Document the vsp1_du_atomic_config structure Laurent Pinchart
2017-12-04  9:31   ` Sergei Shtylyov
2017-12-04 11:14     ` Laurent Pinchart
2017-12-03 10:57 ` [PATCH 6/9] v4l: vsp1: Extend the DU API to support CRC computation Laurent Pinchart
2017-12-03 10:57 ` [PATCH 7/9] v4l: vsp1: Add support for the DISCOM entity Laurent Pinchart
2017-12-03 10:57 ` [PATCH 8/9] v4l: vsp1: Integrate DISCOM in display pipeline Laurent Pinchart
2017-12-03 10:57 ` [PATCH 9/9] drm: rcar-du: Add support for CRC computation Laurent Pinchart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).