All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Herrmann <dh.herrmann@gmail.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support
Date: Fri,  2 Sep 2016 10:22:45 +0200	[thread overview]
Message-ID: <20160902082245.7119-8-dh.herrmann@gmail.com> (raw)
In-Reply-To: <20160902082245.7119-1-dh.herrmann@gmail.com>

Create a simple fbdev device during SimpleDRM setup so legacy user-space
and fbcon can use it.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/simpledrm/Makefile          |   1 +
 drivers/gpu/drm/simpledrm/simpledrm.h       |   8 ++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c   |  13 +++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c | 143 ++++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c   |  55 ++++++-----
 5 files changed, 196 insertions(+), 24 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c

diff --git a/drivers/gpu/drm/simpledrm/Makefile b/drivers/gpu/drm/simpledrm/Makefile
index d7b179d..e368d14 100644
--- a/drivers/gpu/drm/simpledrm/Makefile
+++ b/drivers/gpu/drm/simpledrm/Makefile
@@ -1,6 +1,7 @@
 simpledrm-y := \
 	simpledrm_damage.o \
 	simpledrm_drv.o \
+	simpledrm_fbdev.o \
 	simpledrm_gem.o \
 	simpledrm_kms.o \
 	simpledrm_of.o
diff --git a/drivers/gpu/drm/simpledrm/simpledrm.h b/drivers/gpu/drm/simpledrm/simpledrm.h
index ed6d725..d7a2045 100644
--- a/drivers/gpu/drm/simpledrm/simpledrm.h
+++ b/drivers/gpu/drm/simpledrm/simpledrm.h
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 
 struct clk;
+struct drm_fb_helper;
 struct regulator;
 struct simplefb_format;
 
@@ -49,6 +50,7 @@ struct sdrm_device {
 	atomic_t n_used;
 	struct drm_device *ddev;
 	struct sdrm_hw *hw;
+	struct drm_fb_helper *fbdev;
 
 	size_t n_clks;
 	size_t n_regulators;
@@ -66,6 +68,9 @@ void sdrm_of_unbind(struct sdrm_device *sdrm);
 int sdrm_kms_bind(struct sdrm_device *sdrm);
 void sdrm_kms_unbind(struct sdrm_device *sdrm);
 
+void sdrm_fbdev_bind(struct sdrm_device *sdrm);
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm);
+
 void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height);
 
 struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size);
@@ -80,4 +85,7 @@ int sdrm_dumb_map_offset(struct drm_file *dfile,
 			 uint32_t handle,
 			 uint64_t *offset);
 
+struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo,
+			    const struct drm_mode_fb_cmd2 *cmd);
+
 #endif /* __SDRM_SIMPLEDRM_H */
diff --git a/drivers/gpu/drm/simpledrm/simpledrm_drv.c b/drivers/gpu/drm/simpledrm/simpledrm_drv.c
index d569120..6aefe49 100644
--- a/drivers/gpu/drm/simpledrm/simpledrm_drv.c
+++ b/drivers/gpu/drm/simpledrm/simpledrm_drv.c
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
 #include <linux/atomic.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -210,6 +211,7 @@ error:
 static void sdrm_device_unbind(struct sdrm_device *sdrm)
 {
 	if (sdrm) {
+		sdrm_fbdev_unbind(sdrm);
 		sdrm_kms_unbind(sdrm);
 		sdrm_hw_unbind(sdrm->hw);
 		sdrm_of_unbind(sdrm);
@@ -232,6 +234,8 @@ static int sdrm_device_bind(struct sdrm_device *sdrm)
 	if (r < 0)
 		goto error;
 
+	sdrm_fbdev_bind(sdrm);
+
 	return 0;
 
 error:
@@ -253,6 +257,14 @@ static void sdrm_device_release(struct sdrm_device *sdrm)
 	}
 }
 
+static void sdrm_device_lastclose(struct drm_device *ddev)
+{
+	struct sdrm_device *sdrm = ddev->dev_private;
+
+	if (sdrm->fbdev)
+		drm_fb_helper_restore_fbdev_mode_unlocked(sdrm->fbdev);
+}
+
 static int sdrm_fop_open(struct inode *inode, struct file *file)
 {
 	struct drm_device *ddev;
@@ -411,6 +423,7 @@ static const struct file_operations sdrm_drm_fops = {
 static struct drm_driver sdrm_drm_driver = {
 	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 	.fops = &sdrm_drm_fops,
+	.lastclose = sdrm_device_lastclose,
 
 	.gem_free_object = sdrm_bo_free,
 
diff --git a/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
new file mode 100644
index 0000000..17e4e83
--- /dev/null
+++ b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright (C) 2016 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "simpledrm.h"
+
+static int sdrm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	return -ENODEV;
+}
+
+static struct fb_ops sdrm_fbdev_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= drm_fb_helper_sys_fillrect,
+	.fb_copyarea	= drm_fb_helper_sys_copyarea,
+	.fb_imageblit	= drm_fb_helper_sys_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+	.fb_mmap	= sdrm_fbdev_mmap,
+};
+
+static int sdrm_fbdev_probe(struct drm_fb_helper *fbdev,
+			    struct drm_fb_helper_surface_size *sizes)
+{
+	struct sdrm_device *sdrm = fbdev->dev->dev_private;
+	struct drm_mode_fb_cmd2 cmd = {
+		.width = sdrm->hw->width,
+		.height = sdrm->hw->height,
+		.pitches[0] = sdrm->hw->stride,
+		.pixel_format = sdrm->hw->format,
+	};
+	struct fb_info *fbi;
+	struct sdrm_bo *bo;
+	struct sdrm_fb *fb;
+	int r;
+
+	fbi = drm_fb_helper_alloc_fbi(fbdev);
+	if (IS_ERR(fbi))
+		return PTR_ERR(fbi);
+
+	bo = sdrm_bo_new(sdrm->ddev,
+			 PAGE_ALIGN(sdrm->hw->height * sdrm->hw->stride));
+	if (!bo) {
+		r = -ENOMEM;
+		goto error;
+	}
+
+	fb = sdrm_fb_new(bo, &cmd);
+	drm_gem_object_unreference_unlocked(&bo->base);
+	if (IS_ERR(fb)) {
+		r = PTR_ERR(fb);
+		goto error;
+	}
+
+	fbdev->fb = &fb->base;
+	fbi->par = fbdev;
+	fbi->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
+	fbi->fbops = &sdrm_fbdev_ops;
+
+	drm_fb_helper_fill_fix(fbi, fb->base.pitches[0], fb->base.depth);
+	drm_fb_helper_fill_var(fbi, fbdev, fb->base.width, fb->base.height);
+
+	strncpy(fbi->fix.id, "simpledrmfb", sizeof(fbi->fix.id) - 1);
+	fbi->screen_base = bo->vmapping;
+	fbi->fix.smem_len = bo->base.size;
+
+	return 0;
+
+error:
+	drm_fb_helper_release_fbi(fbdev);
+	return r;
+}
+
+static const struct drm_fb_helper_funcs sdrm_fbdev_funcs = {
+	.fb_probe = sdrm_fbdev_probe,
+};
+
+void sdrm_fbdev_bind(struct sdrm_device *sdrm)
+{
+	struct drm_fb_helper *fbdev;
+	int r;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev)
+		return;
+
+	drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs);
+
+	r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1);
+	if (r < 0)
+		goto error;
+
+	r = drm_fb_helper_single_add_all_connectors(fbdev);
+	if (r < 0)
+		goto error;
+
+	r = drm_fb_helper_initial_config(fbdev,
+				sdrm->ddev->mode_config.preferred_depth);
+	if (r < 0)
+		goto error;
+
+	if (!fbdev->fbdev)
+		goto error;
+
+	sdrm->fbdev = fbdev;
+	return;
+
+error:
+	drm_fb_helper_fini(fbdev);
+	kfree(fbdev);
+}
+
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm)
+{
+	struct drm_fb_helper *fbdev = sdrm->fbdev;
+
+	if (!fbdev)
+		return;
+
+	sdrm->fbdev = NULL;
+	drm_fb_helper_unregister_fbi(fbdev);
+	cancel_work_sync(&fbdev->dirty_work);
+	drm_fb_helper_release_fbi(fbdev);
+	drm_framebuffer_unreference(fbdev->fb);
+	fbdev->fb = NULL;
+	drm_fb_helper_fini(fbdev);
+	kfree(fbdev);
+}
diff --git a/drivers/gpu/drm/simpledrm/simpledrm_kms.c b/drivers/gpu/drm/simpledrm/simpledrm_kms.c
index 00101c9..8f67fe5 100644
--- a/drivers/gpu/drm/simpledrm/simpledrm_kms.c
+++ b/drivers/gpu/drm/simpledrm/simpledrm_kms.c
@@ -169,53 +169,60 @@ static const struct drm_framebuffer_funcs sdrm_fb_ops = {
 	.destroy		= sdrm_fb_destroy,
 };
 
-static struct drm_framebuffer *
-sdrm_fb_create(struct drm_device *ddev,
-	       struct drm_file *dfile,
-	       const struct drm_mode_fb_cmd2 *cmd)
+struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo,
+			    const struct drm_mode_fb_cmd2 *cmd)
 {
-	struct drm_gem_object *dobj;
-	struct sdrm_fb *fb = NULL;
-	struct sdrm_bo *bo;
+	struct sdrm_fb *fb;
 	int r;
 
 	if (cmd->flags)
 		return ERR_PTR(-EINVAL);
 
-	dobj = drm_gem_object_lookup(dfile, cmd->handles[0]);
-	if (!dobj)
-		return ERR_PTR(-EINVAL);
-
-	bo = container_of(dobj, struct sdrm_bo, base);
-
 	r = sdrm_bo_vmap(bo);
 	if (r < 0)
-		goto error;
+		return ERR_PTR(r);
 
 	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-	if (!fb) {
-		r = -ENOMEM;
-		goto error;
-	}
+	if (!fb)
+		return ERR_PTR(r);
 
+	drm_gem_object_reference(&bo->base);
 	fb->bo = bo;
 	drm_helper_mode_fill_fb_struct(&fb->base, cmd);
 
-	r = drm_framebuffer_init(ddev, &fb->base, &sdrm_fb_ops);
+	r = drm_framebuffer_init(bo->base.dev, &fb->base, &sdrm_fb_ops);
 	if (r < 0)
 		goto error;
 
-	DRM_DEBUG_KMS("[FB:%d] pixel_format: %s\n", fb->base.base.id,
-		      drm_get_format_name(fb->base.pixel_format));
-
-	return &fb->base;
+	return fb;
 
 error:
+	drm_gem_object_unreference_unlocked(&bo->base);
 	kfree(fb);
-	drm_gem_object_unreference_unlocked(dobj);
 	return ERR_PTR(r);
 }
 
+static struct drm_framebuffer *
+sdrm_fb_create(struct drm_device *ddev,
+	       struct drm_file *dfile,
+	       const struct drm_mode_fb_cmd2 *cmd)
+{
+	struct drm_gem_object *dobj;
+	struct sdrm_fb *fb;
+
+	dobj = drm_gem_object_lookup(dfile, cmd->handles[0]);
+	if (!dobj)
+		return ERR_PTR(-EINVAL);
+
+	fb = sdrm_fb_new(container_of(dobj, struct sdrm_bo, base), cmd);
+	drm_gem_object_unreference_unlocked(dobj);
+
+	if (IS_ERR(fb))
+		return ERR_CAST(fb);
+
+	return &fb->base;
+}
+
 static const struct drm_mode_config_funcs sdrm_mode_config_ops = {
 	.fb_create		= sdrm_fb_create,
 	.atomic_check		= drm_atomic_helper_check,
-- 
2.9.3

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

  parent reply	other threads:[~2016-09-02  8:23 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-02  8:22 [PATCH v5 0/7] drm: add simpledrm driver David Herrmann
2016-09-02  8:22 ` [PATCH v5 1/7] x86/sysfb: add support for 64bit EFI lfb_base David Herrmann
2016-09-02 10:20   ` Tom Gundersen
2016-09-02  8:22 ` [PATCH v5 2/7] x86/sysfb: fix lfb_size calculation David Herrmann
2016-09-02 10:20   ` Tom Gundersen
2016-09-02  8:22 ` [PATCH v5 3/7] of/platform: expose of_platform_device_destroy() David Herrmann
2016-09-02 10:21   ` Tom Gundersen
2016-09-02  8:22 ` [PATCH v5 4/7] video: add generic framebuffer eviction David Herrmann
2016-09-02 10:21   ` Tom Gundersen
2016-09-03 12:06   ` Noralf Trønnes
2016-09-05 11:19     ` David Herrmann
2016-09-05 16:36       ` Noralf Trønnes
2016-09-02  8:22 ` [PATCH v5 5/7] drm: switch to sysfb_evict_conflicts() David Herrmann
2016-09-03 12:13   ` Noralf Trønnes
2016-09-02  8:22 ` [PATCH v5 6/7] drm: add SimpleDRM driver David Herrmann
2016-09-02 12:45   ` Tom Gundersen
2016-09-03 12:01   ` Noralf Trønnes
2016-09-03 12:05     ` David Herrmann
2016-09-05 16:39   ` Noralf Trønnes
2016-09-02  8:22 ` David Herrmann [this message]
2016-09-03 12:04   ` [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support Noralf Trønnes
2016-09-03 17:15     ` Noralf Trønnes
2016-09-05 11:21       ` David Herrmann
2021-03-10  2:50 ` [PATCH v5 0/7] drm: add simpledrm driver nerdopolis
2021-03-10  9:10   ` Thomas Zimmermann
2021-03-10 13:52     ` nerdopolis
2021-03-12  3:49     ` nerdopolis
2021-03-12  8:03       ` Thomas Zimmermann
2021-03-12 13:25         ` nerdopolis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160902082245.7119-8-dh.herrmann@gmail.com \
    --to=dh.herrmann@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.