Commit 54e0aa64 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-2017-08-18' of git://anongit.freedesktop.org/git/drm-misc into drm-next

Cross-subsystem Changes:
- Add tinydrm to MAINTAINERS using -misc tree and Noralf as maintainer (Noralf)

Core Changes:
- Finish dumb_mmap_offset cleanup by removing gem_cma_dumb_map_offset() (Noralf)
- Add gem_framebuffer helper to facilitate removal of fb_cma cargo cult (Noralf)

Driver Changes:
- Various trivial patches

Cc: Noralf Trønnes <noralf@tronnes.org>

* tag 'drm-misc-next-2017-08-18' of git://anongit.freedesktop.org/git/drm-misc:
  drm: udl: constify usb_device_id
  drm/gma500: fix potential NULL pointer dereference dereference
  drm/tinydrm: make function st7586_pipe_enable static
  MAINTAINERS: Add drm/tinydrm maintainer entry
  drm/vc4: Use drm_gem_fb_create()
  drm/pl111: Use drm_gem_fb_create() and drm_gem_fb_prepare_fb()
  drm/fb-cma-helper: Use drm_gem_framebuffer_helper
  drm: Add GEM backed framebuffer library
parents 8824c751 0e8841ec
...@@ -296,3 +296,12 @@ Auxiliary Modeset Helpers ...@@ -296,3 +296,12 @@ Auxiliary Modeset Helpers
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
:export: :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:
...@@ -4634,6 +4634,14 @@ F: drivers/gpu/drm/panel/ ...@@ -4634,6 +4634,14 @@ F: drivers/gpu/drm/panel/
F: include/drm/drm_panel.h F: include/drm/drm_panel.h
F: Documentation/devicetree/bindings/display/panel/ 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 DSBR100 USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com> M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
......
...@@ -33,7 +33,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ ...@@ -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_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drm_simple_kms_helper.o drm_modeset_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_PANEL_BRIDGE) += bridge/panel.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
......
...@@ -18,27 +18,17 @@ ...@@ -18,27 +18,17 @@
*/ */
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.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_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_cma_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/module.h>
#include <linux/reservation.h>
#define DEFAULT_FBDEFIO_DELAY_MS 50 #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_fbdev_cma {
struct drm_fb_helper fb_helper; struct drm_fb_helper fb_helper;
struct drm_fb_cma *fb;
const struct drm_framebuffer_funcs *fb_funcs; 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) ...@@ -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); 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) void drm_fb_cma_destroy(struct drm_framebuffer *fb)
{ {
struct drm_fb_cma *fb_cma = to_fb_cma(fb); drm_gem_fb_destroy(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);
} }
EXPORT_SYMBOL(drm_fb_cma_destroy); EXPORT_SYMBOL(drm_fb_cma_destroy);
int drm_fb_cma_create_handle(struct drm_framebuffer *fb, int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
struct drm_file *file_priv, unsigned int *handle) struct drm_file *file_priv, unsigned int *handle)
{ {
struct drm_fb_cma *fb_cma = to_fb_cma(fb); return drm_gem_fb_create_handle(fb, file_priv, handle);
return drm_gem_handle_create(file_priv,
&fb_cma->obj[0]->base, handle);
} }
EXPORT_SYMBOL(drm_fb_cma_create_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_fb_cma_create_with_funcs() - helper function for the
* &drm_mode_config_funcs.fb_create * &drm_mode_config_funcs.fb_create
...@@ -170,53 +110,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, ...@@ -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, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd,
const struct drm_framebuffer_funcs *funcs) const struct drm_framebuffer_funcs *funcs)
{ {
const struct drm_format_info *info; return drm_gem_fb_create_with_funcs(dev, file_priv, mode_cmd, funcs);
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);
} }
EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs); EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs);
...@@ -233,8 +127,7 @@ 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_framebuffer *drm_fb_cma_create(struct drm_device *dev,
struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) 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, return drm_gem_fb_create(dev, file_priv, mode_cmd);
&drm_fb_cma_funcs);
} }
EXPORT_SYMBOL_GPL(drm_fb_cma_create); EXPORT_SYMBOL_GPL(drm_fb_cma_create);
...@@ -250,12 +143,13 @@ 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, struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane) 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 NULL;
return fb_cma->obj[plane]; return to_drm_gem_cma_obj(gem);
} }
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); 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, ...@@ -272,13 +166,14 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
struct drm_plane_state *state, struct drm_plane_state *state,
unsigned int plane) unsigned int plane)
{ {
struct drm_fb_cma *fb_cma = to_fb_cma(fb); struct drm_gem_cma_object *obj;
dma_addr_t paddr; dma_addr_t paddr;
if (plane >= 4) obj = drm_fb_cma_get_gem_obj(fb, plane);
if (!obj)
return 0; 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->format->cpp[plane] * (state->src_x >> 16);
paddr += fb->pitches[plane] * (state->src_y >> 16); paddr += fb->pitches[plane] * (state->src_y >> 16);
...@@ -302,26 +197,13 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); ...@@ -302,26 +197,13 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
int drm_fb_cma_prepare_fb(struct drm_plane *plane, int drm_fb_cma_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct dma_buf *dma_buf; return drm_gem_fb_prepare_fb(plane, state);
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;
} }
EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb); EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) 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; int i;
seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, 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) ...@@ -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++) { for (i = 0; i < fb->format->num_planes; i++) {
seq_printf(m, " %d: offset=%d pitch=%d, obj: ", seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
i, fb->offsets[i], fb->pitches[i]); 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, ...@@ -431,7 +313,6 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes) struct drm_fb_helper_surface_size *sizes)
{ {
struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper); 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_device *dev = helper->dev;
struct drm_gem_cma_object *obj; struct drm_gem_cma_object *obj;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
...@@ -446,14 +327,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -446,14 +327,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
sizes->surface_bpp); sizes->surface_bpp);
bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
size = sizes->surface_width * sizes->surface_height * bytes_per_pixel;
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;
obj = drm_gem_cma_create(dev, size); obj = drm_gem_cma_create(dev, size);
if (IS_ERR(obj)) if (IS_ERR(obj))
return -ENOMEM; return -ENOMEM;
...@@ -464,15 +338,14 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -464,15 +338,14 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
goto err_gem_free_object; goto err_gem_free_object;
} }
fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1, fb = drm_gem_fbdev_fb_create(dev, sizes, 0, &obj->base,
fbdev_cma->fb_funcs); fbdev_cma->fb_funcs);
if (IS_ERR(fbdev_cma->fb)) { if (IS_ERR(fb)) {
dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); 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; goto err_fb_info_destroy;
} }
fb = &fbdev_cma->fb->fb;
helper->fb = fb; helper->fb = fb;
fbi->par = helper; fbi->par = helper;
...@@ -500,7 +373,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -500,7 +373,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
return 0; return 0;
err_cma_destroy: err_cma_destroy:
drm_framebuffer_remove(&fbdev_cma->fb->fb); drm_framebuffer_remove(fb);
err_fb_info_destroy: err_fb_info_destroy:
drm_fb_helper_fini(helper); drm_fb_helper_fini(helper);
err_gem_free_object: err_gem_free_object:
...@@ -570,6 +443,11 @@ struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, ...@@ -570,6 +443,11 @@ struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
} }
EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs); 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 * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
* @dev: DRM device * @dev: DRM device
...@@ -597,8 +475,8 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) ...@@ -597,8 +475,8 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
if (fbdev_cma->fb_helper.fbdev) if (fbdev_cma->fb_helper.fbdev)
drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
if (fbdev_cma->fb) if (fbdev_cma->fb_helper.fb)
drm_framebuffer_remove(&fbdev_cma->fb->fb); drm_framebuffer_remove(fbdev_cma->fb_helper.fb);
drm_fb_helper_fini(&fbdev_cma->fb_helper); drm_fb_helper_fini(&fbdev_cma->fb_helper);
kfree(fbdev_cma); kfree(fbdev_cma);
......
/*
* 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);
...@@ -520,7 +520,7 @@ static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ...@@ -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) u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
{ {
unsigned long flags; unsigned long flags;
struct drm_device *dev = sender->dev; struct drm_device *dev;
int i; int i;
u32 gen_data_reg; u32 gen_data_reg;
int retry = MDFLD_DSI_READ_MAX_COUNT; 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, ...@@ -530,6 +530,8 @@ static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
return -EINVAL; return -EINVAL;
} }
dev = sender->dev;
/** /**
* do reading. * do reading.
* 0) send out generic read request * 0) send out generic read request
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include "pl111_drm.h" #include "pl111_drm.h"
...@@ -274,7 +275,7 @@ void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) ...@@ -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, static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state) 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 = { static const struct drm_simple_display_pipe_funcs pl111_display_funcs = {
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include "pl111_drm.h" #include "pl111_drm.h"
...@@ -73,7 +74,7 @@ ...@@ -73,7 +74,7 @@
#define DRIVER_DESC "DRM module for PL111" #define DRIVER_DESC "DRM module for PL111"
static const struct drm_mode_config_funcs mode_config_funcs = { 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_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
......
...@@ -172,7 +172,7 @@ static const struct drm_framebuffer_funcs st7586_fb_funcs = { ...@@ -172,7 +172,7 @@ static const struct drm_framebuffer_funcs st7586_fb_funcs = {
.dirty = st7586_fb_dirty, .dirty = st7586_fb_dirty,
}; };
void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state) struct drm_crtc_state *crtc_state)
{ {
struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
......
...@@ -111,7 +111,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) ...@@ -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, * 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 * 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, {.idVendor = 0x17e9, .bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00, .bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00, .bInterfaceProtocol = 0x00,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include "vc4_drv.h" #include "vc4_drv.h"
static void vc4_output_poll_changed(struct drm_device *dev) 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, ...@@ -189,7 +190,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
mode_cmd = &mode_cmd_local; 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 = { static const struct drm_mode_config_funcs vc4_mode_funcs = {
......
...@@ -190,6 +190,13 @@ struct drm_framebuffer { ...@@ -190,6 +190,13 @@ struct drm_framebuffer {
* @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock. * @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock.
*/ */
struct list_head filp_head; 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) #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
......
#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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment