All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] omapdrm patches for 3.4
@ 2012-03-05 16:48 Rob Clark
  2012-03-05 16:48 ` [PATCH 01/10] staging: drm/omap: get supported color formats from ovl Rob Clark
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

This is the (potentially first) batch of patches for omapdrm for 3.4.
It includes some fixes for OMAP3 (without DMM), and change in how
the DMM code gets it's platform data based on review comments from
the first version of the patch which added the omapdrm platform dev.

Also, a few cleanups, a better solution for handling fbdev calls from
atomix context, deferred unpin until scanout completes, mmap of tiled
buffers w/ stride larger than PAGE_SIZE.

There is one additional patch to come after the platform device patch
is merged (in arch/arm/plat-omap) to remove some duplicated structs.
And I am still working on support for scanout and rotated scanout of
tiled buffers, which may or may not be ready in time for 3.4 merge
window.

Andy Gross (3):
  staging: drm/omap: Disable DMM debugfs for OMAP3
  staging: drm/omap: Validate debugfs device
  staging: drm/omap: Get DMM resources from hwmod

Rob Clark (7):
  staging: drm/omap: get supported color formats from ovl
  staging: drm/omap: add a workqueue
  staging: drm/omap: call omap_gem_roll() in non-atomic ctx
  staging: drm/omap: some minor fb cleanups
  staging: drm/omap: defer unpin until scanout completes
  staging: drm/omap: debugfs for object and fb tracking
  staging: drm/omap: mmap of tiled buffers with stride >4kb

 drivers/staging/omapdrm/omap_debugfs.c   |   97 +++++++++++++++++-
 drivers/staging/omapdrm/omap_dmm_tiler.c |   91 ++++++++++++----
 drivers/staging/omapdrm/omap_dmm_tiler.h |   15 ++--
 drivers/staging/omapdrm/omap_drv.c       |   16 +++
 drivers/staging/omapdrm/omap_drv.h       |   17 +++-
 drivers/staging/omapdrm/omap_fb.c        |  124 +++++++++++++++-------
 drivers/staging/omapdrm/omap_fbdev.c     |   26 ++++-
 drivers/staging/omapdrm/omap_gem.c       |  172 ++++++++++++++++++++++--------
 drivers/staging/omapdrm/omap_plane.c     |  161 +++++++++++++++++++++++-----
 9 files changed, 570 insertions(+), 149 deletions(-)

-- 
1.7.5.4


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

* [PATCH 01/10] staging: drm/omap: get supported color formats from ovl
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 02/10] staging: drm/omap: add a workqueue Rob Clark
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

Get the supported formats for a plane from ovl's supported_modes
bitmask.

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_drv.h   |    2 ++
 drivers/staging/omapdrm/omap_fb.c    |   14 ++++++++++++++
 drivers/staging/omapdrm/omap_plane.c |   27 +++++++--------------------
 3 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index 61fe022..d924c95 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -92,6 +92,8 @@ void omap_connector_mode_set(struct drm_connector *connector,
 void omap_connector_flush(struct drm_connector *connector,
 		int x, int y, int w, int h);
 
+uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
+		uint32_t max_formats, enum omap_color_mode supported_modes);
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index d021a7e..116a8ff 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -59,6 +59,20 @@ static const struct format formats[] = {
 	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     {{2, 1}}, true },
 };
 
+/* convert from overlay's pixel formats bitmask to an array of fourcc's */
+uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
+		uint32_t max_formats, enum omap_color_mode supported_modes)
+{
+	uint32_t nformats = 0;
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(formats) && nformats < max_formats; i++)
+		if (formats[i].dss_format & supported_modes)
+			pixel_formats[nformats++] = formats[i].pixel_format;
+
+	return nformats;
+}
+
 /* per-plane info for the fb: */
 struct plane {
 	struct drm_gem_object *bo;
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
index 9790912..c5625e3 100644
--- a/drivers/staging/omapdrm/omap_plane.c
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -43,8 +43,10 @@ struct omap_plane {
 
 	/* last fb that we pinned: */
 	struct drm_framebuffer *pinned_fb;
-};
 
+	uint32_t nformats;
+	uint32_t formats[32];
+};
 
 /* push changes down to dss2 */
 static int commit(struct drm_plane *plane)
@@ -271,24 +273,6 @@ static const struct drm_plane_funcs omap_plane_funcs = {
 		.destroy = omap_plane_destroy,
 };
 
-static const uint32_t formats[] = {
-		DRM_FORMAT_RGB565,
-		DRM_FORMAT_RGBX4444,
-		DRM_FORMAT_XRGB4444,
-		DRM_FORMAT_RGBA4444,
-		DRM_FORMAT_ABGR4444,
-		DRM_FORMAT_XRGB1555,
-		DRM_FORMAT_ARGB1555,
-		DRM_FORMAT_RGB888,
-		DRM_FORMAT_RGBX8888,
-		DRM_FORMAT_XRGB8888,
-		DRM_FORMAT_RGBA8888,
-		DRM_FORMAT_ARGB8888,
-		DRM_FORMAT_NV12,
-		DRM_FORMAT_YUYV,
-		DRM_FORMAT_UYVY,
-};
-
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
 		struct omap_overlay *ovl, unsigned int possible_crtcs,
@@ -306,11 +290,14 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 		goto fail;
 	}
 
+	omap_plane->nformats = omap_framebuffer_get_formats(
+			omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
+			ovl->supported_modes);
 	omap_plane->ovl = ovl;
 	plane = &omap_plane->base;
 
 	drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
-			formats, ARRAY_SIZE(formats), priv);
+			omap_plane->formats, omap_plane->nformats, priv);
 
 	/* get our starting configuration, set defaults for parameters
 	 * we don't currently use, etc:
-- 
1.7.5.4


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

* [PATCH 02/10] staging: drm/omap: add a workqueue
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
  2012-03-05 16:48 ` [PATCH 01/10] staging: drm/omap: get supported color formats from ovl Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 03/10] staging: drm/omap: call omap_gem_roll() in non-atomic ctx Rob Clark
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

Add a workqueue for omapdrm driver, which is needed for at least a
couple things currently: (1) moving omap_gem_roll() to a non-atomic
context, (2) synchronizing page flips w/ DSS scanout related irq's
(in particular not unmapping previous buffer until DSS finishes
scanout).

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_drv.c |    8 ++++++++
 drivers/staging/omapdrm/omap_drv.h |    2 ++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 3bbea9a..7417e1f 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -570,6 +570,9 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
 	dev->dev_private = priv;
 
+	priv->wq = alloc_workqueue("omapdrm",
+			WQ_UNBOUND | WQ_NON_REENTRANT, 1);
+
 	omap_gem_init(dev);
 
 	ret = omap_modeset_init(dev);
@@ -598,6 +601,8 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
 static int dev_unload(struct drm_device *dev)
 {
+	struct omap_drm_private *priv = dev->dev_private;
+
 	DBG("unload: dev=%p", dev);
 
 	drm_vblank_cleanup(dev);
@@ -607,6 +612,9 @@ static int dev_unload(struct drm_device *dev)
 	omap_modeset_free(dev);
 	omap_gem_deinit(dev);
 
+	flush_workqueue(priv->wq);
+	destroy_workqueue(priv->wq);
+
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index d924c95..a84547c 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -51,6 +51,8 @@ struct omap_drm_private {
 
 	struct drm_fb_helper *fbdev;
 
+	struct workqueue_struct *wq;
+
 	bool has_dmm;
 };
 
-- 
1.7.5.4


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

* [PATCH 03/10] staging: drm/omap: call omap_gem_roll() in non-atomic ctx
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
  2012-03-05 16:48 ` [PATCH 01/10] staging: drm/omap: get supported color formats from ovl Rob Clark
  2012-03-05 16:48 ` [PATCH 02/10] staging: drm/omap: add a workqueue Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 04/10] staging: drm/omap: some minor fb cleanups Rob Clark
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

If fbcon calls us from atomic context, push the work off to the
workqueue to avoid calling into the gem/dmm code in an atomic
context.

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_fbdev.c |   26 ++++++++++++++++++++++----
 drivers/staging/omapdrm/omap_gem.c   |   14 ++------------
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c
index 96940bb..11acd4c 100644
--- a/drivers/staging/omapdrm/omap_fbdev.c
+++ b/drivers/staging/omapdrm/omap_fbdev.c
@@ -37,6 +37,9 @@ struct omap_fbdev {
 	struct drm_framebuffer *fb;
 	struct drm_gem_object *bo;
 	bool ywrap_enabled;
+
+	/* for deferred dmm roll when getting called in atomic ctx */
+	struct work_struct work;
 };
 
 static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h);
@@ -75,12 +78,22 @@ static void omap_fbdev_imageblit(struct fb_info *fbi,
 				image->width, image->height);
 }
 
+static void pan_worker(struct work_struct *work)
+{
+	struct omap_fbdev *fbdev = container_of(work, struct omap_fbdev, work);
+	struct fb_info *fbi = fbdev->base.fbdev;
+	int npages;
+
+	/* DMM roll shifts in 4K pages: */
+	npages = fbi->fix.line_length >> PAGE_SHIFT;
+	omap_gem_roll(fbdev->bo, fbi->var.yoffset * npages);
+}
+
 static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
 		struct fb_info *fbi)
 {
 	struct drm_fb_helper *helper = get_fb(fbi);
 	struct omap_fbdev *fbdev = to_omap_fbdev(helper);
-	int npages;
 
 	if (!helper)
 		goto fallback;
@@ -88,9 +101,12 @@ static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
 	if (!fbdev->ywrap_enabled)
 		goto fallback;
 
-	/* DMM roll shifts in 4K pages: */
-	npages = fbi->fix.line_length >> PAGE_SHIFT;
-	omap_gem_roll(fbdev->bo, var->yoffset * npages);
+	if (drm_can_sleep()) {
+		pan_worker(&fbdev->work);
+	} else {
+		struct omap_drm_private *priv = helper->dev->dev_private;
+		queue_work(priv->wq, &fbdev->work);
+	}
 
 	return 0;
 
@@ -336,6 +352,8 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
 		goto fail;
 	}
 
+	INIT_WORK(&fbdev->work, pan_worker);
+
 	helper = &fbdev->base;
 
 	helper->funcs = &omap_fb_helper_funcs;
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index b7d6f88..bd35520 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -566,6 +566,8 @@ fail:
 
 /* Set scrolling position.  This allows us to implement fast scrolling
  * for console.
+ *
+ * Call only from non-atomic contexts.
  */
 int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)
 {
@@ -580,18 +582,6 @@ int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)
 
 	omap_obj->roll = roll;
 
-	if (in_atomic() || mutex_is_locked(&obj->dev->struct_mutex)) {
-		/* this can get called from fbcon in atomic context.. so
-		 * just ignore it and wait for next time called from
-		 * interruptible context to update the PAT.. the result
-		 * may be that user sees wrap-around instead of scrolling
-		 * momentarily on the screen.  If we wanted to be fancier
-		 * we could perhaps schedule some workqueue work at this
-		 * point.
-		 */
-		return 0;
-	}
-
 	mutex_lock(&obj->dev->struct_mutex);
 
 	/* if we aren't mapped yet, we don't need to do anything */
-- 
1.7.5.4


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

* [PATCH 04/10] staging: drm/omap: some minor fb cleanups
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (2 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 03/10] staging: drm/omap: call omap_gem_roll() in non-atomic ctx Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 05/10] staging: drm/omap: defer unpin until scanout completes Rob Clark
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

Now that 'struct drm_plane' has a pixel_format field, use that.  And
fix a minor typo.

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_fb.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 116a8ff..08e2e35 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -101,7 +101,7 @@ static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
 static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
+	int i, n = drm_format_num_planes(fb->pixel_format);
 
 	DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
 
@@ -204,7 +204,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	if (p >= drm_format_num_planes(omap_fb->format->pixel_format))
+	if (p >= drm_format_num_planes(fb->pixel_format))
 		return NULL;
 	return omap_fb->planes[p].bo;
 }
@@ -351,8 +351,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 
 		plane->bo     = bos[i];
 		plane->offset = mode_cmd->offsets[i];
-		plane->pitch  = mode_cmd->pitches[i];
-		plane->paddr  = pitch;
+		plane->pitch  = pitch;
+		plane->paddr  = 0;
 	}
 
 	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
-- 
1.7.5.4


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

* [PATCH 05/10] staging: drm/omap: defer unpin until scanout completes
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (3 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 04/10] staging: drm/omap: some minor fb cleanups Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 06/10] staging: drm/omap: debugfs for object and fb tracking Rob Clark
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

When flipping, defer unpinning until scanout completes, as indicated
by the appropriate END_WIN irq.

This also re-organizes things a bit, in replacing omap_fb_{pin,unpin}
with omap_fb_replace(), to make it easier to add support for scanout
synchronized DMM refill mode (flipping by just reprogramming DMM
synchronized with DSS scanout).

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_drv.h   |    5 +-
 drivers/staging/omapdrm/omap_fb.c    |   84 ++++++++++++---------
 drivers/staging/omapdrm/omap_plane.c |  136 ++++++++++++++++++++++++++++++++--
 3 files changed, 181 insertions(+), 44 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index a84547c..fe4766e 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -101,8 +101,9 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
-int omap_framebuffer_pin(struct drm_framebuffer *fb);
-void omap_framebuffer_unpin(struct drm_framebuffer *fb);
+int omap_framebuffer_replace(struct drm_framebuffer *a,
+		struct drm_framebuffer *b, void *arg,
+		void (*unpin)(void *arg, struct drm_gem_object *bo));
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
 		struct omap_overlay_info *info);
 struct drm_connector *omap_framebuffer_get_next_connector(
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 08e2e35..fcb248f 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -137,41 +137,6 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
 	.dirty = omap_framebuffer_dirty,
 };
 
-/* pins buffer in preparation for scanout */
-int omap_framebuffer_pin(struct drm_framebuffer *fb)
-{
-	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	int ret, i, n = drm_format_num_planes(omap_fb->format->pixel_format);
-
-	for (i = 0; i < n; i++) {
-		struct plane *plane = &omap_fb->planes[i];
-		ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
-		if (ret)
-			goto fail;
-	}
-
-	return 0;
-
-fail:
-	while (--i > 0) {
-		struct plane *plane = &omap_fb->planes[i];
-		omap_gem_put_paddr(plane->bo);
-	}
-	return ret;
-}
-
-/* releases buffer when done with scanout */
-void omap_framebuffer_unpin(struct drm_framebuffer *fb)
-{
-	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-	int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
-
-	for (i = 0; i < n; i++) {
-		struct plane *plane = &omap_fb->planes[i];
-		omap_gem_put_paddr(plane->bo);
-	}
-}
-
 /* update ovl info for scanout, handles cases of multi-planar fb's, etc.
  */
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
@@ -201,6 +166,55 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
 	}
 }
 
+/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL).  Although
+ * buffers to unpin are just just pushed to the unpin fifo so that the
+ * caller can defer unpin until vblank.
+ *
+ * Note if this fails (ie. something went very wrong!), all buffers are
+ * unpinned, and the caller disables the overlay.  We could have tried
+ * to revert back to the previous set of pinned buffers but if things are
+ * hosed there is no guarantee that would succeed.
+ */
+int omap_framebuffer_replace(struct drm_framebuffer *a,
+		struct drm_framebuffer *b, void *arg,
+		void (*unpin)(void *arg, struct drm_gem_object *bo))
+{
+	int ret = 0, i, na, nb;
+	struct omap_framebuffer *ofba = to_omap_framebuffer(a);
+	struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
+
+	na = a ? drm_format_num_planes(a->pixel_format) : 0;
+	nb = b ? drm_format_num_planes(b->pixel_format) : 0;
+
+	for (i = 0; i < max(na, nb); i++) {
+		struct plane *pa, *pb;
+
+		pa = (i < na) ? &ofba->planes[i] : NULL;
+		pb = (i < nb) ? &ofbb->planes[i] : NULL;
+
+		if (pa) {
+			unpin(arg, pa->bo);
+			pa->paddr = 0;
+		}
+
+		if (pb && !ret)
+			ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
+	}
+
+	if (ret) {
+		/* something went wrong.. unpin what has been pinned */
+		for (i = 0; i < nb; i++) {
+			struct plane *pb = &ofba->planes[i];
+			if (pb->paddr) {
+				unpin(arg, pb->bo);
+				pb->paddr = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
 {
 	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
index c5625e3..55ddc58 100644
--- a/drivers/staging/omapdrm/omap_plane.c
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/kfifo.h>
+
 #include "omap_drv.h"
 
 /* some hackery because omapdss has an 'enum omap_plane' (which would be
@@ -46,8 +48,57 @@ struct omap_plane {
 
 	uint32_t nformats;
 	uint32_t formats[32];
+
+	/* for synchronizing access to unpins fifo */
+	struct mutex unpin_mutex;
+
+	/* set of bo's pending unpin until next END_WIN irq */
+	DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *);
+	int num_unpins, pending_num_unpins;
+
+	/* for deferred unpin when we need to wait for scanout complete irq */
+	struct work_struct work;
+};
+
+/* map from ovl->id to the irq we are interested in for scanout-done */
+static const uint32_t id2irq[] = {
+		[OMAP_DSS_GFX]    = DISPC_IRQ_GFX_END_WIN,
+		[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN,
+		[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN,
+		[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN,
 };
 
+static void dispc_isr(void *arg, uint32_t mask)
+{
+	struct drm_plane *plane = arg;
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+	struct omap_drm_private *priv = plane->dev->dev_private;
+
+	omap_dispc_unregister_isr(dispc_isr, plane,
+			id2irq[omap_plane->ovl->id]);
+
+	queue_work(priv->wq, &omap_plane->work);
+}
+
+static void unpin_worker(struct work_struct *work)
+{
+	struct omap_plane *omap_plane =
+			container_of(work, struct omap_plane, work);
+
+	mutex_lock(&omap_plane->unpin_mutex);
+	DBG("unpinning %d of %d", omap_plane->num_unpins,
+			omap_plane->num_unpins + omap_plane->pending_num_unpins);
+	while (omap_plane->num_unpins > 0) {
+		struct drm_gem_object *bo = NULL;
+		int ret = kfifo_get(&omap_plane->unpin_fifo, &bo);
+		WARN_ON(!ret);
+		omap_gem_put_paddr(bo);
+		drm_gem_object_unreference_unlocked(bo);
+		omap_plane->num_unpins--;
+	}
+	mutex_unlock(&omap_plane->unpin_mutex);
+}
+
 /* push changes down to dss2 */
 static int commit(struct drm_plane *plane)
 {
@@ -73,6 +124,11 @@ static int commit(struct drm_plane *plane)
 		return ret;
 	}
 
+	mutex_lock(&omap_plane->unpin_mutex);
+	omap_plane->num_unpins += omap_plane->pending_num_unpins;
+	omap_plane->pending_num_unpins = 0;
+	mutex_unlock(&omap_plane->unpin_mutex);
+
 	/* our encoder doesn't necessarily get a commit() after this, in
 	 * particular in the dpms() and mode_set_base() cases, so force the
 	 * manager to update:
@@ -85,8 +141,29 @@ static int commit(struct drm_plane *plane)
 			dev_err(dev->dev, "could not apply settings\n");
 			return ret;
 		}
+
+		/*
+		 * NOTE: really this should be atomic w/ mgr->apply() but
+		 * omapdss does not expose such an API
+		 */
+		if (omap_plane->num_unpins > 0) {
+			ret = omap_dispc_register_isr(dispc_isr,
+				plane, id2irq[ovl->id]);
+		}
+
+		/*
+		 * omapdss has upper limit on # of registered irq handlers,
+		 * which we shouldn't hit.. but if we do the limit should
+		 * be raised or bad things happen:
+		 */
+		WARN_ON(ret == -EBUSY);
+
+	} else {
+		struct omap_drm_private *priv = dev->dev_private;
+		queue_work(priv->wq, &omap_plane->work);
 	}
 
+
 	if (ovl->is_enabled(ovl)) {
 		omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
 				info->out_width, info->out_height);
@@ -139,21 +216,48 @@ static void update_manager(struct drm_plane *plane)
 	}
 }
 
+static void unpin(void *arg, struct drm_gem_object *bo)
+{
+	struct drm_plane *plane = arg;
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+
+	if (kfifo_put(&omap_plane->unpin_fifo,
+			(const struct drm_gem_object **)&bo)) {
+		omap_plane->pending_num_unpins++;
+		/* also hold a ref so it isn't free'd while pinned */
+		drm_gem_object_reference(bo);
+	} else {
+		dev_err(plane->dev->dev, "unpin fifo full!\n");
+		omap_gem_put_paddr(bo);
+	}
+}
+
 /* update which fb (if any) is pinned for scanout */
 static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
-	int ret = 0;
+	struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb;
+
+	if (pinned_fb != fb) {
+		int ret;
+
+		DBG("%p -> %p", pinned_fb, fb);
+
+		mutex_lock(&omap_plane->unpin_mutex);
+		ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin);
+		mutex_unlock(&omap_plane->unpin_mutex);
+
+		if (ret) {
+			dev_err(plane->dev->dev, "could not swap %p -> %p\n",
+					omap_plane->pinned_fb, fb);
+			omap_plane->pinned_fb = NULL;
+			return ret;
+		}
 
-	if (omap_plane->pinned_fb != fb) {
-		if (omap_plane->pinned_fb)
-			omap_framebuffer_unpin(omap_plane->pinned_fb);
 		omap_plane->pinned_fb = fb;
-		if (fb)
-			ret = omap_framebuffer_pin(fb);
 	}
 
-	return ret;
+	return 0;
 }
 
 /* update parameters that are dependent on the framebuffer dimensions and
@@ -243,6 +347,8 @@ static void omap_plane_destroy(struct drm_plane *plane)
 	DBG("%s", omap_plane->ovl->name);
 	omap_plane_disable(plane);
 	drm_plane_cleanup(plane);
+	WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0);
+	kfifo_free(&omap_plane->unpin_fifo);
 	kfree(omap_plane);
 }
 
@@ -260,8 +366,10 @@ int omap_plane_dpms(struct drm_plane *plane, int mode)
 		if (!r)
 			r = ovl->enable(ovl);
 	} else {
+		struct omap_drm_private *priv = plane->dev->dev_private;
 		r = ovl->disable(ovl);
 		update_pin(plane, NULL);
+		queue_work(priv->wq, &omap_plane->work);
 	}
 
 	return r;
@@ -280,16 +388,30 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 {
 	struct drm_plane *plane = NULL;
 	struct omap_plane *omap_plane;
+	int ret;
 
 	DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name,
 			possible_crtcs, priv);
 
+	/* friendly reminder to update table for future hw: */
+	WARN_ON(ovl->id >= ARRAY_SIZE(id2irq));
+
 	omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
 	if (!omap_plane) {
 		dev_err(dev->dev, "could not allocate plane\n");
 		goto fail;
 	}
 
+	mutex_init(&omap_plane->unpin_mutex);
+
+	ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev->dev, "could not allocate unpin FIFO\n");
+		goto fail;
+	}
+
+	INIT_WORK(&omap_plane->work, unpin_worker);
+
 	omap_plane->nformats = omap_framebuffer_get_formats(
 			omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
 			ovl->supported_modes);
-- 
1.7.5.4


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

* [PATCH 06/10] staging: drm/omap: debugfs for object and fb tracking
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (4 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 05/10] staging: drm/omap: defer unpin until scanout completes Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 07/10] staging: drm/omap: Disable DMM debugfs for OMAP3 Rob Clark
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

Add some additional debugfs file to aid in tracking buffer usage.

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_debugfs.c |   98 +++++++++++++++++++++++++++++++-
 drivers/staging/omapdrm/omap_drv.c     |    2 +
 drivers/staging/omapdrm/omap_drv.h     |    8 +++
 drivers/staging/omapdrm/omap_fb.c      |   18 ++++++
 drivers/staging/omapdrm/omap_gem.c     |   64 ++++++++++++++++++++-
 5 files changed, 188 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_debugfs.c b/drivers/staging/omapdrm/omap_debugfs.c
index da920df..e23f907 100644
--- a/drivers/staging/omapdrm/omap_debugfs.c
+++ b/drivers/staging/omapdrm/omap_debugfs.c
@@ -20,23 +20,119 @@
 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
 
+#include "drm_fb_helper.h"
+
+
 #ifdef CONFIG_DEBUG_FS
 
+static int gem_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct omap_drm_private *priv = dev->dev_private;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	seq_printf(m, "All Objects:\n");
+	omap_gem_describe_objects(&priv->obj_list, m);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+static int mm_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	return drm_mm_dump_table(m, dev->mm_private);
+}
+
+static int fb_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct omap_drm_private *priv = dev->dev_private;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret) {
+		mutex_unlock(&dev->mode_config.mutex);
+		return ret;
+	}
+
+	seq_printf(m, "fbcon ");
+	omap_framebuffer_describe(priv->fbdev->fb, m);
+
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		if (fb == priv->fbdev->fb)
+			continue;
+
+		seq_printf(m, "user ");
+		omap_framebuffer_describe(fb, m);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+}
+
+/* list of debufs files that are applicable to all devices */
 static struct drm_info_list omap_debugfs_list[] = {
+	{"gem", gem_show, 0},
+	{"mm", mm_show, 0},
+	{"fb", fb_show, 0},
+};
+
+/* list of debugfs files that are specific to devices with dmm/tiler */
+static struct drm_info_list omap_dmm_debugfs_list[] = {
 	{"tiler_map", tiler_map_show, 0},
 };
 
 int omap_debugfs_init(struct drm_minor *minor)
 {
-	return drm_debugfs_create_files(omap_debugfs_list,
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	ret = drm_debugfs_create_files(omap_debugfs_list,
 			ARRAY_SIZE(omap_debugfs_list),
 			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install omap_debugfs_list\n");
+		return ret;
+	}
+
+	/* TODO: only do this if has_dmm.. but this fxn gets called before
+	 * dev_load() so we don't know this yet..
+	 */
+	ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
+			ARRAY_SIZE(omap_dmm_debugfs_list),
+			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install omap_dmm_debugfs_list\n");
+		return ret;
+	}
+
+	return ret;
 }
 
 void omap_debugfs_cleanup(struct drm_minor *minor)
 {
 	drm_debugfs_remove_files(omap_debugfs_list,
 			ARRAY_SIZE(omap_debugfs_list), minor);
+	drm_debugfs_remove_files(omap_dmm_debugfs_list,
+			ARRAY_SIZE(omap_dmm_debugfs_list), minor);
 }
 
 #endif
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 7417e1f..e2100bb 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -573,6 +573,8 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 	priv->wq = alloc_workqueue("omapdrm",
 			WQ_UNBOUND | WQ_NON_REENTRANT, 1);
 
+	INIT_LIST_HEAD(&priv->obj_list);
+
 	omap_gem_init(dev);
 
 	ret = omap_modeset_init(dev);
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index fe4766e..21e48cf 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -42,10 +42,13 @@
 struct omap_drm_private {
 	unsigned int num_crtcs;
 	struct drm_crtc *crtcs[8];
+
 	unsigned int num_planes;
 	struct drm_plane *planes[8];
+
 	unsigned int num_encoders;
 	struct drm_encoder *encoders[8];
+
 	unsigned int num_connectors;
 	struct drm_connector *connectors[8];
 
@@ -53,12 +56,17 @@ struct omap_drm_private {
 
 	struct workqueue_struct *wq;
 
+	struct list_head obj_list;
+
 	bool has_dmm;
 };
 
 #ifdef CONFIG_DEBUG_FS
 int omap_debugfs_init(struct drm_minor *minor);
 void omap_debugfs_cleanup(struct drm_minor *minor);
+void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
+void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
+void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 #endif
 
 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index fcb248f..04b235b 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -277,6 +277,24 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
 	}
 }
 
+#ifdef CONFIG_DEBUG_FS
+void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+	int i, n = drm_format_num_planes(fb->pixel_format);
+
+	seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
+			(char *)&fb->pixel_format);
+
+	for (i = 0; i < n; i++) {
+		struct plane *plane = &omap_fb->planes[i];
+		seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
+				i, plane->offset, plane->pitch);
+		omap_gem_describe(plane->bo, m);
+	}
+}
+#endif
+
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
 {
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index bd35520..1d734bc 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -45,6 +45,8 @@ int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
 struct omap_gem_object {
 	struct drm_gem_object base;
 
+	struct list_head mm_list;
+
 	uint32_t flags;
 
 	/** width/height for tiled formats (rounded up to slot boundaries) */
@@ -254,13 +256,17 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
 /** get mmap offset */
 static uint64_t mmap_offset(struct drm_gem_object *obj)
 {
+	struct drm_device *dev = obj->dev;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
 	if (!obj->map_list.map) {
 		/* Make it mmapable */
 		size_t size = omap_gem_mmap_size(obj);
 		int ret = _drm_gem_create_mmap_offset_size(obj, size);
 
 		if (ret) {
-			dev_err(obj->dev->dev, "could not allocate mmap offset");
+			dev_err(dev->dev, "could not allocate mmap offset\n");
 			return 0;
 		}
 	}
@@ -764,6 +770,56 @@ void *omap_gem_vaddr(struct drm_gem_object *obj)
 	return omap_obj->vaddr;
 }
 
+#ifdef CONFIG_DEBUG_FS
+void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
+{
+	struct drm_device *dev = obj->dev;
+	struct omap_gem_object *omap_obj = to_omap_bo(obj);
+	uint64_t off = 0;
+
+	WARN_ON(! mutex_is_locked(&dev->struct_mutex));
+
+	if (obj->map_list.map)
+		off = (uint64_t)obj->map_list.hash.key;
+
+	seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
+			omap_obj->flags, obj->name, obj->refcount.refcount.counter,
+			off, omap_obj->paddr, omap_obj->paddr_cnt,
+			omap_obj->vaddr, omap_obj->roll);
+
+	if (omap_obj->flags & OMAP_BO_TILED) {
+		seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height);
+		if (omap_obj->block) {
+			struct tcm_area *area = &omap_obj->block->area;
+			seq_printf(m, " (%dx%d, %dx%d)",
+					area->p0.x, area->p0.y,
+					area->p1.x, area->p1.y);
+		}
+	} else {
+		seq_printf(m, " %d", obj->size);
+	}
+
+	seq_printf(m, "\n");
+}
+
+void omap_gem_describe_objects(struct list_head *list, struct seq_file *m)
+{
+	struct omap_gem_object *omap_obj;
+	int count = 0;
+	size_t size = 0;
+
+	list_for_each_entry(omap_obj, list, mm_list) {
+		struct drm_gem_object *obj = &omap_obj->base;
+		seq_printf(m, "   ");
+		omap_gem_describe(obj, m);
+		count++;
+		size += obj->size;
+	}
+
+	seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
+}
+#endif
+
 /* Buffer Synchronization:
  */
 
@@ -1030,6 +1086,10 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 
 	evict(obj);
 
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	list_del(&omap_obj->mm_list);
+
 	if (obj->map_list.map) {
 		drm_gem_free_mmap_offset(obj);
 	}
@@ -1130,6 +1190,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
 		goto fail;
 	}
 
+	list_add(&omap_obj->mm_list, &priv->obj_list);
+
 	obj = &omap_obj->base;
 
 	if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) {
-- 
1.7.5.4


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

* [PATCH 07/10] staging: drm/omap: Disable DMM debugfs for OMAP3
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (5 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 06/10] staging: drm/omap: debugfs for object and fb tracking Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 08/10] staging: drm/omap: Validate debugfs device Rob Clark
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Andy Gross <andy.gross@ti.com>

OMAP3 does not contain a DMM/Tiler block.  As such, we should not
be exposing any DMM debugfs entries on OMAP3 platforms.

Added inline helper function to verify existence of DMM.

Signed-off-by: Andy Gross <andy.gross@ti.com>
Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_debugfs.c   |   15 +++++++--------
 drivers/staging/omapdrm/omap_dmm_tiler.h |    6 ++++++
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_debugfs.c b/drivers/staging/omapdrm/omap_debugfs.c
index e23f907..2f122e0 100644
--- a/drivers/staging/omapdrm/omap_debugfs.c
+++ b/drivers/staging/omapdrm/omap_debugfs.c
@@ -112,12 +112,10 @@ int omap_debugfs_init(struct drm_minor *minor)
 		return ret;
 	}
 
-	/* TODO: only do this if has_dmm.. but this fxn gets called before
-	 * dev_load() so we don't know this yet..
-	 */
-	ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
-			ARRAY_SIZE(omap_dmm_debugfs_list),
-			minor->debugfs_root, minor);
+	if (dmm_is_available())
+		ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
+				ARRAY_SIZE(omap_dmm_debugfs_list),
+				minor->debugfs_root, minor);
 
 	if (ret) {
 		dev_err(dev->dev, "could not install omap_dmm_debugfs_list\n");
@@ -131,8 +129,9 @@ void omap_debugfs_cleanup(struct drm_minor *minor)
 {
 	drm_debugfs_remove_files(omap_debugfs_list,
 			ARRAY_SIZE(omap_debugfs_list), minor);
-	drm_debugfs_remove_files(omap_dmm_debugfs_list,
-			ARRAY_SIZE(omap_dmm_debugfs_list), minor);
+	if (dmm_is_available())
+		drm_debugfs_remove_files(omap_dmm_debugfs_list,
+				ARRAY_SIZE(omap_dmm_debugfs_list), minor);
 }
 
 #endif
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.h b/drivers/staging/omapdrm/omap_dmm_tiler.h
index f87cb65..55ab284 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.h
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.h
@@ -16,6 +16,7 @@
 #ifndef OMAP_DMM_TILER_H
 #define OMAP_DMM_TILER_H
 
+#include <plat/cpu.h>
 #include "omap_drv.h"
 #include "tcm.h"
 
@@ -132,4 +133,9 @@ struct omap_dmm_platform_data {
 	int irq;
 };
 
+static inline int dmm_is_available(void)
+{
+	return cpu_is_omap44xx();
+}
+
 #endif
-- 
1.7.5.4


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

* [PATCH 08/10] staging: drm/omap: Validate debugfs device
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (6 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 07/10] staging: drm/omap: Disable DMM debugfs for OMAP3 Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 09/10] staging: drm/omap: Get DMM resources from hwmod Rob Clark
  2012-03-05 16:48 ` [PATCH 10/10] staging: drm/omap: mmap of tiled buffers with stride >4kb Rob Clark
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Andy Gross <andy.gross@ti.com>

Added check for valid device information before dumping debugfs
information.

Signed-off-by: Andy Gross <andy.gross@ti.com>
Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_dmm_tiler.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
index 852d944..e4c7bb6 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -766,10 +766,18 @@ int tiler_map_show(struct seq_file *s, void *arg)
 	const char *a2d = special;
 	const char *m2dp = m2d, *a2dp = a2d;
 	char nice[128];
-	int h_adj = omap_dmm->lut_height / ydiv;
-	int w_adj = omap_dmm->lut_width / xdiv;
+	int h_adj;
+	int w_adj;
 	unsigned long flags;
 
+	if (!omap_dmm) {
+		/* early return if dmm/tiler device is not initialized */
+		return 0;
+	}
+
+	h_adj = omap_dmm->lut_height / ydiv;
+	w_adj = omap_dmm->lut_width / xdiv;
+
 	map = kzalloc(h_adj * sizeof(*map), GFP_KERNEL);
 	global_map = kzalloc((w_adj + 1) * h_adj, GFP_KERNEL);
 
-- 
1.7.5.4


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

* [PATCH 09/10] staging: drm/omap: Get DMM resources from hwmod
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (7 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 08/10] staging: drm/omap: Validate debugfs device Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  2012-03-05 16:48 ` [PATCH 10/10] staging: drm/omap: mmap of tiled buffers with stride >4kb Rob Clark
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Andy Gross <andy.gross@ti.com>

This patch splits the DMM off into a separate sub-device, in order to
utilize the platform device information that was created as part of
the OMAP hwmod entry for the DMM.

The driver probe function queries the iomem resource and IRQ using
standard platform_get functions.

The OMAP DRM driver now calls the platform_driver_register() function
for the subordinate DMM driver inside its probe function.  This
guarantees the required order for the DMM and ensures the DMM resources
are available for use by the DRM driver.

Signed-off-by: Andy Gross <andy.gross@ti.com>
Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_dmm_tiler.c |   79 +++++++++++++++++++++--------
 drivers/staging/omapdrm/omap_dmm_tiler.h |   11 +---
 drivers/staging/omapdrm/omap_drv.c       |    6 ++
 drivers/staging/omapdrm/omap_gem.c       |    8 +--
 4 files changed, 68 insertions(+), 36 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
index e4c7bb6..1ecb6a7 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -34,6 +34,8 @@
 #include "omap_dmm_tiler.h"
 #include "omap_dmm_priv.h"
 
+#define DMM_DRIVER_NAME "dmm"
+
 /* mappings for associating views to luts */
 static struct tcm *containers[TILFMT_NFORMATS];
 static struct dmm *omap_dmm;
@@ -465,7 +467,12 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
 	return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
 }
 
-int omap_dmm_remove(void)
+bool dmm_is_initialized(void)
+{
+	return omap_dmm ? true : false;
+}
+
+static int omap_dmm_remove(struct platform_device *dev)
 {
 	struct tiler_block *block, *_block;
 	int i;
@@ -499,40 +506,49 @@ int omap_dmm_remove(void)
 		if (omap_dmm->irq != -1)
 			free_irq(omap_dmm->irq, omap_dmm);
 
+		iounmap(omap_dmm->base);
 		kfree(omap_dmm);
+		omap_dmm = NULL;
 	}
 
 	return 0;
 }
 
-int omap_dmm_init(struct drm_device *dev)
+static int omap_dmm_probe(struct platform_device *dev)
 {
 	int ret = -EFAULT, i;
 	struct tcm_area area = {0};
 	u32 hwinfo, pat_geom, lut_table_size;
-	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
-
-	if (!pdata || !pdata->dmm_pdata) {
-		dev_err(dev->dev, "dmm platform data not present, skipping\n");
-		return ret;
-	}
+	struct resource *mem;
 
 	omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
 	if (!omap_dmm) {
-		dev_err(dev->dev, "failed to allocate driver data section\n");
+		dev_err(&dev->dev, "failed to allocate driver data section\n");
 		goto fail;
 	}
 
 	/* lookup hwmod data - base address and irq */
-	omap_dmm->base = pdata->dmm_pdata->base;
-	omap_dmm->irq = pdata->dmm_pdata->irq;
-	omap_dmm->dev = dev->dev;
+	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&dev->dev, "failed to get base address resource\n");
+		goto fail;
+	}
+
+	omap_dmm->base = ioremap(mem->start, SZ_2K);
 
 	if (!omap_dmm->base) {
-		dev_err(dev->dev, "failed to get dmm base address\n");
+		dev_err(&dev->dev, "failed to get dmm base address\n");
 		goto fail;
 	}
 
+	omap_dmm->irq = platform_get_irq(dev, 0);
+	if (omap_dmm->irq < 0) {
+		dev_err(&dev->dev, "failed to get IRQ resource\n");
+		goto fail;
+	}
+
+	omap_dmm->dev = &dev->dev;
+
 	hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
 	omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
 	omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
@@ -556,7 +572,7 @@ int omap_dmm_init(struct drm_device *dev)
 				"omap_dmm_irq_handler", omap_dmm);
 
 	if (ret) {
-		dev_err(dev->dev, "couldn't register IRQ %d, error %d\n",
+		dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
 			omap_dmm->irq, ret);
 		omap_dmm->irq = -1;
 		goto fail;
@@ -575,25 +591,30 @@ int omap_dmm_init(struct drm_device *dev)
 
 	omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut));
 	if (!omap_dmm->lut) {
-		dev_err(dev->dev, "could not allocate lut table\n");
+		dev_err(&dev->dev, "could not allocate lut table\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
 
 	omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
 	if (!omap_dmm->dummy_page) {
-		dev_err(dev->dev, "could not allocate dummy page\n");
+		dev_err(&dev->dev, "could not allocate dummy page\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
+
+	/* set dma mask for device */
+	/* NOTE: this is a workaround for the hwmod not initializing properly */
+	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
 	omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 
 	/* alloc refill memory */
-	omap_dmm->refill_va = dma_alloc_coherent(dev->dev,
+	omap_dmm->refill_va = dma_alloc_coherent(&dev->dev,
 				REFILL_BUFFER_SIZE * omap_dmm->num_engines,
 				&omap_dmm->refill_pa, GFP_KERNEL);
 	if (!omap_dmm->refill_va) {
-		dev_err(dev->dev, "could not allocate refill memory\n");
+		dev_err(&dev->dev, "could not allocate refill memory\n");
 		goto fail;
 	}
 
@@ -602,7 +623,7 @@ int omap_dmm_init(struct drm_device *dev)
 			omap_dmm->num_engines * sizeof(struct refill_engine),
 			GFP_KERNEL);
 	if (!omap_dmm->engines) {
-		dev_err(dev->dev, "could not allocate engines\n");
+		dev_err(&dev->dev, "could not allocate engines\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -624,7 +645,7 @@ int omap_dmm_init(struct drm_device *dev)
 	omap_dmm->tcm = kzalloc(omap_dmm->num_lut * sizeof(*omap_dmm->tcm),
 				GFP_KERNEL);
 	if (!omap_dmm->tcm) {
-		dev_err(dev->dev, "failed to allocate lut ptrs\n");
+		dev_err(&dev->dev, "failed to allocate lut ptrs\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -636,7 +657,7 @@ int omap_dmm_init(struct drm_device *dev)
 						NULL);
 
 		if (!omap_dmm->tcm[i]) {
-			dev_err(dev->dev, "failed to allocate container\n");
+			dev_err(&dev->dev, "failed to allocate container\n");
 			ret = -ENOMEM;
 			goto fail;
 		}
@@ -676,7 +697,7 @@ int omap_dmm_init(struct drm_device *dev)
 	return 0;
 
 fail:
-	omap_dmm_remove();
+	omap_dmm_remove(dev);
 	return ret;
 }
 
@@ -836,3 +857,17 @@ error:
 	return 0;
 }
 #endif
+
+struct platform_driver omap_dmm_driver = {
+	.probe = omap_dmm_probe,
+	.remove = omap_dmm_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DMM_DRIVER_NAME,
+	},
+};
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
+MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
+MODULE_ALIAS("platform:" DMM_DRIVER_NAME);
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.h b/drivers/staging/omapdrm/omap_dmm_tiler.h
index 55ab284..7b1052a 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.h
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.h
@@ -73,10 +73,6 @@ struct tiler_block {
 #define TIL_ADDR(x, orient, a)\
 	((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
 
-/* externally accessible functions */
-int omap_dmm_init(struct drm_device *dev);
-int omap_dmm_remove(void);
-
 #ifdef CONFIG_DEBUG_FS
 int tiler_map_show(struct seq_file *s, void *arg);
 #endif
@@ -98,7 +94,9 @@ uint32_t tiler_stride(enum tiler_fmt fmt);
 size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
+bool dmm_is_initialized(void);
 
+extern struct platform_driver omap_dmm_driver;
 
 /* GEM bo flags -> tiler fmt */
 static inline enum tiler_fmt gem2fmt(uint32_t flags)
@@ -128,11 +126,6 @@ static inline bool validfmt(enum tiler_fmt fmt)
 	}
 }
 
-struct omap_dmm_platform_data {
-	void __iomem *base;
-	int irq;
-};
-
 static inline int dmm_is_available(void)
 {
 	return cpu_is_omap44xx();
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index e2100bb..3df5b4c 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -21,6 +21,7 @@
 
 #include "drm_crtc_helper.h"
 #include "drm_fb_helper.h"
+#include "omap_dmm_tiler.h"
 
 #define DRIVER_NAME		MODULE_NAME
 #define DRIVER_DESC		"OMAP DRM"
@@ -802,6 +803,9 @@ static void pdev_shutdown(struct platform_device *device)
 static int pdev_probe(struct platform_device *device)
 {
 	DBG("%s", device->name);
+	if (platform_driver_register(&omap_dmm_driver))
+		dev_err(&device->dev, "DMM registration failed\n");
+
 	return drm_platform_init(&omap_drm_driver, device);
 }
 
@@ -809,6 +813,8 @@ static int pdev_remove(struct platform_device *device)
 {
 	DBG("");
 	drm_platform_exit(&omap_drm_driver, device);
+
+	platform_driver_unregister(&omap_dmm_driver);
 	return 0;
 }
 
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index 1d734bc..5abd294 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -1238,12 +1238,11 @@ void omap_gem_init(struct drm_device *dev)
 	const enum tiler_fmt fmts[] = {
 			TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT
 	};
-	int i, j, ret;
+	int i, j;
 
-	ret = omap_dmm_init(dev);
-	if (ret) {
+	if (!dmm_is_initialized()) {
 		/* DMM only supported on OMAP4 and later, so this isn't fatal */
-		dev_warn(dev->dev, "omap_dmm_init failed, disabling DMM\n");
+		dev_warn(dev->dev, "DMM not available, disable DMM support\n");
 		return;
 	}
 
@@ -1293,6 +1292,5 @@ void omap_gem_deinit(struct drm_device *dev)
 	/* I believe we can rely on there being no more outstanding GEM
 	 * objects which could depend on usergart/dmm at this point.
 	 */
-	omap_dmm_remove();
 	kfree(usergart);
 }
-- 
1.7.5.4


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

* [PATCH 10/10] staging: drm/omap: mmap of tiled buffers with stride >4kb
  2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
                   ` (8 preceding siblings ...)
  2012-03-05 16:48 ` [PATCH 09/10] staging: drm/omap: Get DMM resources from hwmod Rob Clark
@ 2012-03-05 16:48 ` Rob Clark
  9 siblings, 0 replies; 11+ messages in thread
From: Rob Clark @ 2012-03-05 16:48 UTC (permalink / raw)
  To: dri-devel, linux-omap
  Cc: patches, Greg KH, Tomi Valkeinen, Andy Gross, Rob Clark

From: Rob Clark <rob@ti.com>

Deal with the case of buffers with virtual stride larger than one
page in fault_2d().

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_gem.c |   86 ++++++++++++++++++++++++-----------
 1 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index 5abd294..921f058 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -153,10 +153,23 @@ static void evict_entry(struct drm_gem_object *obj,
 		enum tiler_fmt fmt, struct usergart_entry *entry)
 {
 	if (obj->dev->dev_mapping) {
-		size_t size = PAGE_SIZE * usergart[fmt].height;
+		struct omap_gem_object *omap_obj = to_omap_bo(obj);
+		int n = usergart[fmt].height;
+		size_t size = PAGE_SIZE * n;
 		loff_t off = mmap_offset(obj) +
 				(entry->obj_pgoff << PAGE_SHIFT);
-		unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
+		const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE);
+		if (m > 1) {
+			int i;
+			/* if stride > than PAGE_SIZE then sparse mapping: */
+			for (i = n; i > 0; i--) {
+				unmap_mapping_range(obj->dev->dev_mapping,
+						off, PAGE_SIZE, 1);
+				off += PAGE_SIZE * m;
+			}
+		} else {
+			unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
+		}
 	}
 
 	entry->obj = NULL;
@@ -342,26 +355,39 @@ static int fault_2d(struct drm_gem_object *obj,
 	void __user *vaddr;
 	int i, ret, slots;
 
-	if (!usergart)
-		return -EFAULT;
-
-	/* TODO: this fxn might need a bit tweaking to deal w/ tiled buffers
-	 * that are wider than 4kb
+	/*
+	 * Note the height of the slot is also equal to the number of pages
+	 * that need to be mapped in to fill 4kb wide CPU page.  If the slot
+	 * height is 64, then 64 pages fill a 4kb wide by 64 row region.
+	 */
+	const int n = usergart[fmt].height;
+	const int n_shift = usergart[fmt].height_shift;
+
+	/*
+	 * If buffer width in bytes > PAGE_SIZE then the virtual stride is
+	 * rounded up to next multiple of PAGE_SIZE.. this need to be taken
+	 * into account in some of the math, so figure out virtual stride
+	 * in pages
 	 */
+	const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE);
 
 	/* We don't use vmf->pgoff since that has the fake offset: */
 	pgoff = ((unsigned long)vmf->virtual_address -
 			vma->vm_start) >> PAGE_SHIFT;
 
-	/* actual address we start mapping at is rounded down to previous slot
+	/*
+	 * Actual address we start mapping at is rounded down to previous slot
 	 * boundary in the y direction:
 	 */
-	base_pgoff = round_down(pgoff, usergart[fmt].height);
-	vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
-	entry = &usergart[fmt].entry[usergart[fmt].last];
+	base_pgoff = round_down(pgoff, m << n_shift);
 
+	/* figure out buffer width in slots */
 	slots = omap_obj->width >> usergart[fmt].slot_shift;
 
+	vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
+
+	entry = &usergart[fmt].entry[usergart[fmt].last];
+
 	/* evict previous buffer using this usergart entry, if any: */
 	if (entry->obj)
 		evict_entry(entry->obj, fmt, entry);
@@ -369,23 +395,30 @@ static int fault_2d(struct drm_gem_object *obj,
 	entry->obj = obj;
 	entry->obj_pgoff = base_pgoff;
 
-	/* now convert base_pgoff to phys offset from virt offset:
-	 */
-	base_pgoff = (base_pgoff >> usergart[fmt].height_shift) * slots;
-
-	/* map in pages.  Note the height of the slot is also equal to the
-	 * number of pages that need to be mapped in to fill 4kb wide CPU page.
-	 * If the height is 64, then 64 pages fill a 4kb wide by 64 row region.
-	 * Beyond the valid pixel part of the buffer, we set pages[i] to NULL to
-	 * get a dummy page mapped in.. if someone reads/writes it they will get
-	 * random/undefined content, but at least it won't be corrupting
-	 * whatever other random page used to be mapped in, or other undefined
-	 * behavior.
+	/* now convert base_pgoff to phys offset from virt offset: */
+	base_pgoff = (base_pgoff >> n_shift) * slots;
+
+	/* for wider-than 4k.. figure out which part of the slot-row we want: */
+	if (m > 1) {
+		int off = pgoff % m;
+		entry->obj_pgoff += off;
+		base_pgoff /= m;
+		slots = min(slots - (off << n_shift), n);
+		base_pgoff += off << n_shift;
+		vaddr += off << PAGE_SHIFT;
+	}
+
+	/*
+	 * Map in pages. Beyond the valid pixel part of the buffer, we set
+	 * pages[i] to NULL to get a dummy page mapped in.. if someone
+	 * reads/writes it they will get random/undefined content, but at
+	 * least it won't be corrupting whatever other random page used to
+	 * be mapped in, or other undefined behavior.
 	 */
 	memcpy(pages, &omap_obj->pages[base_pgoff],
 			sizeof(struct page *) * slots);
 	memset(pages + slots, 0,
-			sizeof(struct page *) * (usergart[fmt].height - slots));
+			sizeof(struct page *) * (n - slots));
 
 	ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true);
 	if (ret) {
@@ -393,16 +426,15 @@ static int fault_2d(struct drm_gem_object *obj,
 		return ret;
 	}
 
-	i = usergart[fmt].height;
 	pfn = entry->paddr >> PAGE_SHIFT;
 
 	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
 			pfn, pfn << PAGE_SHIFT);
 
-	while (i--) {
+	for (i = n; i > 0; i--) {
 		vm_insert_mixed(vma, (unsigned long)vaddr, pfn);
 		pfn += usergart[fmt].stride_pfn;
-		vaddr += PAGE_SIZE;
+		vaddr += PAGE_SIZE * m;
 	}
 
 	/* simple round-robin: */
-- 
1.7.5.4


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

end of thread, other threads:[~2012-03-05 16:49 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-05 16:48 [PATCH 00/10] omapdrm patches for 3.4 Rob Clark
2012-03-05 16:48 ` [PATCH 01/10] staging: drm/omap: get supported color formats from ovl Rob Clark
2012-03-05 16:48 ` [PATCH 02/10] staging: drm/omap: add a workqueue Rob Clark
2012-03-05 16:48 ` [PATCH 03/10] staging: drm/omap: call omap_gem_roll() in non-atomic ctx Rob Clark
2012-03-05 16:48 ` [PATCH 04/10] staging: drm/omap: some minor fb cleanups Rob Clark
2012-03-05 16:48 ` [PATCH 05/10] staging: drm/omap: defer unpin until scanout completes Rob Clark
2012-03-05 16:48 ` [PATCH 06/10] staging: drm/omap: debugfs for object and fb tracking Rob Clark
2012-03-05 16:48 ` [PATCH 07/10] staging: drm/omap: Disable DMM debugfs for OMAP3 Rob Clark
2012-03-05 16:48 ` [PATCH 08/10] staging: drm/omap: Validate debugfs device Rob Clark
2012-03-05 16:48 ` [PATCH 09/10] staging: drm/omap: Get DMM resources from hwmod Rob Clark
2012-03-05 16:48 ` [PATCH 10/10] staging: drm/omap: mmap of tiled buffers with stride >4kb Rob Clark

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.