aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fb.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c116
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
42static 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
53static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) 68static 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
231struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, 283struct 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}