Commit b8017d6c authored by Archit Taneja's avatar Archit Taneja Committed by Daniel Vetter

drm/fb_helper: Add drm_fb_helper functions to manage fb_info creation

Every drm driver calls framebuffer_alloc, fb_alloc_cmap,
unregister_framebuffer, fb_dealloc_cmap and framebuffer_release in
order to emulate fbdev support.

Create drm_fb_helper functions that perform the above operations.

This is part of an effort to prevent drm drivers from calling fbdev
functions directly. It also removes repetitive code from drivers.

There are some drivers that call alloc_apertures after framebuffer_alloc
and some that don't. Make the helper always call alloc_apertures. This
would make certain drivers allocate memory for apertures but not use
them. Since it's a small amount of memory, it shouldn't be an issue.

v2:
- Added kerneldocs
- Added a check for non-NULL fb_helper before proceeding. This will
  make the helpers work when we have a module param for fbdev emulation
Signed-off-by: default avatarArchit Taneja <architt@codeaurora.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent c201d00f
...@@ -654,6 +654,86 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -654,6 +654,86 @@ int drm_fb_helper_init(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_fb_helper_init); EXPORT_SYMBOL(drm_fb_helper_init);
/**
* drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to alloc fb_info and the members cmap and apertures. Called
* by the driver within the fb_probe fb_helper callback function.
*
* RETURNS:
* fb_info pointer if things went okay, pointer containing error code
* otherwise
*/
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
{
struct device *dev = fb_helper->dev->dev;
struct fb_info *info;
int ret;
info = framebuffer_alloc(0, dev);
if (!info)
return ERR_PTR(-ENOMEM);
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret)
goto err_release;
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto err_free_cmap;
}
fb_helper->fbdev = info;
return info;
err_free_cmap:
fb_dealloc_cmap(&info->cmap);
err_release:
framebuffer_release(info);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
/**
* drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
* @fb_helper: driver-allocated fbdev helper
*
* A wrapper around unregister_framebuffer, to release the fb_info
* framebuffer device
*/
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
{
if (fb_helper && fb_helper->fbdev)
unregister_framebuffer(fb_helper->fbdev);
}
EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
/**
* drm_fb_helper_release_fbi - dealloc fb_info and its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to free memory taken by fb_info and the members cmap and
* apertures
*/
void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
{
if (fb_helper) {
struct fb_info *info = fb_helper->fbdev;
if (info) {
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
fb_helper->fbdev = NULL;
}
}
EXPORT_SYMBOL(drm_fb_helper_release_fbi);
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{ {
if (!list_empty(&fb_helper->kernel_fb_list)) { if (!list_empty(&fb_helper->kernel_fb_list)) {
......
...@@ -136,6 +136,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, ...@@ -136,6 +136,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct fb_info *info); struct fb_info *info);
bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper);
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
uint32_t fb_width, uint32_t fb_height); uint32_t fb_width, uint32_t fb_height);
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
......
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