Commit 55cdb314 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/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()
parents 99495589 c3058579
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
...@@ -33,12 +32,10 @@ ...@@ -33,12 +32,10 @@
* exynos specific framebuffer structure. * exynos specific framebuffer structure.
* *
* @fb: drm framebuffer obejct. * @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. * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
*/ */
struct exynos_drm_fb { struct exynos_drm_fb {
struct drm_framebuffer fb; struct drm_framebuffer fb;
unsigned int buf_cnt;
struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
}; };
...@@ -98,10 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, ...@@ -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); 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, return drm_gem_handle_create(file_priv,
&exynos_fb->exynos_gem_obj[0]->base, handle); &exynos_fb->exynos_gem_obj[0]->base, handle);
} }
...@@ -122,119 +115,77 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { ...@@ -122,119 +115,77 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
.dirty = exynos_drm_fb_dirty, .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 * struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev, exynos_drm_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd, 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_fb *exynos_fb;
struct exynos_drm_gem_obj *exynos_gem_obj; int i;
int ret; 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); exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) if (!exynos_fb)
return ERR_PTR(-ENOMEM); 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); 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); ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
if (ret) { if (ret < 0) {
kfree(exynos_fb);
DRM_ERROR("failed to initialize framebuffer\n"); DRM_ERROR("failed to initialize framebuffer\n");
return ERR_PTR(ret); goto err;
} }
return &exynos_fb->fb; return &exynos_fb->fb;
err:
kfree(exynos_fb);
return ERR_PTR(ret);
} }
static struct drm_framebuffer * static struct drm_framebuffer *
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
struct drm_mode_fb_cmd2 *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd)
{ {
struct exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER];
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct exynos_drm_gem_obj *exynos_gem_obj; struct drm_framebuffer *fb;
struct exynos_drm_fb *exynos_fb; int i;
int i, ret; int 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);
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, obj = drm_gem_object_lookup(dev, file_priv,
mode_cmd->handles[i]); mode_cmd->handles[i]);
if (!obj) { if (!obj) {
DRM_ERROR("failed to lookup gem object\n"); DRM_ERROR("failed to lookup gem object\n");
ret = -ENOENT; ret = -ENOENT;
exynos_fb->buf_cnt = i; goto err;
goto err_unreference;
} }
exynos_gem_obj = to_exynos_gem_obj(obj); gem_objs[i] = 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;
} }
ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i);
if (ret) { if (IS_ERR(fb)) {
DRM_ERROR("failed to init framebuffer.\n"); ret = PTR_ERR(fb);
goto err_unreference; goto err;
} }
return &exynos_fb->fb; return fb;
err_unreference: err:
for (i = 0; i < exynos_fb->buf_cnt; i++) { while (i--)
struct drm_gem_object *obj; 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); return ERR_PTR(ret);
} }
......
...@@ -14,10 +14,13 @@ ...@@ -14,10 +14,13 @@
#ifndef _EXYNOS_DRM_FB_H_ #ifndef _EXYNOS_DRM_FB_H_
#define _EXYNOS_DRM_FB_H #define _EXYNOS_DRM_FB_H
#include "exynos_drm_gem.h"
struct drm_framebuffer * struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev, exynos_drm_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd, 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 */ /* get gem object of a drm framebuffer */
struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
...@@ -25,11 +28,4 @@ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, ...@@ -25,11 +28,4 @@ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
void exynos_drm_mode_config_init(struct drm_device *dev); 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 #endif
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
#define MAX_CONNECTOR 4 #define MAX_CONNECTOR 4
...@@ -32,7 +31,7 @@ ...@@ -32,7 +31,7 @@
struct exynos_drm_fbdev { struct exynos_drm_fbdev {
struct drm_fb_helper drm_fb_helper; 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, static int exynos_drm_fb_mmap(struct fb_info *info,
...@@ -40,7 +39,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info, ...@@ -40,7 +39,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
{ {
struct drm_fb_helper *helper = info->par; struct drm_fb_helper *helper = info->par;
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); 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; unsigned long vm_size;
int ret; int ret;
...@@ -75,37 +74,38 @@ static struct fb_ops exynos_drm_fb_ops = { ...@@ -75,37 +74,38 @@ static struct fb_ops exynos_drm_fb_ops = {
}; };
static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes, struct drm_fb_helper_surface_size *sizes,
struct drm_framebuffer *fb) struct exynos_drm_gem_obj *obj)
{ {
struct fb_info *fbi = helper->fbdev; struct fb_info *fbi;
struct exynos_drm_gem_obj *obj; struct drm_framebuffer *fb = helper->fb;
unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
unsigned int nr_pages; unsigned int nr_pages;
unsigned long offset; 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_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); 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; nr_pages = obj->size >> PAGE_SHIFT;
obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP, obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL)); pgprot_writecombine(PAGE_KERNEL));
if (!obj->kvaddr) { if (!obj->kvaddr) {
DRM_ERROR("failed to map pages to kernel space.\n"); DRM_ERROR("failed to map pages to kernel space.\n");
drm_fb_helper_release_fbi(helper);
return -EIO; 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.xoffset * (fb->bits_per_pixel >> 3);
offset += fbi->var.yoffset * fb->pitches[0]; offset += fbi->var.yoffset * fb->pitches[0];
...@@ -120,9 +120,8 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, ...@@ -120,9 +120,8 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes) struct drm_fb_helper_surface_size *sizes)
{ {
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); 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 drm_device *dev = helper->dev;
struct fb_info *fbi;
struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct platform_device *pdev = dev->platformdev; struct platform_device *pdev = dev->platformdev;
unsigned long size; unsigned long size;
...@@ -140,47 +139,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, ...@@ -140,47 +139,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
mutex_lock(&dev->struct_mutex); 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; 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 * If physically contiguous memory allocation fails and if IOMMU is
* supported then try to get buffer from non physically contiguous * supported then try to get buffer from non physically contiguous
* memory area. * 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"); 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, obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size);
size);
} }
if (IS_ERR(exynos_gem_obj)) { if (IS_ERR(obj)) {
ret = PTR_ERR(exynos_gem_obj); ret = PTR_ERR(obj);
goto err_release_fbi; goto out;
} }
exynos_fbdev->exynos_gem_obj = exynos_gem_obj; exynos_fbdev->obj = obj;
helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj, 1);
&exynos_gem_obj->base);
if (IS_ERR(helper->fb)) { if (IS_ERR(helper->fb)) {
DRM_ERROR("failed to create drm framebuffer.\n"); DRM_ERROR("failed to create drm framebuffer.\n");
ret = PTR_ERR(helper->fb); ret = PTR_ERR(helper->fb);
goto err_destroy_gem; goto err_destroy_gem;
} }
fbi->par = helper; ret = exynos_drm_fbdev_update(helper, sizes, obj);
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &exynos_drm_fb_ops;
ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
if (ret < 0) if (ret < 0)
goto err_destroy_framebuffer; goto err_destroy_framebuffer;
...@@ -190,9 +176,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, ...@@ -190,9 +176,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
err_destroy_framebuffer: err_destroy_framebuffer:
drm_framebuffer_cleanup(helper->fb); drm_framebuffer_cleanup(helper->fb);
err_destroy_gem: err_destroy_gem:
exynos_drm_gem_destroy(exynos_gem_obj); exynos_drm_gem_destroy(obj);
err_release_fbi:
drm_fb_helper_release_fbi(helper);
/* /*
* if failed, all resources allocated above would be released by * if failed, all resources allocated above would be released by
...@@ -285,11 +269,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, ...@@ -285,11 +269,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
struct drm_fb_helper *fb_helper) struct drm_fb_helper *fb_helper)
{ {
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(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; struct drm_framebuffer *fb;
if (exynos_gem_obj->kvaddr) if (obj->kvaddr)
vunmap(exynos_gem_obj->kvaddr); vunmap(obj->kvaddr);
/* release drm framebuffer and real buffer */ /* release drm framebuffer and real buffer */
if (fb_helper->fb && fb_helper->fb->funcs) { if (fb_helper->fb && fb_helper->fb->funcs) {
......
...@@ -48,11 +48,13 @@ ...@@ -48,11 +48,13 @@
/* registers for base address */ /* registers for base address */
#define G2D_SRC_BASE_ADDR 0x0304 #define G2D_SRC_BASE_ADDR 0x0304
#define G2D_SRC_STRIDE_REG 0x0308
#define G2D_SRC_COLOR_MODE 0x030C #define G2D_SRC_COLOR_MODE 0x030C
#define G2D_SRC_LEFT_TOP 0x0310 #define G2D_SRC_LEFT_TOP 0x0310
#define G2D_SRC_RIGHT_BOTTOM 0x0314 #define G2D_SRC_RIGHT_BOTTOM 0x0314
#define G2D_SRC_PLANE2_BASE_ADDR 0x0318 #define G2D_SRC_PLANE2_BASE_ADDR 0x0318
#define G2D_DST_BASE_ADDR 0x0404 #define G2D_DST_BASE_ADDR 0x0404
#define G2D_DST_STRIDE_REG 0x0408
#define G2D_DST_COLOR_MODE 0x040C #define G2D_DST_COLOR_MODE 0x040C
#define G2D_DST_LEFT_TOP 0x0410 #define G2D_DST_LEFT_TOP 0x0410
#define G2D_DST_RIGHT_BOTTOM 0x0414 #define G2D_DST_RIGHT_BOTTOM 0x0414
...@@ -148,6 +150,7 @@ struct g2d_cmdlist { ...@@ -148,6 +150,7 @@ struct g2d_cmdlist {
* A structure of buffer description * A structure of buffer description
* *
* @format: color format * @format: color format
* @stride: buffer stride/pitch in bytes
* @left_x: the x coordinates of left top corner * @left_x: the x coordinates of left top corner
* @top_y: the y coordinates of left top corner * @top_y: the y coordinates of left top corner
* @right_x: the x coordinates of right bottom corner * @right_x: the x coordinates of right bottom corner
...@@ -156,6 +159,7 @@ struct g2d_cmdlist { ...@@ -156,6 +159,7 @@ struct g2d_cmdlist {
*/ */
struct g2d_buf_desc { struct g2d_buf_desc {
unsigned int format; unsigned int format;
unsigned int stride;
unsigned int left_x; unsigned int left_x;
unsigned int top_y; unsigned int top_y;
unsigned int right_x; unsigned int right_x;
...@@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) ...@@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
switch (reg_offset) { switch (reg_offset) {
case G2D_SRC_BASE_ADDR: case G2D_SRC_BASE_ADDR:
case G2D_SRC_STRIDE_REG:
case G2D_SRC_COLOR_MODE: case G2D_SRC_COLOR_MODE:
case G2D_SRC_LEFT_TOP: case G2D_SRC_LEFT_TOP:
case G2D_SRC_RIGHT_BOTTOM: case G2D_SRC_RIGHT_BOTTOM:
...@@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) ...@@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
reg_type = REG_TYPE_SRC_PLANE2; reg_type = REG_TYPE_SRC_PLANE2;
break; break;
case G2D_DST_BASE_ADDR: case G2D_DST_BASE_ADDR:
case G2D_DST_STRIDE_REG:
case G2D_DST_COLOR_MODE: case G2D_DST_COLOR_MODE:
case G2D_DST_LEFT_TOP: case G2D_DST_LEFT_TOP:
case G2D_DST_RIGHT_BOTTOM: case G2D_DST_RIGHT_BOTTOM:
...@@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, ...@@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
enum g2d_reg_type reg_type, enum g2d_reg_type reg_type,
unsigned long size) unsigned long size)
{ {
unsigned int width, height; int width, height;
unsigned long area; unsigned long bpp, last_pos;
/* /*
* check source and destination buffers only. * check source and destination buffers only.
...@@ -662,22 +668,37 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, ...@@ -662,22 +668,37 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST)
return true; return true;
width = buf_desc->right_x - buf_desc->left_x; /* This check also makes sure that right_x > left_x. */
width = (int)buf_desc->right_x - (int)buf_desc->left_x;
if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) {
DRM_ERROR("width[%u] is out of range!\n", width); DRM_ERROR("width[%d] is out of range!\n", width);
return false; return false;
} }
height = buf_desc->bottom_y - buf_desc->top_y; /* This check also makes sure that bottom_y > top_y. */
height = (int)buf_desc->bottom_y - (int)buf_desc->top_y;
if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) {
DRM_ERROR("height[%u] is out of range!\n", height); DRM_ERROR("height[%d] is out of range!\n", height);
return false; return false;
} }
area = (unsigned long)width * (unsigned long)height * bpp = g2d_get_buf_bpp(buf_desc->format);
g2d_get_buf_bpp(buf_desc->format);
if (area > size) { /* Compute the position of the last byte that the engine accesses. */
DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); last_pos = ((unsigned long)buf_desc->bottom_y - 1) *
(unsigned long)buf_desc->stride +
(unsigned long)buf_desc->right_x * bpp - 1;
/*
* Since right_x > left_x and bottom_y > top_y we already know
* that the first_pos < last_pos (first_pos being the position
* of the first byte the engine accesses), it just remains to
* check if last_pos is smaller then the buffer size.
*/
if (last_pos >= size) {
DRM_ERROR("last engine access position [%lu] "
"is out of range [%lu]!\n", last_pos, size);
return false; return false;
} }
...@@ -973,8 +994,6 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -973,8 +994,6 @@ static int g2d_check_reg_offset(struct device *dev,
goto err; goto err;
reg_type = g2d_get_reg_type(reg_offset); reg_type = g2d_get_reg_type(reg_offset);
if (reg_type == REG_TYPE_NONE)
goto err;
/* check userptr buffer type. */ /* check userptr buffer type. */
if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { if ((cmdlist->data[index] & ~0x7fffffff) >> 31) {
...@@ -983,14 +1002,22 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -983,14 +1002,22 @@ static int g2d_check_reg_offset(struct device *dev,
} else } else
buf_info->types[reg_type] = BUF_TYPE_GEM; buf_info->types[reg_type] = BUF_TYPE_GEM;
break; break;
case G2D_SRC_STRIDE_REG:
case G2D_DST_STRIDE_REG:
if (for_addr)
goto err;
reg_type = g2d_get_reg_type(reg_offset);
buf_desc = &buf_info->descs[reg_type];
buf_desc->stride = cmdlist->data[index + 1];
break;
case G2D_SRC_COLOR_MODE: case G2D_SRC_COLOR_MODE:
case G2D_DST_COLOR_MODE: case G2D_DST_COLOR_MODE:
if (for_addr) if (for_addr)
goto err; goto err;
reg_type = g2d_get_reg_type(reg_offset); reg_type = g2d_get_reg_type(reg_offset);
if (reg_type == REG_TYPE_NONE)
goto err;
buf_desc = &buf_info->descs[reg_type]; buf_desc = &buf_info->descs[reg_type];
value = cmdlist->data[index + 1]; value = cmdlist->data[index + 1];
...@@ -1003,8 +1030,6 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -1003,8 +1030,6 @@ static int g2d_check_reg_offset(struct device *dev,
goto err; goto err;
reg_type = g2d_get_reg_type(reg_offset); reg_type = g2d_get_reg_type(reg_offset);
if (reg_type == REG_TYPE_NONE)
goto err;
buf_desc = &buf_info->descs[reg_type]; buf_desc = &buf_info->descs[reg_type];
value = cmdlist->data[index + 1]; value = cmdlist->data[index + 1];
...@@ -1018,8 +1043,6 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -1018,8 +1043,6 @@ static int g2d_check_reg_offset(struct device *dev,
goto err; goto err;
reg_type = g2d_get_reg_type(reg_offset); reg_type = g2d_get_reg_type(reg_offset);
if (reg_type == REG_TYPE_NONE)
goto err;
buf_desc = &buf_info->descs[reg_type]; buf_desc = &buf_info->descs[reg_type];
value = cmdlist->data[index + 1]; value = cmdlist->data[index + 1];
......
...@@ -126,7 +126,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, ...@@ -126,7 +126,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
if (!state->fb) if (!state->fb)
return 0; return 0;
nr = exynos_drm_fb_get_buf_cnt(state->fb); nr = drm_format_num_planes(state->fb->pixel_format);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct exynos_drm_gem_obj *obj = struct exynos_drm_gem_obj *obj =
exynos_drm_fb_gem_obj(state->fb, i); exynos_drm_fb_gem_obj(state->fb, i);
......
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