1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd |
4 | * Author:Mark Yao <mark.yao@rock-chips.com> |
5 | */ |
6 | |
7 | #include <linux/kernel.h> |
8 | |
9 | #include <drm/drm.h> |
10 | #include <drm/drm_atomic.h> |
11 | #include <drm/drm_damage_helper.h> |
12 | #include <drm/drm_fourcc.h> |
13 | #include <drm/drm_framebuffer.h> |
14 | #include <drm/drm_gem_framebuffer_helper.h> |
15 | #include <drm/drm_probe_helper.h> |
16 | |
17 | #include "rockchip_drm_drv.h" |
18 | #include "rockchip_drm_fb.h" |
19 | #include "rockchip_drm_gem.h" |
20 | |
21 | static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { |
22 | .destroy = drm_gem_fb_destroy, |
23 | .create_handle = drm_gem_fb_create_handle, |
24 | .dirty = drm_atomic_helper_dirtyfb, |
25 | }; |
26 | |
27 | static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { |
28 | .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, |
29 | }; |
30 | |
31 | static struct drm_framebuffer * |
32 | rockchip_fb_create(struct drm_device *dev, struct drm_file *file, |
33 | const struct drm_mode_fb_cmd2 *mode_cmd) |
34 | { |
35 | struct drm_afbc_framebuffer *afbc_fb; |
36 | const struct drm_format_info *info; |
37 | int ret; |
38 | |
39 | info = drm_get_format_info(dev, mode_cmd); |
40 | if (!info) |
41 | return ERR_PTR(error: -ENOMEM); |
42 | |
43 | afbc_fb = kzalloc(size: sizeof(*afbc_fb), GFP_KERNEL); |
44 | if (!afbc_fb) |
45 | return ERR_PTR(error: -ENOMEM); |
46 | |
47 | ret = drm_gem_fb_init_with_funcs(dev, fb: &afbc_fb->base, file, mode_cmd, |
48 | funcs: &rockchip_drm_fb_funcs); |
49 | if (ret) { |
50 | kfree(objp: afbc_fb); |
51 | return ERR_PTR(error: ret); |
52 | } |
53 | |
54 | if (drm_is_afbc(mode_cmd->modifier[0])) { |
55 | int ret, i; |
56 | |
57 | ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); |
58 | if (ret) { |
59 | struct drm_gem_object **obj = afbc_fb->base.obj; |
60 | |
61 | for (i = 0; i < info->num_planes; ++i) |
62 | drm_gem_object_put(obj: obj[i]); |
63 | |
64 | kfree(objp: afbc_fb); |
65 | return ERR_PTR(error: ret); |
66 | } |
67 | } |
68 | |
69 | return &afbc_fb->base; |
70 | } |
71 | |
72 | static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { |
73 | .fb_create = rockchip_fb_create, |
74 | .atomic_check = drm_atomic_helper_check, |
75 | .atomic_commit = drm_atomic_helper_commit, |
76 | }; |
77 | |
78 | void rockchip_drm_mode_config_init(struct drm_device *dev) |
79 | { |
80 | dev->mode_config.min_width = 0; |
81 | dev->mode_config.min_height = 0; |
82 | |
83 | /* |
84 | * set max width and height as default value(4096x4096). |
85 | * this value would be used to check framebuffer size limitation |
86 | * at drm_mode_addfb(). |
87 | */ |
88 | dev->mode_config.max_width = 4096; |
89 | dev->mode_config.max_height = 4096; |
90 | |
91 | dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; |
92 | dev->mode_config.helper_private = &rockchip_mode_config_helpers; |
93 | |
94 | dev->mode_config.normalize_zpos = true; |
95 | } |
96 | |