All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] drm/tinydrm: Use vmalloc BO
@ 2017-10-04 18:06 Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 1/8] drm/fb-helper: Handle function NULL argument Noralf Trønnes
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

This patchset adds a library for vmalloc buffer objects and makes use of
it in tinydrm.

The reason I want to move away from the cma helper, is that it restricts
which drivers to PRIME import from, since cma requires the buffer to be
physically continuous. Initially I looked at udl and decided to use
shmem, but have later decided against it since shmem doesn't work with
fbdev deferred I/O, they both use page->lru and page->mapping. This
meant adding a shadow buffer for fbdev with increased complexity, so I
fell back to the KISS principle.

I'm trying to make tinydrm support drivers like simpledrm and udl, so if
using vmalloc blocks those use cases, please let me know.

I will do a follow up for the cma library which removes struct
drm_fbdev_cma and wrappers.

Noralf.

Noralf Trønnes (8):
  drm/fb-helper: Handle function NULL argument
  drm: Add drm_device->fbdev pointer
  drm/fb-helper: Add simple init/fini functions
  drm/fb-helper: Add .last_close and .output_poll_changed helpers
  drm/gem-fb-helper: Add drm_gem_fb_debugfs_show()
  drm: Add vmalloc BO helper
  drm/tinydrm: Use drm_vmalloc_bo
  drm/tinydrm: Relax buffer line prefetch

 Documentation/gpu/drm-kms-helpers.rst          |  12 +
 drivers/gpu/drm/Kconfig                        |   7 +
 drivers/gpu/drm/Makefile                       |   1 +
 drivers/gpu/drm/drm_fb_helper.c                | 223 +++++++++++++++++-
 drivers/gpu/drm/drm_gem_framebuffer_helper.c   |  45 ++++
 drivers/gpu/drm/drm_vmalloc_bo_helper.c        | 305 +++++++++++++++++++++++++
 drivers/gpu/drm/tinydrm/Kconfig                |   2 +-
 drivers/gpu/drm/tinydrm/core/tinydrm-core.c    | 134 +++--------
 drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c |  56 +++--
 drivers/gpu/drm/tinydrm/mi0283qt.c             |   8 +-
 drivers/gpu/drm/tinydrm/mipi-dbi.c             |  12 +-
 drivers/gpu/drm/tinydrm/repaper.c              |  12 +-
 drivers/gpu/drm/tinydrm/st7586.c               |  14 +-
 include/drm/drm_device.h                       |   8 +
 include/drm/drm_fb_helper.h                    |  32 +++
 include/drm/drm_gem_framebuffer_helper.h       |   6 +
 include/drm/drm_vmalloc_bo_helper.h            |  88 +++++++
 include/drm/tinydrm/mipi-dbi.h                 |   2 +
 include/drm/tinydrm/tinydrm.h                  |  38 +--
 19 files changed, 811 insertions(+), 194 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_vmalloc_bo_helper.c
 create mode 100644 include/drm/drm_vmalloc_bo_helper.h

-- 
2.7.4

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

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

* [PATCH 1/8] drm/fb-helper: Handle function NULL argument
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 2/8] drm: Add drm_device->fbdev pointer Noralf Trønnes
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

Make functions tolerate that the drm_fb_helper argument is NULL.
This is useful for drivers that continue probing when fbdev emulation
fails and not having to do this check themselves.
Update docs for functions that already handles this.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_fb_helper.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 6a31d13..98aa6b5 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -150,6 +150,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
 {
 	int err;
 
+	if (!fb_helper)
+		return 0;
+
 	mutex_lock(&fb_helper->lock);
 	err = __drm_fb_helper_add_one_connector(fb_helper, connector);
 	mutex_unlock(&fb_helper->lock);
@@ -161,7 +164,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
 /**
  * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
  * 					       emulation helper
- * @fb_helper: fbdev initialized with drm_fb_helper_init
+ * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
  *
  * This functions adds all the available connectors for use with the given
  * fb_helper. This is a separate step to allow drivers to freely assign
@@ -179,7 +182,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
 	struct drm_connector_list_iter conn_iter;
 	int i, ret = 0;
 
-	if (!drm_fbdev_emulation)
+	if (!drm_fbdev_emulation || !fb_helper)
 		return 0;
 
 	mutex_lock(&fb_helper->lock);
@@ -245,6 +248,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 {
 	int err;
 
+	if (!fb_helper)
+		return 0;
+
 	mutex_lock(&fb_helper->lock);
 	err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
 	mutex_unlock(&fb_helper->lock);
@@ -484,7 +490,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
- * @fb_helper: fbcon to restore
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * This should be called from driver's drm &drm_driver.lastclose callback
  * when implementing an fbcon on top of kms using this helper. This ensures that
@@ -498,7 +504,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 	bool do_delayed;
 	int ret;
 
-	if (!drm_fbdev_emulation)
+	if (!drm_fbdev_emulation || !fb_helper)
 		return -ENODEV;
 
 	if (READ_ONCE(fb_helper->deferred_setup))
@@ -883,7 +889,7 @@ EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
 
 /**
  * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * A wrapper around unregister_framebuffer, to release the fb_info
  * framebuffer device. This must be called before releasing all resources for
@@ -898,7 +904,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
 
 /**
  * drm_fb_helper_fini - finialize a &struct drm_fb_helper
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * This cleans up all remaining resources associated with @fb_helper. Must be
  * called after drm_fb_helper_unlink_fbi() was called.
@@ -937,7 +943,7 @@ EXPORT_SYMBOL(drm_fb_helper_fini);
 
 /**
  * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * A wrapper around unlink_framebuffer implemented by fbdev core
  */
@@ -1138,7 +1144,7 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
 
 /**
  * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  * @suspend: whether to suspend or resume
  *
  * A wrapper around fb_set_suspend implemented by fbdev core.
@@ -1155,7 +1161,7 @@ EXPORT_SYMBOL(drm_fb_helper_set_suspend);
 /**
  * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
  *                                      takes the console lock
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  * @suspend: whether to suspend or resume
  *
  * A wrapper around fb_set_suspend() that takes the console lock. If the lock
@@ -2568,7 +2574,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
 /**
  * drm_fb_helper_hotplug_event - respond to a hotplug notification by
  *                               probing all the outputs attached to the fb
- * @fb_helper: the drm_fb_helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * Scan the connectors attached to the fb_helper and try to put together a
  * setup after notification of a change in output configuration.
@@ -2590,7 +2596,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
 	int err = 0;
 
-	if (!drm_fbdev_emulation)
+	if (!drm_fbdev_emulation || !fb_helper)
 		return 0;
 
 	mutex_lock(&fb_helper->lock);
-- 
2.7.4

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

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

* [PATCH 2/8] drm: Add drm_device->fbdev pointer
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 1/8] drm/fb-helper: Handle function NULL argument Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 3/8] drm/fb-helper: Add simple init/fini functions Noralf Trønnes
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

drm_fb_helper is *the* way of doing fbdev emulation so add a pointer to
struct drm_device. This makes it possible to add callback helpers for
.last_close and .output_poll_changed further reducing fbdev emulation
footprint in drivers.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 include/drm/drm_device.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index e21af87..3c104b1 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -17,6 +17,7 @@ struct drm_vblank_crtc;
 struct drm_sg_mem;
 struct drm_local_map;
 struct drm_vma_offset_manager;
+struct drm_fb_helper;
 
 struct inode;
 
@@ -185,6 +186,13 @@ struct drm_device {
 	struct drm_vma_offset_manager *vma_offset_manager;
 	/*@} */
 	int switch_power_state;
+
+	/**
+	 * @fbdev:
+	 *
+	 * Optional pointer to the fbdev emulation structure.
+	 */
+	struct drm_fb_helper *fbdev;
 };
 
 #endif
-- 
2.7.4

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

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

* [PATCH 3/8] drm/fb-helper: Add simple init/fini functions
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 1/8] drm/fb-helper: Handle function NULL argument Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 2/8] drm: Add drm_device->fbdev pointer Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 4/8] drm/fb-helper: Add .last_close and .output_poll_changed helpers Noralf Trønnes
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

This adds some simple init/fini helpers for drivers that don't need
anything special in their fbdev emulation setup.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_fb_helper.c | 163 ++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_fb_helper.h     |  22 ++++++
 2 files changed, 185 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 98aa6b5..ca8a961 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -105,6 +105,127 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * mmap page writes.
  */
 
+/**
+ * drm_fb_helper_simple_init - Simple fbdev emulation setup
+ * @dev: DRM device
+ * @funcs: Pointer to structure of functions associated with this helper
+ * @bpp: Bits per pixel value to use for the framebuffer configuration.
+ *       @dev->mode_config.preferred_depth is used if this is zero.
+ * @max_conn: Max connector count. @dev->mode_config.num_connector is used if
+ *            this is zero.
+ *
+ * Simple fbdev emulation initialization. This function allocates a
+ * &drm_fb_helper structure attaches it to &drm_device->fbdev and calls:
+ * drm_fb_helper_prepare(), drm_fb_helper_init(),
+ * drm_fb_helper_single_add_all_connectors() and
+ * drm_fb_helper_initial_config().
+ *
+ * If fbdev emulation is disabled, this function does nothing. In that case
+ * &drm_device->fbdev will be NULL. All drm_fb_helper entry function can handle
+ * a NULL argument.
+ *
+ * fbdev deferred I/O users should use the drm_fb_helper_defio_init() function
+ * in their &drm_fb_helper_funcs.fb_probe callback.
+ *
+ * Returns:
+ * Zero on success or if fbdev emulation is disabled, negative error code on
+ * failure.
+ */
+int drm_fb_helper_simple_init(struct drm_device *dev,
+			      const struct drm_fb_helper_funcs *funcs,
+			      unsigned int bpp, int max_conn)
+{
+	struct drm_fb_helper *fb_helper;
+	int ret;
+
+	if (!drm_fbdev_emulation)
+		return 0;
+
+	if (!bpp)
+		bpp = dev->mode_config.preferred_depth;
+
+	if (!max_conn)
+		max_conn = dev->mode_config.num_connector;
+
+	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+	if (!fb_helper)
+		return -ENOMEM;
+
+	drm_fb_helper_prepare(dev, fb_helper, funcs);
+
+	ret = drm_fb_helper_init(dev, fb_helper, max_conn);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev->dev, "Failed to initialize fb helper.\n");
+		goto err_drm_fb_helper_free;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev->dev, "Failed to add connectors.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	ret = drm_fb_helper_initial_config(fb_helper, bpp);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev->dev, "Failed to set initial hw config.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	dev->fbdev = fb_helper;
+
+	return 0;
+
+err_drm_fb_helper_fini:
+	drm_fb_helper_fini(fb_helper);
+err_drm_fb_helper_free:
+	kfree(fb_helper);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_fb_helper_simple_init);
+
+/**
+ * drm_fb_helper_simple_fini - Simple fbdev cleanup
+ * @dev: DRM device
+ *
+ * Simple fbdev emulation cleanup. This function unregisters fbdev if it is not
+ * done, cleans up deferred IO if necessary, removes framebuffer, finalizes
+ * @fb_helper and frees the structure.
+ */
+void drm_fb_helper_simple_fini(struct drm_device *dev)
+{
+	struct drm_fb_helper *fb_helper = dev->fbdev;
+	struct fb_info *info;
+	struct fb_ops *fbops;
+
+	if (!fb_helper)
+		return;
+
+	dev->fbdev = NULL;
+	info = fb_helper->fbdev;
+
+	/* Make sure it hasn't been unregistered already */
+	if (info && info->dev)
+		drm_fb_helper_unregister_fbi(fb_helper);
+
+	if (info && info->fbdefio) {
+		fb_deferred_io_cleanup(info);
+		kfree(info->fbdefio);
+		fbops = info->fbops;
+	}
+
+	drm_fb_helper_fini(fb_helper);
+
+	if (info && info->fbdefio)
+		kfree(fbops);
+
+	if (fb_helper->fb)
+		drm_framebuffer_remove(fb_helper->fb);
+
+	kfree(fb_helper);
+}
+EXPORT_SYMBOL_GPL(drm_fb_helper_simple_fini);
+
 #define drm_fb_helper_for_each_connector(fbh, i__) \
 	for (({ lockdep_assert_held(&(fbh)->lock); }), \
 	     i__ = 0; i__ < (fbh)->connector_count; i__++)
@@ -954,6 +1075,48 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
 
+/**
+ * drm_fb_helper_defio_init - fbdev deferred I/O initialization
+ * @fb_helper: driver-allocated fbdev helper
+ *
+ * This function allocates &fb_deferred_io, sets callback to
+ * drm_fb_helper_deferred_io(), delay to 50ms and calls fb_deferred_io_init().
+ *
+ * NOTE: A copy of &fb_ops is made and assigned to &info->fbops. This is done
+ * because fb_deferred_io_cleanup() clears &fbops->fb_mmap and would thereby
+ * affect other instances of that &fb_ops. This copy is freed in
+ * drm_fb_helper_simple_fini().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
+{
+	struct fb_info *info = fb_helper->fbdev;
+	struct fb_deferred_io *fbdefio;
+	struct fb_ops *fbops;
+
+	fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
+	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
+	if (!fbdefio || !fbops) {
+		kfree(fbdefio);
+		kfree(fbops);
+		return -ENOMEM;
+	}
+
+	info->fbdefio = fbdefio;
+	fbdefio->delay = msecs_to_jiffies(50);
+	fbdefio->deferred_io = drm_fb_helper_deferred_io;
+
+	*fbops = *info->fbops;
+	info->fbops = fbops;
+
+	fb_deferred_io_init(info);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_defio_init);
+
 static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
 				u32 width, u32 height)
 {
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 33fe959..6503f4c 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -242,6 +242,10 @@ struct drm_fb_helper {
 	.fb_ioctl	= drm_fb_helper_ioctl
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
+int drm_fb_helper_simple_init(struct drm_device *dev,
+			      const struct drm_fb_helper_funcs *funcs,
+			      unsigned int bpp, int max_conn);
+void drm_fb_helper_simple_fini(struct drm_device *dev);
 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 			   const struct drm_fb_helper_funcs *funcs);
 int drm_fb_helper_init(struct drm_device *dev,
@@ -265,6 +269,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 
 void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
 
+int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_deferred_io(struct fb_info *info,
 			       struct list_head *pagelist);
 
@@ -311,6 +316,18 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 				       struct drm_connector *connector);
 #else
+static inline int
+drm_fb_helper_simple_init(struct drm_device *dev,
+			  const struct drm_fb_helper_funcs *funcs,
+			  unsigned int bpp, int max_conn)
+{
+	return 0;
+}
+
+static inline void drm_fb_helper_simple_fini(struct drm_device *dev)
+{
+}
+
 static inline void drm_fb_helper_prepare(struct drm_device *dev,
 					struct drm_fb_helper *helper,
 					const struct drm_fb_helper_funcs *funcs)
@@ -393,6 +410,11 @@ static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
 {
 }
 
+static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
+{
+	return -ENODEV;
+}
+
 static inline void drm_fb_helper_deferred_io(struct fb_info *info,
 					     struct list_head *pagelist)
 {
-- 
2.7.4

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

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

* [PATCH 4/8] drm/fb-helper: Add .last_close and .output_poll_changed helpers
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
                   ` (2 preceding siblings ...)
  2017-10-04 18:06 ` [PATCH 3/8] drm/fb-helper: Add simple init/fini functions Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 5/8] drm/gem-fb-helper: Add drm_gem_fb_debugfs_show() Noralf Trønnes
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

This adds helpers for the drm_driver->last_close and the
drm_mode_config_funcs->output_poll_changed callbacks.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_fb_helper.c | 32 ++++++++++++++++++++++++++++++++
 include/drm/drm_fb_helper.h     | 10 ++++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index ca8a961..a98cc2c 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -226,6 +226,38 @@ void drm_fb_helper_simple_fini(struct drm_device *dev)
 }
 EXPORT_SYMBOL_GPL(drm_fb_helper_simple_fini);
 
+/**
+ * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the &drm_driver->lastclose callback for drivers
+ * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
+ *
+ * Note: &drm_device->fbdev needs to be set.
+ */
+void drm_fb_helper_lastclose(struct drm_device *dev)
+{
+	drm_fb_helper_restore_fbdev_mode_unlocked(dev->fbdev);
+}
+EXPORT_SYMBOL(drm_fb_helper_lastclose);
+
+/**
+ * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
+ *                                     helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the
+ * &drm_mode_config_funcs.output_poll_changed callback for drivers that only
+ * need to call drm_fb_helper_hotplug_event().
+ *
+ * Note: &drm_device->fbdev needs to be set.
+ */
+void drm_fb_helper_output_poll_changed(struct drm_device *dev)
+{
+	drm_fb_helper_hotplug_event(dev->fbdev);
+}
+EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
+
 #define drm_fb_helper_for_each_connector(fbh, i__) \
 	for (({ lockdep_assert_held(&(fbh)->lock); }), \
 	     i__ = 0; i__ < (fbh)->connector_count; i__++)
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 6503f4c..2558425 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -246,6 +246,8 @@ int drm_fb_helper_simple_init(struct drm_device *dev,
 			      const struct drm_fb_helper_funcs *funcs,
 			      unsigned int bpp, int max_conn);
 void drm_fb_helper_simple_fini(struct drm_device *dev);
+void drm_fb_helper_lastclose(struct drm_device *dev);
+void drm_fb_helper_output_poll_changed(struct drm_device *dev);
 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 			   const struct drm_fb_helper_funcs *funcs);
 int drm_fb_helper_init(struct drm_device *dev,
@@ -328,6 +330,14 @@ static inline void drm_fb_helper_simple_fini(struct drm_device *dev)
 {
 }
 
+static inline void drm_fb_helper_lastclose(struct drm_device *dev)
+{
+}
+
+static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
+{
+}
+
 static inline void drm_fb_helper_prepare(struct drm_device *dev,
 					struct drm_fb_helper *helper,
 					const struct drm_fb_helper_funcs *funcs)
-- 
2.7.4

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

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

* [PATCH 5/8] drm/gem-fb-helper: Add drm_gem_fb_debugfs_show()
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
                   ` (3 preceding siblings ...)
  2017-10-04 18:06 ` [PATCH 4/8] drm/fb-helper: Add .last_close and .output_poll_changed helpers Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 6/8] drm: Add vmalloc BO helper Noralf Trønnes
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

Add drm_gem_fb_debugfs_show() function to provide a debugfs
representation of the framebuffer and GEM object(s).

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_gem_framebuffer_helper.c | 45 ++++++++++++++++++++++++++++
 include/drm/drm_gem_framebuffer_helper.h     |  6 ++++
 2 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index fc7e995..054eee0 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -245,6 +245,51 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane,
 }
 EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb);
 
+#ifdef CONFIG_DEBUG_FS
+static void drm_gem_fb_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+	struct drm_gem_object *obj;
+	unsigned int i;
+
+	seq_printf(m, "[FB:%d] %dx%d@%4.4s\n", fb->base.id, fb->width,
+		   fb->height, (char *)&fb->format->format);
+
+	for (i = 0; i < fb->format->num_planes; i++) {
+		obj = fb->obj[i];
+		seq_printf(m, "\t%u: offset=%d pitch=%d, GEM: name=%d",
+			   i, fb->offsets[i], fb->pitches[i], obj->name);
+		seq_printf(m, " refcount=%d start=%08lx size=%zu%s\n",
+			   kref_read(&obj->refcount),
+			   drm_vma_node_start(&obj->vma_node), obj->size,
+			   obj->import_attach ? " (imported)" : "");
+	}
+}
+
+/**
+ * drm_gem_fb_debugfs_show() - Helper to list GEM backed framebuffer objects
+ *                             in debugfs.
+ * @m: Output file
+ * @arg: Private data for the callback
+ *
+ * This function gives a debugfs representation of the framebuffers with their
+ * backing GEM objects. See drm_debugfs_create_files() for more info.
+ */
+int drm_gem_fb_debugfs_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_framebuffer *fb;
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	drm_for_each_fb(fb, dev)
+		drm_gem_fb_describe(fb, m);
+	mutex_unlock(&dev->mode_config.fb_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_debugfs_show);
+#endif
+
 /**
  * drm_gem_fbdev_fb_create - Create a drm_framebuffer for fbdev emulation
  * @dev: DRM device
diff --git a/include/drm/drm_gem_framebuffer_helper.h b/include/drm/drm_gem_framebuffer_helper.h
index 5ca7cdc..1bb73d9 100644
--- a/include/drm/drm_gem_framebuffer_helper.h
+++ b/include/drm/drm_gem_framebuffer_helper.h
@@ -28,6 +28,12 @@ drm_gem_fb_create(struct drm_device *dev, struct drm_file *file,
 int drm_gem_fb_prepare_fb(struct drm_plane *plane,
 			  struct drm_plane_state *state);
 
+#ifdef CONFIG_DEBUG_FS
+struct seq_file;
+
+int drm_gem_fb_debugfs_show(struct seq_file *m, void *arg);
+#endif
+
 struct drm_framebuffer *
 drm_gem_fbdev_fb_create(struct drm_device *dev,
 			struct drm_fb_helper_surface_size *sizes,
-- 
2.7.4

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

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

* [PATCH 6/8] drm: Add vmalloc BO helper
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
                   ` (4 preceding siblings ...)
  2017-10-04 18:06 ` [PATCH 5/8] drm/gem-fb-helper: Add drm_gem_fb_debugfs_show() Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 7/8] drm/tinydrm: Use drm_vmalloc_bo Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 8/8] drm/tinydrm: Relax buffer line prefetch Noralf Trønnes
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

Add vmalloc buffer object helper that can be useful for modesetting
drivers, particularly the framebuffer flushing kind.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 Documentation/gpu/drm-kms-helpers.rst   |  12 ++
 drivers/gpu/drm/Kconfig                 |   7 +
 drivers/gpu/drm/Makefile                |   1 +
 drivers/gpu/drm/drm_vmalloc_bo_helper.c | 305 ++++++++++++++++++++++++++++++++
 include/drm/drm_vmalloc_bo_helper.h     |  88 +++++++++
 5 files changed, 413 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_vmalloc_bo_helper.c
 create mode 100644 include/drm/drm_vmalloc_bo_helper.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 13dd237..fd1ca10 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -305,3 +305,15 @@ Framebuffer GEM Helper Reference
 
 .. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
    :export:
+
+vmalloc buffer object helper
+============================
+
+.. kernel-doc:: drivers/gpu/drm/drm_vmalloc_bo_helper.c
+   :doc: overview
+
+.. kernel-doc:: include/drm/drm_vmalloc_bo_helper.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_vmalloc_bo_helper.c
+   :export:
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c9f09fc..09ccaca 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -145,6 +145,13 @@ config DRM_KMS_CMA_HELPER
 	help
 	  Choose this if you need the KMS CMA helper functions
 
+config DRM_VMALLOC_BO_HELPER
+	bool
+	depends on DRM
+	select DRM_KMS_HELPER
+	help
+	  Choose this if you need the vmalloc buffer object helper functions
+
 config DRM_VM
 	bool
 	depends on DRM && MMU
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0ee184f..c98bf54 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -39,6 +39,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
+drm_kms_helper-$(CONFIG_DRM_VMALLOC_BO_HELPER) += drm_vmalloc_bo_helper.o
 drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
diff --git a/drivers/gpu/drm/drm_vmalloc_bo_helper.c b/drivers/gpu/drm/drm_vmalloc_bo_helper.c
new file mode 100644
index 0000000..4015b9d
--- /dev/null
+++ b/drivers/gpu/drm/drm_vmalloc_bo_helper.c
@@ -0,0 +1,305 @@
+/*
+ * DRM vmalloc buffer object helper functions
+ *
+ * Copyright (C) 2017 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vmalloc_bo_helper.h>
+
+/**
+ * DOC: overview
+ *
+ * This helper provides a simple GEM based buffer object with buffers allocated
+ * using vmalloc(). This is useful for modesetting drivers that do framebuffer
+ * flushing. It supports dumb buffers and PRIME import which can be setup using
+ * the DEFINE_DRM_VMALLOC_BO_FOPS() and DRM_VMALLOC_BO_DRIVER_OPS() macros.
+ *
+ * fbdev emulation can be setup using the drm_vmalloc_bo_fbdev_probe() function.
+ */
+
+static struct drm_vmalloc_bo *
+drm_vmalloc_bo_create(struct drm_device *dev, size_t size, bool backing)
+{
+	struct drm_vmalloc_bo *bo;
+	int ret;
+
+	size = PAGE_ALIGN(size);
+
+	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+	if (!bo)
+		return ERR_PTR(-ENOMEM);
+
+	if (backing) {
+		bo->vaddr = vmalloc_user(size);
+		if (!bo->vaddr) {
+			ret = -ENOMEM;
+			goto error_free;
+		}
+	}
+
+	drm_gem_private_object_init(dev, &bo->base, size);
+
+	return bo;
+
+error_free:
+	kfree(bo);
+
+	return ERR_PTR(ret);
+}
+
+/**
+ * drm_vmalloc_bo_free_object() - Free resources associated with a vmalloc BO
+ *                                object
+ * @obj: GEM object to free
+ *
+ * This function frees the backing memory of the vmalloc BO object, cleans up
+ * the GEM object state and frees the memory used to store the object itself.
+ * Drivers using the vmalloc BO helpers should set this as their
+ * &drm_driver.gem_free_object callback.
+ */
+void drm_vmalloc_bo_free_object(struct drm_gem_object *obj)
+{
+	struct drm_vmalloc_bo *bo = to_drm_vmalloc_bo(obj);
+
+	if (obj->import_attach)
+		dma_buf_vunmap(obj->import_attach->dmabuf, bo->vaddr);
+	else
+		vfree(bo->vaddr);
+
+	drm_gem_object_release(obj);
+	kfree(bo);
+}
+EXPORT_SYMBOL(drm_vmalloc_bo_free_object);
+
+/**
+ * drm_vmalloc_bo_dumb_create() - Create a dumb vmalloc BO
+ * @file: DRM file structure to create the dumb buffer for
+ * @dev: DRM device
+ * @args: IOCTL data
+ *
+ * This function computes the pitch of the dumb buffer and rounds it up to an
+ * integer number of bytes per pixel. Drivers for hardware that doesn't have
+ * any additional restrictions on the pitch can directly use this function as
+ * their &drm_driver.dumb_create callback.
+ *
+ * For hardware with additional restrictions, drivers can adjust the fields
+ * set up by userspace before calling into this function. Also
+ * &drm_mode_create_dumb.pitch and &drm_mode_create_dumb.size can be set.
+ *
+ * Returns:
+ * Zero on success or a negative error code on failure.
+ */
+int drm_vmalloc_bo_dumb_create(struct drm_file *file, struct drm_device *dev,
+			       struct drm_mode_create_dumb *args)
+{
+	struct drm_vmalloc_bo *bo;
+	int ret;
+
+	if (!args->pitch)
+		args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	else
+		args->pitch = max(args->pitch,
+				  DIV_ROUND_UP(args->width * args->bpp, 8));
+	if (!args->size)
+		args->size = args->pitch * args->height;
+	else
+		args->size = max_t(typeof(args->size), args->size,
+				   args->pitch * args->height);
+
+	bo = drm_vmalloc_bo_create(dev, args->size, true);
+	if (IS_ERR(bo))
+		return PTR_ERR(bo);
+
+	ret = drm_gem_handle_create(file, &bo->base, &args->handle);
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_put_unlocked(&bo->base);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_vmalloc_bo_dumb_create);
+
+const struct vm_operations_struct drm_vmalloc_bo_vm_ops = {
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+EXPORT_SYMBOL_GPL(drm_vmalloc_bo_vm_ops);
+
+/**
+ * drm_vmalloc_bo_mmap() - Memory-map a vmalloc BO
+ * @filp: File object
+ * @vma: VMA for the area to be mapped
+ *
+ * This function implements an augmented version of the GEM DRM file mmap
+ * operation for vmalloc buffer objects. Drivers should use this function as
+ * their ->mmap handler in the DRM device file's file_operations structure.
+ *
+ * Instead of directly referencing this function, drivers should use the
+ * DEFINE_DRM_VMALLOC_BO_FOPS() macro.
+ *
+ * Returns:
+ * Zero on success or a negative error code on failure.
+ */
+int drm_vmalloc_bo_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_vmalloc_bo *bo;
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	/* Set by drm_gem_mmap() */
+	vma->vm_flags &= ~VM_IO;
+	vma->vm_flags &= ~VM_PFNMAP;
+
+	bo = to_drm_vmalloc_bo(vma->vm_private_data);
+
+	return remap_vmalloc_range(vma, bo->vaddr, 0);
+}
+EXPORT_SYMBOL(drm_vmalloc_bo_mmap);
+
+/**
+ * drm_vmalloc_bo_prime_import_sg_table() - Produce a vmalloc BO from a dma-buf
+ * @dev: DRM device to import into
+ * @attach: dmabuf attachment
+ * @sgt: Scatter/gather table of pinned pages
+ *
+ * This function creates a vmalloc buffer object using the virtual address on
+ * the dma-buf exported by another driver. Drivers using the vmalloc BO helpers
+ * should set this as their &drm_driver.gem_prime_import_sg_table callback.
+ *
+ * Returns:
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_object *
+drm_vmalloc_bo_prime_import_sg_table(struct drm_device *dev,
+				     struct dma_buf_attachment *attach,
+				     struct sg_table *sgt)
+{
+	struct drm_vmalloc_bo *bo;
+	void *vaddr;
+
+	vaddr = dma_buf_vmap(attach->dmabuf);
+	if (!vaddr) {
+		DRM_ERROR("Failed to vmap PRIME buffer\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	bo = drm_vmalloc_bo_create(dev, attach->dmabuf->size, false);
+	if (IS_ERR(bo)) {
+		dma_buf_vunmap(attach->dmabuf, vaddr);
+		return ERR_CAST(bo);
+	}
+
+	bo->vaddr = vaddr;
+
+	DRM_DEBUG_PRIME("size = %zu\n", attach->dmabuf->size);
+
+	return &bo->base;
+}
+EXPORT_SYMBOL(drm_vmalloc_bo_prime_import_sg_table);
+
+static struct fb_ops drm_vmalloc_bo_fbdev_ops = {
+	.owner		= THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
+	.fb_read	= drm_fb_helper_sys_read,
+	.fb_write	= drm_fb_helper_sys_write,
+	.fb_fillrect	= drm_fb_helper_sys_fillrect,
+	.fb_copyarea	= drm_fb_helper_sys_copyarea,
+	.fb_imageblit	= drm_fb_helper_sys_imageblit,
+};
+
+/**
+ * drm_vmalloc_bo_fbdev_probe - fbdev emulation \.fb_probe helper
+ * @fb_helper: fbdev emulation helper structure
+ * @sizes: Describes fbdev size and scanout surface size
+ * @fb_funcs: DRM framebuffer functions
+ *
+ * This function can be used in the &drm_fb_helper_funcs.fb_probe callback to
+ * setup fbdev emulation. If @fb_funcs->dirty is set, fbdev deferred I/O is
+ * initialized. drm_fb_helper_simple_init() can be used to initialize the fbdev
+ * emulation.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int drm_vmalloc_bo_fbdev_probe(struct drm_fb_helper *fb_helper,
+			       struct drm_fb_helper_surface_size *sizes,
+			       const struct drm_framebuffer_funcs *fb_funcs)
+{
+	struct drm_device *dev = fb_helper->dev;
+	struct drm_framebuffer *fb;
+	struct drm_vmalloc_bo *bo;
+	struct fb_info *fbi;
+	size_t size;
+	int ret;
+
+	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
+		      sizes->surface_width, sizes->surface_height,
+		      sizes->surface_bpp);
+
+	size = sizes->surface_width * sizes->surface_height *
+	       DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	bo = drm_vmalloc_bo_create(dev, size, true);
+	if (IS_ERR(bo))
+		return -ENOMEM;
+
+	fb = drm_gem_fbdev_fb_create(dev, sizes, 0, &bo->base, fb_funcs);
+	if (IS_ERR(fb)) {
+		dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+		ret = PTR_ERR(fb);
+		goto err_bo_free;
+	}
+
+	fb_helper->fb = fb;
+
+	fbi = drm_fb_helper_alloc_fbi(fb_helper);
+	if (IS_ERR(fbi)) {
+		ret = PTR_ERR(fbi);
+		goto err_fb_free;
+	}
+
+	fbi->par = fb_helper;
+	fbi->flags = FBINFO_VIRTFB;
+	fbi->fbops = &drm_vmalloc_bo_fbdev_ops;
+
+	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
+	drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height);
+
+	fbi->screen_base = bo->vaddr;
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+
+	if (fb_funcs->dirty) {
+		ret = drm_fb_helper_defio_init(fb_helper);
+		if (ret)
+			goto err_fb_info_destroy;
+	}
+
+	return 0;
+
+err_fb_info_destroy:
+	drm_fb_helper_fini(fb_helper);
+err_fb_free:
+	drm_framebuffer_remove(fb);
+err_bo_free:
+	drm_gem_object_put_unlocked(&bo->base);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_vmalloc_bo_fbdev_probe);
diff --git a/include/drm/drm_vmalloc_bo_helper.h b/include/drm/drm_vmalloc_bo_helper.h
new file mode 100644
index 0000000..0df3d15
--- /dev/null
+++ b/include/drm/drm_vmalloc_bo_helper.h
@@ -0,0 +1,88 @@
+#ifndef __DRM_VMALLOC_BO_HELPER_H__
+#define __DRM_VMALLOC_BO_HELPER_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+
+struct drm_fb_helper_surface_size;
+
+/**
+ * struct drm_vmalloc_bo - vmalloc buffer object
+ */
+struct drm_vmalloc_bo {
+	/**
+	 * @base:
+	 *
+	 * Base GEM object.
+	 */
+	struct drm_gem_object base;
+
+	/**
+	 * @vaddr:
+	 *
+	 * Kernel virtual address of the buffer.
+	 */
+	void *vaddr;
+};
+
+static inline struct drm_vmalloc_bo *
+to_drm_vmalloc_bo(struct drm_gem_object *obj)
+{
+	return container_of(obj, struct drm_vmalloc_bo, base);
+}
+
+static inline void *drm_vmalloc_bo_fb_vaddr(struct drm_framebuffer *fb)
+{
+	return to_drm_vmalloc_bo(fb->obj[0])->vaddr;
+}
+
+void drm_vmalloc_bo_free_object(struct drm_gem_object *obj);
+int drm_vmalloc_bo_dumb_create(struct drm_file *file, struct drm_device *dev,
+			       struct drm_mode_create_dumb *args);
+int drm_vmalloc_bo_mmap(struct file *filp, struct vm_area_struct *vma);
+struct drm_gem_object *
+drm_vmalloc_bo_prime_import_sg_table(struct drm_device *dev,
+				     struct dma_buf_attachment *attach,
+				     struct sg_table *sgt);
+
+int drm_vmalloc_bo_fbdev_probe(struct drm_fb_helper *fb_helper,
+			       struct drm_fb_helper_surface_size *sizes,
+			       const struct drm_framebuffer_funcs *fb_funcs);
+
+/**
+ * DEFINE_DRM_VMALLOC_BO_FOPS() - Macro to generate file operations for drivers
+ * @name: Name for the generated structure
+ *
+ * This macro autogenerates a suitable &struct file_operations which can be
+ * assigned to &drm_driver.fops for vmalloc BO drivers.
+ */
+#define DEFINE_DRM_VMALLOC_BO_FOPS(name) \
+	static const struct file_operations name = {\
+		.owner		= THIS_MODULE,\
+		.open		= drm_open,\
+		.release	= drm_release,\
+		.unlocked_ioctl	= drm_ioctl,\
+		.compat_ioctl	= drm_compat_ioctl,\
+		.poll		= drm_poll,\
+		.read		= drm_read,\
+		.llseek		= noop_llseek,\
+		.mmap		= drm_vmalloc_bo_mmap,\
+	}
+
+extern const struct vm_operations_struct drm_vmalloc_bo_vm_ops;
+
+/**
+ * DRM_VMALLOC_BO_DRIVER_OPS - Default GEM and PRIME operations
+ *
+ * This macro provides a shortcut for setting the GEM and PRIME operations in
+ * the &drm_driver structure for vmalloc BO drivers.
+ */
+#define DRM_VMALLOC_BO_DRIVER_OPS \
+	.gem_free_object	= drm_vmalloc_bo_free_object, \
+	.gem_vm_ops		= &drm_vmalloc_bo_vm_ops, \
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle, \
+	.gem_prime_import	= drm_gem_prime_import, \
+	.gem_prime_import_sg_table = drm_vmalloc_bo_prime_import_sg_table, \
+	.dumb_create		= drm_vmalloc_bo_dumb_create
+
+#endif /* __DRM_VMALLOC_BO_HELPER_H__ */
-- 
2.7.4

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

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

* [PATCH 7/8] drm/tinydrm: Use drm_vmalloc_bo
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
                   ` (5 preceding siblings ...)
  2017-10-04 18:06 ` [PATCH 6/8] drm: Add vmalloc BO helper Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  2017-10-04 18:06 ` [PATCH 8/8] drm/tinydrm: Relax buffer line prefetch Noralf Trønnes
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, David Lechner

Use the vmalloc BO helper instead of the cma helper to be able to PRIME
import from more drivers. The cma helper can only import physically
continuous buffers, but tinydrm only requires the buffer to be virtually
continuous.

This switch also makes it possible to use the drm_fb_helper_lastclose()
helper.

Some extra includes were necessary in tinydrm-helpers.c, because it
relied on includes in tinydrm.h that are now gone.

Cc: David Lechner <david@lechnology.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/tinydrm/Kconfig                |   2 +-
 drivers/gpu/drm/tinydrm/core/tinydrm-core.c    | 134 +++++--------------------
 drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c |   2 +
 drivers/gpu/drm/tinydrm/mi0283qt.c             |   8 +-
 drivers/gpu/drm/tinydrm/mipi-dbi.c             |  12 +--
 drivers/gpu/drm/tinydrm/repaper.c              |  12 ++-
 drivers/gpu/drm/tinydrm/st7586.c               |  14 +--
 include/drm/tinydrm/mipi-dbi.h                 |   2 +
 include/drm/tinydrm/tinydrm.h                  |  38 ++-----
 9 files changed, 65 insertions(+), 159 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig
index 2e790e7..d47bcd6 100644
--- a/drivers/gpu/drm/tinydrm/Kconfig
+++ b/drivers/gpu/drm/tinydrm/Kconfig
@@ -2,7 +2,7 @@ menuconfig DRM_TINYDRM
 	tristate "Support for simple displays"
 	depends on DRM
 	select DRM_KMS_HELPER
-	select DRM_KMS_CMA_HELPER
+	select DRM_VMALLOC_BO_HELPER
 	select BACKLIGHT_LCD_SUPPORT
 	select BACKLIGHT_CLASS_DEVICE
 	help
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
index 1a8a57c..77c5fd5 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
@@ -10,7 +10,9 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vmalloc_bo_helper.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <linux/device.h>
 #include <linux/dma-buf.h>
@@ -22,9 +24,11 @@
  *
  * It is based on &drm_simple_display_pipe coupled with a &drm_connector which
  * has only one fixed &drm_display_mode. The framebuffers are backed by the
- * cma helper and have support for framebuffer flushing (dirty).
+ * vmalloc BO helper and have support for framebuffer flushing (dirty).
  * fbdev support is also included.
  *
+ * Note: The SPI core is able to create a scatter/gather table from a vmalloc
+ * buffer when dealing with DMA capable SPI controllers
  */
 
 /**
@@ -35,94 +39,6 @@
  * and registers the DRM device using devm_tinydrm_register().
  */
 
-/**
- * tinydrm_lastclose - DRM lastclose helper
- * @drm: DRM device
- *
- * This function ensures that fbdev is restored when drm_lastclose() is called
- * on the last drm_release(). Drivers can use this as their
- * &drm_driver->lastclose callback.
- */
-void tinydrm_lastclose(struct drm_device *drm)
-{
-	struct tinydrm_device *tdev = drm->dev_private;
-
-	DRM_DEBUG_KMS("\n");
-	drm_fbdev_cma_restore_mode(tdev->fbdev_cma);
-}
-EXPORT_SYMBOL(tinydrm_lastclose);
-
-/**
- * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from
- *     another driver's scatter/gather table of pinned pages
- * @drm: DRM device to import into
- * @attach: DMA-BUF attachment
- * @sgt: Scatter/gather table of pinned pages
- *
- * This function imports a scatter/gather table exported via DMA-BUF by
- * another driver using drm_gem_cma_prime_import_sg_table(). It sets the
- * kernel virtual address on the CMA object. Drivers should use this as their
- * &drm_driver->gem_prime_import_sg_table callback if they need the virtual
- * address. tinydrm_gem_cma_free_object() should be used in combination with
- * this function.
- *
- * Returns:
- * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
- * error code on failure.
- */
-struct drm_gem_object *
-tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
-				      struct dma_buf_attachment *attach,
-				      struct sg_table *sgt)
-{
-	struct drm_gem_cma_object *cma_obj;
-	struct drm_gem_object *obj;
-	void *vaddr;
-
-	vaddr = dma_buf_vmap(attach->dmabuf);
-	if (!vaddr) {
-		DRM_ERROR("Failed to vmap PRIME buffer\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt);
-	if (IS_ERR(obj)) {
-		dma_buf_vunmap(attach->dmabuf, vaddr);
-		return obj;
-	}
-
-	cma_obj = to_drm_gem_cma_obj(obj);
-	cma_obj->vaddr = vaddr;
-
-	return obj;
-}
-EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table);
-
-/**
- * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM
- *                               object
- * @gem_obj: GEM object to free
- *
- * This function frees the backing memory of the CMA GEM object, cleans up the
- * GEM object state and frees the memory used to store the object itself using
- * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel
- * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers
- * can use this as their &drm_driver->gem_free_object callback.
- */
-void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
-{
-	if (gem_obj->import_attach) {
-		struct drm_gem_cma_object *cma_obj;
-
-		cma_obj = to_drm_gem_cma_obj(gem_obj);
-		dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
-		cma_obj->vaddr = NULL;
-	}
-
-	drm_gem_cma_free_object(gem_obj);
-}
-EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
-
 static struct drm_framebuffer *
 tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
 		  const struct drm_mode_fb_cmd2 *mode_cmd)
@@ -211,38 +127,40 @@ int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
 }
 EXPORT_SYMBOL(devm_tinydrm_init);
 
+static int tinydrm_fbdev_probe(struct drm_fb_helper *helper,
+			       struct drm_fb_helper_surface_size *sizes)
+
+{
+	struct tinydrm_device *tdev = helper->dev->dev_private;
+
+	return drm_vmalloc_bo_fbdev_probe(helper, sizes, tdev->fb_funcs);
+}
+
+static const struct drm_fb_helper_funcs tinydrm_fb_helper_funcs = {
+	.fb_probe = tinydrm_fbdev_probe,
+};
+
 static int tinydrm_register(struct tinydrm_device *tdev)
 {
 	struct drm_device *drm = tdev->drm;
-	int bpp = drm->mode_config.preferred_depth;
-	struct drm_fbdev_cma *fbdev;
 	int ret;
 
-	ret = drm_dev_register(tdev->drm, 0);
+	ret = drm_dev_register(drm, 0);
 	if (ret)
 		return ret;
 
-	fbdev = drm_fbdev_cma_init_with_funcs(drm, bpp ? bpp : 32,
-					      drm->mode_config.num_connector,
-					      tdev->fb_funcs);
-	if (IS_ERR(fbdev))
-		DRM_ERROR("Failed to initialize fbdev: %ld\n", PTR_ERR(fbdev));
-	else
-		tdev->fbdev_cma = fbdev;
+	ret = drm_fb_helper_simple_init(drm, &tinydrm_fb_helper_funcs, 0, 0);
+	if (ret)
+		DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
 
 	return 0;
 }
 
 static void tinydrm_unregister(struct tinydrm_device *tdev)
 {
-	struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma;
-
 	drm_atomic_helper_shutdown(tdev->drm);
-	/* don't restore fbdev in lastclose, keep pipeline disabled */
-	tdev->fbdev_cma = NULL;
+	drm_fb_helper_simple_fini(tdev->drm);
 	drm_dev_unregister(tdev->drm);
-	if (fbdev_cma)
-		drm_fbdev_cma_fini(fbdev_cma);
 }
 
 static void devm_tinydrm_register_release(void *data)
@@ -312,10 +230,10 @@ int tinydrm_suspend(struct tinydrm_device *tdev)
 		return -EINVAL;
 	}
 
-	drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 1);
+	drm_fb_helper_set_suspend_unlocked(tdev->drm->fbdev, 1);
 	state = drm_atomic_helper_suspend(tdev->drm);
 	if (IS_ERR(state)) {
-		drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0);
+		drm_fb_helper_set_suspend_unlocked(tdev->drm->fbdev, 0);
 		return PTR_ERR(state);
 	}
 
@@ -353,7 +271,7 @@ int tinydrm_resume(struct tinydrm_device *tdev)
 		return ret;
 	}
 
-	drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0);
+	drm_fb_helper_set_suspend_unlocked(tdev->drm->fbdev, 0);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index bd6cce0..ee9a8f3 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -9,10 +9,12 @@
 
 #include <linux/backlight.h>
 #include <linux/dma-buf.h>
+#include <linux/moduleparam.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
 #include <linux/swab.h>
 
+#include <drm/drmP.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index 7fd2691..ac4a194 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -9,6 +9,8 @@
  * (at your option) any later version.
  */
 
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_vmalloc_bo_helper.h>
 #include <drm/tinydrm/ili9341.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
@@ -132,14 +134,14 @@ static const struct drm_display_mode mi0283qt_mode = {
 	TINYDRM_MODE(320, 240, 58, 43),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
+DEFINE_DRM_VMALLOC_BO_FOPS(mi0283qt_fops);
 
 static struct drm_driver mi0283qt_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &mi0283qt_fops,
-	TINYDRM_GEM_DRIVER_OPS,
-	.lastclose		= tinydrm_lastclose,
+	DRM_VMALLOC_BO_DRIVER_OPS,
+	.lastclose		= drm_fb_helper_lastclose,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "mi0283qt",
 	.desc			= "Multi-Inno MI0283QT",
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index d43e992..7aa5954 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -10,6 +10,7 @@
  */
 
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vmalloc_bo_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 #include <linux/debugfs.h>
@@ -157,10 +158,10 @@ EXPORT_SYMBOL(mipi_dbi_command_buf);
 static int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
 				struct drm_clip_rect *clip, bool swap)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+	struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+	struct dma_buf_attachment *import_attach = obj->import_attach;
+	void *src = drm_vmalloc_bo_fb_vaddr(fb);
 	struct drm_format_name_buf format_name;
-	void *src = cma_obj->vaddr;
 	int ret = 0;
 
 	if (import_attach) {
@@ -199,7 +200,6 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
 			     struct drm_clip_rect *clips,
 			     unsigned int num_clips)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
 	struct tinydrm_device *tdev = fb->dev->dev_private;
 	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
 	bool swap = mipi->swap_bytes;
@@ -230,7 +230,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
 		if (ret)
 			goto out_unlock;
 	} else {
-		tr = cma_obj->vaddr;
+		tr = drm_vmalloc_bo_fb_vaddr(fb);
 	}
 
 	mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
@@ -962,7 +962,7 @@ static const struct file_operations mipi_dbi_debugfs_command_fops = {
 };
 
 static const struct drm_info_list mipi_dbi_debugfs_list[] = {
-	{ "fb",   drm_fb_cma_debugfs_show, 0 },
+	{ "fb",  drm_gem_fb_debugfs_show, 0 },
 };
 
 /**
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
index 340198f..ab2636d 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -26,6 +26,7 @@
 #include <linux/spi/spi.h>
 #include <linux/thermal.h>
 
+#include <drm/drm_vmalloc_bo_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
@@ -527,10 +528,11 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
 			    struct drm_clip_rect *clips,
 			    unsigned int num_clips)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
+	struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+	struct dma_buf_attachment *import_attach = obj->import_attach;
 	struct tinydrm_device *tdev = fb->dev->dev_private;
 	struct repaper_epd *epd = epd_from_tinydrm(tdev);
+	void *src = drm_vmalloc_bo_fb_vaddr(fb);
 	struct drm_clip_rect clip;
 	u8 *buf = NULL;
 	int ret = 0;
@@ -568,7 +570,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
 			goto out_unlock;
 	}
 
-	tinydrm_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
+	tinydrm_xrgb8888_to_gray8(buf, src, fb, &clip);
 
 	if (import_attach) {
 		ret = dma_buf_end_cpu_access(import_attach->dmabuf,
@@ -888,13 +890,13 @@ static const struct drm_display_mode repaper_e2271cs021_mode = {
 static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f,
 					    0xff, 0xfe, 0x00, 0x00 };
 
-DEFINE_DRM_GEM_CMA_FOPS(repaper_fops);
+DEFINE_DRM_VMALLOC_BO_FOPS(repaper_fops);
 
 static struct drm_driver repaper_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &repaper_fops,
-	TINYDRM_GEM_DRIVER_OPS,
+	DRM_VMALLOC_BO_DRIVER_OPS,
 	.name			= "repaper",
 	.desc			= "Pervasive Displays RePaper e-ink panels",
 	.date			= "20170405",
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index da9c0d8..239f3e6 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -17,7 +17,9 @@
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vmalloc_bo_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -87,9 +89,9 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
 static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
 			   struct drm_clip_rect *clip)
 {
-	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
-	void *src = cma_obj->vaddr;
+	struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+	struct dma_buf_attachment *import_attach = obj->import_attach;
+	void *src = drm_vmalloc_bo_fb_vaddr(fb);
 	int ret = 0;
 
 	if (import_attach) {
@@ -313,14 +315,14 @@ static const struct drm_display_mode st7586_mode = {
 	TINYDRM_MODE(178, 128, 37, 27),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(st7586_fops);
+DEFINE_DRM_VMALLOC_BO_FOPS(st7586_fops);
 
 static struct drm_driver st7586_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 				  DRIVER_ATOMIC,
 	.fops			= &st7586_fops,
-	TINYDRM_GEM_DRIVER_OPS,
-	.lastclose		= tinydrm_lastclose,
+	DRM_VMALLOC_BO_DRIVER_OPS,
+	.lastclose		= drm_fb_helper_lastclose,
 	.debugfs_init		= mipi_dbi_debugfs_init,
 	.name			= "st7586",
 	.desc			= "Sitronix ST7586",
diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
index 83346dd..ff9626e 100644
--- a/include/drm/tinydrm/mipi-dbi.h
+++ b/include/drm/tinydrm/mipi-dbi.h
@@ -95,6 +95,8 @@ int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len);
 })
 
 #ifdef CONFIG_DEBUG_FS
+struct drm_minor;
+
 int mipi_dbi_debugfs_init(struct drm_minor *minor);
 #else
 #define mipi_dbi_debugfs_init		NULL
diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h
index 4774fe3..8450d1f 100644
--- a/include/drm/tinydrm/tinydrm.h
+++ b/include/drm/tinydrm/tinydrm.h
@@ -10,16 +10,21 @@
 #ifndef __LINUX_TINYDRM_H
 #define __LINUX_TINYDRM_H
 
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <linux/mutex.h>
 #include <drm/drm_simple_kms_helper.h>
 
+struct device;
+struct drm_atomic_state;
+struct drm_device;
+struct drm_driver;
+struct drm_framebuffer_funcs;
+struct drm_plane_state;
+
 /**
  * struct tinydrm_device - tinydrm device
  * @drm: DRM device
  * @pipe: Display pipe structure
  * @dirty_lock: Serializes framebuffer flushing
- * @fbdev_cma: CMA fbdev structure
  * @suspend_state: Atomic state when suspended
  * @fb_funcs: Framebuffer functions used when creating framebuffers
  */
@@ -27,7 +32,6 @@ struct tinydrm_device {
 	struct drm_device *drm;
 	struct drm_simple_display_pipe pipe;
 	struct mutex dirty_lock;
-	struct drm_fbdev_cma *fbdev_cma;
 	struct drm_atomic_state *suspend_state;
 	const struct drm_framebuffer_funcs *fb_funcs;
 };
@@ -39,26 +43,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
 }
 
 /**
- * TINYDRM_GEM_DRIVER_OPS - default tinydrm gem operations
- *
- * This macro provides a shortcut for setting the tinydrm GEM operations in
- * the &drm_driver structure.
- */
-#define TINYDRM_GEM_DRIVER_OPS \
-	.gem_free_object	= tinydrm_gem_cma_free_object, \
-	.gem_vm_ops		= &drm_gem_cma_vm_ops, \
-	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd, \
-	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle, \
-	.gem_prime_import	= drm_gem_prime_import, \
-	.gem_prime_export	= drm_gem_prime_export, \
-	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table, \
-	.gem_prime_import_sg_table = tinydrm_gem_cma_prime_import_sg_table, \
-	.gem_prime_vmap		= drm_gem_cma_prime_vmap, \
-	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap, \
-	.gem_prime_mmap		= drm_gem_cma_prime_mmap, \
-	.dumb_create		= drm_gem_cma_dumb_create
-
-/**
  * TINYDRM_MODE - tinydrm display mode
  * @hd: Horizontal resolution, width
  * @vd: Vertical resolution, height
@@ -81,12 +65,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
 	.type = DRM_MODE_TYPE_DRIVER, \
 	.clock = 1 /* pass validation */
 
-void tinydrm_lastclose(struct drm_device *drm);
-void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj);
-struct drm_gem_object *
-tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
-				      struct dma_buf_attachment *attach,
-				      struct sg_table *sgt);
 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
 		      const struct drm_framebuffer_funcs *fb_funcs,
 		      struct drm_driver *driver);
-- 
2.7.4

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

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

* [PATCH 8/8] drm/tinydrm: Relax buffer line prefetch
  2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
                   ` (6 preceding siblings ...)
  2017-10-04 18:06 ` [PATCH 7/8] drm/tinydrm: Use drm_vmalloc_bo Noralf Trønnes
@ 2017-10-04 18:06 ` Noralf Trønnes
  7 siblings, 0 replies; 9+ messages in thread
From: Noralf Trønnes @ 2017-10-04 18:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter

vmalloc BO's gives us cached reads, so no need to prefetch in that case.
Prefetching gives a ~20% speedup on a cma buffer using the mi0283qt
driver on a Raspberry Pi 1.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c | 54 ++++++++++++++------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index ee9a8f3..bca9052 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -15,6 +15,8 @@
 #include <linux/swab.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -115,22 +117,25 @@ void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
 		    struct drm_clip_rect *clip)
 {
 	size_t len = (clip->x2 - clip->x1) * sizeof(u16);
+	u16 *src, *buf = NULL;
 	unsigned int x, y;
-	u16 *src, *buf;
 
 	/*
-	 * The cma memory is write-combined so reads are uncached.
-	 * Speed up by fetching one line at a time.
+	 * Imported buffers are likely to be write-combined with uncached
+	 * reads. Speed up by fetching one line at a time.
+	 * prefetch_range() was tried, but didn't give any noticeable speedup
+	 * on the Raspberry Pi 1.
 	 */
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return;
+	if (drm_gem_fb_get_obj(fb, 0)->import_attach)
+		buf = kmalloc(len, GFP_KERNEL);
 
 	for (y = clip->y1; y < clip->y2; y++) {
 		src = vaddr + (y * fb->pitches[0]);
 		src += clip->x1;
-		memcpy(buf, src, len);
-		src = buf;
+		if (buf) {
+			memcpy(buf, src, len);
+			src = buf;
+		}
 		for (x = clip->x1; x < clip->x2; x++)
 			*dst++ = swab16(*src++);
 	}
@@ -155,19 +160,21 @@ void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
 				struct drm_clip_rect *clip, bool swap)
 {
 	size_t len = (clip->x2 - clip->x1) * sizeof(u32);
+	u32 *src, *buf = NULL;
 	unsigned int x, y;
-	u32 *src, *buf;
 	u16 val16;
 
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return;
+	/* See tinydrm_swab16() for an explanation */
+	if (drm_gem_fb_get_obj(fb, 0)->import_attach)
+		buf = kmalloc(len, GFP_KERNEL);
 
 	for (y = clip->y1; y < clip->y2; y++) {
 		src = vaddr + (y * fb->pitches[0]);
 		src += clip->x1;
-		memcpy(buf, src, len);
-		src = buf;
+		if (buf) {
+			memcpy(buf, src, len);
+			src = buf;
+		}
 		for (x = clip->x1; x < clip->x2; x++) {
 			val16 = ((*src & 0x00F80000) >> 8) |
 				((*src & 0x0000FC00) >> 5) |
@@ -205,24 +212,23 @@ void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
 {
 	unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
 	unsigned int x, y;
-	void *buf;
+	void *buf = NULL;
 	u32 *src;
 
 	if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
 		return;
-	/*
-	 * The cma memory is write-combined so reads are uncached.
-	 * Speed up by fetching one line at a time.
-	 */
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return;
+
+	/* See tinydrm_swab16() for an explanation */
+	if (drm_gem_fb_get_obj(fb, 0)->import_attach)
+		buf = kmalloc(len, GFP_KERNEL);
 
 	for (y = clip->y1; y < clip->y2; y++) {
 		src = vaddr + (y * fb->pitches[0]);
 		src += clip->x1;
-		memcpy(buf, src, len);
-		src = buf;
+		if (buf) {
+			memcpy(buf, src, len);
+			src = buf;
+		}
 		for (x = clip->x1; x < clip->x2; x++) {
 			u8 r = (*src & 0x00ff0000) >> 16;
 			u8 g = (*src & 0x0000ff00) >> 8;
-- 
2.7.4

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

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

end of thread, other threads:[~2017-10-04 18:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-04 18:06 [PATCH 0/8] drm/tinydrm: Use vmalloc BO Noralf Trønnes
2017-10-04 18:06 ` [PATCH 1/8] drm/fb-helper: Handle function NULL argument Noralf Trønnes
2017-10-04 18:06 ` [PATCH 2/8] drm: Add drm_device->fbdev pointer Noralf Trønnes
2017-10-04 18:06 ` [PATCH 3/8] drm/fb-helper: Add simple init/fini functions Noralf Trønnes
2017-10-04 18:06 ` [PATCH 4/8] drm/fb-helper: Add .last_close and .output_poll_changed helpers Noralf Trønnes
2017-10-04 18:06 ` [PATCH 5/8] drm/gem-fb-helper: Add drm_gem_fb_debugfs_show() Noralf Trønnes
2017-10-04 18:06 ` [PATCH 6/8] drm: Add vmalloc BO helper Noralf Trønnes
2017-10-04 18:06 ` [PATCH 7/8] drm/tinydrm: Use drm_vmalloc_bo Noralf Trønnes
2017-10-04 18:06 ` [PATCH 8/8] drm/tinydrm: Relax buffer line prefetch Noralf Trønnes

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.