]> Git Repo - J-linux.git/blob - drivers/gpu/drm/mediatek/mtk_drm_fb.c
Merge branch 'for-next' into for-linus
[J-linux.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 /*
53  * Wait for any exclusive fence in fb's gem object's reservation object.
54  *
55  * Returns -ERESTARTSYS if interrupted, else 0.
56  */
57 int mtk_fb_wait(struct drm_framebuffer *fb)
58 {
59         struct drm_gem_object *gem;
60         struct reservation_object *resv;
61         long ret;
62
63         if (!fb)
64                 return 0;
65
66         gem = fb->obj[0];
67         if (!gem || !gem->dma_buf || !gem->dma_buf->resv)
68                 return 0;
69
70         resv = gem->dma_buf->resv;
71         ret = reservation_object_wait_timeout_rcu(resv, false, true,
72                                                   MAX_SCHEDULE_TIMEOUT);
73         /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */
74         if (WARN_ON(ret < 0))
75                 return ret;
76
77         return 0;
78 }
79
80 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
81                                                struct drm_file *file,
82                                                const struct drm_mode_fb_cmd2 *cmd)
83 {
84         const struct drm_format_info *info = drm_get_format_info(dev, cmd);
85         struct drm_framebuffer *fb;
86         struct drm_gem_object *gem;
87         unsigned int width = cmd->width;
88         unsigned int height = cmd->height;
89         unsigned int size, bpp;
90         int ret;
91
92         if (info->num_planes != 1)
93                 return ERR_PTR(-EINVAL);
94
95         gem = drm_gem_object_lookup(file, cmd->handles[0]);
96         if (!gem)
97                 return ERR_PTR(-ENOENT);
98
99         bpp = info->cpp[0];
100         size = (height - 1) * cmd->pitches[0] + width * bpp;
101         size += cmd->offsets[0];
102
103         if (gem->size < size) {
104                 ret = -EINVAL;
105                 goto unreference;
106         }
107
108         fb = mtk_drm_framebuffer_init(dev, cmd, gem);
109         if (IS_ERR(fb)) {
110                 ret = PTR_ERR(fb);
111                 goto unreference;
112         }
113
114         return fb;
115
116 unreference:
117         drm_gem_object_put_unlocked(gem);
118         return ERR_PTR(ret);
119 }
This page took 0.036717 seconds and 4 git commands to generate.