Commit f2b816d7 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz

drm/core: Allow drivers allocate a subclass of struct drm_framebuffer

Allow allocating a specialized version of struct drm_framebuffer
by moving the actual fb allocation out of drm_gem_fb_create_with_funcs();
the respective functions names are adjusted to reflect that fact.
Please note, though, that standard size checks are performed on buffers,
so the drm_gem_fb_init_with_funcs() is useful for cases where those
standard size checks are appropriate or at least don't conflict the
checks to be performed in the specialized case.

Thanks to this change the drivers can call drm_gem_fb_init_with_funcs()
having allocated their special version of struct drm_framebuffer, exactly
the way the new version of drm_gem_fb_create_with_funcs() does.
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@collabora.com>
Reviewed-by: default avatarEmil Velikov <emil.velikov@collabora.com>
Reviewed-by: default avatarJames Qian Wang <james.qian.wang@arm.com>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20200311145541.29186-2-andrzej.p@collabora.com
parent 51b8479a
...@@ -54,19 +54,15 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb, ...@@ -54,19 +54,15 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
} }
EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj); EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
static struct drm_framebuffer * static int
drm_gem_fb_alloc(struct drm_device *dev, drm_gem_fb_init(struct drm_device *dev,
struct drm_framebuffer *fb,
const struct drm_mode_fb_cmd2 *mode_cmd, const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **obj, unsigned int num_planes, struct drm_gem_object **obj, unsigned int num_planes,
const struct drm_framebuffer_funcs *funcs) const struct drm_framebuffer_funcs *funcs)
{ {
struct drm_framebuffer *fb;
int ret, i; 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); drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
for (i = 0; i < num_planes; i++) for (i = 0; i < num_planes; i++)
...@@ -76,10 +72,9 @@ drm_gem_fb_alloc(struct drm_device *dev, ...@@ -76,10 +72,9 @@ drm_gem_fb_alloc(struct drm_device *dev,
if (ret) { if (ret) {
drm_err(dev, "Failed to init framebuffer: %d\n", ret); drm_err(dev, "Failed to init framebuffer: %d\n", ret);
kfree(fb); kfree(fb);
return ERR_PTR(ret);
} }
return fb; return ret;
} }
/** /**
...@@ -123,10 +118,13 @@ int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file, ...@@ -123,10 +118,13 @@ int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file,
EXPORT_SYMBOL(drm_gem_fb_create_handle); EXPORT_SYMBOL(drm_gem_fb_create_handle);
/** /**
* drm_gem_fb_create_with_funcs() - Helper function for the * drm_gem_fb_init_with_funcs() - Helper function for implementing
* &drm_mode_config_funcs.fb_create * &drm_mode_config_funcs.fb_create
* callback * callback in cases when the driver
* allocates a subclass of
* struct drm_framebuffer
* @dev: DRM device * @dev: DRM device
* @fb: framebuffer object
* @file: DRM file that holds the GEM handle(s) backing the framebuffer * @file: DRM file that holds the GEM handle(s) backing the framebuffer
* @mode_cmd: Metadata from the userspace framebuffer creation request * @mode_cmd: Metadata from the userspace framebuffer creation request
* @funcs: vtable to be used for the new framebuffer object * @funcs: vtable to be used for the new framebuffer object
...@@ -134,23 +132,26 @@ EXPORT_SYMBOL(drm_gem_fb_create_handle); ...@@ -134,23 +132,26 @@ EXPORT_SYMBOL(drm_gem_fb_create_handle);
* This function can be used to set &drm_framebuffer_funcs for drivers that need * This function can be used to set &drm_framebuffer_funcs for drivers that need
* custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to * custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to
* change &drm_framebuffer_funcs. The function does buffer size validation. * change &drm_framebuffer_funcs. The function does buffer size validation.
* The buffer size validation is for a general case, though, so users should
* pay attention to the checks being appropriate for them or, at least,
* non-conflicting.
* *
* Returns: * Returns:
* Pointer to a &drm_framebuffer on success or an error pointer on failure. * Zero or a negative error code.
*/ */
struct drm_framebuffer * int drm_gem_fb_init_with_funcs(struct drm_device *dev,
drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, struct drm_framebuffer *fb,
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_file *file,
const struct drm_framebuffer_funcs *funcs) const struct drm_mode_fb_cmd2 *mode_cmd,
const struct drm_framebuffer_funcs *funcs)
{ {
const struct drm_format_info *info; const struct drm_format_info *info;
struct drm_gem_object *objs[4]; struct drm_gem_object *objs[4];
struct drm_framebuffer *fb;
int ret, i; int ret, i;
info = drm_get_format_info(dev, mode_cmd); info = drm_get_format_info(dev, mode_cmd);
if (!info) if (!info)
return ERR_PTR(-EINVAL); return -EINVAL;
for (i = 0; i < info->num_planes; i++) { for (i = 0; i < info->num_planes; i++) {
unsigned int width = mode_cmd->width / (i ? info->hsub : 1); unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
...@@ -175,19 +176,55 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, ...@@ -175,19 +176,55 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
} }
} }
fb = drm_gem_fb_alloc(dev, mode_cmd, objs, i, funcs); ret = drm_gem_fb_init(dev, fb, mode_cmd, objs, i, funcs);
if (IS_ERR(fb)) { if (ret)
ret = PTR_ERR(fb);
goto err_gem_object_put; goto err_gem_object_put;
}
return fb; return 0;
err_gem_object_put: err_gem_object_put:
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
drm_gem_object_put_unlocked(objs[i]); drm_gem_object_put_unlocked(objs[i]);
return ERR_PTR(ret); return ret;
}
EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs);
/**
* drm_gem_fb_create_with_funcs() - Helper function for the
* &drm_mode_config_funcs.fb_create
* callback
* @dev: DRM device
* @file: DRM file that holds the GEM handle(s) backing the framebuffer
* @mode_cmd: Metadata from the userspace framebuffer creation request
* @funcs: vtable to be used for the new framebuffer object
*
* This function can be used to set &drm_framebuffer_funcs for drivers that need
* custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to
* change &drm_framebuffer_funcs. The function does buffer size validation.
*
* Returns:
* Pointer to a &drm_framebuffer on success or an error pointer on failure.
*/
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 *fb;
int ret;
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb)
return ERR_PTR(-ENOMEM);
ret = drm_gem_fb_init_with_funcs(dev, fb, file, mode_cmd, funcs);
if (ret) {
kfree(fb);
return ERR_PTR(ret);
}
return fb;
} }
EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_funcs); EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_funcs);
......
...@@ -18,6 +18,11 @@ void drm_gem_fb_destroy(struct drm_framebuffer *fb); ...@@ -18,6 +18,11 @@ void drm_gem_fb_destroy(struct drm_framebuffer *fb);
int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file, int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file,
unsigned int *handle); unsigned int *handle);
int drm_gem_fb_init_with_funcs(struct drm_device *dev,
struct drm_framebuffer *fb,
struct drm_file *file,
const struct drm_mode_fb_cmd2 *mode_cmd,
const struct drm_framebuffer_funcs *funcs);
struct drm_framebuffer * struct drm_framebuffer *
drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, 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_mode_fb_cmd2 *mode_cmd,
......
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