1 /* exynos_drm_fb.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Authors:
5  *	Inki Dae <inki.dae@samsung.com>
6  *	Joonyoung Shim <jy0922.shim@samsung.com>
7  *	Seung-Woo Kim <sw0312.kim@samsung.com>
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
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  */
28 
29 #include <drm/drmP.h>
30 #include <drm/drm_crtc.h>
31 #include <drm/drm_crtc_helper.h>
32 #include <drm/drm_fb_helper.h>
33 #include <uapi/drm/exynos_drm.h>
34 
35 #include "exynos_drm_drv.h"
36 #include "exynos_drm_fb.h"
37 #include "exynos_drm_gem.h"
38 #include "exynos_drm_iommu.h"
39 #include "exynos_drm_encoder.h"
40 
41 #define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
42 
43 /*
44  * exynos specific framebuffer structure.
45  *
46  * @fb: drm framebuffer obejct.
47  * @buf_cnt: a buffer count to drm framebuffer.
48  * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
49  */
50 struct exynos_drm_fb {
51 	struct drm_framebuffer		fb;
52 	unsigned int			buf_cnt;
53 	struct exynos_drm_gem_obj	*exynos_gem_obj[MAX_FB_BUFFER];
54 };
55 
56 static int check_fb_gem_memory_type(struct drm_device *drm_dev,
57 				struct exynos_drm_gem_obj *exynos_gem_obj)
58 {
59 	unsigned int flags;
60 
61 	/*
62 	 * if exynos drm driver supports iommu then framebuffer can use
63 	 * all the buffer types.
64 	 */
65 	if (is_drm_iommu_supported(drm_dev))
66 		return 0;
67 
68 	flags = exynos_gem_obj->flags;
69 
70 	/*
71 	 * without iommu support, not support physically non-continuous memory
72 	 * for framebuffer.
73 	 */
74 	if (IS_NONCONTIG_BUFFER(flags)) {
75 		DRM_ERROR("cannot use this gem memory type for fb.\n");
76 		return -EINVAL;
77 	}
78 
79 	return 0;
80 }
81 
82 static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
83 {
84 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
85 	unsigned int i;
86 
87 	DRM_DEBUG_KMS("%s\n", __FILE__);
88 
89 	/* make sure that overlay data are updated before relesing fb. */
90 	exynos_drm_encoder_complete_scanout(fb);
91 
92 	drm_framebuffer_cleanup(fb);
93 
94 	for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) {
95 		struct drm_gem_object *obj;
96 
97 		if (exynos_fb->exynos_gem_obj[i] == NULL)
98 			continue;
99 
100 		obj = &exynos_fb->exynos_gem_obj[i]->base;
101 		drm_gem_object_unreference_unlocked(obj);
102 	}
103 
104 	kfree(exynos_fb);
105 	exynos_fb = NULL;
106 }
107 
108 static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
109 					struct drm_file *file_priv,
110 					unsigned int *handle)
111 {
112 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
113 
114 	DRM_DEBUG_KMS("%s\n", __FILE__);
115 
116 	return drm_gem_handle_create(file_priv,
117 			&exynos_fb->exynos_gem_obj[0]->base, handle);
118 }
119 
120 static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
121 				struct drm_file *file_priv, unsigned flags,
122 				unsigned color, struct drm_clip_rect *clips,
123 				unsigned num_clips)
124 {
125 	DRM_DEBUG_KMS("%s\n", __FILE__);
126 
127 	/* TODO */
128 
129 	return 0;
130 }
131 
132 static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
133 	.destroy	= exynos_drm_fb_destroy,
134 	.create_handle	= exynos_drm_fb_create_handle,
135 	.dirty		= exynos_drm_fb_dirty,
136 };
137 
138 void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
139 						unsigned int cnt)
140 {
141 	struct exynos_drm_fb *exynos_fb;
142 
143 	exynos_fb = to_exynos_fb(fb);
144 
145 	exynos_fb->buf_cnt = cnt;
146 }
147 
148 unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
149 {
150 	struct exynos_drm_fb *exynos_fb;
151 
152 	exynos_fb = to_exynos_fb(fb);
153 
154 	return exynos_fb->buf_cnt;
155 }
156 
157 struct drm_framebuffer *
158 exynos_drm_framebuffer_init(struct drm_device *dev,
159 			    struct drm_mode_fb_cmd2 *mode_cmd,
160 			    struct drm_gem_object *obj)
161 {
162 	struct exynos_drm_fb *exynos_fb;
163 	struct exynos_drm_gem_obj *exynos_gem_obj;
164 	int ret;
165 
166 	exynos_gem_obj = to_exynos_gem_obj(obj);
167 
168 	ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
169 	if (ret < 0) {
170 		DRM_ERROR("cannot use this gem memory type for fb.\n");
171 		return ERR_PTR(-EINVAL);
172 	}
173 
174 	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
175 	if (!exynos_fb) {
176 		DRM_ERROR("failed to allocate exynos drm framebuffer\n");
177 		return ERR_PTR(-ENOMEM);
178 	}
179 
180 	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
181 	exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
182 
183 	ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
184 	if (ret) {
185 		DRM_ERROR("failed to initialize framebuffer\n");
186 		return ERR_PTR(ret);
187 	}
188 
189 	return &exynos_fb->fb;
190 }
191 
192 static u32 exynos_drm_format_num_buffers(struct drm_mode_fb_cmd2 *mode_cmd)
193 {
194 	unsigned int cnt = 0;
195 
196 	if (mode_cmd->pixel_format != DRM_FORMAT_NV12)
197 		return drm_format_num_planes(mode_cmd->pixel_format);
198 
199 	while (cnt != MAX_FB_BUFFER) {
200 		if (!mode_cmd->handles[cnt])
201 			break;
202 		cnt++;
203 	}
204 
205 	/*
206 	 * check if NV12 or NV12M.
207 	 *
208 	 * NV12
209 	 * handles[0] = base1, offsets[0] = 0
210 	 * handles[1] = base1, offsets[1] = Y_size
211 	 *
212 	 * NV12M
213 	 * handles[0] = base1, offsets[0] = 0
214 	 * handles[1] = base2, offsets[1] = 0
215 	 */
216 	if (cnt == 2) {
217 		/*
218 		 * in case of NV12 format, offsets[1] is not 0 and
219 		 * handles[0] is same as handles[1].
220 		 */
221 		if (mode_cmd->offsets[1] &&
222 			mode_cmd->handles[0] == mode_cmd->handles[1])
223 			cnt = 1;
224 	}
225 
226 	return cnt;
227 }
228 
229 static struct drm_framebuffer *
230 exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
231 		      struct drm_mode_fb_cmd2 *mode_cmd)
232 {
233 	struct drm_gem_object *obj;
234 	struct exynos_drm_fb *exynos_fb;
235 	int i, ret;
236 
237 	DRM_DEBUG_KMS("%s\n", __FILE__);
238 
239 	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
240 	if (!obj) {
241 		DRM_ERROR("failed to lookup gem object\n");
242 		return ERR_PTR(-ENOENT);
243 	}
244 
245 	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
246 	if (!exynos_fb) {
247 		DRM_ERROR("failed to allocate exynos drm framebuffer\n");
248 		return ERR_PTR(-ENOMEM);
249 	}
250 
251 	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
252 	exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
253 	exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd);
254 
255 	DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
256 
257 	for (i = 1; i < exynos_fb->buf_cnt; i++) {
258 		struct exynos_drm_gem_obj *exynos_gem_obj;
259 		int ret;
260 
261 		obj = drm_gem_object_lookup(dev, file_priv,
262 				mode_cmd->handles[i]);
263 		if (!obj) {
264 			DRM_ERROR("failed to lookup gem object\n");
265 			kfree(exynos_fb);
266 			return ERR_PTR(-ENOENT);
267 		}
268 
269 		exynos_gem_obj = to_exynos_gem_obj(obj);
270 
271 		ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
272 		if (ret < 0) {
273 			DRM_ERROR("cannot use this gem memory type for fb.\n");
274 			kfree(exynos_fb);
275 			return ERR_PTR(ret);
276 		}
277 
278 		exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
279 	}
280 
281 	ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
282 	if (ret) {
283 		for (i = 0; i < exynos_fb->buf_cnt; i++) {
284 			struct exynos_drm_gem_obj *gem_obj;
285 
286 			gem_obj = exynos_fb->exynos_gem_obj[i];
287 			drm_gem_object_unreference_unlocked(&gem_obj->base);
288 		}
289 
290 		kfree(exynos_fb);
291 		return ERR_PTR(ret);
292 	}
293 
294 	return &exynos_fb->fb;
295 }
296 
297 struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
298 						int index)
299 {
300 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
301 	struct exynos_drm_gem_buf *buffer;
302 
303 	DRM_DEBUG_KMS("%s\n", __FILE__);
304 
305 	if (index >= MAX_FB_BUFFER)
306 		return NULL;
307 
308 	buffer = exynos_fb->exynos_gem_obj[index]->buffer;
309 	if (!buffer)
310 		return NULL;
311 
312 	DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
313 
314 	return buffer;
315 }
316 
317 static void exynos_drm_output_poll_changed(struct drm_device *dev)
318 {
319 	struct exynos_drm_private *private = dev->dev_private;
320 	struct drm_fb_helper *fb_helper = private->fb_helper;
321 
322 	if (fb_helper)
323 		drm_fb_helper_hotplug_event(fb_helper);
324 }
325 
326 static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
327 	.fb_create = exynos_user_fb_create,
328 	.output_poll_changed = exynos_drm_output_poll_changed,
329 };
330 
331 void exynos_drm_mode_config_init(struct drm_device *dev)
332 {
333 	dev->mode_config.min_width = 0;
334 	dev->mode_config.min_height = 0;
335 
336 	/*
337 	 * set max width and height as default value(4096x4096).
338 	 * this value would be used to check framebuffer size limitation
339 	 * at drm_mode_addfb().
340 	 */
341 	dev->mode_config.max_width = 4096;
342 	dev->mode_config.max_height = 4096;
343 
344 	dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
345 }
346