aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-09-03 23:07:18 -0400
committerDave Airlie <airlied@redhat.com>2015-09-03 23:07:18 -0400
commit55cdb314494b0372c2f0ba3a589aeb412a9626ba (patch)
tree58500c051db12c4dae76d03ec174c6487a7f02f9
parent99495589aa4de7166af254bc497cdbe133fc24bb (diff)
parentc3058579a2882bb4bb6bf1ab0fe65f5ed070e530 (diff)
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()
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c115
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c78
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c59
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c2
5 files changed, 110 insertions, 156 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 59ebbe547290..084280859589 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -23,7 +23,6 @@
23#include "exynos_drm_drv.h" 23#include "exynos_drm_drv.h"
24#include "exynos_drm_fb.h" 24#include "exynos_drm_fb.h"
25#include "exynos_drm_fbdev.h" 25#include "exynos_drm_fbdev.h"
26#include "exynos_drm_gem.h"
27#include "exynos_drm_iommu.h" 26#include "exynos_drm_iommu.h"
28#include "exynos_drm_crtc.h" 27#include "exynos_drm_crtc.h"
29 28
@@ -33,12 +32,10 @@
33 * exynos specific framebuffer structure. 32 * exynos specific framebuffer structure.
34 * 33 *
35 * @fb: drm framebuffer obejct. 34 * @fb: drm framebuffer obejct.
36 * @buf_cnt: a buffer count to drm framebuffer.
37 * @exynos_gem_obj: array of exynos specific gem object containing a gem object. 35 * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
38 */ 36 */
39struct exynos_drm_fb { 37struct exynos_drm_fb {
40 struct drm_framebuffer fb; 38 struct drm_framebuffer fb;
41 unsigned int buf_cnt;
42 struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; 39 struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
43}; 40};
44 41
@@ -98,10 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
98{ 95{
99 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 96 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
100 97
101 /* This fb should have only one gem object. */
102 if (WARN_ON(exynos_fb->buf_cnt != 1))
103 return -EINVAL;
104
105 return drm_gem_handle_create(file_priv, 98 return drm_gem_handle_create(file_priv,
106 &exynos_fb->exynos_gem_obj[0]->base, handle); 99 &exynos_fb->exynos_gem_obj[0]->base, handle);
107} 100}
@@ -122,119 +115,77 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
122 .dirty = exynos_drm_fb_dirty, 115 .dirty = exynos_drm_fb_dirty,
123}; 116};
124 117
125void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
126 unsigned int cnt)
127{
128 struct exynos_drm_fb *exynos_fb;
129
130 exynos_fb = to_exynos_fb(fb);
131
132 exynos_fb->buf_cnt = cnt;
133}
134
135unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
136{
137 struct exynos_drm_fb *exynos_fb;
138
139 exynos_fb = to_exynos_fb(fb);
140
141 return exynos_fb->buf_cnt;
142}
143
144struct drm_framebuffer * 118struct drm_framebuffer *
145exynos_drm_framebuffer_init(struct drm_device *dev, 119exynos_drm_framebuffer_init(struct drm_device *dev,
146 struct drm_mode_fb_cmd2 *mode_cmd, 120 struct drm_mode_fb_cmd2 *mode_cmd,
147 struct drm_gem_object *obj) 121 struct exynos_drm_gem_obj **gem_obj,
122 int count)
148{ 123{
149 struct exynos_drm_fb *exynos_fb; 124 struct exynos_drm_fb *exynos_fb;
150 struct exynos_drm_gem_obj *exynos_gem_obj; 125 int i;
151 int ret; 126 int ret;
152 127
153 exynos_gem_obj = to_exynos_gem_obj(obj);
154
155 ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
156 if (ret < 0)
157 return ERR_PTR(ret);
158
159 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); 128 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
160 if (!exynos_fb) 129 if (!exynos_fb)
161 return ERR_PTR(-ENOMEM); 130 return ERR_PTR(-ENOMEM);
162 131
132 for (i = 0; i < count; i++) {
133 ret = check_fb_gem_memory_type(dev, gem_obj[i]);
134 if (ret < 0)
135 goto err;
136
137 exynos_fb->exynos_gem_obj[i] = gem_obj[i];
138 }
139
163 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); 140 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
164 exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
165 141
166 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); 142 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
167 if (ret) { 143 if (ret < 0) {
168 kfree(exynos_fb);
169 DRM_ERROR("failed to initialize framebuffer\n"); 144 DRM_ERROR("failed to initialize framebuffer\n");
170 return ERR_PTR(ret); 145 goto err;
171 } 146 }
172 147
173 return &exynos_fb->fb; 148 return &exynos_fb->fb;
149
150err:
151 kfree(exynos_fb);
152 return ERR_PTR(ret);
174} 153}
175 154
176static struct drm_framebuffer * 155static struct drm_framebuffer *
177exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, 156exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
178 struct drm_mode_fb_cmd2 *mode_cmd) 157 struct drm_mode_fb_cmd2 *mode_cmd)
179{ 158{
159 struct exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER];
180 struct drm_gem_object *obj; 160 struct drm_gem_object *obj;
181 struct exynos_drm_gem_obj *exynos_gem_obj; 161 struct drm_framebuffer *fb;
182 struct exynos_drm_fb *exynos_fb; 162 int i;
183 int i, ret; 163 int ret;
184
185 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
186 if (!exynos_fb)
187 return ERR_PTR(-ENOMEM);
188
189 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
190 if (!obj) {
191 DRM_ERROR("failed to lookup gem object\n");
192 ret = -ENOENT;
193 goto err_free;
194 }
195
196 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
197 exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
198 exynos_fb->buf_cnt = drm_format_num_planes(mode_cmd->pixel_format);
199
200 DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
201 164
202 for (i = 1; i < exynos_fb->buf_cnt; i++) { 165 for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
203 obj = drm_gem_object_lookup(dev, file_priv, 166 obj = drm_gem_object_lookup(dev, file_priv,
204 mode_cmd->handles[i]); 167 mode_cmd->handles[i]);
205 if (!obj) { 168 if (!obj) {
206 DRM_ERROR("failed to lookup gem object\n"); 169 DRM_ERROR("failed to lookup gem object\n");
207 ret = -ENOENT; 170 ret = -ENOENT;
208 exynos_fb->buf_cnt = i; 171 goto err;
209 goto err_unreference;
210 } 172 }
211 173
212 exynos_gem_obj = to_exynos_gem_obj(obj); 174 gem_objs[i] = to_exynos_gem_obj(obj);
213 exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;
214
215 ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
216 if (ret < 0)
217 goto err_unreference;
218 } 175 }
219 176
220 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); 177 fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i);
221 if (ret) { 178 if (IS_ERR(fb)) {
222 DRM_ERROR("failed to init framebuffer.\n"); 179 ret = PTR_ERR(fb);
223 goto err_unreference; 180 goto err;
224 } 181 }
225 182
226 return &exynos_fb->fb; 183 return fb;
227 184
228err_unreference: 185err:
229 for (i = 0; i < exynos_fb->buf_cnt; i++) { 186 while (i--)
230 struct drm_gem_object *obj; 187 drm_gem_object_unreference_unlocked(&gem_objs[i]->base);
231 188
232 obj = &exynos_fb->exynos_gem_obj[i]->base;
233 if (obj)
234 drm_gem_object_unreference_unlocked(obj);
235 }
236err_free:
237 kfree(exynos_fb);
238 return ERR_PTR(ret); 189 return ERR_PTR(ret);
239} 190}
240 191
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index 1c9e27c32cd1..85e4445b920e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -14,10 +14,13 @@
14#ifndef _EXYNOS_DRM_FB_H_ 14#ifndef _EXYNOS_DRM_FB_H_
15#define _EXYNOS_DRM_FB_H 15#define _EXYNOS_DRM_FB_H
16 16
17#include "exynos_drm_gem.h"
18
17struct drm_framebuffer * 19struct drm_framebuffer *
18exynos_drm_framebuffer_init(struct drm_device *dev, 20exynos_drm_framebuffer_init(struct drm_device *dev,
19 struct drm_mode_fb_cmd2 *mode_cmd, 21 struct drm_mode_fb_cmd2 *mode_cmd,
20 struct drm_gem_object *obj); 22 struct exynos_drm_gem_obj **gem_obj,
23 int count);
21 24
22/* get gem object of a drm framebuffer */ 25/* get gem object of a drm framebuffer */
23struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, 26struct 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 28
26void exynos_drm_mode_config_init(struct drm_device *dev); 29void exynos_drm_mode_config_init(struct drm_device *dev);
27 30
28/* set a buffer count to drm framebuffer. */
29void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
30 unsigned int cnt);
31
32/* get a buffer count to drm framebuffer. */
33unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb);
34
35#endif 31#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 624595afbce0..a221f753ad9c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -21,7 +21,6 @@
21#include "exynos_drm_drv.h" 21#include "exynos_drm_drv.h"
22#include "exynos_drm_fb.h" 22#include "exynos_drm_fb.h"
23#include "exynos_drm_fbdev.h" 23#include "exynos_drm_fbdev.h"
24#include "exynos_drm_gem.h"
25#include "exynos_drm_iommu.h" 24#include "exynos_drm_iommu.h"
26 25
27#define MAX_CONNECTOR 4 26#define MAX_CONNECTOR 4
@@ -32,7 +31,7 @@
32 31
33struct exynos_drm_fbdev { 32struct exynos_drm_fbdev {
34 struct drm_fb_helper drm_fb_helper; 33 struct drm_fb_helper drm_fb_helper;
35 struct exynos_drm_gem_obj *exynos_gem_obj; 34 struct exynos_drm_gem_obj *obj;
36}; 35};
37 36
38static int exynos_drm_fb_mmap(struct fb_info *info, 37static int exynos_drm_fb_mmap(struct fb_info *info,
@@ -40,7 +39,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
40{ 39{
41 struct drm_fb_helper *helper = info->par; 40 struct drm_fb_helper *helper = info->par;
42 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); 41 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper);
43 struct exynos_drm_gem_obj *obj = exynos_fbd->exynos_gem_obj; 42 struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
44 unsigned long vm_size; 43 unsigned long vm_size;
45 int ret; 44 int ret;
46 45
@@ -75,37 +74,38 @@ static struct fb_ops exynos_drm_fb_ops = {
75}; 74};
76 75
77static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, 76static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
78 struct drm_fb_helper_surface_size *sizes, 77 struct drm_fb_helper_surface_size *sizes,
79 struct drm_framebuffer *fb) 78 struct exynos_drm_gem_obj *obj)
80{ 79{
81 struct fb_info *fbi = helper->fbdev; 80 struct fb_info *fbi;
82 struct exynos_drm_gem_obj *obj; 81 struct drm_framebuffer *fb = helper->fb;
83 unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); 82 unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
84 unsigned int nr_pages; 83 unsigned int nr_pages;
85 unsigned long offset; 84 unsigned long offset;
86 85
86 fbi = drm_fb_helper_alloc_fbi(helper);
87 if (IS_ERR(fbi)) {
88 DRM_ERROR("failed to allocate fb info.\n");
89 return PTR_ERR(fbi);
90 }
91
92 fbi->par = helper;
93 fbi->flags = FBINFO_FLAG_DEFAULT;
94 fbi->fbops = &exynos_drm_fb_ops;
95
87 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); 96 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
88 drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); 97 drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
89 98
90 /* RGB formats use only one buffer */
91 obj = exynos_drm_fb_gem_obj(fb, 0);
92 if (!obj) {
93 DRM_DEBUG_KMS("gem object is null.\n");
94 return -EFAULT;
95 }
96
97 nr_pages = obj->size >> PAGE_SHIFT; 99 nr_pages = obj->size >> PAGE_SHIFT;
98 100
99 obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP, 101 obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP,
100 pgprot_writecombine(PAGE_KERNEL)); 102 pgprot_writecombine(PAGE_KERNEL));
101 if (!obj->kvaddr) { 103 if (!obj->kvaddr) {
102 DRM_ERROR("failed to map pages to kernel space.\n"); 104 DRM_ERROR("failed to map pages to kernel space.\n");
105 drm_fb_helper_release_fbi(helper);
103 return -EIO; 106 return -EIO;
104 } 107 }
105 108
106 /* buffer count to framebuffer always is 1 at booting time. */
107 exynos_drm_fb_set_buf_cnt(fb, 1);
108
109 offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); 109 offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
110 offset += fbi->var.yoffset * fb->pitches[0]; 110 offset += fbi->var.yoffset * fb->pitches[0];
111 111
@@ -120,9 +120,8 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
120 struct drm_fb_helper_surface_size *sizes) 120 struct drm_fb_helper_surface_size *sizes)
121{ 121{
122 struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); 122 struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
123 struct exynos_drm_gem_obj *exynos_gem_obj; 123 struct exynos_drm_gem_obj *obj;
124 struct drm_device *dev = helper->dev; 124 struct drm_device *dev = helper->dev;
125 struct fb_info *fbi;
126 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 125 struct drm_mode_fb_cmd2 mode_cmd = { 0 };
127 struct platform_device *pdev = dev->platformdev; 126 struct platform_device *pdev = dev->platformdev;
128 unsigned long size; 127 unsigned long size;
@@ -140,47 +139,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
140 139
141 mutex_lock(&dev->struct_mutex); 140 mutex_lock(&dev->struct_mutex);
142 141
143 fbi = drm_fb_helper_alloc_fbi(helper);
144 if (IS_ERR(fbi)) {
145 DRM_ERROR("failed to allocate fb info.\n");
146 ret = PTR_ERR(fbi);
147 goto out;
148 }
149
150 size = mode_cmd.pitches[0] * mode_cmd.height; 142 size = mode_cmd.pitches[0] * mode_cmd.height;
151 143
152 exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size); 144 obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
153 /* 145 /*
154 * If physically contiguous memory allocation fails and if IOMMU is 146 * If physically contiguous memory allocation fails and if IOMMU is
155 * supported then try to get buffer from non physically contiguous 147 * supported then try to get buffer from non physically contiguous
156 * memory area. 148 * memory area.
157 */ 149 */
158 if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) { 150 if (IS_ERR(obj) && is_drm_iommu_supported(dev)) {
159 dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n"); 151 dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
160 exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, 152 obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size);
161 size);
162 } 153 }
163 154
164 if (IS_ERR(exynos_gem_obj)) { 155 if (IS_ERR(obj)) {
165 ret = PTR_ERR(exynos_gem_obj); 156 ret = PTR_ERR(obj);
166 goto err_release_fbi; 157 goto out;
167 } 158 }
168 159
169 exynos_fbdev->exynos_gem_obj = exynos_gem_obj; 160 exynos_fbdev->obj = obj;
170 161
171 helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, 162 helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj, 1);
172 &exynos_gem_obj->base);
173 if (IS_ERR(helper->fb)) { 163 if (IS_ERR(helper->fb)) {
174 DRM_ERROR("failed to create drm framebuffer.\n"); 164 DRM_ERROR("failed to create drm framebuffer.\n");
175 ret = PTR_ERR(helper->fb); 165 ret = PTR_ERR(helper->fb);
176 goto err_destroy_gem; 166 goto err_destroy_gem;
177 } 167 }
178 168
179 fbi->par = helper; 169 ret = exynos_drm_fbdev_update(helper, sizes, obj);
180 fbi->flags = FBINFO_FLAG_DEFAULT;
181 fbi->fbops = &exynos_drm_fb_ops;
182
183 ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
184 if (ret < 0) 170 if (ret < 0)
185 goto err_destroy_framebuffer; 171 goto err_destroy_framebuffer;
186 172
@@ -190,9 +176,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
190err_destroy_framebuffer: 176err_destroy_framebuffer:
191 drm_framebuffer_cleanup(helper->fb); 177 drm_framebuffer_cleanup(helper->fb);
192err_destroy_gem: 178err_destroy_gem:
193 exynos_drm_gem_destroy(exynos_gem_obj); 179 exynos_drm_gem_destroy(obj);
194err_release_fbi:
195 drm_fb_helper_release_fbi(helper);
196 180
197/* 181/*
198 * if failed, all resources allocated above would be released by 182 * 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 struct drm_fb_helper *fb_helper) 269 struct drm_fb_helper *fb_helper)
286{ 270{
287 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper); 271 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
288 struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; 272 struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
289 struct drm_framebuffer *fb; 273 struct drm_framebuffer *fb;
290 274
291 if (exynos_gem_obj->kvaddr) 275 if (obj->kvaddr)
292 vunmap(exynos_gem_obj->kvaddr); 276 vunmap(obj->kvaddr);
293 277
294 /* release drm framebuffer and real buffer */ 278 /* release drm framebuffer and real buffer */
295 if (fb_helper->fb && fb_helper->fb->funcs) { 279 if (fb_helper->fb && fb_helper->fb->funcs) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index ba008391a2fc..535b4ad6c4b1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -48,11 +48,13 @@
48 48
49/* registers for base address */ 49/* registers for base address */
50#define G2D_SRC_BASE_ADDR 0x0304 50#define G2D_SRC_BASE_ADDR 0x0304
51#define G2D_SRC_STRIDE_REG 0x0308
51#define G2D_SRC_COLOR_MODE 0x030C 52#define G2D_SRC_COLOR_MODE 0x030C
52#define G2D_SRC_LEFT_TOP 0x0310 53#define G2D_SRC_LEFT_TOP 0x0310
53#define G2D_SRC_RIGHT_BOTTOM 0x0314 54#define G2D_SRC_RIGHT_BOTTOM 0x0314
54#define G2D_SRC_PLANE2_BASE_ADDR 0x0318 55#define G2D_SRC_PLANE2_BASE_ADDR 0x0318
55#define G2D_DST_BASE_ADDR 0x0404 56#define G2D_DST_BASE_ADDR 0x0404
57#define G2D_DST_STRIDE_REG 0x0408
56#define G2D_DST_COLOR_MODE 0x040C 58#define G2D_DST_COLOR_MODE 0x040C
57#define G2D_DST_LEFT_TOP 0x0410 59#define G2D_DST_LEFT_TOP 0x0410
58#define G2D_DST_RIGHT_BOTTOM 0x0414 60#define G2D_DST_RIGHT_BOTTOM 0x0414
@@ -148,6 +150,7 @@ struct g2d_cmdlist {
148 * A structure of buffer description 150 * A structure of buffer description
149 * 151 *
150 * @format: color format 152 * @format: color format
153 * @stride: buffer stride/pitch in bytes
151 * @left_x: the x coordinates of left top corner 154 * @left_x: the x coordinates of left top corner
152 * @top_y: the y coordinates of left top corner 155 * @top_y: the y coordinates of left top corner
153 * @right_x: the x coordinates of right bottom corner 156 * @right_x: the x coordinates of right bottom corner
@@ -156,6 +159,7 @@ struct g2d_cmdlist {
156 */ 159 */
157struct g2d_buf_desc { 160struct g2d_buf_desc {
158 unsigned int format; 161 unsigned int format;
162 unsigned int stride;
159 unsigned int left_x; 163 unsigned int left_x;
160 unsigned int top_y; 164 unsigned int top_y;
161 unsigned int right_x; 165 unsigned int right_x;
@@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
589 593
590 switch (reg_offset) { 594 switch (reg_offset) {
591 case G2D_SRC_BASE_ADDR: 595 case G2D_SRC_BASE_ADDR:
596 case G2D_SRC_STRIDE_REG:
592 case G2D_SRC_COLOR_MODE: 597 case G2D_SRC_COLOR_MODE:
593 case G2D_SRC_LEFT_TOP: 598 case G2D_SRC_LEFT_TOP:
594 case G2D_SRC_RIGHT_BOTTOM: 599 case G2D_SRC_RIGHT_BOTTOM:
@@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
598 reg_type = REG_TYPE_SRC_PLANE2; 603 reg_type = REG_TYPE_SRC_PLANE2;
599 break; 604 break;
600 case G2D_DST_BASE_ADDR: 605 case G2D_DST_BASE_ADDR:
606 case G2D_DST_STRIDE_REG:
601 case G2D_DST_COLOR_MODE: 607 case G2D_DST_COLOR_MODE:
602 case G2D_DST_LEFT_TOP: 608 case G2D_DST_LEFT_TOP:
603 case G2D_DST_RIGHT_BOTTOM: 609 case G2D_DST_RIGHT_BOTTOM:
@@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
652 enum g2d_reg_type reg_type, 658 enum g2d_reg_type reg_type,
653 unsigned long size) 659 unsigned long size)
654{ 660{
655 unsigned int width, height; 661 int width, height;
656 unsigned long area; 662 unsigned long bpp, last_pos;
657 663
658 /* 664 /*
659 * check source and destination buffers only. 665 * 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 if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) 668 if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST)
663 return true; 669 return true;
664 670
665 width = buf_desc->right_x - buf_desc->left_x; 671 /* This check also makes sure that right_x > left_x. */
672 width = (int)buf_desc->right_x - (int)buf_desc->left_x;
666 if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { 673 if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) {
667 DRM_ERROR("width[%u] is out of range!\n", width); 674 DRM_ERROR("width[%d] is out of range!\n", width);
668 return false; 675 return false;
669 } 676 }
670 677
671 height = buf_desc->bottom_y - buf_desc->top_y; 678 /* This check also makes sure that bottom_y > top_y. */
679 height = (int)buf_desc->bottom_y - (int)buf_desc->top_y;
672 if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { 680 if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) {
673 DRM_ERROR("height[%u] is out of range!\n", height); 681 DRM_ERROR("height[%d] is out of range!\n", height);
674 return false; 682 return false;
675 } 683 }
676 684
677 area = (unsigned long)width * (unsigned long)height * 685 bpp = g2d_get_buf_bpp(buf_desc->format);
678 g2d_get_buf_bpp(buf_desc->format); 686
679 if (area > size) { 687 /* Compute the position of the last byte that the engine accesses. */
680 DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); 688 last_pos = ((unsigned long)buf_desc->bottom_y - 1) *
689 (unsigned long)buf_desc->stride +
690 (unsigned long)buf_desc->right_x * bpp - 1;
691
692 /*
693 * Since right_x > left_x and bottom_y > top_y we already know
694 * that the first_pos < last_pos (first_pos being the position
695 * of the first byte the engine accesses), it just remains to
696 * check if last_pos is smaller then the buffer size.
697 */
698
699 if (last_pos >= size) {
700 DRM_ERROR("last engine access position [%lu] "
701 "is out of range [%lu]!\n", last_pos, size);
681 return false; 702 return false;
682 } 703 }
683 704
@@ -973,8 +994,6 @@ static int g2d_check_reg_offset(struct device *dev,
973 goto err; 994 goto err;
974 995
975 reg_type = g2d_get_reg_type(reg_offset); 996 reg_type = g2d_get_reg_type(reg_offset);
976 if (reg_type == REG_TYPE_NONE)
977 goto err;
978 997
979 /* check userptr buffer type. */ 998 /* check userptr buffer type. */
980 if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { 999 if ((cmdlist->data[index] & ~0x7fffffff) >> 31) {
@@ -983,14 +1002,22 @@ static int g2d_check_reg_offset(struct device *dev,
983 } else 1002 } else
984 buf_info->types[reg_type] = BUF_TYPE_GEM; 1003 buf_info->types[reg_type] = BUF_TYPE_GEM;
985 break; 1004 break;
1005 case G2D_SRC_STRIDE_REG:
1006 case G2D_DST_STRIDE_REG:
1007 if (for_addr)
1008 goto err;
1009
1010 reg_type = g2d_get_reg_type(reg_offset);
1011
1012 buf_desc = &buf_info->descs[reg_type];
1013 buf_desc->stride = cmdlist->data[index + 1];
1014 break;
986 case G2D_SRC_COLOR_MODE: 1015 case G2D_SRC_COLOR_MODE:
987 case G2D_DST_COLOR_MODE: 1016 case G2D_DST_COLOR_MODE:
988 if (for_addr) 1017 if (for_addr)
989 goto err; 1018 goto err;
990 1019
991 reg_type = g2d_get_reg_type(reg_offset); 1020 reg_type = g2d_get_reg_type(reg_offset);
992 if (reg_type == REG_TYPE_NONE)
993 goto err;
994 1021
995 buf_desc = &buf_info->descs[reg_type]; 1022 buf_desc = &buf_info->descs[reg_type];
996 value = cmdlist->data[index + 1]; 1023 value = cmdlist->data[index + 1];
@@ -1003,8 +1030,6 @@ static int g2d_check_reg_offset(struct device *dev,
1003 goto err; 1030 goto err;
1004 1031
1005 reg_type = g2d_get_reg_type(reg_offset); 1032 reg_type = g2d_get_reg_type(reg_offset);
1006 if (reg_type == REG_TYPE_NONE)
1007 goto err;
1008 1033
1009 buf_desc = &buf_info->descs[reg_type]; 1034 buf_desc = &buf_info->descs[reg_type];
1010 value = cmdlist->data[index + 1]; 1035 value = cmdlist->data[index + 1];
@@ -1018,8 +1043,6 @@ static int g2d_check_reg_offset(struct device *dev,
1018 goto err; 1043 goto err;
1019 1044
1020 reg_type = g2d_get_reg_type(reg_offset); 1045 reg_type = g2d_get_reg_type(reg_offset);
1021 if (reg_type == REG_TYPE_NONE)
1022 goto err;
1023 1046
1024 buf_desc = &buf_info->descs[reg_type]; 1047 buf_desc = &buf_info->descs[reg_type];
1025 value = cmdlist->data[index + 1]; 1048 value = cmdlist->data[index + 1];
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 865d6eb0c845..714822441467 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -126,7 +126,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
126 if (!state->fb) 126 if (!state->fb)
127 return 0; 127 return 0;
128 128
129 nr = exynos_drm_fb_get_buf_cnt(state->fb); 129 nr = drm_format_num_planes(state->fb->pixel_format);
130 for (i = 0; i < nr; i++) { 130 for (i = 0; i < nr; i++) {
131 struct exynos_drm_gem_obj *obj = 131 struct exynos_drm_gem_obj *obj =
132 exynos_drm_fb_gem_obj(state->fb, i); 132 exynos_drm_fb_gem_obj(state->fb, i);