diff options
-rw-r--r-- | Documentation/gpu/drm-kms-helpers.rst | 9 | ||||
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_cma_helper.c | 180 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_gem_framebuffer_helper.c | 283 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/pl111/pl111_display.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/pl111/pl111_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/st7586.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_kms.c | 3 | ||||
-rw-r--r-- | include/drm/drm_framebuffer.h | 7 | ||||
-rw-r--r-- | include/drm/drm_gem_framebuffer_helper.h | 37 |
13 files changed, 386 insertions, 159 deletions
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 7c5e2549a58a..13dd237418cc 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -296,3 +296,12 @@ Auxiliary Modeset Helpers .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c :export: + +Framebuffer GEM Helper Reference +================================ + +.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c + :doc: overview + +.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c + :export: diff --git a/MAINTAINERS b/MAINTAINERS index fdba5f624480..4a5971fa1c21 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4634,6 +4634,14 @@ F: drivers/gpu/drm/panel/ F: include/drm/drm_panel.h F: Documentation/devicetree/bindings/display/panel/ +DRM TINYDRM DRIVERS +M: Noralf Trønnes <noralf@tronnes.org> +W: https://github.com/notro/tinydrm/wiki/Development +T: git git://anongit.freedesktop.org/drm/drm-misc +S: Maintained +F: drivers/gpu/drm/tinydrm/ +F: include/drm/tinydrm/ + DSBR100 USB FM RADIO DRIVER M: Alexey Klimov <klimov.linux@gmail.com> L: linux-media@vger.kernel.org diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 24a066e1841c..a8acc197dec3 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -33,7 +33,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_simple_kms_helper.o drm_modeset_helper.o \ - drm_scdc_helper.o + drm_scdc_helper.o drm_gem_framebuffer_helper.o drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index ade319d10e70..f2ee88363015 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -18,27 +18,17 @@ */ #include <drm/drmP.h> -#include <drm/drm_atomic.h> -#include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_crtc_helper.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> -#include <linux/dma-buf.h> -#include <linux/dma-mapping.h> #include <linux/module.h> -#include <linux/reservation.h> #define DEFAULT_FBDEFIO_DELAY_MS 50 -struct drm_fb_cma { - struct drm_framebuffer fb; - struct drm_gem_cma_object *obj[4]; -}; - struct drm_fbdev_cma { struct drm_fb_helper fb_helper; - struct drm_fb_cma *fb; const struct drm_framebuffer_funcs *fb_funcs; }; @@ -90,69 +80,19 @@ static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper) return container_of(helper, struct drm_fbdev_cma, fb_helper); } -static inline struct drm_fb_cma *to_fb_cma(struct drm_framebuffer *fb) -{ - return container_of(fb, struct drm_fb_cma, fb); -} - void drm_fb_cma_destroy(struct drm_framebuffer *fb) { - struct drm_fb_cma *fb_cma = to_fb_cma(fb); - int i; - - for (i = 0; i < 4; i++) { - if (fb_cma->obj[i]) - drm_gem_object_put_unlocked(&fb_cma->obj[i]->base); - } - - drm_framebuffer_cleanup(fb); - kfree(fb_cma); + drm_gem_fb_destroy(fb); } EXPORT_SYMBOL(drm_fb_cma_destroy); int drm_fb_cma_create_handle(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle) { - struct drm_fb_cma *fb_cma = to_fb_cma(fb); - - return drm_gem_handle_create(file_priv, - &fb_cma->obj[0]->base, handle); + return drm_gem_fb_create_handle(fb, file_priv, handle); } EXPORT_SYMBOL(drm_fb_cma_create_handle); -static struct drm_framebuffer_funcs drm_fb_cma_funcs = { - .destroy = drm_fb_cma_destroy, - .create_handle = drm_fb_cma_create_handle, -}; - -static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_cma_object **obj, - unsigned int num_planes, const struct drm_framebuffer_funcs *funcs) -{ - struct drm_fb_cma *fb_cma; - int ret; - int i; - - fb_cma = kzalloc(sizeof(*fb_cma), GFP_KERNEL); - if (!fb_cma) - return ERR_PTR(-ENOMEM); - - drm_helper_mode_fill_fb_struct(dev, &fb_cma->fb, mode_cmd); - - for (i = 0; i < num_planes; i++) - fb_cma->obj[i] = obj[i]; - - ret = drm_framebuffer_init(dev, &fb_cma->fb, funcs); - if (ret) { - dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", ret); - kfree(fb_cma); - return ERR_PTR(ret); - } - - return fb_cma; -} - /** * drm_fb_cma_create_with_funcs() - helper function for the * &drm_mode_config_funcs.fb_create @@ -170,53 +110,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, const struct drm_framebuffer_funcs *funcs) { - const struct drm_format_info *info; - struct drm_fb_cma *fb_cma; - struct drm_gem_cma_object *objs[4]; - struct drm_gem_object *obj; - int ret; - int i; - - info = drm_get_format_info(dev, mode_cmd); - if (!info) - return ERR_PTR(-EINVAL); - - for (i = 0; i < info->num_planes; i++) { - unsigned int width = mode_cmd->width / (i ? info->hsub : 1); - unsigned int height = mode_cmd->height / (i ? info->vsub : 1); - unsigned int min_size; - - obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); - if (!obj) { - dev_err(dev->dev, "Failed to lookup GEM object\n"); - ret = -ENOENT; - goto err_gem_object_put; - } - - min_size = (height - 1) * mode_cmd->pitches[i] - + width * info->cpp[i] - + mode_cmd->offsets[i]; - - if (obj->size < min_size) { - drm_gem_object_put_unlocked(obj); - ret = -EINVAL; - goto err_gem_object_put; - } - objs[i] = to_drm_gem_cma_obj(obj); - } - - fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i, funcs); - if (IS_ERR(fb_cma)) { - ret = PTR_ERR(fb_cma); - goto err_gem_object_put; - } - - return &fb_cma->fb; - -err_gem_object_put: - for (i--; i >= 0; i--) - drm_gem_object_put_unlocked(&objs[i]->base); - return ERR_PTR(ret); + return drm_gem_fb_create_with_funcs(dev, file_priv, mode_cmd, funcs); } EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs); @@ -233,8 +127,7 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs); struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { - return drm_fb_cma_create_with_funcs(dev, file_priv, mode_cmd, - &drm_fb_cma_funcs); + return drm_gem_fb_create(dev, file_priv, mode_cmd); } EXPORT_SYMBOL_GPL(drm_fb_cma_create); @@ -250,12 +143,13 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_create); struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane) { - struct drm_fb_cma *fb_cma = to_fb_cma(fb); + struct drm_gem_object *gem; - if (plane >= 4) + gem = drm_gem_fb_get_obj(fb, plane); + if (!gem) return NULL; - return fb_cma->obj[plane]; + return to_drm_gem_cma_obj(gem); } EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); @@ -272,13 +166,14 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, struct drm_plane_state *state, unsigned int plane) { - struct drm_fb_cma *fb_cma = to_fb_cma(fb); + struct drm_gem_cma_object *obj; dma_addr_t paddr; - if (plane >= 4) + obj = drm_fb_cma_get_gem_obj(fb, plane); + if (!obj) return 0; - paddr = fb_cma->obj[plane]->paddr + fb->offsets[plane]; + paddr = obj->paddr + fb->offsets[plane]; paddr += fb->format->cpp[plane] * (state->src_x >> 16); paddr += fb->pitches[plane] * (state->src_y >> 16); @@ -302,26 +197,13 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); int drm_fb_cma_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) { - struct dma_buf *dma_buf; - struct dma_fence *fence; - - if ((plane->state->fb == state->fb) || !state->fb) - return 0; - - dma_buf = drm_fb_cma_get_gem_obj(state->fb, 0)->base.dma_buf; - if (dma_buf) { - fence = reservation_object_get_excl_rcu(dma_buf->resv); - drm_atomic_set_fence_for_plane(state, fence); - } - - return 0; + return drm_gem_fb_prepare_fb(plane, state); } EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb); #ifdef CONFIG_DEBUG_FS static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) { - struct drm_fb_cma *fb_cma = to_fb_cma(fb); int i; seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, @@ -330,7 +212,7 @@ static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) for (i = 0; i < fb->format->num_planes; i++) { seq_printf(m, " %d: offset=%d pitch=%d, obj: ", i, fb->offsets[i], fb->pitches[i]); - drm_gem_cma_describe(fb_cma->obj[i], m); + drm_gem_cma_describe(drm_fb_cma_get_gem_obj(fb, i), m); } } @@ -431,7 +313,6 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper); - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_device *dev = helper->dev; struct drm_gem_cma_object *obj; struct drm_framebuffer *fb; @@ -446,14 +327,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, sizes->surface_bpp); bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; + size = sizes->surface_width * sizes->surface_height * bytes_per_pixel; obj = drm_gem_cma_create(dev, size); if (IS_ERR(obj)) return -ENOMEM; @@ -464,15 +338,14 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, goto err_gem_free_object; } - fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1, - fbdev_cma->fb_funcs); - if (IS_ERR(fbdev_cma->fb)) { + fb = drm_gem_fbdev_fb_create(dev, sizes, 0, &obj->base, + fbdev_cma->fb_funcs); + if (IS_ERR(fb)) { dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); - ret = PTR_ERR(fbdev_cma->fb); + ret = PTR_ERR(fb); goto err_fb_info_destroy; } - fb = &fbdev_cma->fb->fb; helper->fb = fb; fbi->par = helper; @@ -500,7 +373,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, return 0; err_cma_destroy: - drm_framebuffer_remove(&fbdev_cma->fb->fb); + drm_framebuffer_remove(fb); err_fb_info_destroy: drm_fb_helper_fini(helper); err_gem_free_object: @@ -570,6 +443,11 @@ err_free: } EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs); +static const struct drm_framebuffer_funcs drm_fb_cma_funcs = { + .destroy = drm_gem_fb_destroy, + .create_handle = drm_gem_fb_create_handle, +}; + /** * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct * @dev: DRM device @@ -597,8 +475,8 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) if (fbdev_cma->fb_helper.fbdev) drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); - if (fbdev_cma->fb) - drm_framebuffer_remove(&fbdev_cma->fb->fb); + if (fbdev_cma->fb_helper.fb) + drm_framebuffer_remove(fbdev_cma->fb_helper.fb); drm_fb_helper_fini(&fbdev_cma->fb_helper); kfree(fbdev_cma); diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c new file mode 100644 index 000000000000..d54a083dc5dd --- /dev/null +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -0,0 +1,283 @@ +/* + * drm gem framebuffer helper functions + * + * Copyright (C) 2017 Noralf Trønnes + * + * 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/dma-buf.h> +#include <linux/dma-fence.h> +#include <linux/reservation.h> +#include <linux/slab.h> + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_modeset_helper.h> + +/** + * DOC: overview + * + * This library provides helpers for drivers that don't subclass + * &drm_framebuffer and and use &drm_gem_object for their backing storage. + * + * Drivers without additional needs to validate framebuffers can simply use + * drm_gem_fb_create() and everything is wired up automatically. But all + * parts can be used individually. + */ + +/** + * drm_gem_fb_get_obj() - Get GEM object for framebuffer + * @fb: The framebuffer + * @plane: Which plane + * + * Returns the GEM object for given framebuffer. + */ +struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb, + unsigned int plane) +{ + if (plane >= 4) + return NULL; + + return fb->obj[plane]; +} +EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj); + +static struct drm_framebuffer * +drm_gem_fb_alloc(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object **obj, unsigned int num_planes, + const struct drm_framebuffer_funcs *funcs) +{ + struct drm_framebuffer *fb; + int ret, i; + + fb = kzalloc(sizeof(*fb), GFP_KERNEL); + if (!fb) + return ERR_PTR(-ENOMEM); + + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); + + for (i = 0; i < num_planes; i++) + fb->obj[i] = obj[i]; + + ret = drm_framebuffer_init(dev, fb, funcs); + if (ret) { + DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n", + ret); + kfree(fb); + return ERR_PTR(ret); + } + + return fb; +} + +/** + * drm_gem_fb_destroy - Free GEM backed framebuffer + * @fb: DRM framebuffer + * + * Frees a GEM backed framebuffer with its backing buffer(s) and the structure + * itself. Drivers can use this as their &drm_framebuffer_funcs->destroy + * callback. + */ +void drm_gem_fb_destroy(struct drm_framebuffer *fb) +{ + int i; + + for (i = 0; i < 4; i++) + drm_gem_object_put_unlocked(fb->obj[i]); + + drm_framebuffer_cleanup(fb); + kfree(fb); +} +EXPORT_SYMBOL(drm_gem_fb_destroy); + +/** + * drm_gem_fb_create_handle - Create handle for GEM backed framebuffer + * @fb: DRM framebuffer + * @file: drm file + * @handle: handle created + * + * Drivers can use this as their &drm_framebuffer_funcs->create_handle + * callback. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file, + unsigned int *handle) +{ + return drm_gem_handle_create(file, fb->obj[0], handle); +} +EXPORT_SYMBOL(drm_gem_fb_create_handle); + +/** + * drm_gem_fb_create_with_funcs() - helper function for the + * &drm_mode_config_funcs.fb_create + * callback + * @dev: DRM device + * @file: drm file for the ioctl call + * @mode_cmd: metadata from the userspace fb creation request + * @funcs: vtable to be used for the new framebuffer object + * + * This can be used to set &drm_framebuffer_funcs for drivers that need the + * &drm_framebuffer_funcs.dirty callback. Use drm_gem_fb_create() if you don't + * need to change &drm_framebuffer_funcs. + * The function does buffer size validation. + */ +struct drm_framebuffer * +drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd, + const struct drm_framebuffer_funcs *funcs) +{ + const struct drm_format_info *info; + struct drm_gem_object *objs[4]; + struct drm_framebuffer *fb; + int ret, i; + + info = drm_get_format_info(dev, mode_cmd); + if (!info) + return ERR_PTR(-EINVAL); + + for (i = 0; i < info->num_planes; i++) { + unsigned int width = mode_cmd->width / (i ? info->hsub : 1); + unsigned int height = mode_cmd->height / (i ? info->vsub : 1); + unsigned int min_size; + + objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); + if (!objs[i]) { + DRM_DEV_ERROR(dev->dev, "Failed to lookup GEM\n"); + ret = -ENOENT; + goto err_gem_object_put; + } + + min_size = (height - 1) * mode_cmd->pitches[i] + + width * info->cpp[i] + + mode_cmd->offsets[i]; + + if (objs[i]->size < min_size) { + drm_gem_object_put_unlocked(objs[i]); + ret = -EINVAL; + goto err_gem_object_put; + } + } + + fb = drm_gem_fb_alloc(dev, mode_cmd, objs, i, funcs); + if (IS_ERR(fb)) { + ret = PTR_ERR(fb); + goto err_gem_object_put; + } + + return fb; + +err_gem_object_put: + for (i--; i >= 0; i--) + drm_gem_object_put_unlocked(objs[i]); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_funcs); + +static const struct drm_framebuffer_funcs drm_gem_fb_funcs = { + .destroy = drm_gem_fb_destroy, + .create_handle = drm_gem_fb_create_handle, +}; + +/** + * drm_gem_fb_create() - &drm_mode_config_funcs.fb_create callback function + * @dev: DRM device + * @file: drm file for the ioctl call + * @mode_cmd: metadata from the userspace fb creation request + * + * If your hardware has special alignment or pitch requirements these should be + * checked before calling this function. The function does buffer size + * validation. Use drm_gem_fb_create_with_funcs() if you need to set + * &drm_framebuffer_funcs.dirty. + */ +struct drm_framebuffer * +drm_gem_fb_create(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + return drm_gem_fb_create_with_funcs(dev, file, mode_cmd, + &drm_gem_fb_funcs); +} +EXPORT_SYMBOL_GPL(drm_gem_fb_create); + +/** + * drm_gem_fb_prepare_fb() - Prepare gem framebuffer + * @plane: Which plane + * @state: Plane state attach fence to + * + * This can be used as the &drm_plane_helper_funcs.prepare_fb hook. + * + * This function checks if the plane FB has an dma-buf attached, extracts + * the exclusive fence and attaches it to plane state for the atomic helper + * to wait on. + * + * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple + * gem based framebuffer drivers which have their buffers always pinned in + * memory. + */ +int drm_gem_fb_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct dma_buf *dma_buf; + struct dma_fence *fence; + + if ((plane->state->fb == state->fb) || !state->fb) + return 0; + + dma_buf = drm_gem_fb_get_obj(state->fb, 0)->dma_buf; + if (dma_buf) { + fence = reservation_object_get_excl_rcu(dma_buf->resv); + drm_atomic_set_fence_for_plane(state, fence); + } + + return 0; +} +EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb); + +/** + * drm_gem_fbdev_fb_create - Create a drm_framebuffer for fbdev emulation + * @dev: DRM device + * @sizes: fbdev size description + * @pitch_align: optional pitch alignment + * @obj: GEM object backing the framebuffer + * @funcs: vtable to be used for the new framebuffer object + * + * This function creates a framebuffer for use with fbdev emulation. + * + * Returns: + * Pointer to a drm_framebuffer on success or an error pointer on failure. + */ +struct drm_framebuffer * +drm_gem_fbdev_fb_create(struct drm_device *dev, + struct drm_fb_helper_surface_size *sizes, + unsigned int pitch_align, struct drm_gem_object *obj, + const struct drm_framebuffer_funcs *funcs) +{ + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = sizes->surface_width * + DIV_ROUND_UP(sizes->surface_bpp, 8); + if (pitch_align) + mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], + pitch_align); + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + if (obj->size < mode_cmd.pitches[0] * mode_cmd.height) + return ERR_PTR(-EINVAL); + + return drm_gem_fb_alloc(dev, &mode_cmd, &obj, 1, funcs); +} +EXPORT_SYMBOL(drm_gem_fbdev_fb_create); diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c index 1616af209bfc..c50534c923df 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c @@ -520,7 +520,7 @@ static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type, u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs) { unsigned long flags; - struct drm_device *dev = sender->dev; + struct drm_device *dev; int i; u32 gen_data_reg; int retry = MDFLD_DSI_READ_MAX_COUNT; @@ -530,6 +530,8 @@ static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type, return -EINVAL; } + dev = sender->dev; + /** * do reading. * 0) send out generic read request diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index f0139fa58d55..b58c988d9da0 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -23,6 +23,7 @@ #include <drm/drmP.h> #include <drm/drm_panel.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> #include "pl111_drm.h" @@ -274,7 +275,7 @@ void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state) { - return drm_fb_cma_prepare_fb(&pipe->plane, plane_state); + return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); } static const struct drm_simple_display_pipe_funcs pl111_display_funcs = { diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 0ea3ca823034..581c452cede1 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -66,6 +66,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> #include "pl111_drm.h" @@ -73,7 +74,7 @@ #define DRIVER_DESC "DRM module for PL111" static const struct drm_mode_config_funcs mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c index 1b39d3fb17f7..b439956a07f4 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tinydrm/st7586.c @@ -172,8 +172,8 @@ static const struct drm_framebuffer_funcs st7586_fb_funcs = { .dirty = st7586_fb_dirty, }; -void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state) +static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state) { struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index bfacb294d5c4..31421b6b586e 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -111,7 +111,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) * which is compatible with all known USB 2.0 era graphics chips and firmware, * but allows DisplayLink to increment those for any future incompatible chips */ -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {.idVendor = 0x17e9, .bInterfaceClass = 0xff, .bInterfaceSubClass = 0x00, .bInterfaceProtocol = 0x00, diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index dfe7554268f0..50c4959b5bd3 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -20,6 +20,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "vc4_drv.h" static void vc4_output_poll_changed(struct drm_device *dev) @@ -189,7 +190,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, mode_cmd = &mode_cmd_local; } - return drm_fb_cma_create(dev, file_priv, mode_cmd); + return drm_gem_fb_create(dev, file_priv, mode_cmd); } static const struct drm_mode_config_funcs vc4_mode_funcs = { diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 5244f059d23a..b6996ddb19d6 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -190,6 +190,13 @@ struct drm_framebuffer { * @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock. */ struct list_head filp_head; + /** + * @obj: GEM objects backing the framebuffer, one per plane (optional). + * + * This is used by the GEM framebuffer helpers, see e.g. + * drm_gem_fb_create(). + */ + struct drm_gem_object *obj[4]; }; #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) diff --git a/include/drm/drm_gem_framebuffer_helper.h b/include/drm/drm_gem_framebuffer_helper.h new file mode 100644 index 000000000000..db9cfa07235e --- /dev/null +++ b/include/drm/drm_gem_framebuffer_helper.h @@ -0,0 +1,37 @@ +#ifndef __DRM_GEM_FB_HELPER_H__ +#define __DRM_GEM_FB_HELPER_H__ + +struct drm_device; +struct drm_file; +struct drm_fb_helper_surface_size; +struct drm_framebuffer; +struct drm_framebuffer_funcs; +struct drm_gem_object; +struct drm_mode_fb_cmd2; +struct drm_plane; +struct drm_plane_state; + +struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb, + unsigned int plane); +void drm_gem_fb_destroy(struct drm_framebuffer *fb); +int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file, + unsigned int *handle); + +struct drm_framebuffer * +drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd, + const struct drm_framebuffer_funcs *funcs); +struct drm_framebuffer * +drm_gem_fb_create(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd); + +int drm_gem_fb_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state); + +struct drm_framebuffer * +drm_gem_fbdev_fb_create(struct drm_device *dev, + struct drm_fb_helper_surface_size *sizes, + unsigned int pitch_align, struct drm_gem_object *obj, + const struct drm_framebuffer_funcs *funcs); + +#endif |