* [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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ messages in thread