Skip to content

Commit

Permalink
drm/exynos: remove buffer creation of fbdev from drm framebuffer crea…
Browse files Browse the repository at this point in the history
…tion

The fbdev fb and the user fb is created from same function -
exynos_drm_fb_create, but this function creates not only drm framebuffer
but buffer of fbdev. Remove it because it complicates codes and use
exynos_drm_gem_create() than exynos_drm_buf_create() to create buffer of
fbdev, it give better consistency of codes and more clear
implementation.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
  • Loading branch information
Joonyoung Shim authored and Inki Dae committed Dec 29, 2011
1 parent 2364839 commit e1533c0
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 133 deletions.
136 changes: 27 additions & 109 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,10 @@
*
* @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.
*/
struct exynos_drm_fb {
struct drm_framebuffer fb;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct exynos_drm_gem_buf *buffer;
};

static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
Expand All @@ -61,13 +57,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;
}
Expand Down Expand Up @@ -102,120 +91,49 @@ 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_cmd2 *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__);

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);

size = mode_cmd->pitches[0] * mode_cmd->height;

/*
* mode_cmd->handles[0] 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->handles[0]) {
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 (!buffer) {
ret = -ENOMEM;
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, 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->handles[0]);
if (!obj) {
DRM_ERROR("failed to lookup gem object.\n");
goto err_buffer;
}

exynos_gem_obj = to_exynos_gem_obj(obj);

drm_gem_object_unreference_unlocked(obj);
}

/*
* 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);

out:
exynos_fb->exynos_gem_obj = exynos_gem_obj;

drm_helper_mode_fill_fb_struct(fb, mode_cmd);
drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj = to_exynos_gem_obj(obj);

return fb;

err_buffer:
drm_framebuffer_cleanup(fb);

err_init:
kfree(exynos_fb);

return ERR_PTR(ret);
return &exynos_fb->fb;
}

struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
struct drm_file *file_priv,
struct drm_mode_fb_cmd2 *mode_cmd)
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;

DRM_DEBUG_KMS("%s\n", __FILE__);

return exynos_drm_fb_init(file_priv, dev, mode_cmd);
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);
}

drm_gem_object_unreference_unlocked(obj);

return exynos_drm_framebuffer_init(dev, mode_cmd, obj);
}

struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
Expand All @@ -225,7 +143,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)

DRM_DEBUG_KMS("%s\n", __FILE__);

buffer = exynos_fb->buffer;
buffer = exynos_fb->exynos_gem_obj->buffer;
if (!buffer)
return NULL;

Expand All @@ -246,7 +164,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,
};

Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/exynos/exynos_drm_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
#ifndef _EXYNOS_DRM_FB_H_
#define _EXYNOS_DRM_FB_H

struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
struct drm_file *filp,
struct drm_mode_fb_cmd2 *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);

void exynos_drm_mode_config_init(struct drm_device *dev);

Expand Down
62 changes: 41 additions & 21 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
drm_fb_helper)

struct exynos_drm_fbdev {
struct drm_fb_helper drm_fb_helper;
struct drm_framebuffer *fb;
struct drm_fb_helper drm_fb_helper;
struct exynos_drm_gem_obj *exynos_gem_obj;
};

static int exynos_drm_fbdev_set_par(struct fb_info *info)
Expand Down Expand Up @@ -90,15 +90,12 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
{
struct fb_info *fbi = helper->fbdev;
struct drm_device *dev = helper->dev;
struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
struct exynos_drm_gem_buf *buffer;
unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
unsigned long offset;

DRM_DEBUG_KMS("%s\n", __FILE__);

exynos_fb->fb = fb;

drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);

Expand All @@ -124,10 +121,12 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_device *dev = helper->dev;
struct fb_info *fbi;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct platform_device *pdev = dev->platformdev;
unsigned long size;
int ret;

DRM_DEBUG_KMS("%s\n", __FILE__);
Expand All @@ -151,14 +150,23 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
goto out;
}

exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
if (IS_ERR_OR_NULL(exynos_fbdev->fb)) {
size = mode_cmd.pitches[0] * mode_cmd.height;
exynos_gem_obj = exynos_drm_gem_create(dev, size);
if (IS_ERR(exynos_gem_obj)) {
ret = PTR_ERR(exynos_gem_obj);
goto out;
}

exynos_fbdev->exynos_gem_obj = exynos_gem_obj;

helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
&exynos_gem_obj->base);
if (IS_ERR_OR_NULL(helper->fb)) {
DRM_ERROR("failed to create drm framebuffer.\n");
ret = PTR_ERR(exynos_fbdev->fb);
ret = PTR_ERR(helper->fb);
goto out;
}

helper->fb = exynos_fbdev->fb;
helper->fbdev = fbi;

fbi->par = helper;
Expand All @@ -172,8 +180,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
}

ret = exynos_drm_fbdev_update(helper, helper->fb);
if (ret < 0)
if (ret < 0) {
fb_dealloc_cmap(&fbi->cmap);
goto out;
}

/*
* if failed, all resources allocated above would be released by
Expand Down Expand Up @@ -206,16 +216,13 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
{
struct drm_device *dev = helper->dev;
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
struct drm_framebuffer *fb = exynos_fbdev->fb;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_framebuffer *fb = helper->fb;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
unsigned long size;

DRM_DEBUG_KMS("%s\n", __FILE__);

if (helper->fb != fb) {
DRM_ERROR("drm framebuffer is different\n");
return -EINVAL;
}

if (exynos_drm_fbdev_is_samefb(fb, sizes))
return 0;

Expand All @@ -225,16 +232,26 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);

if (exynos_fbdev->exynos_gem_obj)
exynos_drm_gem_destroy(exynos_fbdev->exynos_gem_obj);

if (fb->funcs->destroy)
fb->funcs->destroy(fb);

exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
if (IS_ERR(exynos_fbdev->fb)) {
DRM_ERROR("failed to allocate fb.\n");
return PTR_ERR(exynos_fbdev->fb);
size = mode_cmd.pitches[0] * mode_cmd.height;
exynos_gem_obj = exynos_drm_gem_create(dev, size);
if (IS_ERR(exynos_gem_obj))
return PTR_ERR(exynos_gem_obj);

exynos_fbdev->exynos_gem_obj = exynos_gem_obj;

helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
&exynos_gem_obj->base);
if (IS_ERR_OR_NULL(helper->fb)) {
DRM_ERROR("failed to create drm framebuffer.\n");
return PTR_ERR(helper->fb);
}

helper->fb = exynos_fbdev->fb;
return exynos_drm_fbdev_update(helper, helper->fb);
}

Expand Down Expand Up @@ -368,6 +385,9 @@ void exynos_drm_fbdev_fini(struct drm_device *dev)

fbdev = to_exynos_fbdev(private->fb_helper);

if (fbdev->exynos_gem_obj)
exynos_drm_gem_destroy(fbdev->exynos_gem_obj);

exynos_drm_fbdev_destroy(dev, private->fb_helper);
kfree(fbdev);
private->fb_helper = NULL;
Expand Down

0 comments on commit e1533c0

Please sign in to comment.