dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [RFC v4 00/25] drm: Add generic fbdev emulation
@ 2018-04-12 13:17 Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Noralf Trønnes, laurent.pinchart,
	mstaudt, dh.herrmann

This patchset explores the possibility of having generic fbdev emulation
in DRM for drivers that supports dumb buffers which they can export. An
API is added to support in-kernel clients in general.

In this version I was able to reuse the modesetting code from
drm_fb_helper in the client API. This avoids code duplication, carries
over lessons learned and the modesetting code is bisectable. The
downside is that it takes +10 patches to rip drm_fb_helper in two, so
maybe it's not worth it wrt possible breakage and a challenging review.

Does the Intel CI test the fbdev emulation?

Daniel had this concern with the previous version:

    The register/unregister model needs more thought. Allowing both clients
    to register whenever they want to, and drm_device instances to come and
    go is what fbcon has done, and the resulting locking is a horror show.

    I think if we require that all in-kernel drm_clients are registers when
    loading drm.ko (and enabled/disabled only per module options and
    Kconfig), then we can throw out all the locking. That avoids a lot of
    the headaches.

I have solved this by adding a notifier that fires when a new DRM device
is registered (I've removed the new() callback). Currently only
bootsplash uses this. The fbdev client needs to be setup from the driver
since it can't know on device registration if the driver will setup it's
own fbdev emulation later and the vtcon client hooks up to a user
provided device id.

Since fbcon can't handle fb_open failing, the buffer has to be
pre-allocated. Exporting a GEM buffer pins the driver module making it
impossible to unload it.
I have included 2 solutions to the problem:
- sysfs file to remove/close clients: remove_internal_clients
- Change drm_gem_prime_export() so it doesn't pin on client buffers

If a dumb buffer is exported from a kernel thread (worker) context, the
file descriptor isn't closed and I leak a reference so the buffer isn't
freed. Please look at drm_client_buffer_create() in patch
'drm/client: Finish the in-kernel client API'.
This is a blocker that needs a solution.


Noralf.

Changes since version 3:
Client API changes:
- Drop drm_client_register_funcs() which attached clients indirectly.
  Let clients attach directly using drm_client_new{_from_id}(). Clients
  that wants to attach to all devices must be linked into drm.ko and use
  the DRM device notifier. This is done to avoid the lock/race
  register/unregister hell we have with fbcon. (Daniel Vetter)
- drm_client_display_restore() checks if there is a master and if so
  returns -EBUSY. (Daniel Vetter)
- Allocate drm_file up front instead of on-demand. Since fbdev can't do
  on demand buffer allocation because of fbcon, there's no need for this.
- Add sysfs file to remove clients
- Don't pin driver module when exporting gem client buffers
- Dropped page flip support since drm_fb_helper is now used for fbdev
  emulation.

- The bootsplash client now switches over to fbdev on keypress.

Changes since version 2:
- Don't set drm master for in-kernel clients. (Daniel Vetter)
- Add in-kernel client API

Changes since version 1:
- Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
  DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
  The following uses that macro and sets fb_open/close: udlfb_ops,
  amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
  nouveau_fbcon_sw_ops, radeonfb_ops.
  This results in: warning: Initializer entry defined twice
- Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
  ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
- Drop buggy patch: (Chris Wilson)
  drm/prime: Clear drm_gem_object->dma_buf on release
- Defer buffer creation until fb_open.


David Herrmann (1):
  drm: provide management functions for drm_file

Noralf Trønnes (24):
  drm/file: Don't set master on in-kernel clients
  drm/fb-helper: No need to cache rotation and sw_rotations
  drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
  drm/fb-helper: dpms_legacy(): Only set on connectors in use
  drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  drm: Begin an API for in-kernel clients
  drm/fb-helper: Use struct drm_client_display
  drm/fb-helper: Move modeset commit code to drm_client
  drm/connector: Add
    drm_connector_has_preferred_mode/pick_cmdline_mode()
  drm/connector: Add connector array functions
  drm/i915: Add drm_driver->initial_client_display callback
  drm/fb-helper: Remove struct drm_fb_helper_crtc
  drm/fb-helper: Remove struct drm_fb_helper_connector
  drm/fb-helper: Move modeset config code to drm_client
  drm: Make ioctls available for in-kernel clients
  drm/client: Bail out if there's a DRM master
  drm/client: Make the display modes available to clients
  drm/client: Finish the in-kernel client API
  drm/prime: Don't pin module on export for in-kernel clients
  drm/fb-helper: Add drm_fb_helper_fb_open/release()
  drm/fb-helper: Add generic fbdev emulation
  drm: Add DRM device registered notifier
  drm/client: Hack: Add bootsplash
  drm/client: Hack: Add DRM VT console client

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    4 +-
 drivers/gpu/drm/client/Kconfig          |   14 +
 drivers/gpu/drm/client/Makefile         |    3 +
 drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
 drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
 drivers/gpu/drm/client/internal.h       |   19 +
 drivers/gpu/drm/drm_atomic.c            |  168 ++++
 drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
 drivers/gpu/drm/drm_auth.c              |   33 +
 drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_connector.c         |  199 +++++
 drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
 drivers/gpu/drm/drm_debugfs.c           |    7 +
 drivers/gpu/drm/drm_drv.c               |   43 +
 drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
 drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
 drivers/gpu/drm/drm_file.c              |  304 ++++---
 drivers/gpu/drm/drm_framebuffer.c       |   50 +-
 drivers/gpu/drm/drm_internal.h          |    7 +
 drivers/gpu/drm/drm_ioc32.c             |    2 +-
 drivers/gpu/drm/drm_ioctl.c             |    4 +-
 drivers/gpu/drm/drm_prime.c             |   37 +-
 drivers/gpu/drm/drm_probe_helper.c      |    3 +
 drivers/gpu/drm/drm_sysfs.c             |   20 +
 drivers/gpu/drm/i915/i915_drv.c         |    1 +
 drivers/gpu/drm/i915/intel_drv.h        |   11 +
 drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
 include/drm/drm_atomic.h                |    5 +
 include/drm/drm_atomic_helper.h         |    4 -
 include/drm/drm_client.h                |  182 ++++
 include/drm/drm_connector.h             |   11 +
 include/drm/drm_device.h                |    4 +
 include/drm/drm_drv.h                   |   25 +
 include/drm/drm_fb_helper.h             |  126 ++-
 35 files changed, 4007 insertions(+), 1513 deletions(-)
 create mode 100644 drivers/gpu/drm/client/Kconfig
 create mode 100644 drivers/gpu/drm/client/Makefile
 create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
 create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
 create mode 100644 drivers/gpu/drm/client/internal.h
 create mode 100644 drivers/gpu/drm/drm_client.c
 create mode 100644 include/drm/drm_client.h

--
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [RFC v4 01/25] drm: provide management functions for drm_file
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 02/25] drm/file: Don't set master on in-kernel clients Noralf Trønnes
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Noralf Trønnes, laurent.pinchart,
	mstaudt, dh.herrmann

From: David Herrmann <dh.herrmann@gmail.com>

Rather than doing drm_file allocation/destruction right in the fops, lets
provide separate helpers. This decouples drm_file management from the
still-mandatory drm-fops. It prepares for use of drm_file without the
fops, both by possible separate fops implementations and APIs (not that I
am aware of any such plans), and more importantly from in-kernel use where
no real file is available.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_file.c     | 305 +++++++++++++++++++++++------------------
 drivers/gpu/drm/drm_internal.h |   2 +
 2 files changed, 175 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index e394799979a6..d4588d33f91c 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -101,6 +101,175 @@ DEFINE_MUTEX(drm_global_mutex);
 
 static int drm_open_helper(struct file *filp, struct drm_minor *minor);
 
+/**
+ * drm_file_alloc - allocate file context
+ * @minor: minor to allocate on
+ *
+ * This allocates a new DRM file context. It is not linked into any context and
+ * can be used by the caller freely. Note that the context keeps a pointer to
+ * @minor, so it must be freed before @minor is.
+ *
+ * RETURNS:
+ * Pointer to newly allocated context, ERR_PTR on failure.
+ */
+struct drm_file *drm_file_alloc(struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	struct drm_file *file;
+	int ret;
+
+	file = kzalloc(sizeof(*file), GFP_KERNEL);
+	if (!file)
+		return ERR_PTR(-ENOMEM);
+
+	file->pid = get_pid(task_pid(current));
+	file->minor = minor;
+
+	/* for compatibility root is always authenticated */
+	file->authenticated = capable(CAP_SYS_ADMIN);
+	file->lock_count = 0;
+
+	INIT_LIST_HEAD(&file->lhead);
+	INIT_LIST_HEAD(&file->fbs);
+	mutex_init(&file->fbs_lock);
+	INIT_LIST_HEAD(&file->blobs);
+	INIT_LIST_HEAD(&file->pending_event_list);
+	INIT_LIST_HEAD(&file->event_list);
+	init_waitqueue_head(&file->event_wait);
+	file->event_space = 4096; /* set aside 4k for event buffer */
+
+	mutex_init(&file->event_read_lock);
+
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_open(dev, file);
+
+	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
+		drm_syncobj_open(file);
+
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_init_file_private(&file->prime);
+
+	if (dev->driver->open) {
+		ret = dev->driver->open(dev, file);
+		if (ret < 0)
+			goto out_prime_destroy;
+	}
+
+	if (drm_is_primary_client(file)) {
+		ret = drm_master_open(file);
+		if (ret)
+			goto out_close;
+	}
+
+	return file;
+
+out_close:
+	if (dev->driver->postclose)
+		dev->driver->postclose(dev, file);
+out_prime_destroy:
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_destroy_file_private(&file->prime);
+	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
+		drm_syncobj_release(file);
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_release(dev, file);
+	put_pid(file->pid);
+	kfree(file);
+
+	return ERR_PTR(ret);
+}
+
+static void drm_events_release(struct drm_file *file_priv)
+{
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_pending_event *e, *et;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	/* Unlink pending events */
+	list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
+				 pending_link) {
+		list_del(&e->pending_link);
+		e->file_priv = NULL;
+	}
+
+	/* Remove unconsumed events */
+	list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
+		list_del(&e->link);
+		kfree(e);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+/**
+ * drm_file_free - free file context
+ * @file: context to free, or NULL
+ *
+ * This destroys and deallocates a DRM file context previously allocated via
+ * drm_file_alloc(). The caller must make sure to unlink it from any contexts
+ * before calling this.
+ *
+ * If NULL is passed, this is a no-op.
+ *
+ * RETURNS:
+ * 0 on success, or error code on failure.
+ */
+void drm_file_free(struct drm_file *file)
+{
+	struct drm_device *dev;
+
+	if (!file)
+		return;
+
+	dev = file->minor->dev;
+
+	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+		  task_pid_nr(current),
+		  (long)old_encode_dev(file->minor->kdev->devt),
+		  dev->open_count);
+
+	if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
+	    dev->driver->preclose)
+		dev->driver->preclose(dev, file);
+
+	if (drm_core_check_feature(dev, DRIVER_LEGACY))
+		drm_legacy_lock_release(dev, file->filp);
+
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		drm_legacy_reclaim_buffers(dev, file);
+
+	drm_events_release(file);
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		drm_fb_release(file);
+		drm_property_destroy_user_blobs(dev, file);
+	}
+
+	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
+		drm_syncobj_release(file);
+
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_release(dev, file);
+
+	drm_legacy_ctxbitmap_flush(dev, file);
+
+	if (drm_is_primary_client(file))
+		drm_master_release(file);
+
+	if (dev->driver->postclose)
+		dev->driver->postclose(dev, file);
+
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_destroy_file_private(&file->prime);
+
+	WARN_ON(!list_empty(&file->event_list));
+
+	put_pid(file->pid);
+	kfree(file);
+}
+
 static int drm_setup(struct drm_device * dev)
 {
 	int ret;
@@ -196,7 +365,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 {
 	struct drm_device *dev = minor->dev;
 	struct drm_file *priv;
-	int ret;
 
 	if (filp->f_flags & O_EXCL)
 		return -EBUSY;	/* No exclusive opens */
@@ -207,50 +375,12 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 
 	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
+	priv = drm_file_alloc(minor);
+	if (IS_ERR(priv))
+		return PTR_ERR(priv);
 
 	filp->private_data = priv;
 	priv->filp = filp;
-	priv->pid = get_pid(task_pid(current));
-	priv->minor = minor;
-
-	/* for compatibility root is always authenticated */
-	priv->authenticated = capable(CAP_SYS_ADMIN);
-	priv->lock_count = 0;
-
-	INIT_LIST_HEAD(&priv->lhead);
-	INIT_LIST_HEAD(&priv->fbs);
-	mutex_init(&priv->fbs_lock);
-	INIT_LIST_HEAD(&priv->blobs);
-	INIT_LIST_HEAD(&priv->pending_event_list);
-	INIT_LIST_HEAD(&priv->event_list);
-	init_waitqueue_head(&priv->event_wait);
-	priv->event_space = 4096; /* set aside 4k for event buffer */
-
-	mutex_init(&priv->event_read_lock);
-
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_open(dev, priv);
-
-	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
-		drm_syncobj_open(priv);
-
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_init_file_private(&priv->prime);
-
-	if (dev->driver->open) {
-		ret = dev->driver->open(dev, priv);
-		if (ret < 0)
-			goto out_prime_destroy;
-	}
-
-	if (drm_is_primary_client(priv)) {
-		ret = drm_master_open(priv);
-		if (ret)
-			goto out_close;
-	}
 
 	mutex_lock(&dev->filelist_mutex);
 	list_add(&priv->lhead, &dev->filelist);
@@ -277,45 +407,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 #endif
 
 	return 0;
-
-out_close:
-	if (dev->driver->postclose)
-		dev->driver->postclose(dev, priv);
-out_prime_destroy:
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_destroy_file_private(&priv->prime);
-	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
-		drm_syncobj_release(priv);
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_release(dev, priv);
-	put_pid(priv->pid);
-	kfree(priv);
-	filp->private_data = NULL;
-	return ret;
-}
-
-static void drm_events_release(struct drm_file *file_priv)
-{
-	struct drm_device *dev = file_priv->minor->dev;
-	struct drm_pending_event *e, *et;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->event_lock, flags);
-
-	/* Unlink pending events */
-	list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
-				 pending_link) {
-		list_del(&e->pending_link);
-		e->file_priv = NULL;
-	}
-
-	/* Remove unconsumed events */
-	list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
-		list_del(&e->link);
-		kfree(e);
-	}
-
-	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
 static void drm_legacy_dev_reinit(struct drm_device *dev)
@@ -382,57 +473,7 @@ int drm_release(struct inode *inode, struct file *filp)
 	list_del(&file_priv->lhead);
 	mutex_unlock(&dev->filelist_mutex);
 
-	if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
-	    dev->driver->preclose)
-		dev->driver->preclose(dev, file_priv);
-
-	/* ========================================================
-	 * Begin inline drm_release
-	 */
-
-	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-		  task_pid_nr(current),
-		  (long)old_encode_dev(file_priv->minor->kdev->devt),
-		  dev->open_count);
-
-	if (drm_core_check_feature(dev, DRIVER_LEGACY))
-		drm_legacy_lock_release(dev, filp);
-
-	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-		drm_legacy_reclaim_buffers(dev, file_priv);
-
-	drm_events_release(file_priv);
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		drm_fb_release(file_priv);
-		drm_property_destroy_user_blobs(dev, file_priv);
-	}
-
-	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
-		drm_syncobj_release(file_priv);
-
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_release(dev, file_priv);
-
-	drm_legacy_ctxbitmap_flush(dev, file_priv);
-
-	if (drm_is_primary_client(file_priv))
-		drm_master_release(file_priv);
-
-	if (dev->driver->postclose)
-		dev->driver->postclose(dev, file_priv);
-
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_destroy_file_private(&file_priv->prime);
-
-	WARN_ON(!list_empty(&file_priv->event_list));
-
-	put_pid(file_priv->pid);
-	kfree(file_priv);
-
-	/* ========================================================
-	 * End inline drm_release
-	 */
+	drm_file_free(file_priv);
 
 	if (!--dev->open_count) {
 		drm_lastclose(dev);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index b72242e93ea4..40179c5fc6b8 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -26,6 +26,8 @@
 
 /* drm_file.c */
 extern struct mutex drm_global_mutex;
+struct drm_file *drm_file_alloc(struct drm_minor *minor);
+void drm_file_free(struct drm_file *file);
 void drm_lastclose(struct drm_device *dev);
 
 /* drm_pci.c */
-- 
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [RFC v4 02/25] drm/file: Don't set master on in-kernel clients
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations Noralf Trønnes
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Noralf Trønnes, laurent.pinchart,
	mstaudt, dh.herrmann

It only makes sense for userspace clients.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_file.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index d4588d33f91c..55505378df47 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -155,17 +155,8 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
 			goto out_prime_destroy;
 	}
 
-	if (drm_is_primary_client(file)) {
-		ret = drm_master_open(file);
-		if (ret)
-			goto out_close;
-	}
-
 	return file;
 
-out_close:
-	if (dev->driver->postclose)
-		dev->driver->postclose(dev, file);
 out_prime_destroy:
 	if (drm_core_check_feature(dev, DRIVER_PRIME))
 		drm_prime_destroy_file_private(&file->prime);
@@ -365,6 +356,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 {
 	struct drm_device *dev = minor->dev;
 	struct drm_file *priv;
+	int ret;
 
 	if (filp->f_flags & O_EXCL)
 		return -EBUSY;	/* No exclusive opens */
@@ -379,6 +371,14 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 	if (IS_ERR(priv))
 		return PTR_ERR(priv);
 
+	if (drm_is_primary_client(priv)) {
+		ret = drm_master_open(priv);
+		if (ret) {
+			drm_file_free(priv);
+			return ret;
+		}
+	}
+
 	filp->private_data = priv;
 	priv->filp = filp;
 
-- 
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 02/25] drm/file: Don't set master on in-kernel clients Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave() Noralf Trønnes
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Hans de Goede, laurent.pinchart, mstaudt

Getting rotation info is cheap so we can do it on demand.

This is done in preparation for the removal of struct drm_fb_helper_crtc.

Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_fb_helper.c | 131 ++++++++++++++++++++--------------------
 include/drm/drm_fb_helper.h     |   8 ---
 2 files changed, 65 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0646b108030b..e48ace2d55f5 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -361,6 +361,48 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+/* Check if the plane can hw rotate to match panel orientation */
+static bool drm_fb_helper_panel_rotation(struct drm_connector *connector,
+					 struct drm_plane *plane,
+					 unsigned int *rotation)
+{
+	uint64_t valid_mask = 0;
+	unsigned int i;
+
+	if (!connector)
+		return false;
+
+	switch (connector->display_info.panel_orientation) {
+	case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+		*rotation = DRM_MODE_ROTATE_180;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+		*rotation = DRM_MODE_ROTATE_90;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+		*rotation = DRM_MODE_ROTATE_270;
+		break;
+	default:
+		*rotation = DRM_MODE_ROTATE_0;
+	}
+
+	/*
+	 * TODO: support 90 / 270 degree hardware rotation,
+	 * depending on the hardware this may require the framebuffer
+	 * to be in a specific tiling format.
+	 */
+	if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+		return false;
+
+	for (i = 0; i < plane->rotation_property->num_values; i++)
+		valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+	if (!(*rotation & valid_mask))
+		return false;
+
+	return true;
+}
+
 static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
 {
 	struct drm_device *dev = fb_helper->dev;
@@ -406,10 +448,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
 		struct drm_plane *primary = mode_set->crtc->primary;
+		unsigned int rotation;
 
-		/* Cannot fail as we've already gotten the plane state above */
-		plane_state = drm_atomic_get_new_plane_state(state, primary);
-		plane_state->rotation = fb_helper->crtc_info[i].rotation;
+		if (drm_fb_helper_panel_rotation(mode_set->connectors[0], primary, &rotation)) {
+			/* Cannot fail as we've already gotten the plane state above */
+			plane_state = drm_atomic_get_new_plane_state(state, primary);
+			plane_state->rotation = rotation;
+		}
 
 		ret = __drm_atomic_helper_set_config(mode_set, state);
 		if (ret != 0)
@@ -841,7 +886,6 @@ int drm_fb_helper_init(struct drm_device *dev,
 		if (!fb_helper->crtc_info[i].mode_set.connectors)
 			goto out_free;
 		fb_helper->crtc_info[i].mode_set.num_connectors = 0;
-		fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0;
 	}
 
 	i = 0;
@@ -2414,62 +2458,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 	return best_score;
 }
 
-/*
- * This function checks if rotation is necessary because of panel orientation
- * and if it is, if it is supported.
- * If rotation is necessary and supported, its gets set in fb_crtc.rotation.
- * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets
- * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only
- * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do
- * the unsupported rotation.
- */
-static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
-				    struct drm_fb_helper_crtc *fb_crtc,
-				    struct drm_connector *connector)
-{
-	struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
-	uint64_t valid_mask = 0;
-	int i, rotation;
-
-	fb_crtc->rotation = DRM_MODE_ROTATE_0;
-
-	switch (connector->display_info.panel_orientation) {
-	case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
-		rotation = DRM_MODE_ROTATE_180;
-		break;
-	case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
-		rotation = DRM_MODE_ROTATE_90;
-		break;
-	case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
-		rotation = DRM_MODE_ROTATE_270;
-		break;
-	default:
-		rotation = DRM_MODE_ROTATE_0;
-	}
-
-	/*
-	 * TODO: support 90 / 270 degree hardware rotation,
-	 * depending on the hardware this may require the framebuffer
-	 * to be in a specific tiling format.
-	 */
-	if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) {
-		fb_helper->sw_rotations |= rotation;
-		return;
-	}
-
-	for (i = 0; i < plane->rotation_property->num_values; i++)
-		valid_mask |= (1ULL << plane->rotation_property->values[i]);
-
-	if (!(rotation & valid_mask)) {
-		fb_helper->sw_rotations |= rotation;
-		return;
-	}
-
-	fb_crtc->rotation = rotation;
-	/* Rotating in hardware, fbcon should not rotate */
-	fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
-}
-
 static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 			    u32 width, u32 height)
 {
@@ -2529,7 +2517,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 		drm_fb_helper_modeset_release(fb_helper,
 					      &fb_helper->crtc_info[i].mode_set);
 
-	fb_helper->sw_rotations = 0;
 	drm_fb_helper_for_each_connector(fb_helper, i) {
 		struct drm_display_mode *mode = modes[i];
 		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
@@ -2549,7 +2536,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 			modeset->mode = drm_mode_duplicate(dev,
 							   fb_crtc->desired_mode);
 			drm_connector_get(connector);
-			drm_setup_crtc_rotation(fb_helper, fb_crtc, connector);
 			modeset->connectors[modeset->num_connectors++] = connector;
 			modeset->x = offset->x;
 			modeset->y = offset->y;
@@ -2572,11 +2558,24 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
 {
 	struct fb_info *info = fb_helper->fbdev;
+	unsigned int rotation, sw_rotations = 0;
 	int i;
 
-	for (i = 0; i < fb_helper->crtc_count; i++)
-		if (fb_helper->crtc_info[i].mode_set.num_connectors)
-			fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
+	for (i = 0; i < fb_helper->crtc_count; i++) {
+		struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
+
+		if (!modeset->num_connectors)
+			continue;
+
+		modeset->fb = fb_helper->fb;
+
+		if (drm_fb_helper_panel_rotation(modeset->connectors[0],
+						 modeset->crtc->primary, &rotation))
+			/* Rotating in hardware, fbcon should not rotate */
+			sw_rotations |= DRM_MODE_ROTATE_0;
+		else
+			sw_rotations |= rotation;
+	}
 
 	mutex_lock(&fb_helper->dev->mode_config.mutex);
 	drm_fb_helper_for_each_connector(fb_helper, i) {
@@ -2592,7 +2591,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
 	}
 	mutex_unlock(&fb_helper->dev->mode_config.mutex);
 
-	switch (fb_helper->sw_rotations) {
+	switch (sw_rotations) {
 	case DRM_MODE_ROTATE_0:
 		info->fbcon_rotate_hint = FB_ROTATE_UR;
 		break;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index b069433e7fc1..d1e45c832cd5 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -49,7 +49,6 @@ struct drm_fb_helper_crtc {
 	struct drm_mode_set mode_set;
 	struct drm_display_mode *desired_mode;
 	int x, y;
-	int rotation;
 };
 
 /**
@@ -160,13 +159,6 @@ struct drm_fb_helper {
 	struct drm_fb_helper_crtc *crtc_info;
 	int connector_count;
 	int connector_info_alloc_count;
-	/**
-	 * @sw_rotations:
-	 * Bitmask of all rotations requested for panel-orientation which
-	 * could not be handled in hardware. If only one bit is set
-	 * fbdev->fbcon_rotate_hint gets set to the requested rotation.
-	 */
-	int sw_rotations;
 	/**
 	 * @connector_info:
 	 *
-- 
2.15.1

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

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

* [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (2 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use Noralf Trønnes
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Noralf Trønnes, laurent.pinchart,
	mstaudt, dh.herrmann

Atomic drivers can't use them so finish what was started in
commit 9c79e0b1d096 ("drm/fb-helper: Give up on kgdb for atomic drivers").

This prepares the ground for creating modesets on demand.

TODO:
- Actually remove the functions, not just the contents.
- Nuke drm_crtc_helper_funcs->mode_set_base_atomic
- Documentation/dev-tools/kgdb.rst

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

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e48ace2d55f5..06e94de6452a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -267,96 +267,14 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 }
 EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
 
-static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
-{
-	uint16_t *r_base, *g_base, *b_base;
-
-	if (crtc->funcs->gamma_set == NULL)
-		return;
-
-	r_base = crtc->gamma_store;
-	g_base = r_base + crtc->gamma_size;
-	b_base = g_base + crtc->gamma_size;
-
-	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
-			       crtc->gamma_size, NULL);
-}
-
-/**
- * drm_fb_helper_debug_enter - implementation for &fb_ops.fb_debug_enter
- * @info: fbdev registered by the helper
- */
 int drm_fb_helper_debug_enter(struct fb_info *info)
 {
-	struct drm_fb_helper *helper = info->par;
-	const struct drm_crtc_helper_funcs *funcs;
-	int i;
-
-	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-		for (i = 0; i < helper->crtc_count; i++) {
-			struct drm_mode_set *mode_set =
-				&helper->crtc_info[i].mode_set;
-
-			if (!mode_set->crtc->enabled)
-				continue;
-
-			funcs =	mode_set->crtc->helper_private;
-			if (funcs->mode_set_base_atomic == NULL)
-				continue;
-
-			if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev))
-				continue;
-
-			funcs->mode_set_base_atomic(mode_set->crtc,
-						    mode_set->fb,
-						    mode_set->x,
-						    mode_set->y,
-						    ENTER_ATOMIC_MODE_SET);
-		}
-	}
-
 	return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_enter);
 
-/**
- * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave
- * @info: fbdev registered by the helper
- */
 int drm_fb_helper_debug_leave(struct fb_info *info)
 {
-	struct drm_fb_helper *helper = info->par;
-	struct drm_crtc *crtc;
-	const struct drm_crtc_helper_funcs *funcs;
-	struct drm_framebuffer *fb;
-	int i;
-
-	for (i = 0; i < helper->crtc_count; i++) {
-		struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-
-		crtc = mode_set->crtc;
-		if (drm_drv_uses_atomic_modeset(crtc->dev))
-			continue;
-
-		funcs = crtc->helper_private;
-		fb = crtc->primary->fb;
-
-		if (!crtc->enabled)
-			continue;
-
-		if (!fb) {
-			DRM_ERROR("no fb to restore??\n");
-			continue;
-		}
-
-		if (funcs->mode_set_base_atomic == NULL)
-			continue;
-
-		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
-		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
-					    crtc->y, LEAVE_ATOMIC_MODE_SET);
-	}
-
 	return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
-- 
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (3 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave() Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Noralf Trønnes
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

For each enabled crtc the functions sets dpms on all registered connectors.
Limit this to only doing it once and on the connectors actually in use.

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

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 06e94de6452a..d0936671a9a6 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -583,20 +583,19 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
 static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
 {
 	struct drm_device *dev = fb_helper->dev;
-	struct drm_crtc *crtc;
 	struct drm_connector *connector;
+	struct drm_mode_set *modeset;
 	int i, j;
 
 	drm_modeset_lock_all(dev);
 	for (i = 0; i < fb_helper->crtc_count; i++) {
-		crtc = fb_helper->crtc_info[i].mode_set.crtc;
+		modeset = &fb_helper->crtc_info[i].mode_set;
 
-		if (!crtc->enabled)
+		if (!modeset->crtc->enabled)
 			continue;
 
-		/* Walk the connectors & encoders on this fb turning them on/off */
-		drm_fb_helper_for_each_connector(fb_helper, j) {
-			connector = fb_helper->connector_info[j]->connector;
+		for (j = 0; j < modeset->num_connectors; j++) {
+			connector = modeset->connectors[j];
 			connector->funcs->dpms(connector, dpms_mode);
 			drm_object_property_set_value(&connector->base,
 				dev->mode_config.dpms_property, dpms_mode);
-- 
2.15.1

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

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

* [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (4 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 07/25] drm: Begin an API for in-kernel clients Noralf Trønnes
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

Prepare for moving drm_fb_helper modesetting code to drm_client.
drm_client will be linked to drm.ko, so move
__drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config()
out of drm_kms_helper.ko.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_atomic.c        | 168 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_atomic_helper.c | 168 +-----------------------------------
 drivers/gpu/drm/drm_fb_helper.c     |   8 +-
 include/drm/drm_atomic.h            |   5 ++
 include/drm/drm_atomic_helper.h     |   4 -
 5 files changed, 179 insertions(+), 174 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 7d25c42f22db..1fb602b6c8b1 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -2060,6 +2060,174 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_clean_old_fb);
 
+/* just used from drm_client and atomic-helper: */
+int drm_atomic_disable_plane(struct drm_plane *plane,
+			     struct drm_plane_state *plane_state)
+{
+	int ret;
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+	if (ret != 0)
+		return ret;
+
+	drm_atomic_set_fb_for_plane(plane_state, NULL);
+	plane_state->crtc_x = 0;
+	plane_state->crtc_y = 0;
+	plane_state->crtc_w = 0;
+	plane_state->crtc_h = 0;
+	plane_state->src_x = 0;
+	plane_state->src_y = 0;
+	plane_state->src_w = 0;
+	plane_state->src_h = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_disable_plane);
+
+static int update_output_state(struct drm_atomic_state *state,
+			       struct drm_mode_set *set)
+{
+	struct drm_device *dev = set->crtc->dev;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *new_crtc_state;
+	struct drm_connector *connector;
+	struct drm_connector_state *new_conn_state;
+	int ret, i;
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
+			       state->acquire_ctx);
+	if (ret)
+		return ret;
+
+	/* First disable all connectors on the target crtc. */
+	ret = drm_atomic_add_affected_connectors(state, set->crtc);
+	if (ret)
+		return ret;
+
+	for_each_new_connector_in_state(state, connector, new_conn_state, i) {
+		if (new_conn_state->crtc == set->crtc) {
+			ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+								NULL);
+			if (ret)
+				return ret;
+
+			/* Make sure legacy setCrtc always re-trains */
+			new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
+		}
+	}
+
+	/* Then set all connectors from set->connectors on the target crtc */
+	for (i = 0; i < set->num_connectors; i++) {
+		new_conn_state = drm_atomic_get_connector_state(state,
+							    set->connectors[i]);
+		if (IS_ERR(new_conn_state))
+			return PTR_ERR(new_conn_state);
+
+		ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+							set->crtc);
+		if (ret)
+			return ret;
+	}
+
+	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+		/*
+		 * Don't update ->enable for the CRTC in the set_config request,
+		 * since a mismatch would indicate a bug in the upper layers.
+		 * The actual modeset code later on will catch any
+		 * inconsistencies here.
+		 */
+		if (crtc == set->crtc)
+			continue;
+
+		if (!new_crtc_state->connector_mask) {
+			ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
+								NULL);
+			if (ret < 0)
+				return ret;
+
+			new_crtc_state->active = false;
+		}
+	}
+
+	return 0;
+}
+
+/* just used from drm_client and atomic-helper: */
+int drm_atomic_set_config(struct drm_mode_set *set,
+			  struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane_state *primary_state;
+	struct drm_crtc *crtc = set->crtc;
+	int hdisplay, vdisplay;
+	int ret;
+
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	primary_state = drm_atomic_get_plane_state(state, crtc->primary);
+	if (IS_ERR(primary_state))
+		return PTR_ERR(primary_state);
+
+	if (!set->mode) {
+		WARN_ON(set->fb);
+		WARN_ON(set->num_connectors);
+
+		ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+		if (ret != 0)
+			return ret;
+
+		crtc_state->active = false;
+
+		ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
+		if (ret != 0)
+			return ret;
+
+		drm_atomic_set_fb_for_plane(primary_state, NULL);
+
+		goto commit;
+	}
+
+	WARN_ON(!set->fb);
+	WARN_ON(!set->num_connectors);
+
+	ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
+	if (ret != 0)
+		return ret;
+
+	crtc_state->active = true;
+
+	ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
+	if (ret != 0)
+		return ret;
+
+	drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);
+
+	drm_atomic_set_fb_for_plane(primary_state, set->fb);
+	primary_state->crtc_x = 0;
+	primary_state->crtc_y = 0;
+	primary_state->crtc_w = hdisplay;
+	primary_state->crtc_h = vdisplay;
+	primary_state->src_x = set->x << 16;
+	primary_state->src_y = set->y << 16;
+	if (drm_rotation_90_or_270(primary_state->rotation)) {
+		primary_state->src_w = vdisplay << 16;
+		primary_state->src_h = hdisplay << 16;
+	} else {
+		primary_state->src_w = hdisplay << 16;
+		primary_state->src_h = vdisplay << 16;
+	}
+
+commit:
+	ret = update_output_state(state, set);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_config);
+
 /**
  * DOC: explicit fencing properties
  *
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index ee03c1ed2521..4f20eb58dd4f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2673,7 +2673,7 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane,
 	if (plane_state->crtc && plane_state->crtc->cursor == plane)
 		plane_state->state->legacy_cursor_update = true;
 
-	ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+	ret = drm_atomic_disable_plane(plane, plane_state);
 	if (ret != 0)
 		goto fail;
 
@@ -2684,95 +2684,6 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane,
 }
 EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
 
-/* just used from fb-helper and atomic-helper: */
-int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
-		struct drm_plane_state *plane_state)
-{
-	int ret;
-
-	ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
-	if (ret != 0)
-		return ret;
-
-	drm_atomic_set_fb_for_plane(plane_state, NULL);
-	plane_state->crtc_x = 0;
-	plane_state->crtc_y = 0;
-	plane_state->crtc_w = 0;
-	plane_state->crtc_h = 0;
-	plane_state->src_x = 0;
-	plane_state->src_y = 0;
-	plane_state->src_w = 0;
-	plane_state->src_h = 0;
-
-	return 0;
-}
-
-static int update_output_state(struct drm_atomic_state *state,
-			       struct drm_mode_set *set)
-{
-	struct drm_device *dev = set->crtc->dev;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *new_crtc_state;
-	struct drm_connector *connector;
-	struct drm_connector_state *new_conn_state;
-	int ret, i;
-
-	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
-			       state->acquire_ctx);
-	if (ret)
-		return ret;
-
-	/* First disable all connectors on the target crtc. */
-	ret = drm_atomic_add_affected_connectors(state, set->crtc);
-	if (ret)
-		return ret;
-
-	for_each_new_connector_in_state(state, connector, new_conn_state, i) {
-		if (new_conn_state->crtc == set->crtc) {
-			ret = drm_atomic_set_crtc_for_connector(new_conn_state,
-								NULL);
-			if (ret)
-				return ret;
-
-			/* Make sure legacy setCrtc always re-trains */
-			new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
-		}
-	}
-
-	/* Then set all connectors from set->connectors on the target crtc */
-	for (i = 0; i < set->num_connectors; i++) {
-		new_conn_state = drm_atomic_get_connector_state(state,
-							    set->connectors[i]);
-		if (IS_ERR(new_conn_state))
-			return PTR_ERR(new_conn_state);
-
-		ret = drm_atomic_set_crtc_for_connector(new_conn_state,
-							set->crtc);
-		if (ret)
-			return ret;
-	}
-
-	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		/* Don't update ->enable for the CRTC in the set_config request,
-		 * since a mismatch would indicate a bug in the upper layers.
-		 * The actual modeset code later on will catch any
-		 * inconsistencies here. */
-		if (crtc == set->crtc)
-			continue;
-
-		if (!new_crtc_state->connector_mask) {
-			ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
-								NULL);
-			if (ret < 0)
-				return ret;
-
-			new_crtc_state->active = false;
-		}
-	}
-
-	return 0;
-}
-
 /**
  * drm_atomic_helper_set_config - set a new config from userspace
  * @set: mode set configuration
@@ -2801,7 +2712,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set,
 		return -ENOMEM;
 
 	state->acquire_ctx = ctx;
-	ret = __drm_atomic_helper_set_config(set, state);
+	ret = drm_atomic_set_config(set, state);
 	if (ret != 0)
 		goto fail;
 
@@ -2817,81 +2728,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set,
 }
 EXPORT_SYMBOL(drm_atomic_helper_set_config);
 
-/* just used from fb-helper and atomic-helper: */
-int __drm_atomic_helper_set_config(struct drm_mode_set *set,
-		struct drm_atomic_state *state)
-{
-	struct drm_crtc_state *crtc_state;
-	struct drm_plane_state *primary_state;
-	struct drm_crtc *crtc = set->crtc;
-	int hdisplay, vdisplay;
-	int ret;
-
-	crtc_state = drm_atomic_get_crtc_state(state, crtc);
-	if (IS_ERR(crtc_state))
-		return PTR_ERR(crtc_state);
-
-	primary_state = drm_atomic_get_plane_state(state, crtc->primary);
-	if (IS_ERR(primary_state))
-		return PTR_ERR(primary_state);
-
-	if (!set->mode) {
-		WARN_ON(set->fb);
-		WARN_ON(set->num_connectors);
-
-		ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
-		if (ret != 0)
-			return ret;
-
-		crtc_state->active = false;
-
-		ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
-		if (ret != 0)
-			return ret;
-
-		drm_atomic_set_fb_for_plane(primary_state, NULL);
-
-		goto commit;
-	}
-
-	WARN_ON(!set->fb);
-	WARN_ON(!set->num_connectors);
-
-	ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
-	if (ret != 0)
-		return ret;
-
-	crtc_state->active = true;
-
-	ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
-	if (ret != 0)
-		return ret;
-
-	drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);
-
-	drm_atomic_set_fb_for_plane(primary_state, set->fb);
-	primary_state->crtc_x = 0;
-	primary_state->crtc_y = 0;
-	primary_state->crtc_w = hdisplay;
-	primary_state->crtc_h = vdisplay;
-	primary_state->src_x = set->x << 16;
-	primary_state->src_y = set->y << 16;
-	if (drm_rotation_90_or_270(primary_state->rotation)) {
-		primary_state->src_w = vdisplay << 16;
-		primary_state->src_h = hdisplay << 16;
-	} else {
-		primary_state->src_w = hdisplay << 16;
-		primary_state->src_h = vdisplay << 16;
-	}
-
-commit:
-	ret = update_output_state(state, set);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
 static int __drm_atomic_helper_disable_all(struct drm_device *dev,
 					   struct drm_modeset_acquire_ctx *ctx,
 					   bool clean_old_fbs)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d0936671a9a6..2eef24db21f8 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -358,7 +358,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 			continue;
 
-		ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+		ret = drm_atomic_disable_plane(plane, plane_state);
 		if (ret != 0)
 			goto out_state;
 	}
@@ -374,13 +374,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 			plane_state->rotation = rotation;
 		}
 
-		ret = __drm_atomic_helper_set_config(mode_set, state);
+		ret = drm_atomic_set_config(mode_set, state);
 		if (ret != 0)
 			goto out_state;
 
 		/*
-		 * __drm_atomic_helper_set_config() sets active when a
-		 * mode is set, unconditionally clear it if we force DPMS off
+		 * drm_atomic_set_config() sets active when a mode is set,
+		 * unconditionally clear it if we force DPMS off
 		 */
 		if (!active) {
 			struct drm_crtc *crtc = mode_set->crtc;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index a57a8aa90ffb..0b0827ff2169 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -604,6 +604,11 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 void
 drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
 
+int drm_atomic_disable_plane(struct drm_plane *plane,
+			     struct drm_plane_state *plane_state);
+int drm_atomic_set_config(struct drm_mode_set *set,
+			  struct drm_atomic_state *state);
+
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
 int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 26aaba58d6ce..8d88a8b2ad52 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -114,12 +114,8 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
 				   struct drm_modeset_acquire_ctx *ctx);
 int drm_atomic_helper_disable_plane(struct drm_plane *plane,
 				    struct drm_modeset_acquire_ctx *ctx);
-int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
-		struct drm_plane_state *plane_state);
 int drm_atomic_helper_set_config(struct drm_mode_set *set,
 				 struct drm_modeset_acquire_ctx *ctx);
-int __drm_atomic_helper_set_config(struct drm_mode_set *set,
-		struct drm_atomic_state *state);
 
 int drm_atomic_helper_disable_all(struct drm_device *dev,
 				  struct drm_modeset_acquire_ctx *ctx);
-- 
2.15.1

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

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

* [RFC v4 07/25] drm: Begin an API for in-kernel clients
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (5 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

This the beginning of an API for in-kernel clients.
First out is a display representation that will be used by drm_fb_helper
in order to move out its mode setting code.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/Makefile     |   2 +-
 drivers/gpu/drm/drm_client.c | 119 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_client.h     |  44 ++++++++++++++++
 3 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_client.c
 create mode 100644 include/drm/drm_client.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9d66657ea117..d25afa136d8f 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,7 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_encoder.o drm_mode_object.o drm_property.o \
 		drm_plane.o drm_color_mgmt.o drm_print.o \
 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-		drm_syncobj.o drm_lease.o
+		drm_syncobj.o drm_lease.o drm_client.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
new file mode 100644
index 000000000000..7c31a6efb2f4
--- /dev/null
+++ b/drivers/gpu/drm/drm_client.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Noralf Trønnes
+ *
+ * For parts copied from drm_fb_helper:
+ * Copyright (c) 2006-2009 Red Hat Inc.
+ * Copyright (c) 2006-2008 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ */
+
+#include <linux/slab.h>
+
+#include <drm/drm_client.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_modes.h>
+
+/**
+ * drm_client_display_create() - Create display structure
+ * @dev: DRM device
+ *
+ * This function creates a display structure for clients backed by an array of
+ * &drm_mode_set, one per CRTC.
+ *
+ * Returns:
+ * A &drm_client_display or an error pointer on allocation failure.
+ */
+struct drm_client_display *drm_client_display_create(struct drm_device *dev)
+{
+	unsigned int num_crtc = dev->mode_config.num_crtc;
+	struct drm_client_display *display;
+	struct drm_mode_set *modeset;
+	struct drm_crtc *crtc;
+	unsigned int i = 0;
+
+	display = kzalloc(sizeof(*display), GFP_KERNEL);
+	if (!display)
+		return ERR_PTR(-ENOMEM);
+
+	/* Add NULL terminating entry to enable index less iteration */
+	display->modesets = kcalloc(num_crtc + 1, sizeof(*display->modesets), GFP_KERNEL);
+	if (!display->modesets) {
+		kfree(display);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	display->dev = dev;
+	display->modeset_count = num_crtc;
+
+	drm_for_each_crtc(crtc, dev)
+		display->modesets[i++].crtc = crtc;
+
+	drm_client_display_for_each_modeset(modeset, display) {
+		/* One connector per crtc except for the cloned case */
+		modeset->connectors = kcalloc(2, sizeof(*modeset->connectors), GFP_KERNEL);
+		if (!modeset->connectors)
+			goto err_free;
+	}
+
+	return display;
+
+err_free:
+	drm_client_display_free(display);
+
+	return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL(drm_client_display_create);
+
+/**
+ * drm_client_display_free() - Free display structure
+ * @display: Client display
+ *
+ * This function frees the structure allocated by drm_client_display_create().
+ * It also destroys display modes and puts connectors.
+ */
+void drm_client_display_free(struct drm_client_display *display)
+{
+	struct drm_mode_set *modeset;
+	unsigned int i;
+
+	if (!display)
+		return;
+
+	drm_client_display_for_each_modeset(modeset, display) {
+		if (modeset->mode)
+			drm_mode_destroy(display->dev, modeset->mode);
+
+		for (i = 0; i < modeset->num_connectors; i++)
+			drm_connector_put(modeset->connectors[i]);
+		kfree(modeset->connectors);
+	}
+	kfree(display->modesets);
+	kfree(display);
+}
+EXPORT_SYMBOL(drm_client_display_free);
+
+/**
+ * drm_client_display_find_modeset() - Find modeset matching a CRTC
+ * @display: Client display
+ * @crtc: CRTC
+ *
+ * This function looks up the @display modeset connected to @crtc.
+ *
+ * Returns:
+ * A &drm_mode_set or NULL.
+ */
+struct drm_mode_set *
+drm_client_display_find_modeset(struct drm_client_display *display, struct drm_crtc *crtc)
+{
+	struct drm_mode_set *modeset;
+
+	drm_client_display_for_each_modeset(modeset, display)
+		if (modeset->crtc == crtc)
+			return modeset;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_client_display_find_modeset);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
new file mode 100644
index 000000000000..b6a057802769
--- /dev/null
+++ b/include/drm/drm_client.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DRM_CLIENT_H_
+#define _DRM_CLIENT_H_
+
+struct drm_crtc;
+struct drm_device;
+struct drm_mode_set;
+
+/**
+ * struct drm_client_display - DRM client display
+ */
+struct drm_client_display {
+	/**
+	 * @dev:
+	 *
+	 * DRM device.
+	 */
+	struct drm_device *dev;
+
+	/**
+	 * @modesets:
+	 *
+	 * Per CRTC array of modeset configurations.
+	 */
+	struct drm_mode_set *modesets;
+
+	/**
+	 * @modeset_count:
+	 *
+	 * Number of modesets
+	 */
+	unsigned int modeset_count;
+};
+
+struct drm_client_display *drm_client_display_create(struct drm_device *dev);
+void drm_client_display_free(struct drm_client_display *display);
+struct drm_mode_set *
+drm_client_display_find_modeset(struct drm_client_display *display, struct drm_crtc *crtc);
+
+#define drm_client_display_for_each_modeset(modeset, display) \
+	for (modeset = display->modesets; modeset->crtc; modeset++)
+
+#endif
-- 
2.15.1

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

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

* [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (6 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 07/25] drm: Begin an API for in-kernel clients Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Noralf Trønnes
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

Prepare to move the modeset committing code to drm_client.

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

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 2eef24db21f8..bdb4b57d2c12 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <drm/drmP.h>
+#include <drm/drm_client.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -321,13 +322,14 @@ static bool drm_fb_helper_panel_rotation(struct drm_connector *connector,
 	return true;
 }
 
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
+static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active)
 {
-	struct drm_device *dev = fb_helper->dev;
+	struct drm_device *dev = display->dev;
 	struct drm_plane_state *plane_state;
+	struct drm_mode_set *mode_set;
 	struct drm_plane *plane;
 	struct drm_atomic_state *state;
-	int i, ret;
+	int ret;
 	unsigned int plane_mask;
 	struct drm_modeset_acquire_ctx ctx;
 
@@ -363,8 +365,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 			goto out_state;
 	}
 
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+	drm_client_display_for_each_modeset(mode_set, display) {
 		struct drm_plane *primary = mode_set->crtc->primary;
 		unsigned int rotation;
 
@@ -412,13 +413,14 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 	goto retry;
 }
 
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore_legacy(struct drm_client_display *display)
 {
-	struct drm_device *dev = fb_helper->dev;
+	struct drm_device *dev = display->dev;
+	struct drm_mode_set *mode_set;
 	struct drm_plane *plane;
-	int i, ret = 0;
+	int ret = 0;
 
-	drm_modeset_lock_all(fb_helper->dev);
+	drm_modeset_lock_all(dev);
 	drm_for_each_plane(plane, dev) {
 		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
 			drm_plane_force_disable(plane);
@@ -429,8 +431,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
 						    DRM_MODE_ROTATE_0);
 	}
 
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+	drm_client_display_for_each_modeset(mode_set, display) {
 		struct drm_crtc *crtc = mode_set->crtc;
 
 		if (crtc->funcs->cursor_set2) {
@@ -448,19 +449,17 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
 			goto out;
 	}
 out:
-	drm_modeset_unlock_all(fb_helper->dev);
+	drm_modeset_unlock_all(dev);
 
 	return ret;
 }
 
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore(struct drm_client_display *display)
 {
-	struct drm_device *dev = fb_helper->dev;
-
-	if (drm_drv_uses_atomic_modeset(dev))
-		return restore_fbdev_mode_atomic(fb_helper, true);
+	if (drm_drv_uses_atomic_modeset(display->dev))
+		return drm_client_display_restore_atomic(display, true);
 	else
-		return restore_fbdev_mode_legacy(fb_helper);
+		return drm_client_display_restore_legacy(display);
 }
 
 /**
@@ -486,7 +485,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 		return 0;
 
 	mutex_lock(&fb_helper->lock);
-	ret = restore_fbdev_mode(fb_helper);
+	ret = drm_client_display_restore(fb_helper->display);
 
 	do_delayed = fb_helper->delayed_hotplug;
 	if (do_delayed)
@@ -548,7 +547,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
 			continue;
 
 		mutex_lock(&helper->lock);
-		ret = restore_fbdev_mode(helper);
+		ret = drm_client_display_restore(helper->display);
 		if (ret)
 			error = true;
 		mutex_unlock(&helper->lock);
@@ -580,22 +579,20 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
 #endif
 
-static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
+static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode)
 {
-	struct drm_device *dev = fb_helper->dev;
+	struct drm_device *dev = display->dev;
 	struct drm_connector *connector;
 	struct drm_mode_set *modeset;
-	int i, j;
+	int i;
 
 	drm_modeset_lock_all(dev);
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		modeset = &fb_helper->crtc_info[i].mode_set;
-
+	drm_client_display_for_each_modeset(modeset, display) {
 		if (!modeset->crtc->enabled)
 			continue;
 
-		for (j = 0; j < modeset->num_connectors; j++) {
-			connector = modeset->connectors[j];
+		for (i = 0; i < modeset->num_connectors; i++) {
+			connector = modeset->connectors[i];
 			connector->funcs->dpms(connector, dpms_mode);
 			drm_object_property_set_value(&connector->base,
 				dev->mode_config.dpms_property, dpms_mode);
@@ -604,23 +601,21 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
 	drm_modeset_unlock_all(dev);
 }
 
+static void drm_client_display_dpms(struct drm_client_display *display, int mode)
+{
+	if (drm_drv_uses_atomic_modeset(display->dev))
+		drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON);
+	else
+		drm_client_display_dpms_legacy(display, mode);
+}
+
 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 {
 	struct drm_fb_helper *fb_helper = info->par;
 
-	/*
-	 * For each CRTC in this fb, turn the connectors on/off.
-	 */
 	mutex_lock(&fb_helper->lock);
-	if (!drm_fb_helper_is_bound(fb_helper)) {
-		mutex_unlock(&fb_helper->lock);
-		return;
-	}
-
-	if (drm_drv_uses_atomic_modeset(fb_helper->dev))
-		restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
-	else
-		dpms_legacy(fb_helper, dpms_mode);
+	if (drm_fb_helper_is_bound(fb_helper))
+		drm_client_display_dpms(fb_helper->display, dpms_mode);
 	mutex_unlock(&fb_helper->lock);
 }
 
@@ -811,6 +806,10 @@ int drm_fb_helper_init(struct drm_device *dev,
 		i++;
 	}
 
+	fb_helper->display = drm_client_display_create(dev);
+	if (IS_ERR(fb_helper->display))
+		goto out_free;
+
 	dev->fb_helper = fb_helper;
 
 	return 0;
@@ -919,6 +918,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 	mutex_unlock(&kernel_fb_helper_lock);
 
 	mutex_destroy(&fb_helper->lock);
+	drm_client_display_free(fb_helper->display);
 	drm_fb_helper_crtc_free(fb_helper);
 
 }
@@ -1265,13 +1265,14 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info)
 static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
 {
 	struct drm_fb_helper *fb_helper = info->par;
+	struct drm_mode_set *modeset;
 	struct drm_crtc *crtc;
 	u16 *r, *g, *b;
-	int i, ret = 0;
+	int ret = 0;
 
 	drm_modeset_lock_all(fb_helper->dev);
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		crtc = fb_helper->crtc_info[i].mode_set.crtc;
+	drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+		crtc = modeset->crtc;
 		if (!crtc->funcs->gamma_set || !crtc->gamma_size)
 			return -EINVAL;
 
@@ -1347,9 +1348,10 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
 	struct drm_modeset_acquire_ctx ctx;
 	struct drm_crtc_state *crtc_state;
 	struct drm_atomic_state *state;
+	struct drm_mode_set *modeset;
 	struct drm_crtc *crtc;
 	u16 *r, *g, *b;
-	int i, ret = 0;
+	int ret = 0;
 	bool replaced;
 
 	drm_modeset_acquire_init(&ctx, 0);
@@ -1362,8 +1364,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
 
 	state->acquire_ctx = &ctx;
 retry:
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		crtc = fb_helper->crtc_info[i].mode_set.crtc;
+	drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+		crtc = modeset->crtc;
 
 		if (!gamma_lut)
 			gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
@@ -1391,8 +1393,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
 	if (ret)
 		goto out_state;
 
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		crtc = fb_helper->crtc_info[i].mode_set.crtc;
+	drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+		crtc = modeset->crtc;
 
 		r = crtc->gamma_store;
 		g = r + crtc->gamma_size;
@@ -1468,7 +1470,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
 			unsigned long arg)
 {
 	struct drm_fb_helper *fb_helper = info->par;
-	struct drm_mode_set *mode_set;
 	struct drm_crtc *crtc;
 	int ret = 0;
 
@@ -1496,8 +1497,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
 		 * make. If we're not smart enough here, one should
 		 * just consider switch the userspace to KMS.
 		 */
-		mode_set = &fb_helper->crtc_info[0].mode_set;
-		crtc = mode_set->crtc;
+		crtc = fb_helper->display->modesets[0].crtc;
 
 		/*
 		 * Only wait for a vblank event if the CRTC is
@@ -1651,13 +1651,9 @@ EXPORT_SYMBOL(drm_fb_helper_set_par);
 
 static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
 {
-	int i;
-
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		struct drm_mode_set *mode_set;
-
-		mode_set = &fb_helper->crtc_info[i].mode_set;
+	struct drm_mode_set *mode_set;
 
+	drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
 		mode_set->x = x;
 		mode_set->y = y;
 	}
@@ -1671,7 +1667,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
 
 	pan_set(fb_helper, var->xoffset, var->yoffset);
 
-	ret = restore_fbdev_mode_atomic(fb_helper, true);
+	ret = drm_client_display_restore(fb_helper->display);
 	if (!ret) {
 		info->var.xoffset = var->xoffset;
 		info->var.yoffset = var->yoffset;
@@ -1687,12 +1683,9 @@ static int pan_display_legacy(struct fb_var_screeninfo *var,
 	struct drm_fb_helper *fb_helper = info->par;
 	struct drm_mode_set *modeset;
 	int ret = 0;
-	int i;
 
 	drm_modeset_lock_all(fb_helper->dev);
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		modeset = &fb_helper->crtc_info[i].mode_set;
-
+	drm_client_display_for_each_modeset(modeset, fb_helper->display) {
 		modeset->x = var->xoffset;
 		modeset->y = var->yoffset;
 
@@ -1751,6 +1744,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	int crtc_count = 0;
 	int i;
 	struct drm_fb_helper_surface_size sizes;
+	struct drm_mode_set *mode_set;
 	int gamma_size = 0;
 
 	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
@@ -1795,9 +1789,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	}
 
 	crtc_count = 0;
-	for (i = 0; i < fb_helper->crtc_count; i++) {
+	drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
 		struct drm_display_mode *desired_mode;
-		struct drm_mode_set *mode_set;
 		int x, y, j;
 		/* in case of tile group, are we the last tile vert or horiz?
 		 * If no tile group you are always the last one both vertically
@@ -1805,19 +1798,18 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 		 */
 		bool lastv = true, lasth = true;
 
-		desired_mode = fb_helper->crtc_info[i].desired_mode;
-		mode_set = &fb_helper->crtc_info[i].mode_set;
+		desired_mode = mode_set->mode;
 
 		if (!desired_mode)
 			continue;
 
 		crtc_count++;
 
-		x = fb_helper->crtc_info[i].x;
-		y = fb_helper->crtc_info[i].y;
+		x = mode_set->x;
+		y = mode_set->y;
 
 		if (gamma_size == 0)
-			gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
+			gamma_size = mode_set->crtc->gamma_size;
 
 		sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
 		sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
@@ -1844,7 +1836,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 
 		/* First time: disable all crtc's.. */
 		if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))
-			restore_fbdev_mode(fb_helper);
+			drm_client_display_restore(fb_helper->display);
 		return -EAGAIN;
 	}
 
@@ -2379,6 +2371,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 			    u32 width, u32 height)
 {
 	struct drm_device *dev = fb_helper->dev;
+	struct drm_client_display *display;
 	struct drm_fb_helper_crtc **crtcs;
 	struct drm_display_mode **modes;
 	struct drm_fb_offset *offsets;
@@ -2402,6 +2395,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 		goto out;
 	}
 
+	display = drm_client_display_create(dev);
+	if (IS_ERR(display))
+		goto out;
+
 	mutex_lock(&fb_helper->dev->mode_config.mutex);
 	if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
 		DRM_DEBUG_KMS("No connectors reported connected with modes\n");
@@ -2440,24 +2437,29 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
 		struct drm_fb_offset *offset = &offsets[i];
 
 		if (mode && fb_crtc) {
-			struct drm_mode_set *modeset = &fb_crtc->mode_set;
 			struct drm_connector *connector =
 				fb_helper->connector_info[i]->connector;
+			struct drm_mode_set *modeset;
+
+			modeset = drm_client_display_find_modeset(display, fb_crtc->mode_set.crtc);
+			if (WARN_ON(!modeset)) {
+				drm_client_display_free(display);
+				goto out;
+			}
 
 			DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
-				      mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
+				      mode->name, modeset->crtc->base.id, offset->x, offset->y);
 
-			fb_crtc->desired_mode = mode;
-			fb_crtc->x = offset->x;
-			fb_crtc->y = offset->y;
-			modeset->mode = drm_mode_duplicate(dev,
-							   fb_crtc->desired_mode);
+			modeset->mode = drm_mode_duplicate(dev, mode);
 			drm_connector_get(connector);
 			modeset->connectors[modeset->num_connectors++] = connector;
 			modeset->x = offset->x;
 			modeset->y = offset->y;
 		}
 	}
+
+	drm_client_display_free(fb_helper->display);
+	fb_helper->display = display;
 out:
 	kfree(crtcs);
 	kfree(modes);
@@ -2476,11 +2478,10 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
 {
 	struct fb_info *info = fb_helper->fbdev;
 	unsigned int rotation, sw_rotations = 0;
+	struct drm_mode_set *modeset;
 	int i;
 
-	for (i = 0; i < fb_helper->crtc_count; i++) {
-		struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
-
+	drm_client_display_for_each_modeset(modeset, fb_helper->display) {
 		if (!modeset->num_connectors)
 			continue;
 
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index d1e45c832cd5..e2df40ad5063 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -155,6 +155,14 @@ struct drm_fb_helper_connector {
 struct drm_fb_helper {
 	struct drm_framebuffer *fb;
 	struct drm_device *dev;
+
+	/**
+	 * @display:
+	 *
+	 * Display representation.
+	 */
+	struct drm_client_display *display;
+
 	int crtc_count;
 	struct drm_fb_helper_crtc *crtc_info;
 	int connector_count;
-- 
2.15.1

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

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

* [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (7 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode() Noralf Trønnes
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

This moves the committing part of the modesetting code to drm_client.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_client.c    | 242 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_fb_helper.c | 216 +----------------------------------
 include/drm/drm_client.h        |   8 ++
 3 files changed, 252 insertions(+), 214 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 7c31a6efb2f4..c85c13568cf9 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -10,6 +10,8 @@
 
 #include <linux/slab.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_client.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
@@ -117,3 +119,243 @@ drm_client_display_find_modeset(struct drm_client_display *display, struct drm_c
 	return NULL;
 }
 EXPORT_SYMBOL(drm_client_display_find_modeset);
+
+/**
+ * drm_client_display_panel_rotation() - Check panel orientation
+ * @connector: DRM connector
+ * @plane: DRM plane
+ * @rotation: Returned rotation value
+ *
+ * This function checks if @plane can hw rotate to match the panel orientation
+ * on @connector.
+ *
+ * Return:
+ * True if the plane can do the rotation, false otherwise.
+ */
+bool drm_client_display_panel_rotation(struct drm_connector *connector,
+				       struct drm_plane *plane,
+				       unsigned int *rotation)
+{
+	uint64_t valid_mask = 0;
+	unsigned int i;
+
+	if (!connector)
+		return false;
+
+	switch (connector->display_info.panel_orientation) {
+	case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+		*rotation = DRM_MODE_ROTATE_180;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+		*rotation = DRM_MODE_ROTATE_90;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+		*rotation = DRM_MODE_ROTATE_270;
+		break;
+	default:
+		*rotation = DRM_MODE_ROTATE_0;
+	}
+
+	/*
+	 * TODO: support 90 / 270 degree hardware rotation,
+	 * depending on the hardware this may require the framebuffer
+	 * to be in a specific tiling format.
+	 */
+	if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+		return false;
+
+	for (i = 0; i < plane->rotation_property->num_values; i++)
+		valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+	if (!(*rotation & valid_mask))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(drm_client_display_panel_rotation);
+
+static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active)
+{
+	struct drm_device *dev = display->dev;
+	struct drm_plane_state *plane_state;
+	struct drm_mode_set *mode_set;
+	struct drm_plane *plane;
+	struct drm_atomic_state *state;
+	int ret;
+	unsigned int plane_mask;
+	struct drm_modeset_acquire_ctx ctx;
+
+	drm_modeset_acquire_init(&ctx, 0);
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state) {
+		ret = -ENOMEM;
+		goto out_ctx;
+	}
+
+	state->acquire_ctx = &ctx;
+retry:
+	plane_mask = 0;
+	drm_for_each_plane(plane, dev) {
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			ret = PTR_ERR(plane_state);
+			goto out_state;
+		}
+
+		plane_state->rotation = DRM_MODE_ROTATE_0;
+
+		plane->old_fb = plane->fb;
+		plane_mask |= 1 << drm_plane_index(plane);
+
+		/* disable non-primary: */
+		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+			continue;
+
+		ret = drm_atomic_disable_plane(plane, plane_state);
+		if (ret != 0)
+			goto out_state;
+	}
+
+	drm_client_display_for_each_modeset(mode_set, display) {
+		struct drm_plane *primary = mode_set->crtc->primary;
+		unsigned int rotation;
+
+		if (drm_client_display_panel_rotation(mode_set->connectors[0], primary, &rotation)) {
+			/* Cannot fail as we've already gotten the plane state above */
+			plane_state = drm_atomic_get_new_plane_state(state, primary);
+			plane_state->rotation = rotation;
+		}
+
+		ret = drm_atomic_set_config(mode_set, state);
+		if (ret != 0)
+			goto out_state;
+
+		/*
+		 * drm_atomic_set_config() sets active when a
+		 * mode is set, unconditionally clear it if we force DPMS off
+		 */
+		if (!active) {
+			struct drm_crtc *crtc = mode_set->crtc;
+			struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+			crtc_state->active = false;
+		}
+	}
+
+	ret = drm_atomic_commit(state);
+
+out_state:
+	drm_atomic_clean_old_fb(dev, plane_mask, ret);
+
+	if (ret == -EDEADLK)
+		goto backoff;
+
+	drm_atomic_state_put(state);
+out_ctx:
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+
+backoff:
+	drm_atomic_state_clear(state);
+	drm_modeset_backoff(&ctx);
+
+	goto retry;
+}
+
+static int drm_client_display_restore_legacy(struct drm_client_display *display)
+{
+	struct drm_device *dev = display->dev;
+	struct drm_mode_set *mode_set;
+	struct drm_plane *plane;
+	int ret = 0;
+
+	drm_modeset_lock_all(dev);
+	drm_for_each_plane(plane, dev) {
+		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+			drm_plane_force_disable(plane);
+
+		if (plane->rotation_property)
+			drm_mode_plane_set_obj_prop(plane,
+						    plane->rotation_property,
+						    DRM_MODE_ROTATE_0);
+	}
+
+	drm_client_display_for_each_modeset(mode_set, display) {
+		struct drm_crtc *crtc = mode_set->crtc;
+
+		if (crtc->funcs->cursor_set2) {
+			ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
+			if (ret)
+				goto out;
+		} else if (crtc->funcs->cursor_set) {
+			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
+			if (ret)
+				goto out;
+		}
+
+		ret = drm_mode_set_config_internal(mode_set);
+		if (ret)
+			goto out;
+	}
+out:
+	drm_modeset_unlock_all(dev);
+
+	return ret;
+}
+
+/**
+ * drm_client_display_restore() - Restore client display
+ * @display: Client display
+ *
+ * Restore client display using the current modeset configuration.
+ *
+ * Return:
+ * Zero on succes or negative error code on failure.
+ */
+int drm_client_display_restore(struct drm_client_display *display)
+{
+	if (drm_drv_uses_atomic_modeset(display->dev))
+		return drm_client_display_restore_atomic(display, true);
+	else
+		return drm_client_display_restore_legacy(display);
+}
+EXPORT_SYMBOL(drm_client_display_restore);
+
+static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode)
+{
+	struct drm_device *dev = display->dev;
+	struct drm_connector *connector;
+	struct drm_mode_set *modeset;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	drm_client_display_for_each_modeset(modeset, display) {
+		if (!modeset->crtc->enabled)
+			continue;
+
+		for (i = 0; i < modeset->num_connectors; i++) {
+			connector = modeset->connectors[i];
+			connector->funcs->dpms(connector, dpms_mode);
+			drm_object_property_set_value(&connector->base,
+				dev->mode_config.dpms_property, dpms_mode);
+		}
+	}
+	drm_modeset_unlock_all(dev);
+}
+
+/**
+ * drm_client_display_dpms() - Set display DPMS mode
+ * @display: Client display
+ * @mode: DPMS mode
+ */
+void drm_client_display_dpms(struct drm_client_display *display, int mode)
+{
+	if (drm_drv_uses_atomic_modeset(display->dev))
+		drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON);
+	else
+		drm_client_display_dpms_legacy(display, mode);
+}
+EXPORT_SYMBOL(drm_client_display_dpms);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index bdb4b57d2c12..785a2f5d2647 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -280,188 +280,6 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
-/* Check if the plane can hw rotate to match panel orientation */
-static bool drm_fb_helper_panel_rotation(struct drm_connector *connector,
-					 struct drm_plane *plane,
-					 unsigned int *rotation)
-{
-	uint64_t valid_mask = 0;
-	unsigned int i;
-
-	if (!connector)
-		return false;
-
-	switch (connector->display_info.panel_orientation) {
-	case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
-		*rotation = DRM_MODE_ROTATE_180;
-		break;
-	case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
-		*rotation = DRM_MODE_ROTATE_90;
-		break;
-	case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
-		*rotation = DRM_MODE_ROTATE_270;
-		break;
-	default:
-		*rotation = DRM_MODE_ROTATE_0;
-	}
-
-	/*
-	 * TODO: support 90 / 270 degree hardware rotation,
-	 * depending on the hardware this may require the framebuffer
-	 * to be in a specific tiling format.
-	 */
-	if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
-		return false;
-
-	for (i = 0; i < plane->rotation_property->num_values; i++)
-		valid_mask |= (1ULL << plane->rotation_property->values[i]);
-
-	if (!(*rotation & valid_mask))
-		return false;
-
-	return true;
-}
-
-static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active)
-{
-	struct drm_device *dev = display->dev;
-	struct drm_plane_state *plane_state;
-	struct drm_mode_set *mode_set;
-	struct drm_plane *plane;
-	struct drm_atomic_state *state;
-	int ret;
-	unsigned int plane_mask;
-	struct drm_modeset_acquire_ctx ctx;
-
-	drm_modeset_acquire_init(&ctx, 0);
-
-	state = drm_atomic_state_alloc(dev);
-	if (!state) {
-		ret = -ENOMEM;
-		goto out_ctx;
-	}
-
-	state->acquire_ctx = &ctx;
-retry:
-	plane_mask = 0;
-	drm_for_each_plane(plane, dev) {
-		plane_state = drm_atomic_get_plane_state(state, plane);
-		if (IS_ERR(plane_state)) {
-			ret = PTR_ERR(plane_state);
-			goto out_state;
-		}
-
-		plane_state->rotation = DRM_MODE_ROTATE_0;
-
-		plane->old_fb = plane->fb;
-		plane_mask |= 1 << drm_plane_index(plane);
-
-		/* disable non-primary: */
-		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-			continue;
-
-		ret = drm_atomic_disable_plane(plane, plane_state);
-		if (ret != 0)
-			goto out_state;
-	}
-
-	drm_client_display_for_each_modeset(mode_set, display) {
-		struct drm_plane *primary = mode_set->crtc->primary;
-		unsigned int rotation;
-
-		if (drm_fb_helper_panel_rotation(mode_set->connectors[0], primary, &rotation)) {
-			/* Cannot fail as we've already gotten the plane state above */
-			plane_state = drm_atomic_get_new_plane_state(state, primary);
-			plane_state->rotation = rotation;
-		}
-
-		ret = drm_atomic_set_config(mode_set, state);
-		if (ret != 0)
-			goto out_state;
-
-		/*
-		 * drm_atomic_set_config() sets active when a mode is set,
-		 * unconditionally clear it if we force DPMS off
-		 */
-		if (!active) {
-			struct drm_crtc *crtc = mode_set->crtc;
-			struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
-
-			crtc_state->active = false;
-		}
-	}
-
-	ret = drm_atomic_commit(state);
-
-out_state:
-	drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
-	if (ret == -EDEADLK)
-		goto backoff;
-
-	drm_atomic_state_put(state);
-out_ctx:
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
-
-	return ret;
-
-backoff:
-	drm_atomic_state_clear(state);
-	drm_modeset_backoff(&ctx);
-
-	goto retry;
-}
-
-static int drm_client_display_restore_legacy(struct drm_client_display *display)
-{
-	struct drm_device *dev = display->dev;
-	struct drm_mode_set *mode_set;
-	struct drm_plane *plane;
-	int ret = 0;
-
-	drm_modeset_lock_all(dev);
-	drm_for_each_plane(plane, dev) {
-		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
-			drm_plane_force_disable(plane);
-
-		if (plane->rotation_property)
-			drm_mode_plane_set_obj_prop(plane,
-						    plane->rotation_property,
-						    DRM_MODE_ROTATE_0);
-	}
-
-	drm_client_display_for_each_modeset(mode_set, display) {
-		struct drm_crtc *crtc = mode_set->crtc;
-
-		if (crtc->funcs->cursor_set2) {
-			ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
-			if (ret)
-				goto out;
-		} else if (crtc->funcs->cursor_set) {
-			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
-			if (ret)
-				goto out;
-		}
-
-		ret = drm_mode_set_config_internal(mode_set);
-		if (ret)
-			goto out;
-	}
-out:
-	drm_modeset_unlock_all(dev);
-
-	return ret;
-}
-
-static int drm_client_display_restore(struct drm_client_display *display)
-{
-	if (drm_drv_uses_atomic_modeset(display->dev))
-		return drm_client_display_restore_atomic(display, true);
-	else
-		return drm_client_display_restore_legacy(display);
-}
-
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
  * @fb_helper: driver-allocated fbdev helper, can be NULL
@@ -579,36 +397,6 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
 #endif
 
-static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode)
-{
-	struct drm_device *dev = display->dev;
-	struct drm_connector *connector;
-	struct drm_mode_set *modeset;
-	int i;
-
-	drm_modeset_lock_all(dev);
-	drm_client_display_for_each_modeset(modeset, display) {
-		if (!modeset->crtc->enabled)
-			continue;
-
-		for (i = 0; i < modeset->num_connectors; i++) {
-			connector = modeset->connectors[i];
-			connector->funcs->dpms(connector, dpms_mode);
-			drm_object_property_set_value(&connector->base,
-				dev->mode_config.dpms_property, dpms_mode);
-		}
-	}
-	drm_modeset_unlock_all(dev);
-}
-
-static void drm_client_display_dpms(struct drm_client_display *display, int mode)
-{
-	if (drm_drv_uses_atomic_modeset(display->dev))
-		drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON);
-	else
-		drm_client_display_dpms_legacy(display, mode);
-}
-
 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 {
 	struct drm_fb_helper *fb_helper = info->par;
@@ -2487,8 +2275,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
 
 		modeset->fb = fb_helper->fb;
 
-		if (drm_fb_helper_panel_rotation(modeset->connectors[0],
-						 modeset->crtc->primary, &rotation))
+		if (drm_client_display_panel_rotation(modeset->connectors[0],
+						      modeset->crtc->primary, &rotation))
 			/* Rotating in hardware, fbcon should not rotate */
 			sw_rotations |= DRM_MODE_ROTATE_0;
 		else
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index b6a057802769..ed028f5877d0 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -3,9 +3,11 @@
 #ifndef _DRM_CLIENT_H_
 #define _DRM_CLIENT_H_
 
+struct drm_connector;
 struct drm_crtc;
 struct drm_device;
 struct drm_mode_set;
+struct drm_plane;
 
 /**
  * struct drm_client_display - DRM client display
@@ -41,4 +43,10 @@ drm_client_display_find_modeset(struct drm_client_display *display, struct drm_c
 #define drm_client_display_for_each_modeset(modeset, display) \
 	for (modeset = display->modesets; modeset->crtc; modeset++)
 
+bool drm_client_display_panel_rotation(struct drm_connector *connector,
+				       struct drm_plane *plane,
+				       unsigned int *rotation);
+int drm_client_display_restore(struct drm_client_display *display);
+void drm_client_display_dpms(struct drm_client_display *display, int mode);
+
 #endif
-- 
2.15.1

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

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

* [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode()
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (8 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 13:17 ` [RFC v4 11/25] drm/connector: Add connector array functions Noralf Trønnes
  2018-04-12 16:34 ` [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

Move them over from drm_fb_helper since they are connector functions.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_connector.c    | 94 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_fb_helper.c    | 75 ++----------------------------
 drivers/gpu/drm/i915/intel_fbdev.c |  7 +--
 include/drm/drm_connector.h        |  6 +++
 include/drm/drm_fb_helper.h        | 19 --------
 5 files changed, 108 insertions(+), 93 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b3cde897cd80..b9eb143d70fc 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1760,3 +1760,97 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
 	return tg;
 }
 EXPORT_SYMBOL(drm_mode_create_tile_group);
+
+/**
+ * drm_connector_has_preferred_mode() - Lookup preferred display mode
+ * @connector: DRM connector
+ * @width: Max width
+ * @height: Max height
+ *
+ * Look for a preferred display mode within the bounds of @width and @height
+ * (inclusive).
+ *
+ * Returns:
+ * A &drm_display_mode or NULL.
+ */
+struct drm_display_mode *
+drm_connector_has_preferred_mode(struct drm_connector *connector,
+				 int width, int height)
+{
+	struct drm_display_mode *mode;
+
+	list_for_each_entry(mode, &connector->modes, head) {
+		if (mode->hdisplay > width || mode->vdisplay > height)
+			continue;
+		if (mode->type & DRM_MODE_TYPE_PREFERRED)
+			return mode;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_connector_has_preferred_mode);
+
+/**
+ * drm_connector_pick_cmdline_mode() - Get commandline display mode
+ * @connector: DRM connector
+ *
+ * Return the display mode specified on the kernel commandline or NULL if not
+ * specified.
+ *
+ * Returns:
+ * A &drm_display_mode or NULL.
+ */
+struct drm_display_mode *
+drm_connector_pick_cmdline_mode(struct drm_connector *connector)
+{
+	struct drm_cmdline_mode *cmdline_mode;
+	struct drm_display_mode *mode;
+	bool prefer_non_interlace;
+
+	cmdline_mode = &connector->cmdline_mode;
+	if (!cmdline_mode->specified)
+		return NULL;
+
+	/* attempt to find a matching mode in the list of modes
+	 *  we have gotten so far, if not add a CVT mode that conforms
+	 */
+	if (cmdline_mode->rb || cmdline_mode->margins)
+		goto create_mode;
+
+	prefer_non_interlace = !cmdline_mode->interlace;
+again:
+	list_for_each_entry(mode, &connector->modes, head) {
+		/* check width/height */
+		if (mode->hdisplay != cmdline_mode->xres ||
+		    mode->vdisplay != cmdline_mode->yres)
+			continue;
+
+		if (cmdline_mode->refresh_specified) {
+			if (mode->vrefresh != cmdline_mode->refresh)
+				continue;
+		}
+
+		if (cmdline_mode->interlace) {
+			if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+				continue;
+		} else if (prefer_non_interlace) {
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				continue;
+		}
+
+		return mode;
+	}
+
+	if (prefer_non_interlace) {
+		prefer_non_interlace = false;
+		goto again;
+	}
+
+create_mode:
+	mode = drm_mode_create_from_cmdline_mode(connector->dev,
+						 cmdline_mode);
+	list_add(&mode->head, &connector->modes);
+
+	return mode;
+}
+EXPORT_SYMBOL(drm_connector_pick_cmdline_mode);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 785a2f5d2647..b992f59dad30 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1774,78 +1774,11 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
 	return count;
 }
 
-struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
-{
-	struct drm_display_mode *mode;
-
-	list_for_each_entry(mode, &fb_connector->connector->modes, head) {
-		if (mode->hdisplay > width ||
-		    mode->vdisplay > height)
-			continue;
-		if (mode->type & DRM_MODE_TYPE_PREFERRED)
-			return mode;
-	}
-	return NULL;
-}
-EXPORT_SYMBOL(drm_has_preferred_mode);
-
 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 {
 	return fb_connector->connector->cmdline_mode.specified;
 }
 
-struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn)
-{
-	struct drm_cmdline_mode *cmdline_mode;
-	struct drm_display_mode *mode;
-	bool prefer_non_interlace;
-
-	cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
-	if (cmdline_mode->specified == false)
-		return NULL;
-
-	/* attempt to find a matching mode in the list of modes
-	 *  we have gotten so far, if not add a CVT mode that conforms
-	 */
-	if (cmdline_mode->rb || cmdline_mode->margins)
-		goto create_mode;
-
-	prefer_non_interlace = !cmdline_mode->interlace;
-again:
-	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
-		/* check width/height */
-		if (mode->hdisplay != cmdline_mode->xres ||
-		    mode->vdisplay != cmdline_mode->yres)
-			continue;
-
-		if (cmdline_mode->refresh_specified) {
-			if (mode->vrefresh != cmdline_mode->refresh)
-				continue;
-		}
-
-		if (cmdline_mode->interlace) {
-			if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
-				continue;
-		} else if (prefer_non_interlace) {
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				continue;
-		}
-		return mode;
-	}
-
-	if (prefer_non_interlace) {
-		prefer_non_interlace = false;
-		goto again;
-	}
-
-create_mode:
-	mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
-						 cmdline_mode);
-	list_add(&mode->head, &fb_helper_conn->connector->modes);
-	return mode;
-}
-EXPORT_SYMBOL(drm_pick_cmdline_mode);
-
 static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
 {
 	bool enable;
@@ -1916,7 +1849,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
 		if (!enabled[i])
 			continue;
 		fb_helper_conn = fb_helper->connector_info[i];
-		modes[i] = drm_pick_cmdline_mode(fb_helper_conn);
+		modes[i] = drm_connector_pick_cmdline_mode(fb_helper_conn->connector);
 		if (!modes[i]) {
 			can_clone = false;
 			break;
@@ -2040,11 +1973,11 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
 			      fb_helper_conn->connector->base.id);
 
 		/* got for command line mode first */
-		modes[i] = drm_pick_cmdline_mode(fb_helper_conn);
+		modes[i] = drm_connector_pick_cmdline_mode(fb_helper_conn->connector);
 		if (!modes[i]) {
 			DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
 				      fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0);
-			modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
+			modes[i] = drm_connector_has_preferred_mode(fb_helper_conn->connector, width, height);
 		}
 		/* No preferred modes, pick one off the list */
 		if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
@@ -2097,7 +2030,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 		my_score++;
 	if (drm_has_cmdline_mode(fb_helper_conn))
 		my_score++;
-	if (drm_has_preferred_mode(fb_helper_conn, width, height))
+	if (drm_connector_has_preferred_mode(connector, width, height))
 		my_score++;
 
 	connector_funcs = connector->helper_private;
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 89592ecc44ca..a4ab8575a72e 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -421,14 +421,15 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 			      connector->name);
 
 		/* go for command line mode first */
-		modes[i] = drm_pick_cmdline_mode(fb_conn);
+		modes[i] = drm_connector_pick_cmdline_mode(connector);
 
 		/* try for preferred next */
 		if (!modes[i]) {
 			DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
 				      connector->name, connector->has_tile);
-			modes[i] = drm_has_preferred_mode(fb_conn, width,
-							  height);
+			modes[i] = drm_connector_has_preferred_mode(connector,
+								    width,
+								    height);
 		}
 
 		/* No preferred mode marked by the EDID? Are there any modes? */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 675cc3f8cf85..9cb4ca42373c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1163,4 +1163,10 @@ void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
 #define drm_for_each_connector_iter(connector, iter) \
 	while ((connector = drm_connector_list_iter_next(iter)))
 
+struct drm_display_mode *
+drm_connector_has_preferred_mode(struct drm_connector *connector,
+				 int width, int height);
+struct drm_display_mode *
+drm_connector_pick_cmdline_mode(struct drm_connector *connector);
+
 #endif
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index e2df40ad5063..f379ef6d6085 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -311,11 +311,6 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
 int drm_fb_helper_debug_enter(struct fb_info *info);
 int drm_fb_helper_debug_leave(struct fb_info *info);
-struct drm_display_mode *
-drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
-			int width, int height);
-struct drm_display_mode *
-drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
 
 int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
@@ -510,20 +505,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info)
 	return 0;
 }
 
-static inline struct drm_display_mode *
-drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
-		       int width, int height)
-{
-	return NULL;
-}
-
-static inline struct drm_display_mode *
-drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
-		      int width, int height)
-{
-	return NULL;
-}
-
 static inline int
 drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
 				struct drm_connector *connector)
-- 
2.15.1

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

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

* [RFC v4 11/25] drm/connector: Add connector array functions
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (9 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode() Noralf Trønnes
@ 2018-04-12 13:17 ` Noralf Trønnes
  2018-04-12 16:34 ` [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
  11 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 13:17 UTC (permalink / raw)
  To: dri-devel
  Cc: daniel.vetter, intel-gfx, Noralf Trønnes, laurent.pinchart,
	mstaudt, dh.herrmann

Add functions to deal with the registred connectors as an array:
- drm_connector_get_all()
- drm_connector_put_all()

And to get the enabled status of those connectors:
drm_connector_get_enabled_status()

This is prep work to remove struct drm_fb_helper_connector.

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

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b9eb143d70fc..25c333c05a4e 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1854,3 +1854,108 @@ drm_connector_pick_cmdline_mode(struct drm_connector *connector)
 	return mode;
 }
 EXPORT_SYMBOL(drm_connector_pick_cmdline_mode);
+
+/**
+ * drm_connector_get_all - Get all connectors into an array
+ * @dev: DRM device
+ * @connectors: Returned connector array
+ *
+ * This function iterates through all registered connectors and adds them to an
+ * array allocated by this function. A ref is taken on the connectors.
+ *
+ * Use drm_connector_put_all() to drop refs and free the array.
+ *
+ * Returns:
+ * Number of connectors or -ENOMEM on failure.
+ */
+int drm_connector_get_all(struct drm_device *dev, struct drm_connector ***connectors)
+{
+	struct drm_connector *connector, **temp, **conns = NULL;
+	struct drm_connector_list_iter conn_iter;
+	int connector_count = 0;
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		temp = krealloc(conns, (connector_count + 1) * sizeof(*conns), GFP_KERNEL);
+		if (!temp)
+			goto err_put_free;
+
+		conns = temp;
+		conns[connector_count++] = connector;
+		drm_connector_get(connector);
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	*connectors = conns;
+
+	return connector_count;
+
+err_put_free:
+	drm_connector_list_iter_end(&conn_iter);
+	drm_connector_put_all(conns, connector_count);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(drm_connector_get_all);
+
+/**
+ * drm_connector_put_all - Put and free connector array
+ * @connectors: Array of connectors
+ * @connector_count: Number of connectors in the array (can be negative or zero)
+ *
+ * This function drops the ref on the connectors an frees the array.
+ */
+void drm_connector_put_all(struct drm_connector **connectors, int connector_count)
+{
+	int i;
+
+	if (connector_count < 1)
+		return;
+
+	for (i = 0; i < connector_count; i++)
+		drm_connector_put(connectors[i]);
+	kfree(connectors);
+}
+EXPORT_SYMBOL(drm_connector_put_all);
+
+/**
+ * drm_connector_get_enabled_status - Get enabled status on connectors
+ * @connectors: Array of connectors
+ * @connector_count: Number of connectors in the array
+ *
+ * This loops over the connector array and sets enabled if connector status is
+ * _connected_. If no connectors are connected, a new pass is done and
+ * connectors that are not _disconnected_ are set enabled.
+ *
+ * The caller is responsible for freeing the array using kfree().
+ *
+ * Returns:
+ * A boolean array of connector enabled statuses or NULL on allocation failure.
+ */
+bool *drm_connector_get_enabled_status(struct drm_connector **connectors,
+				       unsigned int connector_count)
+{
+	bool *enabled, any_enabled = false;
+	unsigned int i;
+
+	enabled = kcalloc(connector_count, sizeof(*enabled), GFP_KERNEL);
+	if (!enabled)
+		return NULL;
+
+	for (i = 0; i < connector_count; i++) {
+		if (connectors[i]->status == connector_status_connected) {
+			enabled[i] = true;
+			any_enabled = true;
+		}
+	}
+
+	if (any_enabled)
+		return enabled;
+
+	for (i = 0; i < connector_count; i++)
+		if (connectors[i]->status != connector_status_disconnected)
+			enabled[i] = true;
+
+	return enabled;
+}
+EXPORT_SYMBOL(drm_connector_get_enabled_status);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 9cb4ca42373c..c3556a5f40c9 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1169,4 +1169,9 @@ drm_connector_has_preferred_mode(struct drm_connector *connector,
 struct drm_display_mode *
 drm_connector_pick_cmdline_mode(struct drm_connector *connector);
 
+int drm_connector_get_all(struct drm_device *dev, struct drm_connector ***connectors);
+void drm_connector_put_all(struct drm_connector **connectors, int connector_count);
+bool *drm_connector_get_enabled_status(struct drm_connector **connectors,
+				       unsigned int connector_count);
+
 #endif
-- 
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [RFC v4 00/25] drm: Add generic fbdev emulation
  2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
                   ` (10 preceding siblings ...)
  2018-04-12 13:17 ` [RFC v4 11/25] drm/connector: Add connector array functions Noralf Trønnes
@ 2018-04-12 16:34 ` Noralf Trønnes
  2018-04-16  7:47   ` Daniel Vetter
  11 siblings, 1 reply; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-12 16:34 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

I hit a 'Sending rate exceeded' error with this patchset, so it didn't 
go out as it should.
I will resend the patchset when I find out how to avoid this problem.

Noralf.


Den 12.04.2018 15.17, skrev Noralf Trønnes:
> This patchset explores the possibility of having generic fbdev emulation
> in DRM for drivers that supports dumb buffers which they can export. An
> API is added to support in-kernel clients in general.
>
> In this version I was able to reuse the modesetting code from
> drm_fb_helper in the client API. This avoids code duplication, carries
> over lessons learned and the modesetting code is bisectable. The
> downside is that it takes +10 patches to rip drm_fb_helper in two, so
> maybe it's not worth it wrt possible breakage and a challenging review.
>
> Does the Intel CI test the fbdev emulation?
>
> Daniel had this concern with the previous version:
>
>      The register/unregister model needs more thought. Allowing both clients
>      to register whenever they want to, and drm_device instances to come and
>      go is what fbcon has done, and the resulting locking is a horror show.
>
>      I think if we require that all in-kernel drm_clients are registers when
>      loading drm.ko (and enabled/disabled only per module options and
>      Kconfig), then we can throw out all the locking. That avoids a lot of
>      the headaches.
>
> I have solved this by adding a notifier that fires when a new DRM device
> is registered (I've removed the new() callback). Currently only
> bootsplash uses this. The fbdev client needs to be setup from the driver
> since it can't know on device registration if the driver will setup it's
> own fbdev emulation later and the vtcon client hooks up to a user
> provided device id.
>
> Since fbcon can't handle fb_open failing, the buffer has to be
> pre-allocated. Exporting a GEM buffer pins the driver module making it
> impossible to unload it.
> I have included 2 solutions to the problem:
> - sysfs file to remove/close clients: remove_internal_clients
> - Change drm_gem_prime_export() so it doesn't pin on client buffers
>
> If a dumb buffer is exported from a kernel thread (worker) context, the
> file descriptor isn't closed and I leak a reference so the buffer isn't
> freed. Please look at drm_client_buffer_create() in patch
> 'drm/client: Finish the in-kernel client API'.
> This is a blocker that needs a solution.
>
>
> Noralf.
>
> Changes since version 3:
> Client API changes:
> - Drop drm_client_register_funcs() which attached clients indirectly.
>    Let clients attach directly using drm_client_new{_from_id}(). Clients
>    that wants to attach to all devices must be linked into drm.ko and use
>    the DRM device notifier. This is done to avoid the lock/race
>    register/unregister hell we have with fbcon. (Daniel Vetter)
> - drm_client_display_restore() checks if there is a master and if so
>    returns -EBUSY. (Daniel Vetter)
> - Allocate drm_file up front instead of on-demand. Since fbdev can't do
>    on demand buffer allocation because of fbcon, there's no need for this.
> - Add sysfs file to remove clients
> - Don't pin driver module when exporting gem client buffers
> - Dropped page flip support since drm_fb_helper is now used for fbdev
>    emulation.
>
> - The bootsplash client now switches over to fbdev on keypress.
>
> Changes since version 2:
> - Don't set drm master for in-kernel clients. (Daniel Vetter)
> - Add in-kernel client API
>
> Changes since version 1:
> - Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
>    DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
>    The following uses that macro and sets fb_open/close: udlfb_ops,
>    amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
>    nouveau_fbcon_sw_ops, radeonfb_ops.
>    This results in: warning: Initializer entry defined twice
> - Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
>    ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
> - Drop buggy patch: (Chris Wilson)
>    drm/prime: Clear drm_gem_object->dma_buf on release
> - Defer buffer creation until fb_open.
>
>
> David Herrmann (1):
>    drm: provide management functions for drm_file
>
> Noralf Trønnes (24):
>    drm/file: Don't set master on in-kernel clients
>    drm/fb-helper: No need to cache rotation and sw_rotations
>    drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
>    drm/fb-helper: dpms_legacy(): Only set on connectors in use
>    drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>    drm: Begin an API for in-kernel clients
>    drm/fb-helper: Use struct drm_client_display
>    drm/fb-helper: Move modeset commit code to drm_client
>    drm/connector: Add
>      drm_connector_has_preferred_mode/pick_cmdline_mode()
>    drm/connector: Add connector array functions
>    drm/i915: Add drm_driver->initial_client_display callback
>    drm/fb-helper: Remove struct drm_fb_helper_crtc
>    drm/fb-helper: Remove struct drm_fb_helper_connector
>    drm/fb-helper: Move modeset config code to drm_client
>    drm: Make ioctls available for in-kernel clients
>    drm/client: Bail out if there's a DRM master
>    drm/client: Make the display modes available to clients
>    drm/client: Finish the in-kernel client API
>    drm/prime: Don't pin module on export for in-kernel clients
>    drm/fb-helper: Add drm_fb_helper_fb_open/release()
>    drm/fb-helper: Add generic fbdev emulation
>    drm: Add DRM device registered notifier
>    drm/client: Hack: Add bootsplash
>    drm/client: Hack: Add DRM VT console client
>
>   drivers/gpu/drm/Kconfig                 |    2 +
>   drivers/gpu/drm/Makefile                |    4 +-
>   drivers/gpu/drm/client/Kconfig          |   14 +
>   drivers/gpu/drm/client/Makefile         |    3 +
>   drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
>   drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
>   drivers/gpu/drm/client/internal.h       |   19 +
>   drivers/gpu/drm/drm_atomic.c            |  168 ++++
>   drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
>   drivers/gpu/drm/drm_auth.c              |   33 +
>   drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
>   drivers/gpu/drm/drm_connector.c         |  199 +++++
>   drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
>   drivers/gpu/drm/drm_debugfs.c           |    7 +
>   drivers/gpu/drm/drm_drv.c               |   43 +
>   drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
>   drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
>   drivers/gpu/drm/drm_file.c              |  304 ++++---
>   drivers/gpu/drm/drm_framebuffer.c       |   50 +-
>   drivers/gpu/drm/drm_internal.h          |    7 +
>   drivers/gpu/drm/drm_ioc32.c             |    2 +-
>   drivers/gpu/drm/drm_ioctl.c             |    4 +-
>   drivers/gpu/drm/drm_prime.c             |   37 +-
>   drivers/gpu/drm/drm_probe_helper.c      |    3 +
>   drivers/gpu/drm/drm_sysfs.c             |   20 +
>   drivers/gpu/drm/i915/i915_drv.c         |    1 +
>   drivers/gpu/drm/i915/intel_drv.h        |   11 +
>   drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
>   include/drm/drm_atomic.h                |    5 +
>   include/drm/drm_atomic_helper.h         |    4 -
>   include/drm/drm_client.h                |  182 ++++
>   include/drm/drm_connector.h             |   11 +
>   include/drm/drm_device.h                |    4 +
>   include/drm/drm_drv.h                   |   25 +
>   include/drm/drm_fb_helper.h             |  126 ++-
>   35 files changed, 4007 insertions(+), 1513 deletions(-)
>   create mode 100644 drivers/gpu/drm/client/Kconfig
>   create mode 100644 drivers/gpu/drm/client/Makefile
>   create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
>   create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
>   create mode 100644 drivers/gpu/drm/client/internal.h
>   create mode 100644 drivers/gpu/drm/drm_client.c
>   create mode 100644 include/drm/drm_client.h
>
> --
> 2.15.1
>

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

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

* Re: [RFC v4 00/25] drm: Add generic fbdev emulation
  2018-04-12 16:34 ` [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
@ 2018-04-16  7:47   ` Daniel Vetter
  0 siblings, 0 replies; 19+ messages in thread
From: Daniel Vetter @ 2018-04-16  7:47 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: daniel.vetter, intel-gfx, dri-devel, laurent.pinchart, mstaudt

On Thu, Apr 12, 2018 at 06:34:46PM +0200, Noralf Trønnes wrote:
> I hit a 'Sending rate exceeded' error with this patchset, so it didn't go
> out as it should.
> I will resend the patchset when I find out how to avoid this problem.

That's generally an issue with your ISP. gmail works ime for mail bombs,
even big ones.
-Daniel

> 
> Noralf.
> 
> 
> Den 12.04.2018 15.17, skrev Noralf Trønnes:
> > This patchset explores the possibility of having generic fbdev emulation
> > in DRM for drivers that supports dumb buffers which they can export. An
> > API is added to support in-kernel clients in general.
> > 
> > In this version I was able to reuse the modesetting code from
> > drm_fb_helper in the client API. This avoids code duplication, carries
> > over lessons learned and the modesetting code is bisectable. The
> > downside is that it takes +10 patches to rip drm_fb_helper in two, so
> > maybe it's not worth it wrt possible breakage and a challenging review.
> > 
> > Does the Intel CI test the fbdev emulation?
> > 
> > Daniel had this concern with the previous version:
> > 
> >      The register/unregister model needs more thought. Allowing both clients
> >      to register whenever they want to, and drm_device instances to come and
> >      go is what fbcon has done, and the resulting locking is a horror show.
> > 
> >      I think if we require that all in-kernel drm_clients are registers when
> >      loading drm.ko (and enabled/disabled only per module options and
> >      Kconfig), then we can throw out all the locking. That avoids a lot of
> >      the headaches.
> > 
> > I have solved this by adding a notifier that fires when a new DRM device
> > is registered (I've removed the new() callback). Currently only
> > bootsplash uses this. The fbdev client needs to be setup from the driver
> > since it can't know on device registration if the driver will setup it's
> > own fbdev emulation later and the vtcon client hooks up to a user
> > provided device id.
> > 
> > Since fbcon can't handle fb_open failing, the buffer has to be
> > pre-allocated. Exporting a GEM buffer pins the driver module making it
> > impossible to unload it.
> > I have included 2 solutions to the problem:
> > - sysfs file to remove/close clients: remove_internal_clients
> > - Change drm_gem_prime_export() so it doesn't pin on client buffers
> > 
> > If a dumb buffer is exported from a kernel thread (worker) context, the
> > file descriptor isn't closed and I leak a reference so the buffer isn't
> > freed. Please look at drm_client_buffer_create() in patch
> > 'drm/client: Finish the in-kernel client API'.
> > This is a blocker that needs a solution.
> > 
> > 
> > Noralf.
> > 
> > Changes since version 3:
> > Client API changes:
> > - Drop drm_client_register_funcs() which attached clients indirectly.
> >    Let clients attach directly using drm_client_new{_from_id}(). Clients
> >    that wants to attach to all devices must be linked into drm.ko and use
> >    the DRM device notifier. This is done to avoid the lock/race
> >    register/unregister hell we have with fbcon. (Daniel Vetter)
> > - drm_client_display_restore() checks if there is a master and if so
> >    returns -EBUSY. (Daniel Vetter)
> > - Allocate drm_file up front instead of on-demand. Since fbdev can't do
> >    on demand buffer allocation because of fbcon, there's no need for this.
> > - Add sysfs file to remove clients
> > - Don't pin driver module when exporting gem client buffers
> > - Dropped page flip support since drm_fb_helper is now used for fbdev
> >    emulation.
> > 
> > - The bootsplash client now switches over to fbdev on keypress.
> > 
> > Changes since version 2:
> > - Don't set drm master for in-kernel clients. (Daniel Vetter)
> > - Add in-kernel client API
> > 
> > Changes since version 1:
> > - Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
> >    DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
> >    The following uses that macro and sets fb_open/close: udlfb_ops,
> >    amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
> >    nouveau_fbcon_sw_ops, radeonfb_ops.
> >    This results in: warning: Initializer entry defined twice
> > - Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
> >    ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
> > - Drop buggy patch: (Chris Wilson)
> >    drm/prime: Clear drm_gem_object->dma_buf on release
> > - Defer buffer creation until fb_open.
> > 
> > 
> > David Herrmann (1):
> >    drm: provide management functions for drm_file
> > 
> > Noralf Trønnes (24):
> >    drm/file: Don't set master on in-kernel clients
> >    drm/fb-helper: No need to cache rotation and sw_rotations
> >    drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
> >    drm/fb-helper: dpms_legacy(): Only set on connectors in use
> >    drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
> >    drm: Begin an API for in-kernel clients
> >    drm/fb-helper: Use struct drm_client_display
> >    drm/fb-helper: Move modeset commit code to drm_client
> >    drm/connector: Add
> >      drm_connector_has_preferred_mode/pick_cmdline_mode()
> >    drm/connector: Add connector array functions
> >    drm/i915: Add drm_driver->initial_client_display callback
> >    drm/fb-helper: Remove struct drm_fb_helper_crtc
> >    drm/fb-helper: Remove struct drm_fb_helper_connector
> >    drm/fb-helper: Move modeset config code to drm_client
> >    drm: Make ioctls available for in-kernel clients
> >    drm/client: Bail out if there's a DRM master
> >    drm/client: Make the display modes available to clients
> >    drm/client: Finish the in-kernel client API
> >    drm/prime: Don't pin module on export for in-kernel clients
> >    drm/fb-helper: Add drm_fb_helper_fb_open/release()
> >    drm/fb-helper: Add generic fbdev emulation
> >    drm: Add DRM device registered notifier
> >    drm/client: Hack: Add bootsplash
> >    drm/client: Hack: Add DRM VT console client
> > 
> >   drivers/gpu/drm/Kconfig                 |    2 +
> >   drivers/gpu/drm/Makefile                |    4 +-
> >   drivers/gpu/drm/client/Kconfig          |   14 +
> >   drivers/gpu/drm/client/Makefile         |    3 +
> >   drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
> >   drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
> >   drivers/gpu/drm/client/internal.h       |   19 +
> >   drivers/gpu/drm/drm_atomic.c            |  168 ++++
> >   drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
> >   drivers/gpu/drm/drm_auth.c              |   33 +
> >   drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
> >   drivers/gpu/drm/drm_connector.c         |  199 +++++
> >   drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
> >   drivers/gpu/drm/drm_debugfs.c           |    7 +
> >   drivers/gpu/drm/drm_drv.c               |   43 +
> >   drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
> >   drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
> >   drivers/gpu/drm/drm_file.c              |  304 ++++---
> >   drivers/gpu/drm/drm_framebuffer.c       |   50 +-
> >   drivers/gpu/drm/drm_internal.h          |    7 +
> >   drivers/gpu/drm/drm_ioc32.c             |    2 +-
> >   drivers/gpu/drm/drm_ioctl.c             |    4 +-
> >   drivers/gpu/drm/drm_prime.c             |   37 +-
> >   drivers/gpu/drm/drm_probe_helper.c      |    3 +
> >   drivers/gpu/drm/drm_sysfs.c             |   20 +
> >   drivers/gpu/drm/i915/i915_drv.c         |    1 +
> >   drivers/gpu/drm/i915/intel_drv.h        |   11 +
> >   drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
> >   include/drm/drm_atomic.h                |    5 +
> >   include/drm/drm_atomic_helper.h         |    4 -
> >   include/drm/drm_client.h                |  182 ++++
> >   include/drm/drm_connector.h             |   11 +
> >   include/drm/drm_device.h                |    4 +
> >   include/drm/drm_drv.h                   |   25 +
> >   include/drm/drm_fb_helper.h             |  126 ++-
> >   35 files changed, 4007 insertions(+), 1513 deletions(-)
> >   create mode 100644 drivers/gpu/drm/client/Kconfig
> >   create mode 100644 drivers/gpu/drm/client/Makefile
> >   create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
> >   create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
> >   create mode 100644 drivers/gpu/drm/client/internal.h
> >   create mode 100644 drivers/gpu/drm/drm_client.c
> >   create mode 100644 include/drm/drm_client.h
> > 
> > --
> > 2.15.1
> > 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [RFC v4 00/25] drm: Add generic fbdev emulation
  2018-04-16  8:21 ` Daniel Vetter
@ 2018-04-16 18:49   ` Noralf Trønnes
  0 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-16 18:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel


Den 16.04.2018 10.21, skrev Daniel Vetter:
> On Sat, Apr 14, 2018 at 01:52:53PM +0200, Noralf Trønnes wrote:
>> This patchset explores the possibility of having generic fbdev emulation
>> in DRM for drivers that supports dumb buffers which they can export. An
>> API is added to support in-kernel clients in general.
>>
>> In this version I was able to reuse the modesetting code from
>> drm_fb_helper in the client API. This avoids code duplication, carries
>> over lessons learned and the modesetting code is bisectable. The
>> downside is that it takes +10 patches to rip drm_fb_helper in two, so
>> maybe it's not worth it wrt possible breakage and a challenging review.
> So my idea wasn't to rip the fbdev helper in  half first (that's indeed a
> lot of work). But start out right away with using every piece of the
> drm_client infrastructure you're adding in the existing fbdev code.
>
> That way there's not a huge patch series which just adds code, with no
> users, but every step of the way and every addition is tested almost right
> away. That makes more gradual merging also easier. The things I have in
> mind here is the generic fb_probe, or the drm_client block/unblock masters
> and all that stuff.
>
> Then, once we've demonstrated all these auxiliary pieces necessary for
> drm_client.c work, we can cut the fb-helper in half and move the modeset
> code into the drm_client library.

I agree. I wished for a way to cut this patchset in half, but I just
couldn't see how. I was tired of working on this, so I just put it out
hoping that you would provide some clarity. Which you did, thanks :-)

So, I think I'll strip this down to just the buffer part of the client API
and use that in the generic fbdev emulation, and start converting some
drivers.

I'll pick up the rest of the client API when I'm done with moving tinydrm
over to vmalloc buffers and have added support for device unplug.

Noralf.

>
> I still prefer an even more gradual path like this compared to what you
> have in your patch series, but I understand that's yet another huge
> shuffle. And the current series seems like a good enough approach to get
> to essentially the same place.
>
>> Does the Intel CI test the fbdev emulation?
> We have fbdev emulation enabled, and iirc there's even a few tests for
> fbdev. Just booting it on 20+ machines is a lot of testing itsefl already.
>
>> Daniel had this concern with the previous version:
>>
>>      The register/unregister model needs more thought. Allowing both clients
>>      to register whenever they want to, and drm_device instances to come and
>>      go is what fbcon has done, and the resulting locking is a horror show.
>>
>>      I think if we require that all in-kernel drm_clients are registers when
>>      loading drm.ko (and enabled/disabled only per module options and
>>      Kconfig), then we can throw out all the locking. That avoids a lot of
>>      the headaches.
>>
>> I have solved this by adding a notifier that fires when a new DRM device
>> is registered (I've removed the new() callback). Currently only
>> bootsplash uses this. The fbdev client needs to be setup from the driver
>> since it can't know on device registration if the driver will setup it's
>> own fbdev emulation later and the vtcon client hooks up to a user
>> provided device id.
> Ugh, notifier is exactly what fbcon also uses. It just hides the locking
> horror show slightly, but it's equally bad. I'm working on a multi-year
> plan to rip out the fbcon notifier, please don't start another one. See
>
> commit 6104c37094e729f3d4ce65797002112735d49cd1
> Author: Daniel Vetter <daniel.vetter@ffwll.ch>
> Date:   Tue Aug 1 17:32:07 2017 +0200
>
>      fbcon: Make fbcon a built-time depency for fbdev
>
> for full details.
>
>> Since fbcon can't handle fb_open failing, the buffer has to be
>> pre-allocated. Exporting a GEM buffer pins the driver module making it
>> impossible to unload it.
>> I have included 2 solutions to the problem:
>> - sysfs file to remove/close clients: remove_internal_clients
> This is the same thing that defacto happens already with fbcon: You have
> to remove fbcon first (which holds a full ref on the fbdev, which prevents
> the drm driver from unloading). I think explicitly asking for that
> reference to disappear is ok.
>
> It does mean everyone has to update their unload scripts, but oh well.
>
>> - Change drm_gem_prime_export() so it doesn't pin on client buffers
> The double-loop in that patch definitely doesn't cut it, but worst case I
> think something like that could be made to work.
>
>> If a dumb buffer is exported from a kernel thread (worker) context, the
>> file descriptor isn't closed and I leak a reference so the buffer isn't
>> freed. Please look at drm_client_buffer_create() in patch
>> 'drm/client: Finish the in-kernel client API'.
>> This is a blocker that needs a solution.
> Hm, missed that in my first cursory read of the series, I'l take another
> look.
> -Daniel
>
>>
>> Noralf.
>>
>> Changes since version 3:
>> Client API changes:
>> - Drop drm_client_register_funcs() which attached clients indirectly.
>>    Let clients attach directly using drm_client_new{_from_id}(). Clients
>>    that wants to attach to all devices must be linked into drm.ko and use
>>    the DRM device notifier. This is done to avoid the lock/race
>>    register/unregister hell we have with fbcon. (Daniel Vetter)
>> - drm_client_display_restore() checks if there is a master and if so
>>    returns -EBUSY. (Daniel Vetter)
>> - Allocate drm_file up front instead of on-demand. Since fbdev can't do
>>    on demand buffer allocation because of fbcon, there's no need for this.
>> - Add sysfs file to remove clients
>> - Don't pin driver module when exporting gem client buffers
>> - Dropped page flip support since drm_fb_helper is now used for fbdev
>>    emulation.
>>
>> - The bootsplash client now switches over to fbdev on keypress.
>>
>> Changes since version 2:
>> - Don't set drm master for in-kernel clients. (Daniel Vetter)
>> - Add in-kernel client API
>>
>> Changes since version 1:
>> - Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
>>    DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
>>    The following uses that macro and sets fb_open/close: udlfb_ops,
>>    amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
>>    nouveau_fbcon_sw_ops, radeonfb_ops.
>>    This results in: warning: Initializer entry defined twice
>> - Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
>>    ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
>> - Drop buggy patch: (Chris Wilson)
>>    drm/prime: Clear drm_gem_object->dma_buf on release
>> - Defer buffer creation until fb_open.
>>
>>
>> David Herrmann (1):
>>    drm: provide management functions for drm_file
>>
>> Noralf Trønnes (24):
>>    drm/file: Don't set master on in-kernel clients
>>    drm/fb-helper: No need to cache rotation and sw_rotations
>>    drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
>>    drm/fb-helper: dpms_legacy(): Only set on connectors in use
>>    drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>>    drm: Begin an API for in-kernel clients
>>    drm/fb-helper: Use struct drm_client_display
>>    drm/fb-helper: Move modeset commit code to drm_client
>>    drm/connector: Add
>>      drm_connector_has_preferred_mode/pick_cmdline_mode()
>>    drm/connector: Add connector array functions
>>    drm/i915: Add drm_driver->initial_client_display callback
>>    drm/fb-helper: Remove struct drm_fb_helper_crtc
>>    drm/fb-helper: Remove struct drm_fb_helper_connector
>>    drm/fb-helper: Move modeset config code to drm_client
>>    drm: Make ioctls available for in-kernel clients
>>    drm/client: Bail out if there's a DRM master
>>    drm/client: Make the display modes available to clients
>>    drm/client: Finish the in-kernel client API
>>    drm/prime: Don't pin module on export for in-kernel clients
>>    drm/fb-helper: Add drm_fb_helper_fb_open/release()
>>    drm/fb-helper: Add generic fbdev emulation
>>    drm: Add DRM device registered notifier
>>    drm/client: Hack: Add bootsplash
>>    drm/client: Hack: Add DRM VT console client
>>
>>   drivers/gpu/drm/Kconfig                 |    2 +
>>   drivers/gpu/drm/Makefile                |    4 +-
>>   drivers/gpu/drm/client/Kconfig          |   14 +
>>   drivers/gpu/drm/client/Makefile         |    3 +
>>   drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
>>   drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
>>   drivers/gpu/drm/client/internal.h       |   19 +
>>   drivers/gpu/drm/drm_atomic.c            |  168 ++++
>>   drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
>>   drivers/gpu/drm/drm_auth.c              |   33 +
>>   drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/drm_connector.c         |  199 +++++
>>   drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
>>   drivers/gpu/drm/drm_debugfs.c           |    7 +
>>   drivers/gpu/drm/drm_drv.c               |   43 +
>>   drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
>>   drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
>>   drivers/gpu/drm/drm_file.c              |  304 ++++---
>>   drivers/gpu/drm/drm_framebuffer.c       |   50 +-
>>   drivers/gpu/drm/drm_internal.h          |    7 +
>>   drivers/gpu/drm/drm_ioc32.c             |    2 +-
>>   drivers/gpu/drm/drm_ioctl.c             |    4 +-
>>   drivers/gpu/drm/drm_prime.c             |   37 +-
>>   drivers/gpu/drm/drm_probe_helper.c      |    3 +
>>   drivers/gpu/drm/drm_sysfs.c             |   20 +
>>   drivers/gpu/drm/i915/i915_drv.c         |    1 +
>>   drivers/gpu/drm/i915/intel_drv.h        |   11 +
>>   drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
>>   include/drm/drm_atomic.h                |    5 +
>>   include/drm/drm_atomic_helper.h         |    4 -
>>   include/drm/drm_client.h                |  182 ++++
>>   include/drm/drm_connector.h             |   11 +
>>   include/drm/drm_device.h                |    4 +
>>   include/drm/drm_drv.h                   |   25 +
>>   include/drm/drm_fb_helper.h             |  126 ++-
>>   35 files changed, 4007 insertions(+), 1513 deletions(-)
>>   create mode 100644 drivers/gpu/drm/client/Kconfig
>>   create mode 100644 drivers/gpu/drm/client/Makefile
>>   create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
>>   create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
>>   create mode 100644 drivers/gpu/drm/client/internal.h
>>   create mode 100644 drivers/gpu/drm/drm_client.c
>>   create mode 100644 include/drm/drm_client.h
>>
>> --
>> 2.15.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [RFC v4 00/25] drm: Add generic fbdev emulation
  2018-04-14 11:52 Noralf Trønnes
@ 2018-04-16  8:21 ` Daniel Vetter
  2018-04-16 18:49   ` Noralf Trønnes
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Vetter @ 2018-04-16  8:21 UTC (permalink / raw)
  To: Noralf Trønnes; +Cc: intel-gfx, dri-devel

On Sat, Apr 14, 2018 at 01:52:53PM +0200, Noralf Trønnes wrote:
> This patchset explores the possibility of having generic fbdev emulation
> in DRM for drivers that supports dumb buffers which they can export. An
> API is added to support in-kernel clients in general.
> 
> In this version I was able to reuse the modesetting code from
> drm_fb_helper in the client API. This avoids code duplication, carries
> over lessons learned and the modesetting code is bisectable. The
> downside is that it takes +10 patches to rip drm_fb_helper in two, so
> maybe it's not worth it wrt possible breakage and a challenging review.

So my idea wasn't to rip the fbdev helper in  half first (that's indeed a
lot of work). But start out right away with using every piece of the
drm_client infrastructure you're adding in the existing fbdev code.

That way there's not a huge patch series which just adds code, with no
users, but every step of the way and every addition is tested almost right
away. That makes more gradual merging also easier. The things I have in
mind here is the generic fb_probe, or the drm_client block/unblock masters
and all that stuff.

Then, once we've demonstrated all these auxiliary pieces necessary for
drm_client.c work, we can cut the fb-helper in half and move the modeset
code into the drm_client library.

I still prefer an even more gradual path like this compared to what you
have in your patch series, but I understand that's yet another huge
shuffle. And the current series seems like a good enough approach to get
to essentially the same place.

> Does the Intel CI test the fbdev emulation?

We have fbdev emulation enabled, and iirc there's even a few tests for
fbdev. Just booting it on 20+ machines is a lot of testing itsefl already.

> 
> Daniel had this concern with the previous version:
> 
>     The register/unregister model needs more thought. Allowing both clients
>     to register whenever they want to, and drm_device instances to come and
>     go is what fbcon has done, and the resulting locking is a horror show.
> 
>     I think if we require that all in-kernel drm_clients are registers when
>     loading drm.ko (and enabled/disabled only per module options and
>     Kconfig), then we can throw out all the locking. That avoids a lot of
>     the headaches.
> 
> I have solved this by adding a notifier that fires when a new DRM device
> is registered (I've removed the new() callback). Currently only
> bootsplash uses this. The fbdev client needs to be setup from the driver
> since it can't know on device registration if the driver will setup it's
> own fbdev emulation later and the vtcon client hooks up to a user
> provided device id.

Ugh, notifier is exactly what fbcon also uses. It just hides the locking
horror show slightly, but it's equally bad. I'm working on a multi-year
plan to rip out the fbcon notifier, please don't start another one. See

commit 6104c37094e729f3d4ce65797002112735d49cd1
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Tue Aug 1 17:32:07 2017 +0200

    fbcon: Make fbcon a built-time depency for fbdev

for full details.

> Since fbcon can't handle fb_open failing, the buffer has to be
> pre-allocated. Exporting a GEM buffer pins the driver module making it
> impossible to unload it.
> I have included 2 solutions to the problem:
> - sysfs file to remove/close clients: remove_internal_clients

This is the same thing that defacto happens already with fbcon: You have
to remove fbcon first (which holds a full ref on the fbdev, which prevents
the drm driver from unloading). I think explicitly asking for that
reference to disappear is ok.

It does mean everyone has to update their unload scripts, but oh well.

> - Change drm_gem_prime_export() so it doesn't pin on client buffers

The double-loop in that patch definitely doesn't cut it, but worst case I
think something like that could be made to work.

> If a dumb buffer is exported from a kernel thread (worker) context, the
> file descriptor isn't closed and I leak a reference so the buffer isn't
> freed. Please look at drm_client_buffer_create() in patch
> 'drm/client: Finish the in-kernel client API'.
> This is a blocker that needs a solution.

Hm, missed that in my first cursory read of the series, I'l take another
look.
-Daniel

> 
> 
> Noralf.
> 
> Changes since version 3:
> Client API changes:
> - Drop drm_client_register_funcs() which attached clients indirectly.
>   Let clients attach directly using drm_client_new{_from_id}(). Clients
>   that wants to attach to all devices must be linked into drm.ko and use
>   the DRM device notifier. This is done to avoid the lock/race
>   register/unregister hell we have with fbcon. (Daniel Vetter)
> - drm_client_display_restore() checks if there is a master and if so
>   returns -EBUSY. (Daniel Vetter)
> - Allocate drm_file up front instead of on-demand. Since fbdev can't do
>   on demand buffer allocation because of fbcon, there's no need for this.
> - Add sysfs file to remove clients
> - Don't pin driver module when exporting gem client buffers
> - Dropped page flip support since drm_fb_helper is now used for fbdev
>   emulation.
> 
> - The bootsplash client now switches over to fbdev on keypress.
> 
> Changes since version 2:
> - Don't set drm master for in-kernel clients. (Daniel Vetter)
> - Add in-kernel client API
> 
> Changes since version 1:
> - Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
>   DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
>   The following uses that macro and sets fb_open/close: udlfb_ops,
>   amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
>   nouveau_fbcon_sw_ops, radeonfb_ops.
>   This results in: warning: Initializer entry defined twice
> - Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
>   ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
> - Drop buggy patch: (Chris Wilson)
>   drm/prime: Clear drm_gem_object->dma_buf on release
> - Defer buffer creation until fb_open.
> 
> 
> David Herrmann (1):
>   drm: provide management functions for drm_file
> 
> Noralf Trønnes (24):
>   drm/file: Don't set master on in-kernel clients
>   drm/fb-helper: No need to cache rotation and sw_rotations
>   drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
>   drm/fb-helper: dpms_legacy(): Only set on connectors in use
>   drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>   drm: Begin an API for in-kernel clients
>   drm/fb-helper: Use struct drm_client_display
>   drm/fb-helper: Move modeset commit code to drm_client
>   drm/connector: Add
>     drm_connector_has_preferred_mode/pick_cmdline_mode()
>   drm/connector: Add connector array functions
>   drm/i915: Add drm_driver->initial_client_display callback
>   drm/fb-helper: Remove struct drm_fb_helper_crtc
>   drm/fb-helper: Remove struct drm_fb_helper_connector
>   drm/fb-helper: Move modeset config code to drm_client
>   drm: Make ioctls available for in-kernel clients
>   drm/client: Bail out if there's a DRM master
>   drm/client: Make the display modes available to clients
>   drm/client: Finish the in-kernel client API
>   drm/prime: Don't pin module on export for in-kernel clients
>   drm/fb-helper: Add drm_fb_helper_fb_open/release()
>   drm/fb-helper: Add generic fbdev emulation
>   drm: Add DRM device registered notifier
>   drm/client: Hack: Add bootsplash
>   drm/client: Hack: Add DRM VT console client
> 
>  drivers/gpu/drm/Kconfig                 |    2 +
>  drivers/gpu/drm/Makefile                |    4 +-
>  drivers/gpu/drm/client/Kconfig          |   14 +
>  drivers/gpu/drm/client/Makefile         |    3 +
>  drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
>  drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
>  drivers/gpu/drm/client/internal.h       |   19 +
>  drivers/gpu/drm/drm_atomic.c            |  168 ++++
>  drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
>  drivers/gpu/drm/drm_auth.c              |   33 +
>  drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_connector.c         |  199 +++++
>  drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
>  drivers/gpu/drm/drm_debugfs.c           |    7 +
>  drivers/gpu/drm/drm_drv.c               |   43 +
>  drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
>  drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
>  drivers/gpu/drm/drm_file.c              |  304 ++++---
>  drivers/gpu/drm/drm_framebuffer.c       |   50 +-
>  drivers/gpu/drm/drm_internal.h          |    7 +
>  drivers/gpu/drm/drm_ioc32.c             |    2 +-
>  drivers/gpu/drm/drm_ioctl.c             |    4 +-
>  drivers/gpu/drm/drm_prime.c             |   37 +-
>  drivers/gpu/drm/drm_probe_helper.c      |    3 +
>  drivers/gpu/drm/drm_sysfs.c             |   20 +
>  drivers/gpu/drm/i915/i915_drv.c         |    1 +
>  drivers/gpu/drm/i915/intel_drv.h        |   11 +
>  drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
>  include/drm/drm_atomic.h                |    5 +
>  include/drm/drm_atomic_helper.h         |    4 -
>  include/drm/drm_client.h                |  182 ++++
>  include/drm/drm_connector.h             |   11 +
>  include/drm/drm_device.h                |    4 +
>  include/drm/drm_drv.h                   |   25 +
>  include/drm/drm_fb_helper.h             |  126 ++-
>  35 files changed, 4007 insertions(+), 1513 deletions(-)
>  create mode 100644 drivers/gpu/drm/client/Kconfig
>  create mode 100644 drivers/gpu/drm/client/Makefile
>  create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
>  create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
>  create mode 100644 drivers/gpu/drm/client/internal.h
>  create mode 100644 drivers/gpu/drm/drm_client.c
>  create mode 100644 include/drm/drm_client.h
> 
> --
> 2.15.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [RFC v4 00/25] drm: Add generic fbdev emulation
@ 2018-04-14 11:52 Noralf Trønnes
  2018-04-16  8:21 ` Daniel Vetter
  0 siblings, 1 reply; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-14 11:52 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, Noralf Trønnes

This patchset explores the possibility of having generic fbdev emulation
in DRM for drivers that supports dumb buffers which they can export. An
API is added to support in-kernel clients in general.

In this version I was able to reuse the modesetting code from
drm_fb_helper in the client API. This avoids code duplication, carries
over lessons learned and the modesetting code is bisectable. The
downside is that it takes +10 patches to rip drm_fb_helper in two, so
maybe it's not worth it wrt possible breakage and a challenging review.

Does the Intel CI test the fbdev emulation?

Daniel had this concern with the previous version:

    The register/unregister model needs more thought. Allowing both clients
    to register whenever they want to, and drm_device instances to come and
    go is what fbcon has done, and the resulting locking is a horror show.

    I think if we require that all in-kernel drm_clients are registers when
    loading drm.ko (and enabled/disabled only per module options and
    Kconfig), then we can throw out all the locking. That avoids a lot of
    the headaches.

I have solved this by adding a notifier that fires when a new DRM device
is registered (I've removed the new() callback). Currently only
bootsplash uses this. The fbdev client needs to be setup from the driver
since it can't know on device registration if the driver will setup it's
own fbdev emulation later and the vtcon client hooks up to a user
provided device id.

Since fbcon can't handle fb_open failing, the buffer has to be
pre-allocated. Exporting a GEM buffer pins the driver module making it
impossible to unload it.
I have included 2 solutions to the problem:
- sysfs file to remove/close clients: remove_internal_clients
- Change drm_gem_prime_export() so it doesn't pin on client buffers

If a dumb buffer is exported from a kernel thread (worker) context, the
file descriptor isn't closed and I leak a reference so the buffer isn't
freed. Please look at drm_client_buffer_create() in patch
'drm/client: Finish the in-kernel client API'.
This is a blocker that needs a solution.


Noralf.

Changes since version 3:
Client API changes:
- Drop drm_client_register_funcs() which attached clients indirectly.
  Let clients attach directly using drm_client_new{_from_id}(). Clients
  that wants to attach to all devices must be linked into drm.ko and use
  the DRM device notifier. This is done to avoid the lock/race
  register/unregister hell we have with fbcon. (Daniel Vetter)
- drm_client_display_restore() checks if there is a master and if so
  returns -EBUSY. (Daniel Vetter)
- Allocate drm_file up front instead of on-demand. Since fbdev can't do
  on demand buffer allocation because of fbcon, there's no need for this.
- Add sysfs file to remove clients
- Don't pin driver module when exporting gem client buffers
- Dropped page flip support since drm_fb_helper is now used for fbdev
  emulation.

- The bootsplash client now switches over to fbdev on keypress.

Changes since version 2:
- Don't set drm master for in-kernel clients. (Daniel Vetter)
- Add in-kernel client API

Changes since version 1:
- Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
  DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
  The following uses that macro and sets fb_open/close: udlfb_ops,
  amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
  nouveau_fbcon_sw_ops, radeonfb_ops.
  This results in: warning: Initializer entry defined twice
- Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
  ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
- Drop buggy patch: (Chris Wilson)
  drm/prime: Clear drm_gem_object->dma_buf on release
- Defer buffer creation until fb_open.


David Herrmann (1):
  drm: provide management functions for drm_file

Noralf Trønnes (24):
  drm/file: Don't set master on in-kernel clients
  drm/fb-helper: No need to cache rotation and sw_rotations
  drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
  drm/fb-helper: dpms_legacy(): Only set on connectors in use
  drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  drm: Begin an API for in-kernel clients
  drm/fb-helper: Use struct drm_client_display
  drm/fb-helper: Move modeset commit code to drm_client
  drm/connector: Add
    drm_connector_has_preferred_mode/pick_cmdline_mode()
  drm/connector: Add connector array functions
  drm/i915: Add drm_driver->initial_client_display callback
  drm/fb-helper: Remove struct drm_fb_helper_crtc
  drm/fb-helper: Remove struct drm_fb_helper_connector
  drm/fb-helper: Move modeset config code to drm_client
  drm: Make ioctls available for in-kernel clients
  drm/client: Bail out if there's a DRM master
  drm/client: Make the display modes available to clients
  drm/client: Finish the in-kernel client API
  drm/prime: Don't pin module on export for in-kernel clients
  drm/fb-helper: Add drm_fb_helper_fb_open/release()
  drm/fb-helper: Add generic fbdev emulation
  drm: Add DRM device registered notifier
  drm/client: Hack: Add bootsplash
  drm/client: Hack: Add DRM VT console client

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    4 +-
 drivers/gpu/drm/client/Kconfig          |   14 +
 drivers/gpu/drm/client/Makefile         |    3 +
 drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
 drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
 drivers/gpu/drm/client/internal.h       |   19 +
 drivers/gpu/drm/drm_atomic.c            |  168 ++++
 drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
 drivers/gpu/drm/drm_auth.c              |   33 +
 drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_connector.c         |  199 +++++
 drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
 drivers/gpu/drm/drm_debugfs.c           |    7 +
 drivers/gpu/drm/drm_drv.c               |   43 +
 drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
 drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
 drivers/gpu/drm/drm_file.c              |  304 ++++---
 drivers/gpu/drm/drm_framebuffer.c       |   50 +-
 drivers/gpu/drm/drm_internal.h          |    7 +
 drivers/gpu/drm/drm_ioc32.c             |    2 +-
 drivers/gpu/drm/drm_ioctl.c             |    4 +-
 drivers/gpu/drm/drm_prime.c             |   37 +-
 drivers/gpu/drm/drm_probe_helper.c      |    3 +
 drivers/gpu/drm/drm_sysfs.c             |   20 +
 drivers/gpu/drm/i915/i915_drv.c         |    1 +
 drivers/gpu/drm/i915/intel_drv.h        |   11 +
 drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
 include/drm/drm_atomic.h                |    5 +
 include/drm/drm_atomic_helper.h         |    4 -
 include/drm/drm_client.h                |  182 ++++
 include/drm/drm_connector.h             |   11 +
 include/drm/drm_device.h                |    4 +
 include/drm/drm_drv.h                   |   25 +
 include/drm/drm_fb_helper.h             |  126 ++-
 35 files changed, 4007 insertions(+), 1513 deletions(-)
 create mode 100644 drivers/gpu/drm/client/Kconfig
 create mode 100644 drivers/gpu/drm/client/Makefile
 create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
 create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
 create mode 100644 drivers/gpu/drm/client/internal.h
 create mode 100644 drivers/gpu/drm/drm_client.c
 create mode 100644 include/drm/drm_client.h

--
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [RFC v4 00/25] drm: Add generic fbdev emulation
  2018-04-13 16:53 Noralf Trønnes
@ 2018-04-13 17:06 ` Noralf Trønnes
  0 siblings, 0 replies; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-13 17:06 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

Argh, it didn't go through this time either.
I'll just have to strip off recipients and just send to the lists when 
the cool off period is over.

Sorry about the noise, I'll have to investigate this further.

Noralf.


Den 13.04.2018 18.53, skrev Noralf Trønnes:
> This patchset explores the possibility of having generic fbdev emulation
> in DRM for drivers that supports dumb buffers which they can export. An
> API is added to support in-kernel clients in general.
>
> In this version I was able to reuse the modesetting code from
> drm_fb_helper in the client API. This avoids code duplication, carries
> over lessons learned and the modesetting code is bisectable. The
> downside is that it takes +10 patches to rip drm_fb_helper in two, so
> maybe it's not worth it wrt possible breakage and a challenging review.
>
> Does the Intel CI test the fbdev emulation?
>
> Daniel had this concern with the previous version:
>
>      The register/unregister model needs more thought. Allowing both clients
>      to register whenever they want to, and drm_device instances to come and
>      go is what fbcon has done, and the resulting locking is a horror show.
>
>      I think if we require that all in-kernel drm_clients are registers when
>      loading drm.ko (and enabled/disabled only per module options and
>      Kconfig), then we can throw out all the locking. That avoids a lot of
>      the headaches.
>
> I have solved this by adding a notifier that fires when a new DRM device
> is registered (I've removed the new() callback). Currently only
> bootsplash uses this. The fbdev client needs to be setup from the driver
> since it can't know on device registration if the driver will setup it's
> own fbdev emulation later and the vtcon client hooks up to a user
> provided device id.
>
> Since fbcon can't handle fb_open failing, the buffer has to be
> pre-allocated. Exporting a GEM buffer pins the driver module making it
> impossible to unload it.
> I have included 2 solutions to the problem:
> - sysfs file to remove/close clients: remove_internal_clients
> - Change drm_gem_prime_export() so it doesn't pin on client buffers
>
> If a dumb buffer is exported from a kernel thread (worker) context, the
> file descriptor isn't closed and I leak a reference so the buffer isn't
> freed. Please look at drm_client_buffer_create() in patch
> 'drm/client: Finish the in-kernel client API'.
> This is a blocker that needs a solution.
>
>
> Noralf.
>
> Changes since version 3:
> Client API changes:
> - Drop drm_client_register_funcs() which attached clients indirectly.
>    Let clients attach directly using drm_client_new{_from_id}(). Clients
>    that wants to attach to all devices must be linked into drm.ko and use
>    the DRM device notifier. This is done to avoid the lock/race
>    register/unregister hell we have with fbcon. (Daniel Vetter)
> - drm_client_display_restore() checks if there is a master and if so
>    returns -EBUSY. (Daniel Vetter)
> - Allocate drm_file up front instead of on-demand. Since fbdev can't do
>    on demand buffer allocation because of fbcon, there's no need for this.
> - Add sysfs file to remove clients
> - Don't pin driver module when exporting gem client buffers
> - Dropped page flip support since drm_fb_helper is now used for fbdev
>    emulation.
>
> - The bootsplash client now switches over to fbdev on keypress.
>
> Changes since version 2:
> - Don't set drm master for in-kernel clients. (Daniel Vetter)
> - Add in-kernel client API
>
> Changes since version 1:
> - Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
>    DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
>    The following uses that macro and sets fb_open/close: udlfb_ops,
>    amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
>    nouveau_fbcon_sw_ops, radeonfb_ops.
>    This results in: warning: Initializer entry defined twice
> - Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
>    ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
> - Drop buggy patch: (Chris Wilson)
>    drm/prime: Clear drm_gem_object->dma_buf on release
> - Defer buffer creation until fb_open.
>
>
> David Herrmann (1):
>    drm: provide management functions for drm_file
>
> Noralf Trønnes (24):
>    drm/file: Don't set master on in-kernel clients
>    drm/fb-helper: No need to cache rotation and sw_rotations
>    drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
>    drm/fb-helper: dpms_legacy(): Only set on connectors in use
>    drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>    drm: Begin an API for in-kernel clients
>    drm/fb-helper: Use struct drm_client_display
>    drm/fb-helper: Move modeset commit code to drm_client
>    drm/connector: Add
>      drm_connector_has_preferred_mode/pick_cmdline_mode()
>    drm/connector: Add connector array functions
>    drm/i915: Add drm_driver->initial_client_display callback
>    drm/fb-helper: Remove struct drm_fb_helper_crtc
>    drm/fb-helper: Remove struct drm_fb_helper_connector
>    drm/fb-helper: Move modeset config code to drm_client
>    drm: Make ioctls available for in-kernel clients
>    drm/client: Bail out if there's a DRM master
>    drm/client: Make the display modes available to clients
>    drm/client: Finish the in-kernel client API
>    drm/prime: Don't pin module on export for in-kernel clients
>    drm/fb-helper: Add drm_fb_helper_fb_open/release()
>    drm/fb-helper: Add generic fbdev emulation
>    drm: Add DRM device registered notifier
>    drm/client: Hack: Add bootsplash
>    drm/client: Hack: Add DRM VT console client
>
>   drivers/gpu/drm/Kconfig                 |    2 +
>   drivers/gpu/drm/Makefile                |    4 +-
>   drivers/gpu/drm/client/Kconfig          |   14 +
>   drivers/gpu/drm/client/Makefile         |    3 +
>   drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
>   drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
>   drivers/gpu/drm/client/internal.h       |   19 +
>   drivers/gpu/drm/drm_atomic.c            |  168 ++++
>   drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
>   drivers/gpu/drm/drm_auth.c              |   33 +
>   drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
>   drivers/gpu/drm/drm_connector.c         |  199 +++++
>   drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
>   drivers/gpu/drm/drm_debugfs.c           |    7 +
>   drivers/gpu/drm/drm_drv.c               |   43 +
>   drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
>   drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
>   drivers/gpu/drm/drm_file.c              |  304 ++++---
>   drivers/gpu/drm/drm_framebuffer.c       |   50 +-
>   drivers/gpu/drm/drm_internal.h          |    7 +
>   drivers/gpu/drm/drm_ioc32.c             |    2 +-
>   drivers/gpu/drm/drm_ioctl.c             |    4 +-
>   drivers/gpu/drm/drm_prime.c             |   37 +-
>   drivers/gpu/drm/drm_probe_helper.c      |    3 +
>   drivers/gpu/drm/drm_sysfs.c             |   20 +
>   drivers/gpu/drm/i915/i915_drv.c         |    1 +
>   drivers/gpu/drm/i915/intel_drv.h        |   11 +
>   drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
>   include/drm/drm_atomic.h                |    5 +
>   include/drm/drm_atomic_helper.h         |    4 -
>   include/drm/drm_client.h                |  182 ++++
>   include/drm/drm_connector.h             |   11 +
>   include/drm/drm_device.h                |    4 +
>   include/drm/drm_drv.h                   |   25 +
>   include/drm/drm_fb_helper.h             |  126 ++-
>   35 files changed, 4007 insertions(+), 1513 deletions(-)
>   create mode 100644 drivers/gpu/drm/client/Kconfig
>   create mode 100644 drivers/gpu/drm/client/Makefile
>   create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
>   create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
>   create mode 100644 drivers/gpu/drm/client/internal.h
>   create mode 100644 drivers/gpu/drm/drm_client.c
>   create mode 100644 include/drm/drm_client.h
>
> --
> 2.15.1
>

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

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

* [RFC v4 00/25] drm: Add generic fbdev emulation
@ 2018-04-13 16:53 Noralf Trønnes
  2018-04-13 17:06 ` Noralf Trønnes
  0 siblings, 1 reply; 19+ messages in thread
From: Noralf Trønnes @ 2018-04-13 16:53 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, intel-gfx, laurent.pinchart, mstaudt

This patchset explores the possibility of having generic fbdev emulation
in DRM for drivers that supports dumb buffers which they can export. An
API is added to support in-kernel clients in general.

In this version I was able to reuse the modesetting code from
drm_fb_helper in the client API. This avoids code duplication, carries
over lessons learned and the modesetting code is bisectable. The
downside is that it takes +10 patches to rip drm_fb_helper in two, so
maybe it's not worth it wrt possible breakage and a challenging review.

Does the Intel CI test the fbdev emulation?

Daniel had this concern with the previous version:

    The register/unregister model needs more thought. Allowing both clients
    to register whenever they want to, and drm_device instances to come and
    go is what fbcon has done, and the resulting locking is a horror show.

    I think if we require that all in-kernel drm_clients are registers when
    loading drm.ko (and enabled/disabled only per module options and
    Kconfig), then we can throw out all the locking. That avoids a lot of
    the headaches.

I have solved this by adding a notifier that fires when a new DRM device
is registered (I've removed the new() callback). Currently only
bootsplash uses this. The fbdev client needs to be setup from the driver
since it can't know on device registration if the driver will setup it's
own fbdev emulation later and the vtcon client hooks up to a user
provided device id.

Since fbcon can't handle fb_open failing, the buffer has to be
pre-allocated. Exporting a GEM buffer pins the driver module making it
impossible to unload it.
I have included 2 solutions to the problem:
- sysfs file to remove/close clients: remove_internal_clients
- Change drm_gem_prime_export() so it doesn't pin on client buffers

If a dumb buffer is exported from a kernel thread (worker) context, the
file descriptor isn't closed and I leak a reference so the buffer isn't
freed. Please look at drm_client_buffer_create() in patch
'drm/client: Finish the in-kernel client API'.
This is a blocker that needs a solution.


Noralf.

Changes since version 3:
Client API changes:
- Drop drm_client_register_funcs() which attached clients indirectly.
  Let clients attach directly using drm_client_new{_from_id}(). Clients
  that wants to attach to all devices must be linked into drm.ko and use
  the DRM device notifier. This is done to avoid the lock/race
  register/unregister hell we have with fbcon. (Daniel Vetter)
- drm_client_display_restore() checks if there is a master and if so
  returns -EBUSY. (Daniel Vetter)
- Allocate drm_file up front instead of on-demand. Since fbdev can't do
  on demand buffer allocation because of fbcon, there's no need for this.
- Add sysfs file to remove clients
- Don't pin driver module when exporting gem client buffers
- Dropped page flip support since drm_fb_helper is now used for fbdev
  emulation.

- The bootsplash client now switches over to fbdev on keypress.

Changes since version 2:
- Don't set drm master for in-kernel clients. (Daniel Vetter)
- Add in-kernel client API

Changes since version 1:
- Don't add drm_fb_helper_fb_open() and drm_fb_helper_fb_release() to
  DRM_FB_HELPER_DEFAULT_OPS(). (Fi.CI.STATIC)
  The following uses that macro and sets fb_open/close: udlfb_ops,
  amdgpufb_ops, drm_fb_helper_generic_fbdev_ops, nouveau_fbcon_ops,
  nouveau_fbcon_sw_ops, radeonfb_ops.
  This results in: warning: Initializer entry defined twice
- Support CONFIG_DRM_KMS_HELPER=m (kbuild test robot)
  ERROR: <function> [drivers/gpu/drm/drm_kms_helper.ko] undefined!
- Drop buggy patch: (Chris Wilson)
  drm/prime: Clear drm_gem_object->dma_buf on release
- Defer buffer creation until fb_open.


David Herrmann (1):
  drm: provide management functions for drm_file

Noralf Trønnes (24):
  drm/file: Don't set master on in-kernel clients
  drm/fb-helper: No need to cache rotation and sw_rotations
  drm/fb-helper: Remove drm_fb_helper_debug_enter/leave()
  drm/fb-helper: dpms_legacy(): Only set on connectors in use
  drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  drm: Begin an API for in-kernel clients
  drm/fb-helper: Use struct drm_client_display
  drm/fb-helper: Move modeset commit code to drm_client
  drm/connector: Add
    drm_connector_has_preferred_mode/pick_cmdline_mode()
  drm/connector: Add connector array functions
  drm/i915: Add drm_driver->initial_client_display callback
  drm/fb-helper: Remove struct drm_fb_helper_crtc
  drm/fb-helper: Remove struct drm_fb_helper_connector
  drm/fb-helper: Move modeset config code to drm_client
  drm: Make ioctls available for in-kernel clients
  drm/client: Bail out if there's a DRM master
  drm/client: Make the display modes available to clients
  drm/client: Finish the in-kernel client API
  drm/prime: Don't pin module on export for in-kernel clients
  drm/fb-helper: Add drm_fb_helper_fb_open/release()
  drm/fb-helper: Add generic fbdev emulation
  drm: Add DRM device registered notifier
  drm/client: Hack: Add bootsplash
  drm/client: Hack: Add DRM VT console client

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    4 +-
 drivers/gpu/drm/client/Kconfig          |   14 +
 drivers/gpu/drm/client/Makefile         |    3 +
 drivers/gpu/drm/client/drm_bootsplash.c |  248 ++++++
 drivers/gpu/drm/client/drm_vtcon.c      |  785 +++++++++++++++++
 drivers/gpu/drm/client/internal.h       |   19 +
 drivers/gpu/drm/drm_atomic.c            |  168 ++++
 drivers/gpu/drm/drm_atomic_helper.c     |  168 +---
 drivers/gpu/drm/drm_auth.c              |   33 +
 drivers/gpu/drm/drm_client.c            | 1448 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_connector.c         |  199 +++++
 drivers/gpu/drm/drm_crtc_internal.h     |   18 +-
 drivers/gpu/drm/drm_debugfs.c           |    7 +
 drivers/gpu/drm/drm_drv.c               |   43 +
 drivers/gpu/drm/drm_dumb_buffers.c      |   33 +-
 drivers/gpu/drm/drm_fb_helper.c         | 1420 ++++++++----------------------
 drivers/gpu/drm/drm_file.c              |  304 ++++---
 drivers/gpu/drm/drm_framebuffer.c       |   50 +-
 drivers/gpu/drm/drm_internal.h          |    7 +
 drivers/gpu/drm/drm_ioc32.c             |    2 +-
 drivers/gpu/drm/drm_ioctl.c             |    4 +-
 drivers/gpu/drm/drm_prime.c             |   37 +-
 drivers/gpu/drm/drm_probe_helper.c      |    3 +
 drivers/gpu/drm/drm_sysfs.c             |   20 +
 drivers/gpu/drm/i915/i915_drv.c         |    1 +
 drivers/gpu/drm/i915/intel_drv.h        |   11 +
 drivers/gpu/drm/i915/intel_fbdev.c      |  112 +--
 include/drm/drm_atomic.h                |    5 +
 include/drm/drm_atomic_helper.h         |    4 -
 include/drm/drm_client.h                |  182 ++++
 include/drm/drm_connector.h             |   11 +
 include/drm/drm_device.h                |    4 +
 include/drm/drm_drv.h                   |   25 +
 include/drm/drm_fb_helper.h             |  126 ++-
 35 files changed, 4007 insertions(+), 1513 deletions(-)
 create mode 100644 drivers/gpu/drm/client/Kconfig
 create mode 100644 drivers/gpu/drm/client/Makefile
 create mode 100644 drivers/gpu/drm/client/drm_bootsplash.c
 create mode 100644 drivers/gpu/drm/client/drm_vtcon.c
 create mode 100644 drivers/gpu/drm/client/internal.h
 create mode 100644 drivers/gpu/drm/drm_client.c
 create mode 100644 include/drm/drm_client.h

--
2.15.1

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

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

end of thread, other threads:[~2018-04-16 18:49 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 02/25] drm/file: Don't set master on in-kernel clients Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave() Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 07/25] drm: Begin an API for in-kernel clients Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode() Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 11/25] drm/connector: Add connector array functions Noralf Trønnes
2018-04-12 16:34 ` [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-16  7:47   ` Daniel Vetter
2018-04-13 16:53 Noralf Trønnes
2018-04-13 17:06 ` Noralf Trønnes
2018-04-14 11:52 Noralf Trønnes
2018-04-16  8:21 ` Daniel Vetter
2018-04-16 18:49   ` Noralf Trønnes

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