This adds kms helpers for the shmem gem library. Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel