• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015 MediaTek Inc.
4  */
5 
6 #include <linux/dma-buf.h>
7 #include <linux/dma-resv.h>
8 
9 #include <drm/drm_modeset_helper.h>
10 #include <drm/drm_fb_helper.h>
11 #include <drm/drm_fourcc.h>
12 #include <drm/drm_gem.h>
13 #include <drm/drm_gem_framebuffer_helper.h>
14 
15 #include "mtk_drm_drv.h"
16 #include "mtk_drm_fb.h"
17 #include "mtk_drm_gem.h"
18 
19 static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = {
20 	.create_handle = drm_gem_fb_create_handle,
21 	.destroy = drm_gem_fb_destroy,
22 };
23 
mtk_drm_framebuffer_init(struct drm_device * dev,const struct drm_mode_fb_cmd2 * mode,struct drm_gem_object * obj)24 static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev,
25 					const struct drm_mode_fb_cmd2 *mode,
26 					struct drm_gem_object *obj)
27 {
28 	const struct drm_format_info *info = drm_get_format_info(dev, mode);
29 	struct drm_framebuffer *fb;
30 	int ret;
31 
32 	if (info->num_planes != 1)
33 		return ERR_PTR(-EINVAL);
34 
35 	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
36 	if (!fb)
37 		return ERR_PTR(-ENOMEM);
38 
39 	drm_helper_mode_fill_fb_struct(dev, fb, mode);
40 
41 	fb->obj[0] = obj;
42 
43 	ret = drm_framebuffer_init(dev, fb, &mtk_drm_fb_funcs);
44 	if (ret) {
45 		DRM_ERROR("failed to initialize framebuffer\n");
46 		kfree(fb);
47 		return ERR_PTR(ret);
48 	}
49 
50 	return fb;
51 }
52 
mtk_drm_mode_fb_create(struct drm_device * dev,struct drm_file * file,const struct drm_mode_fb_cmd2 * cmd)53 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
54 					       struct drm_file *file,
55 					       const struct drm_mode_fb_cmd2 *cmd)
56 {
57 	const struct drm_format_info *info = drm_get_format_info(dev, cmd);
58 	struct drm_framebuffer *fb;
59 	struct drm_gem_object *gem;
60 	unsigned int width = cmd->width;
61 	unsigned int height = cmd->height;
62 	unsigned int size, bpp;
63 	int ret;
64 
65 	if (info->num_planes != 1)
66 		return ERR_PTR(-EINVAL);
67 
68 	gem = drm_gem_object_lookup(file, cmd->handles[0]);
69 	if (!gem)
70 		return ERR_PTR(-ENOENT);
71 
72 	bpp = info->cpp[0];
73 	size = (height - 1) * cmd->pitches[0] + width * bpp;
74 	size += cmd->offsets[0];
75 
76 	if (gem->size < size) {
77 		ret = -EINVAL;
78 		goto unreference;
79 	}
80 
81 	fb = mtk_drm_framebuffer_init(dev, cmd, gem);
82 	if (IS_ERR(fb)) {
83 		ret = PTR_ERR(fb);
84 		goto unreference;
85 	}
86 
87 	return fb;
88 
89 unreference:
90 	drm_gem_object_put_unlocked(gem);
91 	return ERR_PTR(ret);
92 }
93