[RFC 6/7] drm: Add kms library for shmem backed GEM
Noralf Trønnes
noralf at tronnes.org
Wed Jul 12 13:46:04 UTC 2017
This adds kms helpers for the shmem gem library.
Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
---
drivers/gpu/drm/Kconfig | 11 +++
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/drm_fb_shmem_helper.c | 168 ++++++++++++++++++++++++++++++++++
include/drm/drm_fb_shmem_helper.h | 18 ++++
4 files changed, 198 insertions(+)
create mode 100644 drivers/gpu/drm/drm_fb_shmem_helper.c
create mode 100644 include/drm/drm_fb_shmem_helper.h
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 8e709c2..4c9010d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -151,6 +151,17 @@ config DRM_GEM_SHMEM_HELPER
help
Choose this if you need the GEM SHMEM helper functions
+config DRM_KMS_SHMEM_HELPER
+ bool
+ depends on DRM
+ select DRM_GEM_SHMEM_HELPER
+ select DRM_KMS_FB_HELPER
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ help
+ Choose this if you need the KMS SHMEM helper functions
+
config DRM_VM
bool
depends on DRM && MMU
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 598c247..706037c 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -40,6 +40,7 @@ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
+drm_kms_helper-$(CONFIG_DRM_KMS_SHMEM_HELPER) += drm_fb_shmem_helper.o
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
diff --git a/drivers/gpu/drm/drm_fb_shmem_helper.c b/drivers/gpu/drm/drm_fb_shmem_helper.c
new file mode 100644
index 0000000..ddcf24f
--- /dev/null
+++ b/drivers/gpu/drm/drm_fb_shmem_helper.c
@@ -0,0 +1,168 @@
+/*
+ * drm kms/fb shmem (shared memory) helper functions
+ *
+ * Copyright (C) 2017 Noralf Trønnes
+ *
+ * Based on drm_fb_cma_helper.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_fb_gem_helper.h>
+#include <drm/drm_fb_shmem_helper.h>
+
+#ifdef CONFIG_DEBUG_FS
+static void drm_fb_shmem_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+ struct drm_fb_gem *fb_gem = to_fb_gem(fb);
+ struct drm_gem_shmem_object *obj;
+ int i;
+
+ seq_printf(m, "[FB:%d] %dx%d@%4.4s\n", fb->base.id, fb->width, fb->height,
+ (char *)&fb->format->format);
+
+ for (i = 0; i < fb->format->num_planes; i++) {
+ obj = to_drm_gem_shmem_obj(fb_gem->obj[i]);
+ seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
+ i, fb->offsets[i], fb->pitches[i]);
+ drm_gem_shmem_describe(obj, m);
+ }
+}
+
+/**
+ * drm_fb_shmem_debugfs_show() - Helper to list shmem framebuffer objects
+ * in debugfs.
+ * @m: output file
+ * @arg: private data for the callback
+ */
+int drm_fb_shmem_debugfs_show(struct seq_file *m, void *arg)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_framebuffer *fb;
+
+ mutex_lock(&dev->mode_config.fb_lock);
+ drm_for_each_fb(fb, dev)
+ drm_fb_shmem_describe(fb, m);
+ mutex_unlock(&dev->mode_config.fb_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(drm_fb_shmem_debugfs_show);
+#endif
+
+static int drm_fb_shmem_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *helper = fbi->par;
+ struct drm_fb_gem *fb_gem = to_fb_gem(helper->fb);
+
+ return drm_gem_shmem_prime_mmap(fb_gem->obj[0], vma);
+}
+
+static int drm_fb_helper_fb_open(struct fb_info *fbi, int user)
+{
+ struct drm_fb_helper *helper = fbi->par;
+
+ if (!try_module_get(helper->dev->driver->fops->owner))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int drm_fb_helper_fb_release(struct fb_info *fbi, int user)
+{
+ struct drm_fb_helper *helper = fbi->par;
+
+ module_put(helper->dev->driver->fops->owner);
+
+ return 0;
+}
+
+static struct fb_ops drm_fb_helper_fb_ops = {
+ .owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
+ .fb_open = drm_fb_helper_fb_open,
+ .fb_release = drm_fb_helper_fb_release,
+ .fb_read = drm_fb_helper_sys_read,
+ .fb_write = drm_fb_helper_sys_write,
+ .fb_fillrect = drm_fb_helper_sys_fillrect,
+ .fb_copyarea = drm_fb_helper_sys_copyarea,
+ .fb_imageblit = drm_fb_helper_sys_imageblit,
+ .fb_mmap = drm_fb_shmem_mmap,
+};
+
+/**
+ * drm_fb_shmem_fbdev_probe -
+ * @helper: fbdev emulation structure
+ * @sizes: fbdev description
+ * @fb_funcs: Framebuffer helper functions
+ *
+ * Drivers can use this in their &drm_fb_helper_funcs->fb_probe function.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_fb_shmem_fbdev_probe(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes,
+ const struct drm_framebuffer_funcs *fb_funcs)
+{
+ struct drm_device *dev = helper->dev;
+ struct drm_mode_fb_cmd2 mode_cmd;
+ struct drm_gem_shmem_object *obj;
+ struct drm_gem_object *gem;
+ struct drm_fb_gem *fb_gem;
+ void *shadow = NULL;
+ size_t size;
+ int ret;
+
+ size = drm_fb_helper_mode_cmd(&mode_cmd, sizes);
+
+ obj = drm_gem_shmem_create(dev, size);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ gem = &obj->base;
+ fb_gem = drm_fb_gem_alloc(dev, &mode_cmd, &gem, 1, fb_funcs);
+ if (IS_ERR(fb_gem)) {
+ dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+ drm_gem_object_put_unlocked(&obj->base);
+ return PTR_ERR(fb_gem);
+ }
+
+ ret = drm_gem_shmem_vmap(obj);
+ if (ret)
+ goto error;
+
+ if (fb_funcs->dirty) {
+ shadow = vzalloc(size);
+ if (!shadow) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ helper->defio_vaddr = obj->vaddr;
+ }
+
+ ret = drm_fb_helper_simple_fb_probe(helper, sizes, &fb_gem->base,
+ &drm_fb_helper_fb_ops,
+ shadow ? shadow : obj->vaddr, 0,
+ size);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ vfree(shadow);
+ drm_framebuffer_remove(&fb_gem->base);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_fb_shmem_fbdev_probe);
diff --git a/include/drm/drm_fb_shmem_helper.h b/include/drm/drm_fb_shmem_helper.h
new file mode 100644
index 0000000..5c57131
--- /dev/null
+++ b/include/drm/drm_fb_shmem_helper.h
@@ -0,0 +1,18 @@
+#ifndef __DRM_FB_SHMEM_HELPER_H__
+#define __DRM_FB_SHMEM_HELPER_H__
+
+struct drm_fb_helper_surface_size;
+struct drm_framebuffer_funcs;
+struct drm_fb_helper;
+
+int drm_fb_shmem_fbdev_probe(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes,
+ const struct drm_framebuffer_funcs *fb_funcs);
+
+#ifdef CONFIG_DEBUG_FS
+struct seq_file;
+
+int drm_fb_shmem_debugfs_show(struct seq_file *m, void *arg);
+#endif
+
+#endif
--
2.7.4
More information about the dri-devel
mailing list