2 * Copyright (c) 2015 MediaTek Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <drm/drm_modeset_helper.h>
16 #include <drm/drm_fb_helper.h>
17 #include <drm/drm_gem.h>
18 #include <drm/drm_gem_framebuffer_helper.h>
19 #include <linux/dma-buf.h>
20 #include <linux/reservation.h>
22 #include "mtk_drm_drv.h"
23 #include "mtk_drm_fb.h"
24 #include "mtk_drm_gem.h"
26 static const struct drm_framebuffer_funcs mtk_drm_fb_funcs
= {
27 .create_handle
= drm_gem_fb_create_handle
,
28 .destroy
= drm_gem_fb_destroy
,
31 static struct drm_framebuffer
*mtk_drm_framebuffer_init(struct drm_device
*dev
,
32 const struct drm_mode_fb_cmd2
*mode
,
33 struct drm_gem_object
*obj
)
35 struct drm_framebuffer
*fb
;
38 if (drm_format_num_planes(mode
->pixel_format
) != 1)
39 return ERR_PTR(-EINVAL
);
41 fb
= kzalloc(sizeof(*fb
), GFP_KERNEL
);
43 return ERR_PTR(-ENOMEM
);
45 drm_helper_mode_fill_fb_struct(dev
, fb
, mode
);
49 ret
= drm_framebuffer_init(dev
, fb
, &mtk_drm_fb_funcs
);
51 DRM_ERROR("failed to initialize framebuffer\n");
60 * Wait for any exclusive fence in fb's gem object's reservation object.
62 * Returns -ERESTARTSYS if interrupted, else 0.
64 int mtk_fb_wait(struct drm_framebuffer
*fb
)
66 struct drm_gem_object
*gem
;
67 struct reservation_object
*resv
;
74 if (!gem
|| !gem
->dma_buf
|| !gem
->dma_buf
->resv
)
77 resv
= gem
->dma_buf
->resv
;
78 ret
= reservation_object_wait_timeout_rcu(resv
, false, true,
79 MAX_SCHEDULE_TIMEOUT
);
80 /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */
87 struct drm_framebuffer
*mtk_drm_mode_fb_create(struct drm_device
*dev
,
88 struct drm_file
*file
,
89 const struct drm_mode_fb_cmd2
*cmd
)
91 struct drm_framebuffer
*fb
;
92 struct drm_gem_object
*gem
;
93 unsigned int width
= cmd
->width
;
94 unsigned int height
= cmd
->height
;
95 unsigned int size
, bpp
;
98 if (drm_format_num_planes(cmd
->pixel_format
) != 1)
99 return ERR_PTR(-EINVAL
);
101 gem
= drm_gem_object_lookup(file
, cmd
->handles
[0]);
103 return ERR_PTR(-ENOENT
);
105 bpp
= drm_format_plane_cpp(cmd
->pixel_format
, 0);
106 size
= (height
- 1) * cmd
->pitches
[0] + width
* bpp
;
107 size
+= cmd
->offsets
[0];
109 if (gem
->size
< size
) {
114 fb
= mtk_drm_framebuffer_init(dev
, cmd
, gem
);
123 drm_gem_object_put_unlocked(gem
);