All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/20] OMAP DRM fixes and improvements
@ 2016-06-06 23:42 Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
                   ` (19 more replies)
  0 siblings, 20 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Hello,

Here's the second version of my current stack of pending patches for the
omapdrm driver.

All comments received for v1 have been taken into account. Changes since v1
include

- Rebase on top to Tomi's 4.8/omapdrm branch and drop already merged patches
  (git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git)
- Drop "drm: omapdrm: Remove buffer synchronization support" (23/23)
- Replace "drm: omapdrm: fb: Don't store format BPP for each plane" (02/23)
  and "drm: omapdrm: fb: Store number of planes in format structure" (03/23)
  with "drm: omapdrm: fb: Use format information provided by the DRM core"
  (02/20)

Individual changelogs are available in the patches.

The most notable change in this series is still the rework of the IRQ handling
code (patches 06/20 to 19/20) that, beside simplifying the code, ensures that
the vblank count and timestamp get updated properly in order to be reported to
userspace.

The series is now based on top of the "[PATCH 0/4] Centralize format
information" series I have just sent to the dri-devel mailing list.

Laurent Pinchart (20):
  drm: omapdrm: fb: Limit number of planes per framebuffer to two
  drm: omapdrm: fb: Use format information provided by the DRM core
  drm: omapdrm: fb: Simplify objects lookup when creating framebuffer
  drm: omapdrm: fb: Simplify mode command checks when creating
    framebuffer
  drm: omapdrm: fb: Turn framebuffer creation error messages into debug
  drm: omapdrm: Handle FIFO underflow IRQs internally
  drm: omapdrm: Handle CRTC error IRQs directly
  drm: omapdrm: Handle OCP error IRQ directly
  drm: omapdrm: Use atomic state instead of local device state
  drm: omapdrm: Only commit planes on active CRTCs
  drm: omapdrm: Check DSS manager state in the enable/disable helpers
  drm: omapdrm: Prevent processing the same event multiple times
  drm: omapdrm: Use a spinlock to protect the CRTC pending flag
  drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  drm: omapdrm: Don't expose the omap_irq_(un)register() functions
  drm: omapdrm: Remove unused parameter from omap_drm_irq handler
  drm: omapdrm: Don't call DISPC power handling in IRQ wait functions
  drm: omapdrm: Make pipe2vbl function static
  drm: omapdrm: Simplify IRQ wait implementation
  drm: omapdrm: Remove global variables

 drivers/gpu/drm/omapdrm/dss/dispc.c  |   1 -
 drivers/gpu/drm/omapdrm/dss/output.c |   6 +
 drivers/gpu/drm/omapdrm/omap_crtc.c  | 121 ++++++++++--------
 drivers/gpu/drm/omapdrm/omap_drv.c   |   6 +-
 drivers/gpu/drm/omapdrm/omap_drv.h   |  51 +-------
 drivers/gpu/drm/omapdrm/omap_fb.c    | 170 ++++++++++++------------
 drivers/gpu/drm/omapdrm/omap_irq.c   | 242 +++++++++++++++++++----------------
 drivers/gpu/drm/omapdrm/omap_plane.c |  24 ----
 8 files changed, 305 insertions(+), 316 deletions(-)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-10 11:58   ` Tomi Valkeinen
  2016-06-06 23:42 ` [PATCH v2 02/20] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The only multi-planar format supported by the driver is NV12, there will
thus never be more than two planes per framebuffer.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 530567cc25b7..4214138d5795 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -36,7 +36,7 @@ struct format {
 	struct {
 		int stride_bpp;           /* this times width is stride */
 		int sub_y;                /* sub-sample in y dimension */
-	} planes[4];
+	} planes[2];
 	bool yuv;
 };
 
@@ -90,7 +90,7 @@ struct omap_framebuffer {
 	struct drm_framebuffer base;
 	int pin_count;
 	const struct format *format;
-	struct plane planes[4];
+	struct plane planes[2];
 	/* lock for pinning (pin_count and planes.paddr) */
 	struct mutex lock;
 };
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 02/20] drm: omapdrm: fb: Use format information provided by the DRM core
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 03/20] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The driver stores in a custom structure named format several pieces of
information about the format that are available in the DRM core. Remove
them and get the information from the DRM core instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 91 ++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 4214138d5795..d87caf3f8a8f 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -29,37 +29,30 @@
  * framebuffer funcs
  */
 
-/* per-format info: */
-struct format {
+/* DSS to DRM formats mapping */
+static const struct {
 	enum omap_color_mode dss_format;
 	uint32_t pixel_format;
-	struct {
-		int stride_bpp;           /* this times width is stride */
-		int sub_y;                /* sub-sample in y dimension */
-	} planes[2];
-	bool yuv;
-};
-
-static const struct format formats[] = {
+} formats[] = {
 	/* 16bpp [A]RGB: */
-	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565,   {{2, 1}}, false }, /* RGB16-565 */
-	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */
-	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */
-	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */
-	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */
-	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */
-	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */
+	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565 },   /* RGB16-565 */
+	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444 }, /* RGB12x-4444 */
+	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444 }, /* xRGB12-4444 */
+	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444 }, /* RGBA12-4444 */
+	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444 }, /* ARGB16-4444 */
+	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555 }, /* xRGB15-1555 */
+	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555 }, /* ARGB16-1555 */
 	/* 24bpp RGB: */
-	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888,   {{3, 1}}, false }, /* RGB24-888 */
+	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888 },   /* RGB24-888 */
 	/* 32bpp [A]RGB: */
-	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */
-	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */
-	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */
-	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */
+	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888 }, /* RGBx24-8888 */
+	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888 }, /* xRGB24-8888 */
+	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888 }, /* RGBA32-8888 */
+	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888 }, /* ARGB32-8888 */
 	/* YUV: */
-	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12,     {{1, 1}, {1, 2}}, true },
-	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV,     {{2, 1}}, true },
-	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     {{2, 1}}, true },
+	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12 },
+	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV },
+	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY },
 };
 
 /* convert from overlay's pixel formats bitmask to an array of fourcc's */
@@ -89,7 +82,8 @@ struct plane {
 struct omap_framebuffer {
 	struct drm_framebuffer base;
 	int pin_count;
-	const struct format *format;
+	const struct drm_format_info *format;
+	enum omap_color_mode dss_format;
 	struct plane planes[2];
 	/* lock for pinning (pin_count and planes.paddr) */
 	struct mutex lock;
@@ -136,13 +130,13 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
 };
 
 static uint32_t get_linear_addr(struct plane *plane,
-		const struct format *format, int n, int x, int y)
+		const struct drm_format_info *format, int n, int x, int y)
 {
 	uint32_t offset;
 
-	offset = plane->offset +
-			(x * format->planes[n].stride_bpp) +
-			(y * plane->pitch / format->planes[n].sub_y);
+	offset = plane->offset
+	       + (x * format->cpp[n] / (n == 1 ? 1 : format->hsub))
+	       + (y * plane->pitch / (n == 1 ? 1 : format->vsub));
 
 	return plane->paddr + offset;
 }
@@ -161,11 +155,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 		struct omap_drm_window *win, struct omap_overlay_info *info)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	const struct format *format = omap_fb->format;
+	const struct drm_format_info *format = omap_fb->format;
 	struct plane *plane = &omap_fb->planes[0];
 	uint32_t x, y, orient = 0;
 
-	info->color_mode = format->dss_format;
+	info->color_mode = omap_fb->dss_format;
 
 	info->pos_x      = win->crtc_x;
 	info->pos_y      = win->crtc_y;
@@ -239,9 +233,9 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 	}
 
 	/* convert to pixels: */
-	info->screen_width /= format->planes[0].stride_bpp;
+	info->screen_width /= format->cpp[0];
 
-	if (format->dss_format == OMAP_DSS_COLOR_NV12) {
+	if (omap_fb->dss_format == OMAP_DSS_COLOR_NV12) {
 		plane = &omap_fb->planes[1];
 
 		if (info->rotation_type == OMAP_DSS_ROT_TILER) {
@@ -390,23 +384,26 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
 {
+	const struct drm_format_info *format = NULL;
 	struct omap_framebuffer *omap_fb = NULL;
 	struct drm_framebuffer *fb = NULL;
-	const struct format *format = NULL;
-	int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
+	enum omap_color_mode dss_format = 0;
+	int ret, i;
 
 	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
 			dev, mode_cmd, mode_cmd->width, mode_cmd->height,
 			(char *)&mode_cmd->pixel_format);
 
+	format = drm_format_info(mode_cmd->pixel_format);
+
 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
 		if (formats[i].pixel_format == mode_cmd->pixel_format) {
-			format = &formats[i];
+			dss_format = formats[i].dss_format;
 			break;
 		}
 	}
 
-	if (!format) {
+	if (!format || !dss_format) {
 		dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
 				(char *)&mode_cmd->pixel_format);
 		ret = -EINVAL;
@@ -421,28 +418,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 
 	fb = &omap_fb->base;
 	omap_fb->format = format;
+	omap_fb->dss_format = dss_format;
 	mutex_init(&omap_fb->lock);
 
-	for (i = 0; i < n; i++) {
+	for (i = 0; i < format->num_planes; i++) {
 		struct plane *plane = &omap_fb->planes[i];
-		int size, pitch = mode_cmd->pitches[i];
+		unsigned int pitch = mode_cmd->pitches[i];
+		unsigned int hsub = i == 0 ? 1 : format->hsub;
+		unsigned int vsub = i == 0 ? 1 : format->vsub;
+		unsigned int size;
 
-		if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
+		if (pitch < mode_cmd->width * format->cpp[i] / hsub) {
 			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
-					pitch, mode_cmd->width * format->planes[i].stride_bpp);
+				pitch, mode_cmd->width * format->cpp[i] / hsub);
 			ret = -EINVAL;
 			goto fail;
 		}
 
-		if (pitch % format->planes[i].stride_bpp != 0) {
+		if (pitch % format->cpp[i] != 0) {
 			dev_err(dev->dev,
 				"buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n",
-				pitch, format->planes[i].stride_bpp);
+				pitch, format->cpp[i]);
 			ret = -EINVAL;
 			goto fail;
 		}
 
-		size = pitch * mode_cmd->height / format->planes[i].sub_y;
+		size = pitch * mode_cmd->height / vsub;
 
 		if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
 			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 03/20] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 02/20] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 04/20] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Merge the single-user objects_lookup inline function into its caller,
allowing reuse of the error code path.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 25 -------------------------
 drivers/gpu/drm/omapdrm/omap_fb.c  | 29 ++++++++++++++++++-----------
 2 files changed, 18 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 51dbb820ff1d..799f26b0573a 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -241,29 +241,4 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 uint32_t pipe2vbl(struct drm_crtc *crtc);
 struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
 
-/* should these be made into common util helpers?
- */
-
-static inline int objects_lookup(
-		struct drm_file *filp, uint32_t pixel_format,
-		struct drm_gem_object **bos, const uint32_t *handles)
-{
-	int i, n = drm_format_num_planes(pixel_format);
-
-	for (i = 0; i < n; i++) {
-		bos[i] = drm_gem_object_lookup(filp, handles[i]);
-		if (!bos[i])
-			goto fail;
-
-	}
-
-	return 0;
-
-fail:
-	while (--i > 0)
-		drm_gem_object_unreference_unlocked(bos[i]);
-
-	return -ENOENT;
-}
-
 #endif /* __OMAP_DRV_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index d87caf3f8a8f..dc30a7501fe0 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -362,22 +362,29 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 		struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
 {
+	unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format);
 	struct drm_gem_object *bos[4];
 	struct drm_framebuffer *fb;
-	int ret;
+	int i;
 
-	ret = objects_lookup(file, mode_cmd->pixel_format,
-			bos, mode_cmd->handles);
-	if (ret)
-		return ERR_PTR(ret);
+	for (i = 0; i < num_planes; i++) {
+		bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
+		if (!bos[i]) {
+			fb = ERR_PTR(-ENOENT);
+			goto error;
+		}
+	}
 
 	fb = omap_framebuffer_init(dev, mode_cmd, bos);
-	if (IS_ERR(fb)) {
-		int i, n = drm_format_num_planes(mode_cmd->pixel_format);
-		for (i = 0; i < n; i++)
-			drm_gem_object_unreference_unlocked(bos[i]);
-		return fb;
-	}
+	if (IS_ERR(fb))
+		goto error;
+
+	return fb;
+
+error:
+	while (--i > 0)
+		drm_gem_object_unreference_unlocked(bos[i]);
+
 	return fb;
 }
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 04/20] drm: omapdrm: fb: Simplify mode command checks when creating framebuffer
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (2 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 03/20] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 05/20] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The hardware requires all planes to have an identical pitch in number of
pixels. Given that all supported formats use the same number of bytes
per pixel in all planes, framebuffer creation checks can be simplified.
The implementations assumes that no format use more than two planes
which is true with the existing hardware.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Clarify commit message and mention explicitly in the code that only
  one and two planes formats are supported.
- Rebase on top of the switch to drm_format_info()
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 58 +++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index dc30a7501fe0..3eca8c36ee92 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -395,6 +395,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	struct omap_framebuffer *omap_fb = NULL;
 	struct drm_framebuffer *fb = NULL;
 	enum omap_color_mode dss_format = 0;
+	unsigned int pitch = mode_cmd->pitches[0];
 	int ret, i;
 
 	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
@@ -428,41 +429,44 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	omap_fb->dss_format = dss_format;
 	mutex_init(&omap_fb->lock);
 
+	/*
+	 * The code below assumes that no format use more than two planes, and
+	 * that the two planes of multiplane formats need the same number of
+	 * bytes per pixel.
+	 */
+	if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
+		dev_err(dev->dev, "pitches differ between planes 0 and 1\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (pitch < mode_cmd->width * format->cpp[0]) {
+		dev_err(dev->dev,
+			"provided buffer pitch is too small! %u < %u\n",
+			pitch, mode_cmd->width * format->cpp[0]);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (pitch % format->cpp[0]) {
+		dev_err(dev->dev,
+			"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n",
+			pitch, format->cpp[0]);
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	for (i = 0; i < format->num_planes; i++) {
 		struct plane *plane = &omap_fb->planes[i];
-		unsigned int pitch = mode_cmd->pitches[i];
-		unsigned int hsub = i == 0 ? 1 : format->hsub;
 		unsigned int vsub = i == 0 ? 1 : format->vsub;
 		unsigned int size;
 
-		if (pitch < mode_cmd->width * format->cpp[i] / hsub) {
-			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
-				pitch, mode_cmd->width * format->cpp[i] / hsub);
-			ret = -EINVAL;
-			goto fail;
-		}
-
-		if (pitch % format->cpp[i] != 0) {
-			dev_err(dev->dev,
-				"buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n",
-				pitch, format->cpp[i]);
-			ret = -EINVAL;
-			goto fail;
-		}
-
 		size = pitch * mode_cmd->height / vsub;
 
-		if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
-			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
-					bos[i]->size - mode_cmd->offsets[i], size);
-			ret = -EINVAL;
-			goto fail;
-		}
-
-		if (i > 0 && pitch != mode_cmd->pitches[i - 1]) {
+		if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) {
 			dev_err(dev->dev,
-				"pitches are not the same between framebuffer planes %d != %d\n",
-				pitch, mode_cmd->pitches[i - 1]);
+				"provided buffer object is too small! %d < %d\n",
+				bos[i]->size - mode_cmd->offsets[i], size);
 			ret = -EINVAL;
 			goto fail;
 		}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 05/20] drm: omapdrm: fb: Turn framebuffer creation error messages into debug
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (3 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 04/20] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 06/20] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Don't print userspace parameters validation failures as error messages
to avoid giving userspace the ability to flood the kernel log.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 3eca8c36ee92..bc0fb805696e 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -412,8 +412,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	}
 
 	if (!format || !dss_format) {
-		dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
-				(char *)&mode_cmd->pixel_format);
+		dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n",
+			(char *)&mode_cmd->pixel_format);
 		ret = -EINVAL;
 		goto fail;
 	}
@@ -435,13 +435,13 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	 * bytes per pixel.
 	 */
 	if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) {
-		dev_err(dev->dev, "pitches differ between planes 0 and 1\n");
+		dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n");
 		ret = -EINVAL;
 		goto fail;
 	}
 
 	if (pitch < mode_cmd->width * format->cpp[0]) {
-		dev_err(dev->dev,
+		dev_dbg(dev->dev,
 			"provided buffer pitch is too small! %u < %u\n",
 			pitch, mode_cmd->width * format->cpp[0]);
 		ret = -EINVAL;
@@ -449,7 +449,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	}
 
 	if (pitch % format->cpp[0]) {
-		dev_err(dev->dev,
+		dev_dbg(dev->dev,
 			"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n",
 			pitch, format->cpp[0]);
 		ret = -EINVAL;
@@ -464,7 +464,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		size = pitch * mode_cmd->height / vsub;
 
 		if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) {
-			dev_err(dev->dev,
+			dev_dbg(dev->dev,
 				"provided buffer object is too small! %d < %d\n",
 				bos[i]->size - mode_cmd->offsets[i], size);
 			ret = -EINVAL;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 06/20] drm: omapdrm: Handle FIFO underflow IRQs internally
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (4 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 05/20] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 07/20] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

As the FIFO underflow IRQ handler just prints an error message to the
kernel log, simplify the code by not registering one IRQ handler per
plane but print the messages directly from the main IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Only register error IRQs that exist on the HW
---
 drivers/gpu/drm/omapdrm/omap_drv.c   |  4 +--
 drivers/gpu/drm/omapdrm/omap_drv.h   |  2 +-
 drivers/gpu/drm/omapdrm/omap_irq.c   | 66 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/omapdrm/omap_plane.c | 24 -------------
 4 files changed, 66 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 6c0647486945..65f280f5d947 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -322,8 +322,6 @@ static int omap_modeset_init(struct drm_device *dev)
 
 	drm_mode_config_init(dev);
 
-	omap_drm_irq_install(dev);
-
 	ret = omap_modeset_init_properties(dev);
 	if (ret < 0)
 		return ret;
@@ -492,6 +490,8 @@ static int omap_modeset_init(struct drm_device *dev)
 
 	drm_mode_config_reset(dev);
 
+	omap_drm_irq_install(dev);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 799f26b0573a..edd8518b8ad4 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -103,7 +103,7 @@ struct omap_drm_private {
 
 	/* irq handling: */
 	struct list_head irq_list;    /* list of omap_drm_irq */
-	uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
 	struct omap_drm_irq error_handler;
 
 	/* atomic commit */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 60e1e8016708..245263b09759 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -32,7 +32,7 @@ static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *irq;
-	uint32_t irqmask = priv->vblank_mask;
+	uint32_t irqmask = priv->irq_mask;
 
 	assert_spin_locked(&list_lock);
 
@@ -153,7 +153,7 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->vblank_mask |= pipe2vbl(crtc);
+	priv->irq_mask |= pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -178,11 +178,52 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
 	spin_lock_irqsave(&list_lock, flags);
-	priv->vblank_mask &= ~pipe2vbl(crtc);
+	priv->irq_mask &= ~pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
 }
 
+static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
+				    u32 irqstatus)
+{
+	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
+				      DEFAULT_RATELIMIT_BURST);
+	static const struct {
+		const char *name;
+		u32 mask;
+	} sources[] = {
+		{ "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
+		{ "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
+		{ "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
+		{ "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
+	};
+
+	const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID1_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID2_FIFO_UNDERFLOW
+		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+	unsigned int i;
+
+	spin_lock(&list_lock);
+	irqstatus &= priv->irq_mask & mask;
+	spin_unlock(&list_lock);
+
+	if (!irqstatus)
+		return;
+
+	if (!__ratelimit(&_rs))
+		return;
+
+	drm_err("error: FIFO underflow on ");
+
+	for (i = 0; i < ARRAY_SIZE(sources); ++i) {
+		if (sources[i].mask & irqstatus)
+			pr_cont("%s ", sources[i].name);
+	}
+
+	pr_cont("(0x%08x)\n", irqstatus);
+}
+
 static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -205,6 +246,8 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 			drm_handle_vblank(dev, id);
 	}
 
+	omap_irq_fifo_underflow(priv, irqstatus);
+
 	spin_lock_irqsave(&list_lock, flags);
 	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
 		if (handler->irqmask & irqstatus) {
@@ -218,6 +261,13 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+static const u32 error_irqs[] = {
+	[OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+	[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+};
+
 /*
  * We need a special version, instead of just using drm_irq_install(),
  * because we need to register the irq via omapdss.  Once omapdss and
@@ -229,10 +279,20 @@ int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *error_handler = &priv->error_handler;
+	unsigned int max_planes;
+	unsigned int i;
 	int ret;
 
 	INIT_LIST_HEAD(&priv->irq_list);
 
+	priv->irq_mask = 0;
+
+	max_planes = min(ARRAY_SIZE(priv->planes), ARRAY_SIZE(error_irqs));
+	for (i = 0; i < max_planes; ++i) {
+		if (priv->planes[i])
+			priv->irq_mask |= error_irqs[i];
+	}
+
 	dispc_runtime_get();
 	dispc_clear_irqstatus(0xffffffff);
 	dispc_runtime_put();
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 5252ab720e70..037bd1f7c70a 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -43,8 +43,6 @@ struct omap_plane {
 
 	uint32_t nformats;
 	uint32_t formats[32];
-
-	struct omap_drm_irq error_irq;
 };
 
 struct omap_plane_state {
@@ -200,8 +198,6 @@ static void omap_plane_destroy(struct drm_plane *plane)
 
 	DBG("%s", omap_plane->name);
 
-	omap_irq_unregister(plane->dev, &omap_plane->error_irq);
-
 	drm_plane_cleanup(plane);
 
 	kfree(omap_plane);
@@ -320,14 +316,6 @@ static const struct drm_plane_funcs omap_plane_funcs = {
 	.atomic_get_property = omap_plane_atomic_get_property,
 };
 
-static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
-	struct omap_plane *omap_plane =
-			container_of(irq, struct omap_plane, error_irq);
-	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_plane->name,
-		irqstatus);
-}
-
 static const char *plane_names[] = {
 	[OMAP_DSS_GFX] = "gfx",
 	[OMAP_DSS_VIDEO1] = "vid1",
@@ -335,13 +323,6 @@ static const char *plane_names[] = {
 	[OMAP_DSS_VIDEO3] = "vid3",
 };
 
-static const uint32_t error_irqs[] = {
-	[OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
-	[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-};
-
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type)
@@ -365,10 +346,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 
 	plane = &omap_plane->base;
 
-	omap_plane->error_irq.irqmask = error_irqs[id];
-	omap_plane->error_irq.irq = omap_plane_error_irq;
-	omap_irq_register(dev, &omap_plane->error_irq);
-
 	ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1,
 				       &omap_plane_funcs, omap_plane->formats,
 				       omap_plane->nformats, type, NULL);
@@ -382,7 +359,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 	return plane;
 
 error:
-	omap_irq_unregister(plane->dev, &omap_plane->error_irq);
 	kfree(omap_plane);
 	return NULL;
 }
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 07/20] drm: omapdrm: Handle CRTC error IRQs directly
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (5 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 06/20] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 08/20] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated registration mechanism, just
expose the CRTC error IRQ function and call it directly from the main
IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 12 ++----------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 drivers/gpu/drm/omapdrm/omap_irq.c  |  8 ++++++++
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 075f2bb44867..6359d7933b93 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -37,7 +37,6 @@ struct omap_crtc {
 	struct omap_video_timings timings;
 
 	struct omap_drm_irq vblank_irq;
-	struct omap_drm_irq error_irq;
 
 	bool ignore_digit_sync_lost;
 
@@ -275,10 +274,9 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 {
-	struct omap_crtc *omap_crtc =
-			container_of(irq, struct omap_crtc, error_irq);
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
 	if (omap_crtc->ignore_digit_sync_lost) {
 		irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
@@ -325,7 +323,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 	DBG("%s", omap_crtc->name);
 
 	WARN_ON(omap_crtc->vblank_irq.registered);
-	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
 
 	drm_crtc_cleanup(crtc);
 
@@ -520,11 +517,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
 	omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
 
-	omap_crtc->error_irq.irqmask =
-			dispc_mgr_get_sync_lost_irq(channel);
-	omap_crtc->error_irq.irq = omap_crtc_error_irq;
-	omap_irq_register(dev, &omap_crtc->error_irq);
-
 	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 					&omap_crtc_funcs, NULL);
 	if (ret < 0) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index edd8518b8ad4..ffc958eea5a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -156,6 +156,7 @@ void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
+void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type);
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 245263b09759..c21ed4afd1ac 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -241,9 +241,13 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 
 	for (id = 0; id < priv->num_crtcs; id++) {
 		struct drm_crtc *crtc = priv->crtcs[id];
+		enum omap_channel channel = omap_crtc_channel(crtc);
 
 		if (irqstatus & pipe2vbl(crtc))
 			drm_handle_vblank(dev, id);
+
+		if (irqstatus & dispc_mgr_get_sync_lost_irq(channel))
+			omap_crtc_error_irq(crtc, irqstatus);
 	}
 
 	omap_irq_fifo_underflow(priv, irqstatus);
@@ -279,6 +283,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_drm_irq *error_handler = &priv->error_handler;
+	unsigned int num_mgrs = dss_feat_get_num_mgrs();
 	unsigned int max_planes;
 	unsigned int i;
 	int ret;
@@ -293,6 +298,9 @@ int omap_drm_irq_install(struct drm_device *dev)
 			priv->irq_mask |= error_irqs[i];
 	}
 
+	for (i = 0; i < num_mgrs; ++i)
+		priv->irq_mask |= dispc_mgr_get_sync_lost_irq(i);
+
 	dispc_runtime_get();
 	dispc_clear_irqstatus(0xffffffff);
 	dispc_runtime_put();
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 08/20] drm: omapdrm: Handle OCP error IRQ directly
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (6 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 07/20] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 09/20] drm: omapdrm: Use atomic state instead of local device state Laurent Pinchart
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated registration mechanism, just
call the OCP error IRQ handler directly from the main IRQ handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Rename IRQ handler to omap_irq_ocp_error_handler()
- Replace hex error value with "OCP error" message
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  1 -
 drivers/gpu/drm/omapdrm/omap_irq.c | 28 ++++++++++------------------
 2 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index ffc958eea5a3..4bbfe0869a48 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -104,7 +104,6 @@ struct omap_drm_private {
 	/* irq handling: */
 	struct list_head irq_list;    /* list of omap_drm_irq */
 	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
-	struct omap_drm_irq error_handler;
 
 	/* atomic commit */
 	struct {
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index c21ed4afd1ac..d0730178888f 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -21,12 +21,6 @@
 
 static DEFINE_SPINLOCK(list_lock);
 
-static void omap_irq_error_handler(struct omap_drm_irq *irq,
-		uint32_t irqstatus)
-{
-	DRM_ERROR("errors: %08x\n", irqstatus);
-}
-
 /* call with list_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
@@ -224,6 +218,14 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
 	pr_cont("(0x%08x)\n", irqstatus);
 }
 
+static void omap_irq_ocp_error_handler(u32 irqstatus)
+{
+	if (!(irqstatus & DISPC_IRQ_OCP_ERR))
+		return;
+
+	DRM_ERROR("OCP error\n");
+}
+
 static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -250,6 +252,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 			omap_crtc_error_irq(crtc, irqstatus);
 	}
 
+	omap_irq_ocp_error_handler(irqstatus);
 	omap_irq_fifo_underflow(priv, irqstatus);
 
 	spin_lock_irqsave(&list_lock, flags);
@@ -282,7 +285,6 @@ static const u32 error_irqs[] = {
 int omap_drm_irq_install(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *error_handler = &priv->error_handler;
 	unsigned int num_mgrs = dss_feat_get_num_mgrs();
 	unsigned int max_planes;
 	unsigned int i;
@@ -290,7 +292,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 
 	INIT_LIST_HEAD(&priv->irq_list);
 
-	priv->irq_mask = 0;
+	priv->irq_mask = DISPC_IRQ_OCP_ERR;
 
 	max_planes = min(ARRAY_SIZE(priv->planes), ARRAY_SIZE(error_irqs));
 	for (i = 0; i < max_planes; ++i) {
@@ -309,16 +311,6 @@ int omap_drm_irq_install(struct drm_device *dev)
 	if (ret < 0)
 		return ret;
 
-	error_handler->irq = omap_irq_error_handler;
-	error_handler->irqmask = DISPC_IRQ_OCP_ERR;
-
-	/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
-	 * we just need to ignore it while enabling tv-out
-	 */
-	error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-
-	omap_irq_register(dev, error_handler);
-
 	dev->irq_enabled = true;
 
 	return 0;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 09/20] drm: omapdrm: Use atomic state instead of local device state
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (7 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 08/20] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 10/20] drm: omapdrm: Only commit planes on active CRTCs Laurent Pinchart
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of conditioning planes update based on the hardware device
state, use the CRTC state stored in the atomic state. This reduces the
dependency from the DRM layer to the DSS layer.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 6359d7933b93..4c56d6a68390 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -381,18 +381,23 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	WARN_ON(omap_crtc->vblank_irq.registered);
 
-	if (dispc_mgr_is_enabled(omap_crtc->channel)) {
+	/*
+	 * Only flush the CRTC if it is currently active. CRTCs that require a
+	 * mode set are disabled prior plane updates and enabled afterwards.
+	 * They are thus not active, regardless of what their state report.
+	 */
+	if (!crtc->state->active || drm_atomic_crtc_needs_modeset(crtc->state))
+		return;
 
-		DBG("%s: GO", omap_crtc->name);
+	DBG("%s: GO", omap_crtc->name);
 
-		rmb();
-		WARN_ON(omap_crtc->pending);
-		omap_crtc->pending = true;
-		wmb();
+	rmb();
+	WARN_ON(omap_crtc->pending);
+	omap_crtc->pending = true;
+	wmb();
 
-		dispc_mgr_go(omap_crtc->channel);
-		omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-	}
+	dispc_mgr_go(omap_crtc->channel);
+	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
 
 static bool omap_crtc_is_plane_prop(struct drm_device *dev,
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 10/20] drm: omapdrm: Only commit planes on active CRTCs
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (8 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 09/20] drm: omapdrm: Use atomic state instead of local device state Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 11/20] drm: omapdrm: Check DSS manager state in the enable/disable helpers Laurent Pinchart
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The DRM core supports skipping plane update for inactive CRTCs for
hardware that don't need it or can't cope with it. That's our case, so
use the DRM core infrastructure instead of reinventing it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 6 ++++--
 drivers/gpu/drm/omapdrm/omap_drv.c  | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 4c56d6a68390..37b5f7096c6e 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -384,9 +384,11 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 	/*
 	 * Only flush the CRTC if it is currently active. CRTCs that require a
 	 * mode set are disabled prior plane updates and enabled afterwards.
-	 * They are thus not active, regardless of what their state report.
+	 * They are thus not active, regardless of what their state report, and
+	 * the DRM core could thus call this function even though the CRTC is
+	 * currently disabled. Do nothing in that case.
 	 */
-	if (!crtc->state->active || drm_atomic_crtc_needs_modeset(crtc->state))
+	if (drm_atomic_crtc_needs_modeset(crtc->state))
 		return;
 
 	DBG("%s: GO", omap_crtc->name);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 65f280f5d947..70c5f24e67f7 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -96,7 +96,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
 	dispc_runtime_get();
 
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state, false);
+	drm_atomic_helper_commit_planes(dev, old_state, true);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
 	omap_atomic_wait_for_completion(dev, old_state);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 11/20] drm: omapdrm: Check DSS manager state in the enable/disable helpers
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (9 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 10/20] drm: omapdrm: Only commit planes on active CRTCs Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 12/20] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The omapdrm DSS manager enable/disable operations check the DSS manager
state to avoid double enabling/disabling. Move that code to the DSS
manager to decrease the dependency of the DRM layer to the DSS layer.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/dispc.c  | 1 -
 drivers/gpu/drm/omapdrm/dss/output.c | 6 ++++++
 drivers/gpu/drm/omapdrm/omap_crtc.c  | 3 ---
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index 7b78da6d51cf..f51f10a2c829 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -2887,7 +2887,6 @@ bool dispc_mgr_is_enabled(enum omap_channel channel)
 {
 	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
-EXPORT_SYMBOL(dispc_mgr_is_enabled);
 
 void dispc_wb_enable(bool enable)
 {
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 829232ad8c81..e6f67d76ec95 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -218,12 +218,18 @@ EXPORT_SYMBOL(dss_mgr_set_lcd_config);
 
 int dss_mgr_enable(enum omap_channel channel)
 {
+	if (dispc_mgr_is_enabled(channel))
+		return 0;
+
 	return dss_mgr_ops->enable(channel);
 }
 EXPORT_SYMBOL(dss_mgr_enable);
 
 void dss_mgr_disable(enum omap_channel channel)
 {
+	if (!dispc_mgr_is_enabled(channel))
+		return;
+
 	dss_mgr_ops->disable(channel);
 }
 EXPORT_SYMBOL(dss_mgr_disable);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 37b5f7096c6e..14fad7777b2c 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -139,9 +139,6 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
 		return;
 	}
 
-	if (dispc_mgr_is_enabled(channel) == enable)
-		return;
-
 	if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
 		/*
 		 * Digit output produces some sync lost interrupts during the
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 12/20] drm: omapdrm: Prevent processing the same event multiple times
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (10 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 11/20] drm: omapdrm: Check DSS manager state in the enable/disable helpers Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 13/20] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The vblank interrupt is disabled after one occurrence, preventing the
atomic update event from being processed twice. However, this also
prevents the software frame counter from being updated correctly that
would require vblank interrupts to be kept enabled while the CRTC is
active.

In preparation for vblank interrupt fixes, make sure that the atomic
update event will be processed once only when the vblank interrupt will
be kept enabled.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 14fad7777b2c..c4877d626577 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -42,6 +42,7 @@ struct omap_crtc {
 
 	bool pending;
 	wait_queue_head_t pending_wait;
+	struct drm_pending_vblank_event *event;
 };
 
 /* -----------------------------------------------------------------------------
@@ -257,11 +258,15 @@ static const struct dss_mgr_ops mgr_ops = {
 
 static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
 {
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 	struct drm_pending_vblank_event *event;
 	struct drm_device *dev = crtc->dev;
 	unsigned long flags;
 
-	event = crtc->state->event;
+	spin_lock_irqsave(&dev->event_lock, flags);
+	event = omap_crtc->event;
+	omap_crtc->event = NULL;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	if (!event)
 		return;
@@ -367,12 +372,23 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
 }
 
 static void omap_crtc_atomic_begin(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *old_crtc_state)
+				   struct drm_crtc_state *old_crtc_state)
 {
+	struct drm_pending_vblank_event *event = crtc->state->event;
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	unsigned long flags;
+
+	if (event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		omap_crtc->event = event;
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
 }
 
 static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *old_crtc_state)
+				   struct drm_crtc_state *old_crtc_state)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 13/20] drm: omapdrm: Use a spinlock to protect the CRTC pending flag
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (11 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 12/20] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 14/20] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The flag will need to be accessed atomically in the vblank interrupt
handler, memory barriers won't be enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index c4877d626577..c83e836dfa29 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -68,6 +68,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
 	return omap_crtc->channel;
 }
 
+static bool omap_crtc_is_pending(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	unsigned long flags;
+	bool pending;
+
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	pending = omap_crtc->pending;
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
+	return pending;
+}
+
 int omap_crtc_wait_pending(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -77,7 +90,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
 	 * a single frame refresh even on slower displays.
 	 */
 	return wait_event_timeout(omap_crtc->pending_wait,
-				  !omap_crtc->pending,
+				  !omap_crtc_is_pending(crtc),
 				  msecs_to_jiffies(250));
 }
 
@@ -294,6 +307,7 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 	struct omap_crtc *omap_crtc =
 			container_of(irq, struct omap_crtc, vblank_irq);
 	struct drm_device *dev = omap_crtc->base.dev;
+	struct drm_crtc *crtc = &omap_crtc->base;
 
 	if (dispc_mgr_go_busy(omap_crtc->channel))
 		return;
@@ -302,10 +316,10 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 
 	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
 
-	rmb();
+	spin_lock(&crtc->dev->event_lock);
 	WARN_ON(!omap_crtc->pending);
 	omap_crtc->pending = false;
-	wmb();
+	spin_unlock(&crtc->dev->event_lock);
 
 	/* wake up userspace */
 	omap_crtc_complete_page_flip(&omap_crtc->base);
@@ -337,10 +351,10 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
-	rmb();
+	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
-	wmb();
+	spin_unlock_irq(&crtc->dev->event_lock);
 
 	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 
@@ -406,10 +420,10 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DBG("%s: GO", omap_crtc->name);
 
-	rmb();
+	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
-	wmb();
+	spin_unlock_irq(&crtc->dev->event_lock);
 
 	dispc_mgr_go(omap_crtc->channel);
 	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 14/20] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (12 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 13/20] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 15/20] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Instead of going through a complicated private IRQ registration
mechanism, handle the vblank interrupt activation with the standard
drm_crtc_vblank_get() and drm_crtc_vblank_put() mechanism. This will let
the DRM core keep the vblank interrupt enabled as long as needed to
update the frame counter.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 38 ++++++++++++++-----------------------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 drivers/gpu/drm/omapdrm/omap_irq.c  |  4 +++-
 3 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index c83e836dfa29..a2587fd403a0 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -36,8 +36,6 @@ struct omap_crtc {
 
 	struct omap_video_timings timings;
 
-	struct omap_drm_irq vblank_irq;
-
 	bool ignore_digit_sync_lost;
 
 	bool pending;
@@ -302,25 +300,24 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus)
 	DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
 }
 
-static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+void omap_crtc_vblank_irq(struct drm_crtc *crtc)
 {
-	struct omap_crtc *omap_crtc =
-			container_of(irq, struct omap_crtc, vblank_irq);
-	struct drm_device *dev = omap_crtc->base.dev;
-	struct drm_crtc *crtc = &omap_crtc->base;
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	bool pending;
 
 	if (dispc_mgr_go_busy(omap_crtc->channel))
 		return;
 
 	DBG("%s: apply done", omap_crtc->name);
 
-	__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
-
 	spin_lock(&crtc->dev->event_lock);
-	WARN_ON(!omap_crtc->pending);
+	pending = omap_crtc->pending;
 	omap_crtc->pending = false;
 	spin_unlock(&crtc->dev->event_lock);
 
+	if (pending)
+		drm_crtc_vblank_put(crtc);
+
 	/* wake up userspace */
 	omap_crtc_complete_page_flip(&omap_crtc->base);
 
@@ -338,8 +335,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
-	WARN_ON(omap_crtc->vblank_irq.registered);
-
 	drm_crtc_cleanup(crtc);
 
 	kfree(omap_crtc);
@@ -351,14 +346,13 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
 
 	DBG("%s", omap_crtc->name);
 
+	drm_crtc_vblank_on(crtc);
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
-
-	drm_crtc_vblank_on(crtc);
 }
 
 static void omap_crtc_disable(struct drm_crtc *crtc)
@@ -406,8 +400,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
-	WARN_ON(omap_crtc->vblank_irq.registered);
-
 	/*
 	 * Only flush the CRTC if it is currently active. CRTCs that require a
 	 * mode set are disabled prior plane updates and enabled afterwards.
@@ -420,13 +412,14 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DBG("%s: GO", omap_crtc->name);
 
+	dispc_mgr_go(omap_crtc->channel);
+
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	WARN_ON(omap_crtc->pending);
 	omap_crtc->pending = true;
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	dispc_mgr_go(omap_crtc->channel);
-	omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
 }
 
 static bool omap_crtc_is_plane_prop(struct drm_device *dev,
@@ -548,9 +541,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	omap_crtc->channel = channel;
 	omap_crtc->name = channel_names[channel];
 
-	omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
-	omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
-
 	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 					&omap_crtc_funcs, NULL);
 	if (ret < 0) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 4bbfe0869a48..36b20c085026 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -156,6 +156,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
+void omap_crtc_vblank_irq(struct drm_crtc *crtc);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		int id, enum drm_plane_type type);
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index d0730178888f..b0aa33d3570c 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -245,8 +245,10 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 		struct drm_crtc *crtc = priv->crtcs[id];
 		enum omap_channel channel = omap_crtc_channel(crtc);
 
-		if (irqstatus & pipe2vbl(crtc))
+		if (irqstatus & pipe2vbl(crtc)) {
 			drm_handle_vblank(dev, id);
+			omap_crtc_vblank_irq(crtc);
+		}
 
 		if (irqstatus & dispc_mgr_get_sync_lost_irq(channel))
 			omap_crtc_error_irq(crtc, irqstatus);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 15/20] drm: omapdrm: Don't expose the omap_irq_(un)register() functions
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (13 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 14/20] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 16/20] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The IRQ registration functions are not used outside of their compilation
unit, make them static. As the __omap_irq_(un)register() functions are
only called by their omap_irq_(un)register() counterparts, merge them
together.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Split the omap_drm_irq irqstatus parameter removal change out
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  4 ----
 drivers/gpu/drm/omapdrm/omap_irq.c | 23 +++++------------------
 2 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 36b20c085026..e15f6b384f65 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -128,10 +128,6 @@ int omap_gem_resume(struct device *dev);
 
 int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe);
 void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe);
-void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
-void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_drm_irq_uninstall(struct drm_device *dev);
 int omap_drm_irq_install(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index b0aa33d3570c..c14530922f42 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -39,11 +39,12 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
 
+	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(irq->registered)) {
@@ -53,21 +54,15 @@ void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	dispc_runtime_get();
-
-	__omap_irq_register(dev, irq);
-
 	dispc_runtime_put();
 }
 
-void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+static void omap_irq_unregister(struct drm_device *dev,
+				struct omap_drm_irq *irq)
 {
 	unsigned long flags;
 
+	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(!irq->registered)) {
@@ -77,14 +72,6 @@ void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	dispc_runtime_get();
-
-	__omap_irq_unregister(dev, irq);
-
 	dispc_runtime_put();
 }
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 16/20] drm: omapdrm: Remove unused parameter from omap_drm_irq handler
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (14 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 15/20] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 17/20] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The only omap_drm_irq handler doesn't use the irqstatus parameter passed
to the function. Remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- New patch
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 2 +-
 drivers/gpu/drm/omapdrm/omap_irq.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index e15f6b384f65..5200fde1f38e 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -59,7 +59,7 @@ struct omap_drm_irq {
 	struct list_head node;
 	uint32_t irqmask;
 	bool registered;
-	void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
+	void (*irq)(struct omap_drm_irq *irq);
 };
 
 /* For KMS code that needs to wait for a certain # of IRQs:
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index c14530922f42..058ffdc0244d 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -82,7 +82,7 @@ struct omap_irq_wait {
 
 static DECLARE_WAIT_QUEUE_HEAD(wait_event);
 
-static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+static void wait_irq(struct omap_drm_irq *irq)
 {
 	struct omap_irq_wait *wait =
 			container_of(irq, struct omap_irq_wait, irq);
@@ -248,7 +248,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
 		if (handler->irqmask & irqstatus) {
 			spin_unlock_irqrestore(&list_lock, flags);
-			handler->irq(handler, handler->irqmask & irqstatus);
+			handler->irq(handler);
 			spin_lock_irqsave(&list_lock, flags);
 		}
 	}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 17/20] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (15 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 16/20] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 18/20] drm: omapdrm: Make pipe2vbl function static Laurent Pinchart
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The IRQ wait functions are called from the DSS enable and disable
operations only, where the DISPC is guaranteed to be enabled. There's no
need for manual DISPC power management there.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_irq.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 058ffdc0244d..23e1ef5c42bf 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -44,7 +44,6 @@ static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(irq->registered)) {
@@ -54,7 +53,6 @@ static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 }
 
 static void omap_irq_unregister(struct drm_device *dev,
@@ -62,7 +60,6 @@ static void omap_irq_unregister(struct drm_device *dev,
 {
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(!irq->registered)) {
@@ -72,7 +69,6 @@ static void omap_irq_unregister(struct drm_device *dev,
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 }
 
 struct omap_irq_wait {
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 18/20] drm: omapdrm: Make pipe2vbl function static
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (16 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 17/20] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 19/20] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 20/20] drm: omapdrm: Remove global variables Laurent Pinchart
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

The function is only used in omap_irq.c, move it there and make it
static.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 7 -------
 drivers/gpu/drm/omapdrm/omap_drv.h  | 1 -
 drivers/gpu/drm/omapdrm/omap_irq.c  | 7 ++++++-
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index a2587fd403a0..0d97dfd6108f 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -47,13 +47,6 @@ struct omap_crtc {
  * Helper Functions
  */
 
-uint32_t pipe2vbl(struct drm_crtc *crtc)
-{
-	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-
-	return dispc_mgr_get_vsync_irq(omap_crtc->channel);
-}
-
 struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 5200fde1f38e..447cf0e013d8 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -235,7 +235,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 		struct dma_buf *buffer);
 
 /* map crtc to vblank mask */
-uint32_t pipe2vbl(struct drm_crtc *crtc);
 struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
 
 #endif /* __OMAP_DRV_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 23e1ef5c42bf..dbcf9af4c7c8 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -108,6 +108,11 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
 	return 0;
 }
 
+static uint32_t pipe2vbl(struct drm_crtc *crtc)
+{
+	return dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
+}
+
 /**
  * enable_vblank - enable vblank interrupt events
  * @dev: DRM device
@@ -228,7 +233,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 		struct drm_crtc *crtc = priv->crtcs[id];
 		enum omap_channel channel = omap_crtc_channel(crtc);
 
-		if (irqstatus & pipe2vbl(crtc)) {
+		if (irqstatus & dispc_mgr_get_vsync_irq(channel)) {
 			drm_handle_vblank(dev, id);
 			omap_crtc_vblank_irq(crtc);
 		}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 19/20] drm: omapdrm: Simplify IRQ wait implementation
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (17 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 18/20] drm: omapdrm: Make pipe2vbl function static Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  2016-06-06 23:42 ` [PATCH v2 20/20] drm: omapdrm: Remove global variables Laurent Pinchart
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Now that the IRQ list is used for IRQ wait only we can merge
omap_drm_irq and omap_irq_wait and simplify the implementation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h | 17 +------
 drivers/gpu/drm/omapdrm/omap_irq.c | 94 ++++++++++++++------------------------
 2 files changed, 37 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 447cf0e013d8..c250ffe270cc 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -49,19 +49,6 @@ struct omap_drm_window {
 	uint32_t src_w, src_h;
 };
 
-/* For transiently registering for different DSS irqs that various parts
- * of the KMS code need during setup/configuration.  We these are not
- * necessarily the same as what drm_vblank_get/put() are requesting, and
- * the hysteresis in drm_vblank_put() is not necessarily desirable for
- * internal housekeeping related irq usage.
- */
-struct omap_drm_irq {
-	struct list_head node;
-	uint32_t irqmask;
-	bool registered;
-	void (*irq)(struct omap_drm_irq *irq);
-};
-
 /* For KMS code that needs to wait for a certain # of IRQs:
  */
 struct omap_irq_wait;
@@ -102,8 +89,8 @@ struct omap_drm_private {
 	struct drm_property *zorder_prop;
 
 	/* irq handling: */
-	struct list_head irq_list;    /* list of omap_drm_irq */
-	uint32_t irq_mask;		/* enabled irqs in addition to irq_list */
+	struct list_head wait_list;     /* list of omap_irq_wait */
+	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
 
 	/* atomic commit */
 	struct {
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index dbcf9af4c7c8..947c58d956c6 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -21,17 +21,23 @@
 
 static DEFINE_SPINLOCK(list_lock);
 
+struct omap_irq_wait {
+	struct list_head node;
+	uint32_t irqmask;
+	int count;
+};
+
 /* call with list_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *irq;
+	struct omap_irq_wait *wait;
 	uint32_t irqmask = priv->irq_mask;
 
 	assert_spin_locked(&list_lock);
 
-	list_for_each_entry(irq, &priv->irq_list, node)
-		irqmask |= irq->irqmask;
+	list_for_each_entry(wait, &priv->wait_list, node)
+		irqmask |= wait->irqmask;
 
 	DBG("irqmask=%08x", irqmask);
 
@@ -39,61 +45,29 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-static void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-
-	if (!WARN_ON(irq->registered)) {
-		irq->registered = true;
-		list_add(&irq->node, &priv->irq_list);
-		omap_irq_update(dev);
-	}
-
-	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void omap_irq_unregister(struct drm_device *dev,
-				struct omap_drm_irq *irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-
-	if (!WARN_ON(!irq->registered)) {
-		irq->registered = false;
-		list_del(&irq->node);
-		omap_irq_update(dev);
-	}
-
-	spin_unlock_irqrestore(&list_lock, flags);
-}
-
-struct omap_irq_wait {
-	struct omap_drm_irq irq;
-	int count;
-};
-
 static DECLARE_WAIT_QUEUE_HEAD(wait_event);
 
-static void wait_irq(struct omap_drm_irq *irq)
+static void omap_irq_wait_irq(struct omap_irq_wait *wait)
 {
-	struct omap_irq_wait *wait =
-			container_of(irq, struct omap_irq_wait, irq);
 	wait->count--;
-	wake_up_all(&wait_event);
+	wake_up(&wait_event);
 }
 
 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 		uint32_t irqmask, int count)
 {
+	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
-	wait->irq.irq = wait_irq;
-	wait->irq.irqmask = irqmask;
+	unsigned long flags;
+
+	wait->irqmask = irqmask;
 	wait->count = count;
-	omap_irq_register(dev, &wait->irq);
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_add(&wait->node, &priv->wait_list);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+
 	return wait;
 }
 
@@ -101,11 +75,16 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
 		unsigned long timeout)
 {
 	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
-	omap_irq_unregister(dev, &wait->irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_del(&wait->node);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+
 	kfree(wait);
-	if (ret == 0)
-		return -1;
-	return 0;
+
+	return ret == 0 ? -1 : 0;
 }
 
 static uint32_t pipe2vbl(struct drm_crtc *crtc)
@@ -218,7 +197,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_drm_irq *handler, *n;
+	struct omap_irq_wait *wait, *n;
 	unsigned long flags;
 	unsigned int id;
 	u32 irqstatus;
@@ -246,12 +225,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	omap_irq_fifo_underflow(priv, irqstatus);
 
 	spin_lock_irqsave(&list_lock, flags);
-	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
-		if (handler->irqmask & irqstatus) {
-			spin_unlock_irqrestore(&list_lock, flags);
-			handler->irq(handler);
-			spin_lock_irqsave(&list_lock, flags);
-		}
+	list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
+		if (wait->irqmask & irqstatus)
+			omap_irq_wait_irq(wait);
 	}
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -280,7 +256,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 	unsigned int i;
 	int ret;
 
-	INIT_LIST_HEAD(&priv->irq_list);
+	INIT_LIST_HEAD(&priv->wait_list);
 
 	priv->irq_mask = DISPC_IRQ_OCP_ERR;
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 20/20] drm: omapdrm: Remove global variables
  2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
                   ` (18 preceding siblings ...)
  2016-06-06 23:42 ` [PATCH v2 19/20] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
@ 2016-06-06 23:42 ` Laurent Pinchart
  19 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2016-06-06 23:42 UTC (permalink / raw)
  To: dri-devel; +Cc: Tomi Valkeinen

Move the list of pending IRQ wait instances to the omap_drm_private
structure and the wait queue head to the IRQ wait structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h |  3 ++-
 drivers/gpu/drm/omapdrm/omap_irq.c | 42 ++++++++++++++++++++------------------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index c250ffe270cc..a842b42b6053 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -89,7 +89,8 @@ struct omap_drm_private {
 	struct drm_property *zorder_prop;
 
 	/* irq handling: */
-	struct list_head wait_list;     /* list of omap_irq_wait */
+	spinlock_t wait_lock;		/* protects the wait_list */
+	struct list_head wait_list;	/* list of omap_irq_wait */
 	uint32_t irq_mask;		/* enabled irqs in addition to wait_list */
 
 	/* atomic commit */
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 947c58d956c6..53f951d88bbe 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -19,22 +19,21 @@
 
 #include "omap_drv.h"
 
-static DEFINE_SPINLOCK(list_lock);
-
 struct omap_irq_wait {
 	struct list_head node;
+	wait_queue_head_t wq;
 	uint32_t irqmask;
 	int count;
 };
 
-/* call with list_lock and dispc runtime held */
+/* call with wait_lock and dispc runtime held */
 static void omap_irq_update(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_irq_wait *wait;
 	uint32_t irqmask = priv->irq_mask;
 
-	assert_spin_locked(&list_lock);
+	assert_spin_locked(&priv->wait_lock);
 
 	list_for_each_entry(wait, &priv->wait_list, node)
 		irqmask |= wait->irqmask;
@@ -45,12 +44,10 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-static DECLARE_WAIT_QUEUE_HEAD(wait_event);
-
 static void omap_irq_wait_irq(struct omap_irq_wait *wait)
 {
 	wait->count--;
-	wake_up(&wait_event);
+	wake_up(&wait->wq);
 }
 
 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
@@ -60,13 +57,14 @@ struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
 	unsigned long flags;
 
+	init_waitqueue_head(&wait->wq);
 	wait->irqmask = irqmask;
 	wait->count = count;
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_add(&wait->node, &priv->wait_list);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return wait;
 }
@@ -74,13 +72,16 @@ struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
 int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
 		unsigned long timeout)
 {
-	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
+	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
+	int ret;
+
+	ret = wait_event_timeout(wait->wq, (wait->count <= 0), timeout);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_del(&wait->node);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	kfree(wait);
 
@@ -113,10 +114,10 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
 
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	priv->irq_mask |= pipe2vbl(crtc);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return 0;
 }
@@ -138,10 +139,10 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
 
 	DBG("dev=%p, crtc=%u", dev, pipe);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	priv->irq_mask &= ~pipe2vbl(crtc);
 	omap_irq_update(dev);
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 }
 
 static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
@@ -165,9 +166,9 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
 		       | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
 	unsigned int i;
 
-	spin_lock(&list_lock);
+	spin_lock(&priv->wait_lock);
 	irqstatus &= priv->irq_mask & mask;
-	spin_unlock(&list_lock);
+	spin_unlock(&priv->wait_lock);
 
 	if (!irqstatus)
 		return;
@@ -224,12 +225,12 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
 	omap_irq_ocp_error_handler(irqstatus);
 	omap_irq_fifo_underflow(priv, irqstatus);
 
-	spin_lock_irqsave(&list_lock, flags);
+	spin_lock_irqsave(&priv->wait_lock, flags);
 	list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
 		if (wait->irqmask & irqstatus)
 			omap_irq_wait_irq(wait);
 	}
-	spin_unlock_irqrestore(&list_lock, flags);
+	spin_unlock_irqrestore(&priv->wait_lock, flags);
 
 	return IRQ_HANDLED;
 }
@@ -256,6 +257,7 @@ int omap_drm_irq_install(struct drm_device *dev)
 	unsigned int i;
 	int ret;
 
+	spin_lock_init(&priv->wait_lock);
 	INIT_LIST_HEAD(&priv->wait_list);
 
 	priv->irq_mask = DISPC_IRQ_OCP_ERR;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two
  2016-06-06 23:42 ` [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
@ 2016-06-10 11:58   ` Tomi Valkeinen
  0 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2016-06-10 11:58 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1171 bytes --]


On 07/06/16 02:42, Laurent Pinchart wrote:
> The only multi-planar format supported by the driver is NV12, there will
> thus never be more than two planes per framebuffer.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_fb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
> index 530567cc25b7..4214138d5795 100644
> --- a/drivers/gpu/drm/omapdrm/omap_fb.c
> +++ b/drivers/gpu/drm/omapdrm/omap_fb.c
> @@ -36,7 +36,7 @@ struct format {
>  	struct {
>  		int stride_bpp;           /* this times width is stride */
>  		int sub_y;                /* sub-sample in y dimension */
> -	} planes[4];
> +	} planes[2];
>  	bool yuv;
>  };
>  
> @@ -90,7 +90,7 @@ struct omap_framebuffer {
>  	struct drm_framebuffer base;
>  	int pin_count;
>  	const struct format *format;
> -	struct plane planes[4];
> +	struct plane planes[2];
>  	/* lock for pinning (pin_count and planes.paddr) */
>  	struct mutex lock;
>  };
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2016-06-10 11:58 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-06 23:42 [PATCH v2 00/20] OMAP DRM fixes and improvements Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 01/20] drm: omapdrm: fb: Limit number of planes per framebuffer to two Laurent Pinchart
2016-06-10 11:58   ` Tomi Valkeinen
2016-06-06 23:42 ` [PATCH v2 02/20] drm: omapdrm: fb: Use format information provided by the DRM core Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 03/20] drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 04/20] drm: omapdrm: fb: Simplify mode command checks " Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 05/20] drm: omapdrm: fb: Turn framebuffer creation error messages into debug Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 06/20] drm: omapdrm: Handle FIFO underflow IRQs internally Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 07/20] drm: omapdrm: Handle CRTC error IRQs directly Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 08/20] drm: omapdrm: Handle OCP error IRQ directly Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 09/20] drm: omapdrm: Use atomic state instead of local device state Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 10/20] drm: omapdrm: Only commit planes on active CRTCs Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 11/20] drm: omapdrm: Check DSS manager state in the enable/disable helpers Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 12/20] drm: omapdrm: Prevent processing the same event multiple times Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 13/20] drm: omapdrm: Use a spinlock to protect the CRTC pending flag Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 14/20] drm: omapdrm: Keep vblank interrupt enabled while CRTC is active Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 15/20] drm: omapdrm: Don't expose the omap_irq_(un)register() functions Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 16/20] drm: omapdrm: Remove unused parameter from omap_drm_irq handler Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 17/20] drm: omapdrm: Don't call DISPC power handling in IRQ wait functions Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 18/20] drm: omapdrm: Make pipe2vbl function static Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 19/20] drm: omapdrm: Simplify IRQ wait implementation Laurent Pinchart
2016-06-06 23:42 ` [PATCH v2 20/20] drm: omapdrm: Remove global variables Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.