diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fb.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 116 |
1 files changed, 83 insertions, 33 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 4ef4cd3f9936..294c0513f587 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
@@ -6,34 +6,23 @@ | |||
6 | * Joonyoung Shim <jy0922.shim@samsung.com> | 6 | * Joonyoung Shim <jy0922.shim@samsung.com> |
7 | * Seung-Woo Kim <sw0312.kim@samsung.com> | 7 | * Seung-Woo Kim <sw0312.kim@samsung.com> |
8 | * | 8 | * |
9 | * Permission is hereby granted, free of charge, to any person obtaining a | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * copy of this software and associated documentation files (the "Software"), | 10 | * under the terms of the GNU General Public License as published by the |
11 | * to deal in the Software without restriction, including without limitation | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 12 | * option) any later version. |
13 | * and/or sell copies of the Software, and to permit persons to whom the | ||
14 | * Software is furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice (including the next | ||
17 | * paragraph) shall be included in all copies or substantial portions of the | ||
18 | * Software. | ||
19 | * | ||
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
23 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
24 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
25 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
26 | * OTHER DEALINGS IN THE SOFTWARE. | ||
27 | */ | 13 | */ |
28 | 14 | ||
29 | #include <drm/drmP.h> | 15 | #include <drm/drmP.h> |
30 | #include <drm/drm_crtc.h> | 16 | #include <drm/drm_crtc.h> |
31 | #include <drm/drm_crtc_helper.h> | 17 | #include <drm/drm_crtc_helper.h> |
32 | #include <drm/drm_fb_helper.h> | 18 | #include <drm/drm_fb_helper.h> |
19 | #include <uapi/drm/exynos_drm.h> | ||
33 | 20 | ||
34 | #include "exynos_drm_drv.h" | 21 | #include "exynos_drm_drv.h" |
35 | #include "exynos_drm_fb.h" | 22 | #include "exynos_drm_fb.h" |
36 | #include "exynos_drm_gem.h" | 23 | #include "exynos_drm_gem.h" |
24 | #include "exynos_drm_iommu.h" | ||
25 | #include "exynos_drm_encoder.h" | ||
37 | 26 | ||
38 | #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) | 27 | #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) |
39 | 28 | ||
@@ -50,6 +39,32 @@ struct exynos_drm_fb { | |||
50 | struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; | 39 | struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; |
51 | }; | 40 | }; |
52 | 41 | ||
42 | static int check_fb_gem_memory_type(struct drm_device *drm_dev, | ||
43 | struct exynos_drm_gem_obj *exynos_gem_obj) | ||
44 | { | ||
45 | unsigned int flags; | ||
46 | |||
47 | /* | ||
48 | * if exynos drm driver supports iommu then framebuffer can use | ||
49 | * all the buffer types. | ||
50 | */ | ||
51 | if (is_drm_iommu_supported(drm_dev)) | ||
52 | return 0; | ||
53 | |||
54 | flags = exynos_gem_obj->flags; | ||
55 | |||
56 | /* | ||
57 | * without iommu support, not support physically non-continuous memory | ||
58 | * for framebuffer. | ||
59 | */ | ||
60 | if (IS_NONCONTIG_BUFFER(flags)) { | ||
61 | DRM_ERROR("cannot use this gem memory type for fb.\n"); | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
53 | static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) | 68 | static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) |
54 | { | 69 | { |
55 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); | 70 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); |
@@ -57,6 +72,9 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) | |||
57 | 72 | ||
58 | DRM_DEBUG_KMS("%s\n", __FILE__); | 73 | DRM_DEBUG_KMS("%s\n", __FILE__); |
59 | 74 | ||
75 | /* make sure that overlay data are updated before relesing fb. */ | ||
76 | exynos_drm_encoder_complete_scanout(fb); | ||
77 | |||
60 | drm_framebuffer_cleanup(fb); | 78 | drm_framebuffer_cleanup(fb); |
61 | 79 | ||
62 | for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { | 80 | for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { |
@@ -128,23 +146,32 @@ exynos_drm_framebuffer_init(struct drm_device *dev, | |||
128 | struct drm_gem_object *obj) | 146 | struct drm_gem_object *obj) |
129 | { | 147 | { |
130 | struct exynos_drm_fb *exynos_fb; | 148 | struct exynos_drm_fb *exynos_fb; |
149 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
131 | int ret; | 150 | int ret; |
132 | 151 | ||
152 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
153 | |||
154 | ret = check_fb_gem_memory_type(dev, exynos_gem_obj); | ||
155 | if (ret < 0) { | ||
156 | DRM_ERROR("cannot use this gem memory type for fb.\n"); | ||
157 | return ERR_PTR(-EINVAL); | ||
158 | } | ||
159 | |||
133 | exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); | 160 | exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); |
134 | if (!exynos_fb) { | 161 | if (!exynos_fb) { |
135 | DRM_ERROR("failed to allocate exynos drm framebuffer\n"); | 162 | DRM_ERROR("failed to allocate exynos drm framebuffer\n"); |
136 | return ERR_PTR(-ENOMEM); | 163 | return ERR_PTR(-ENOMEM); |
137 | } | 164 | } |
138 | 165 | ||
166 | drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); | ||
167 | exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; | ||
168 | |||
139 | ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); | 169 | ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); |
140 | if (ret) { | 170 | if (ret) { |
141 | DRM_ERROR("failed to initialize framebuffer\n"); | 171 | DRM_ERROR("failed to initialize framebuffer\n"); |
142 | return ERR_PTR(ret); | 172 | return ERR_PTR(ret); |
143 | } | 173 | } |
144 | 174 | ||
145 | drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); | ||
146 | exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); | ||
147 | |||
148 | return &exynos_fb->fb; | 175 | return &exynos_fb->fb; |
149 | } | 176 | } |
150 | 177 | ||
@@ -190,9 +217,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, | |||
190 | struct drm_mode_fb_cmd2 *mode_cmd) | 217 | struct drm_mode_fb_cmd2 *mode_cmd) |
191 | { | 218 | { |
192 | struct drm_gem_object *obj; | 219 | struct drm_gem_object *obj; |
193 | struct drm_framebuffer *fb; | ||
194 | struct exynos_drm_fb *exynos_fb; | 220 | struct exynos_drm_fb *exynos_fb; |
195 | int i; | 221 | int i, ret; |
196 | 222 | ||
197 | DRM_DEBUG_KMS("%s\n", __FILE__); | 223 | DRM_DEBUG_KMS("%s\n", __FILE__); |
198 | 224 | ||
@@ -202,30 +228,56 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, | |||
202 | return ERR_PTR(-ENOENT); | 228 | return ERR_PTR(-ENOENT); |
203 | } | 229 | } |
204 | 230 | ||
205 | fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); | 231 | exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); |
206 | if (IS_ERR(fb)) { | 232 | if (!exynos_fb) { |
207 | drm_gem_object_unreference_unlocked(obj); | 233 | DRM_ERROR("failed to allocate exynos drm framebuffer\n"); |
208 | return fb; | 234 | return ERR_PTR(-ENOMEM); |
209 | } | 235 | } |
210 | 236 | ||
211 | exynos_fb = to_exynos_fb(fb); | 237 | drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); |
238 | exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); | ||
212 | exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); | 239 | exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); |
213 | 240 | ||
214 | DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); | 241 | DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); |
215 | 242 | ||
216 | for (i = 1; i < exynos_fb->buf_cnt; i++) { | 243 | for (i = 1; i < exynos_fb->buf_cnt; i++) { |
244 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
245 | int ret; | ||
246 | |||
217 | obj = drm_gem_object_lookup(dev, file_priv, | 247 | obj = drm_gem_object_lookup(dev, file_priv, |
218 | mode_cmd->handles[i]); | 248 | mode_cmd->handles[i]); |
219 | if (!obj) { | 249 | if (!obj) { |
220 | DRM_ERROR("failed to lookup gem object\n"); | 250 | DRM_ERROR("failed to lookup gem object\n"); |
221 | exynos_drm_fb_destroy(fb); | 251 | kfree(exynos_fb); |
222 | return ERR_PTR(-ENOENT); | 252 | return ERR_PTR(-ENOENT); |
223 | } | 253 | } |
224 | 254 | ||
255 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
256 | |||
257 | ret = check_fb_gem_memory_type(dev, exynos_gem_obj); | ||
258 | if (ret < 0) { | ||
259 | DRM_ERROR("cannot use this gem memory type for fb.\n"); | ||
260 | kfree(exynos_fb); | ||
261 | return ERR_PTR(ret); | ||
262 | } | ||
263 | |||
225 | exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); | 264 | exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); |
226 | } | 265 | } |
227 | 266 | ||
228 | return fb; | 267 | ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); |
268 | if (ret) { | ||
269 | for (i = 0; i < exynos_fb->buf_cnt; i++) { | ||
270 | struct exynos_drm_gem_obj *gem_obj; | ||
271 | |||
272 | gem_obj = exynos_fb->exynos_gem_obj[i]; | ||
273 | drm_gem_object_unreference_unlocked(&gem_obj->base); | ||
274 | } | ||
275 | |||
276 | kfree(exynos_fb); | ||
277 | return ERR_PTR(ret); | ||
278 | } | ||
279 | |||
280 | return &exynos_fb->fb; | ||
229 | } | 281 | } |
230 | 282 | ||
231 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | 283 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, |
@@ -243,9 +295,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | |||
243 | if (!buffer) | 295 | if (!buffer) |
244 | return NULL; | 296 | return NULL; |
245 | 297 | ||
246 | DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", | 298 | DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr); |
247 | (unsigned long)buffer->kvaddr, | ||
248 | (unsigned long)buffer->dma_addr); | ||
249 | 299 | ||
250 | return buffer; | 300 | return buffer; |
251 | } | 301 | } |