diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fb.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 166 |
1 files changed, 54 insertions, 112 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 5bf4a1ac7f8..3733fe6723d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -33,7 +33,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_fb.h" -#include "exynos_drm_buf.h" #include "exynos_drm_gem.h" #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) @@ -42,15 +41,11 @@ * exynos specific framebuffer structure. * * @fb: drm framebuffer obejct. - * @exynos_gem_obj: exynos specific gem object containing a gem object. - * @buffer: pointer to exynos_drm_gem_buffer object. - * - contain the memory information to memory region allocated - * at default framebuffer creation. + * @exynos_gem_obj: array of exynos specific gem object containing a gem object. */ struct exynos_drm_fb { struct drm_framebuffer fb; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buffer; + struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; }; static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) @@ -61,13 +56,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) drm_framebuffer_cleanup(fb); - /* - * default framebuffer has no gem object so - * a buffer of the default framebuffer should be released at here. - */ - if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer) - exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer); - kfree(exynos_fb); exynos_fb = NULL; } @@ -81,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, DRM_DEBUG_KMS("%s\n", __FILE__); return drm_gem_handle_create(file_priv, - &exynos_fb->exynos_gem_obj->base, handle); + &exynos_fb->exynos_gem_obj[0]->base, handle); } static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, @@ -102,134 +90,88 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { .dirty = exynos_drm_fb_dirty, }; -static struct drm_framebuffer * -exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, - struct drm_mode_fb_cmd *mode_cmd) +struct drm_framebuffer * +exynos_drm_framebuffer_init(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) { struct exynos_drm_fb *exynos_fb; - struct drm_framebuffer *fb; - struct exynos_drm_gem_obj *exynos_gem_obj = NULL; - struct drm_gem_object *obj; - unsigned int size; int ret; - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode_cmd->pitch = max(mode_cmd->pitch, - mode_cmd->width * (mode_cmd->bpp >> 3)); - - DRM_LOG_KMS("drm fb create(%dx%d)\n", - mode_cmd->width, mode_cmd->height); - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); if (!exynos_fb) { - DRM_ERROR("failed to allocate exynos drm framebuffer.\n"); + DRM_ERROR("failed to allocate exynos drm framebuffer\n"); return ERR_PTR(-ENOMEM); } - fb = &exynos_fb->fb; - ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs); + ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { - DRM_ERROR("failed to initialize framebuffer.\n"); - goto err_init; + DRM_ERROR("failed to initialize framebuffer\n"); + return ERR_PTR(ret); } - DRM_LOG_KMS("create: fb id: %d\n", fb->base.id); + drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); + exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); - size = mode_cmd->pitch * mode_cmd->height; + return &exynos_fb->fb; +} - /* - * mode_cmd->handle could be NULL at booting time or - * with user request. if NULL, a new buffer or a gem object - * would be allocated. - */ - if (!mode_cmd->handle) { - if (!file_priv) { - struct exynos_drm_gem_buf *buffer; - - /* - * in case that file_priv is NULL, it allocates - * only buffer and this buffer would be used - * for default framebuffer. - */ - buffer = exynos_drm_buf_create(dev, size); - if (IS_ERR(buffer)) { - ret = PTR_ERR(buffer); - goto err_buffer; - } - - exynos_fb->buffer = buffer; - - DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n", - (unsigned long)buffer->dma_addr, size); - - goto out; - } else { - exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, - &mode_cmd->handle, - size); - if (IS_ERR(exynos_gem_obj)) { - ret = PTR_ERR(exynos_gem_obj); - goto err_buffer; - } - } - } else { - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - goto err_buffer; - } +static struct drm_framebuffer * +exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct drm_gem_object *obj; + struct drm_framebuffer *fb; + struct exynos_drm_fb *exynos_fb; + int nr; + int i; - exynos_gem_obj = to_exynos_gem_obj(obj); + DRM_DEBUG_KMS("%s\n", __FILE__); - drm_gem_object_unreference_unlocked(obj); + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) { + DRM_ERROR("failed to lookup gem object\n"); + return ERR_PTR(-ENOENT); } - /* - * if got a exynos_gem_obj from either a handle or - * a new creation then exynos_fb->exynos_gem_obj is NULL - * so that default framebuffer has no its own gem object, - * only its own buffer object. - */ - exynos_fb->buffer = exynos_gem_obj->buffer; - - DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n", - (unsigned long)exynos_fb->buffer->dma_addr, size, - (unsigned int)&exynos_gem_obj->base); + drm_gem_object_unreference_unlocked(obj); -out: - exynos_fb->exynos_gem_obj = exynos_gem_obj; + fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); + if (IS_ERR(fb)) + return fb; - drm_helper_mode_fill_fb_struct(fb, mode_cmd); + exynos_fb = to_exynos_fb(fb); + nr = exynos_drm_format_num_buffers(fb->pixel_format); - return fb; - -err_buffer: - drm_framebuffer_cleanup(fb); - -err_init: - kfree(exynos_fb); + for (i = 1; i < nr; i++) { + obj = drm_gem_object_lookup(dev, file_priv, + mode_cmd->handles[i]); + if (!obj) { + DRM_ERROR("failed to lookup gem object\n"); + exynos_drm_fb_destroy(fb); + return ERR_PTR(-ENOENT); + } - return ERR_PTR(ret); -} + drm_gem_object_unreference_unlocked(obj); -struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_mode_fb_cmd *mode_cmd) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); + exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); + } - return exynos_drm_fb_init(file_priv, dev, mode_cmd); + return fb; } -struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) +struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, + int index) { struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); struct exynos_drm_gem_buf *buffer; DRM_DEBUG_KMS("%s\n", __FILE__); - buffer = exynos_fb->buffer; + if (index >= MAX_FB_BUFFER) + return NULL; + + buffer = exynos_fb->exynos_gem_obj[index]->buffer; if (!buffer) return NULL; @@ -250,7 +192,7 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev) } static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { - .fb_create = exynos_drm_fb_create, + .fb_create = exynos_user_fb_create, .output_poll_changed = exynos_drm_output_poll_changed, }; |