Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/daeinki/drm-exynos into drm-next

   This is a last pull request, which includes two g2d patches
   I missed, and more cleanup series of Exynos drm driver.

   The cleanup series makes Exynos drm driver more simple,
   and removes unnecessary codes, and considers multiple plane format
   of framebuffer. I hope this not to be late.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: remove buf_cnt from struct exynos_drm_fb
  drm/exynos: remove exynos_drm_fb_get_buf_cnt()
  drm/exynos: cleanup exynos_user_fb_create()
  drm/exynos: update exynos_drm_framebuffer_init() for multiple buffers
  drm/exynos: cleanup to get gem object for fb
  drm/exynos: update fb_info via only one function
  drm/exynos: cleanup exynos_drm_fbdev_update()
  drm/exynos: s/exynos_gem_obj/obj in exynos_drm_fbdev.c
  drm/exynos: remove exynos_drm_fb_set_buf_cnt()
  drm/exynos: remove superfluous checks in g2d_check_reg_offset()
  drm/exynos: fix size check in g2d_check_buf_desc_is_valid()
  • Loading branch information
Dave Airlie committed Sep 4, 2015
2 parents 9949558 + c305857 commit 55cdb31
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 156 deletions.
115 changes: 33 additions & 82 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
#include "exynos_drm_crtc.h"

Expand All @@ -33,12 +32,10 @@
* exynos specific framebuffer structure.
*
* @fb: drm framebuffer obejct.
* @buf_cnt: a buffer count to drm framebuffer.
* @exynos_gem_obj: array of exynos specific gem object containing a gem object.
*/
struct exynos_drm_fb {
struct drm_framebuffer fb;
unsigned int buf_cnt;
struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
};

Expand Down Expand Up @@ -98,10 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);

/* This fb should have only one gem object. */
if (WARN_ON(exynos_fb->buf_cnt != 1))
return -EINVAL;

return drm_gem_handle_create(file_priv,
&exynos_fb->exynos_gem_obj[0]->base, handle);
}
Expand All @@ -122,119 +115,77 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
.dirty = exynos_drm_fb_dirty,
};

void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
unsigned int cnt)
{
struct exynos_drm_fb *exynos_fb;

exynos_fb = to_exynos_fb(fb);

exynos_fb->buf_cnt = cnt;
}

unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
{
struct exynos_drm_fb *exynos_fb;

exynos_fb = to_exynos_fb(fb);

return exynos_fb->buf_cnt;
}

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_gem_obj **gem_obj,
int count)
{
struct exynos_drm_fb *exynos_fb;
struct exynos_drm_gem_obj *exynos_gem_obj;
int i;
int ret;

exynos_gem_obj = to_exynos_gem_obj(obj);

ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0)
return ERR_PTR(ret);

exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb)
return ERR_PTR(-ENOMEM);

for (i = 0; i < count; i++) {
ret = check_fb_gem_memory_type(dev, gem_obj[i]);
if (ret < 0)
goto err;

exynos_fb->exynos_gem_obj[i] = gem_obj[i];
}

drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;

ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
if (ret) {
kfree(exynos_fb);
if (ret < 0) {
DRM_ERROR("failed to initialize framebuffer\n");
return ERR_PTR(ret);
goto err;
}

return &exynos_fb->fb;

err:
kfree(exynos_fb);
return ERR_PTR(ret);
}

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 exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER];
struct drm_gem_object *obj;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct exynos_drm_fb *exynos_fb;
int i, ret;

exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb)
return ERR_PTR(-ENOMEM);

obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!obj) {
DRM_ERROR("failed to lookup gem object\n");
ret = -ENOENT;
goto err_free;
}

drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
exynos_fb->buf_cnt = drm_format_num_planes(mode_cmd->pixel_format);

DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
struct drm_framebuffer *fb;
int i;
int ret;

for (i = 1; i < exynos_fb->buf_cnt; i++) {
for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
obj = drm_gem_object_lookup(dev, file_priv,
mode_cmd->handles[i]);
mode_cmd->handles[i]);
if (!obj) {
DRM_ERROR("failed to lookup gem object\n");
ret = -ENOENT;
exynos_fb->buf_cnt = i;
goto err_unreference;
goto err;
}

exynos_gem_obj = to_exynos_gem_obj(obj);
exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;

ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0)
goto err_unreference;
gem_objs[i] = to_exynos_gem_obj(obj);
}

ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
if (ret) {
DRM_ERROR("failed to init framebuffer.\n");
goto err_unreference;
fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i);
if (IS_ERR(fb)) {
ret = PTR_ERR(fb);
goto err;
}

return &exynos_fb->fb;
return fb;

err_unreference:
for (i = 0; i < exynos_fb->buf_cnt; i++) {
struct drm_gem_object *obj;
err:
while (i--)
drm_gem_object_unreference_unlocked(&gem_objs[i]->base);

obj = &exynos_fb->exynos_gem_obj[i]->base;
if (obj)
drm_gem_object_unreference_unlocked(obj);
}
err_free:
kfree(exynos_fb);
return ERR_PTR(ret);
}

Expand Down
12 changes: 4 additions & 8 deletions drivers/gpu/drm/exynos/exynos_drm_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,18 @@
#ifndef _EXYNOS_DRM_FB_H_
#define _EXYNOS_DRM_FB_H

#include "exynos_drm_gem.h"

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_gem_obj **gem_obj,
int count);

/* get gem object of a drm framebuffer */
struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
int index);

void exynos_drm_mode_config_init(struct drm_device *dev);

/* set a buffer count to drm framebuffer. */
void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
unsigned int cnt);

/* get a buffer count to drm framebuffer. */
unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb);

#endif
78 changes: 31 additions & 47 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"

#define MAX_CONNECTOR 4
Expand All @@ -32,15 +31,15 @@

struct exynos_drm_fbdev {
struct drm_fb_helper drm_fb_helper;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct exynos_drm_gem_obj *obj;
};

static int exynos_drm_fb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct drm_fb_helper *helper = info->par;
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper);
struct exynos_drm_gem_obj *obj = exynos_fbd->exynos_gem_obj;
struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
unsigned long vm_size;
int ret;

Expand Down Expand Up @@ -75,37 +74,38 @@ static struct fb_ops exynos_drm_fb_ops = {
};

static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes,
struct drm_framebuffer *fb)
struct drm_fb_helper_surface_size *sizes,
struct exynos_drm_gem_obj *obj)
{
struct fb_info *fbi = helper->fbdev;
struct exynos_drm_gem_obj *obj;
struct fb_info *fbi;
struct drm_framebuffer *fb = helper->fb;
unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
unsigned int nr_pages;
unsigned long offset;

fbi = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(fbi)) {
DRM_ERROR("failed to allocate fb info.\n");
return PTR_ERR(fbi);
}

fbi->par = helper;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &exynos_drm_fb_ops;

drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);

/* RGB formats use only one buffer */
obj = exynos_drm_fb_gem_obj(fb, 0);
if (!obj) {
DRM_DEBUG_KMS("gem object is null.\n");
return -EFAULT;
}

nr_pages = obj->size >> PAGE_SHIFT;

obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
if (!obj->kvaddr) {
DRM_ERROR("failed to map pages to kernel space.\n");
drm_fb_helper_release_fbi(helper);
return -EIO;
}

/* buffer count to framebuffer always is 1 at booting time. */
exynos_drm_fb_set_buf_cnt(fb, 1);

offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
offset += fbi->var.yoffset * fb->pitches[0];

Expand All @@ -120,9 +120,8 @@ 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 exynos_drm_gem_obj *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;
Expand All @@ -140,47 +139,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,

mutex_lock(&dev->struct_mutex);

fbi = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(fbi)) {
DRM_ERROR("failed to allocate fb info.\n");
ret = PTR_ERR(fbi);
goto out;
}

size = mode_cmd.pitches[0] * mode_cmd.height;

exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
/*
* If physically contiguous memory allocation fails and if IOMMU is
* supported then try to get buffer from non physically contiguous
* memory area.
*/
if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) {
if (IS_ERR(obj) && is_drm_iommu_supported(dev)) {
dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
size);
obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size);
}

if (IS_ERR(exynos_gem_obj)) {
ret = PTR_ERR(exynos_gem_obj);
goto err_release_fbi;
if (IS_ERR(obj)) {
ret = PTR_ERR(obj);
goto out;
}

exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
exynos_fbdev->obj = obj;

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

fbi->par = helper;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &exynos_drm_fb_ops;

ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
ret = exynos_drm_fbdev_update(helper, sizes, obj);
if (ret < 0)
goto err_destroy_framebuffer;

Expand All @@ -190,9 +176,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
err_destroy_framebuffer:
drm_framebuffer_cleanup(helper->fb);
err_destroy_gem:
exynos_drm_gem_destroy(exynos_gem_obj);
err_release_fbi:
drm_fb_helper_release_fbi(helper);
exynos_drm_gem_destroy(obj);

/*
* if failed, all resources allocated above would be released by
Expand Down Expand Up @@ -285,11 +269,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
struct drm_fb_helper *fb_helper)
{
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
struct drm_framebuffer *fb;

if (exynos_gem_obj->kvaddr)
vunmap(exynos_gem_obj->kvaddr);
if (obj->kvaddr)
vunmap(obj->kvaddr);

/* release drm framebuffer and real buffer */
if (fb_helper->fb && fb_helper->fb->funcs) {
Expand Down
Loading

0 comments on commit 55cdb31

Please sign in to comment.