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