diff options
author | Dave Airlie <airlied@redhat.com> | 2015-09-03 23:07:18 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-09-03 23:07:18 -0400 |
commit | 55cdb314494b0372c2f0ba3a589aeb412a9626ba (patch) | |
tree | 58500c051db12c4dae76d03ec174c6487a7f02f9 | |
parent | 99495589aa4de7166af254bc497cdbe133fc24bb (diff) | |
parent | c3058579a2882bb4bb6bf1ab0fe65f5ed070e530 (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.c | 115 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_g2d.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 2 |
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 | */ |
39 | struct exynos_drm_fb { | 37 | struct 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 | ||
125 | void 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 | |||
135 | unsigned 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 | |||
144 | struct drm_framebuffer * | 118 | struct drm_framebuffer * |
145 | exynos_drm_framebuffer_init(struct drm_device *dev, | 119 | exynos_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 | |||
150 | err: | ||
151 | kfree(exynos_fb); | ||
152 | return ERR_PTR(ret); | ||
174 | } | 153 | } |
175 | 154 | ||
176 | static struct drm_framebuffer * | 155 | static struct drm_framebuffer * |
177 | exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, | 156 | exynos_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 | ||
228 | err_unreference: | 185 | err: |
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 | } | ||
236 | err_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 | |||
17 | struct drm_framebuffer * | 19 | struct drm_framebuffer * |
18 | exynos_drm_framebuffer_init(struct drm_device *dev, | 20 | exynos_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 */ |
23 | struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, | 26 | 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 | 28 | ||
26 | void exynos_drm_mode_config_init(struct drm_device *dev); | 29 | void exynos_drm_mode_config_init(struct drm_device *dev); |
27 | 30 | ||
28 | /* set a buffer count to drm framebuffer. */ | ||
29 | void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb, | ||
30 | unsigned int cnt); | ||
31 | |||
32 | /* get a buffer count to drm framebuffer. */ | ||
33 | unsigned 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 | ||
33 | struct exynos_drm_fbdev { | 32 | struct 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 | ||
38 | static int exynos_drm_fb_mmap(struct fb_info *info, | 37 | 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 | { | 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 | ||
77 | static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | 76 | static 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, | |||
190 | err_destroy_framebuffer: | 176 | err_destroy_framebuffer: |
191 | drm_framebuffer_cleanup(helper->fb); | 177 | drm_framebuffer_cleanup(helper->fb); |
192 | err_destroy_gem: | 178 | err_destroy_gem: |
193 | exynos_drm_gem_destroy(exynos_gem_obj); | 179 | exynos_drm_gem_destroy(obj); |
194 | err_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 | */ |
157 | struct g2d_buf_desc { | 160 | struct 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); |