diff options
| author | Rongrong Zou <zourongrong@gmail.com> | 2016-11-16 20:52:37 +0800 |
|---|---|---|
| committer | Rongrong Zou <zourongrong@gmail.com> | 2016-11-17 15:26:25 +0800 |
| commit | d1667b86795a6a1f904c5c30e38d6f8f3c8dfa64 (patch) | |
| tree | b100f49ceab3ebde223e96c58e0d22eb79e5b763 /drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | |
| parent | e4daebc77e7b34fc7442ff78a3c3410376f1bcba (diff) | |
drm/hisilicon/hibmc: Add support for frame buffer
Add support for fbdev and kms fb management.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Xinliang Liu <xinliang.liu@linaro.org>
Acked-by: Sean Paul <seanpaul@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c')
| -rw-r--r-- | drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 036d3ac06e54..3ff65f4f5620 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -16,6 +16,7 @@ * */ +#include <drm/drm_atomic_helper.h> #include <ttm/ttm_page_alloc.h> #include "hibmc_drm_drv.h" @@ -483,3 +484,69 @@ int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, drm_gem_object_unreference_unlocked(obj); return 0; } + +static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb) +{ + struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb); + + drm_gem_object_unreference_unlocked(hibmc_fb->obj); + drm_framebuffer_cleanup(fb); + kfree(hibmc_fb); +} + +static const struct drm_framebuffer_funcs hibmc_fb_funcs = { + .destroy = hibmc_user_framebuffer_destroy, +}; + +struct hibmc_framebuffer * +hibmc_framebuffer_init(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) +{ + struct hibmc_framebuffer *hibmc_fb; + int ret; + + hibmc_fb = kzalloc(sizeof(*hibmc_fb), GFP_KERNEL); + if (!hibmc_fb) { + DRM_ERROR("failed to allocate hibmc_fb\n"); + return ERR_PTR(-ENOMEM); + } + + drm_helper_mode_fill_fb_struct(&hibmc_fb->fb, mode_cmd); + hibmc_fb->obj = obj; + ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs); + if (ret) { + DRM_ERROR("drm_framebuffer_init failed: %d\n", ret); + kfree(hibmc_fb); + return ERR_PTR(ret); + } + + return hibmc_fb; +} + +static struct drm_framebuffer * +hibmc_user_framebuffer_create(struct drm_device *dev, + struct drm_file *filp, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct drm_gem_object *obj; + struct hibmc_framebuffer *hibmc_fb; + + DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n", + mode_cmd->width, mode_cmd->height, + (mode_cmd->pixel_format) & 0xff, + (mode_cmd->pixel_format >> 8) & 0xff, + (mode_cmd->pixel_format >> 16) & 0xff, + (mode_cmd->pixel_format >> 24) & 0xff); + + obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); + if (!obj) + return ERR_PTR(-ENOENT); + + hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj); + if (IS_ERR(hibmc_fb)) { + drm_gem_object_unreference_unlocked(obj); + return ERR_PTR((long)hibmc_fb); + } + return &hibmc_fb->fb; +} |
