Commit | Line | Data |
---|---|---|
9c92ab61 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2048e328 MY |
2 | /* |
3 | * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd | |
4 | * Author:Mark Yao <mark.yao@rock-chips.com> | |
2048e328 MY |
5 | */ |
6 | ||
7 | #include <linux/kernel.h> | |
c2156ccd | 8 | |
2048e328 | 9 | #include <drm/drm.h> |
63ebb9fa | 10 | #include <drm/drm_atomic.h> |
6c83ca79 | 11 | #include <drm/drm_damage_helper.h> |
2048e328 | 12 | #include <drm/drm_fb_helper.h> |
c2156ccd | 13 | #include <drm/drm_fourcc.h> |
4c7c9a63 | 14 | #include <drm/drm_gem_framebuffer_helper.h> |
fcd70cd3 | 15 | #include <drm/drm_probe_helper.h> |
2048e328 MY |
16 | |
17 | #include "rockchip_drm_drv.h" | |
a7e03fb5 | 18 | #include "rockchip_drm_fb.h" |
2048e328 MY |
19 | #include "rockchip_drm_gem.h" |
20 | ||
28c508ec | 21 | static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { |
4c7c9a63 DS |
22 | .destroy = drm_gem_fb_destroy, |
23 | .create_handle = drm_gem_fb_create_handle, | |
6c83ca79 | 24 | .dirty = drm_atomic_helper_dirtyfb, |
2048e328 MY |
25 | }; |
26 | ||
957428f9 | 27 | static struct drm_framebuffer * |
1eb83451 | 28 | rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, |
2048e328 MY |
29 | struct drm_gem_object **obj, unsigned int num_planes) |
30 | { | |
957428f9 | 31 | struct drm_framebuffer *fb; |
2048e328 MY |
32 | int ret; |
33 | int i; | |
34 | ||
957428f9 DS |
35 | fb = kzalloc(sizeof(*fb), GFP_KERNEL); |
36 | if (!fb) | |
2048e328 MY |
37 | return ERR_PTR(-ENOMEM); |
38 | ||
957428f9 | 39 | drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); |
2048e328 MY |
40 | |
41 | for (i = 0; i < num_planes; i++) | |
957428f9 | 42 | fb->obj[i] = obj[i]; |
2048e328 | 43 | |
957428f9 | 44 | ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs); |
2048e328 | 45 | if (ret) { |
d8dd6804 HM |
46 | DRM_DEV_ERROR(dev->dev, |
47 | "Failed to initialize framebuffer: %d\n", | |
48 | ret); | |
957428f9 | 49 | kfree(fb); |
2048e328 MY |
50 | return ERR_PTR(ret); |
51 | } | |
52 | ||
957428f9 | 53 | return fb; |
2048e328 MY |
54 | } |
55 | ||
a4b10cce | 56 | static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { |
c87fb38d | 57 | .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, |
893b6cad | 58 | }; |
63ebb9fa | 59 | |
7707f722 AP |
60 | static struct drm_framebuffer * |
61 | rockchip_fb_create(struct drm_device *dev, struct drm_file *file, | |
62 | const struct drm_mode_fb_cmd2 *mode_cmd) | |
63 | { | |
64 | struct drm_afbc_framebuffer *afbc_fb; | |
65 | const struct drm_format_info *info; | |
66 | int ret; | |
67 | ||
68 | info = drm_get_format_info(dev, mode_cmd); | |
69 | if (!info) | |
70 | return ERR_PTR(-ENOMEM); | |
71 | ||
72 | afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL); | |
73 | if (!afbc_fb) | |
74 | return ERR_PTR(-ENOMEM); | |
75 | ||
76 | ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd, | |
77 | &rockchip_drm_fb_funcs); | |
78 | if (ret) { | |
79 | kfree(afbc_fb); | |
80 | return ERR_PTR(ret); | |
81 | } | |
82 | ||
83 | if (drm_is_afbc(mode_cmd->modifier[0])) { | |
84 | int ret, i; | |
85 | ||
86 | ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); | |
87 | if (ret) { | |
88 | struct drm_gem_object **obj = afbc_fb->base.obj; | |
89 | ||
90 | for (i = 0; i < info->num_planes; ++i) | |
91 | drm_gem_object_put_unlocked(obj[i]); | |
92 | ||
93 | kfree(afbc_fb); | |
94 | return ERR_PTR(ret); | |
95 | } | |
96 | } | |
97 | ||
98 | return &afbc_fb->base; | |
99 | } | |
100 | ||
2048e328 | 101 | static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { |
7707f722 | 102 | .fb_create = rockchip_fb_create, |
33e9d038 | 103 | .output_poll_changed = drm_fb_helper_output_poll_changed, |
63ebb9fa | 104 | .atomic_check = drm_atomic_helper_check, |
893b6cad | 105 | .atomic_commit = drm_atomic_helper_commit, |
2048e328 MY |
106 | }; |
107 | ||
108 | struct drm_framebuffer * | |
109 | rockchip_drm_framebuffer_init(struct drm_device *dev, | |
1eb83451 | 110 | const struct drm_mode_fb_cmd2 *mode_cmd, |
2048e328 MY |
111 | struct drm_gem_object *obj) |
112 | { | |
957428f9 | 113 | struct drm_framebuffer *fb; |
2048e328 | 114 | |
957428f9 DS |
115 | fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1); |
116 | if (IS_ERR(fb)) | |
117 | return ERR_CAST(fb); | |
2048e328 | 118 | |
957428f9 | 119 | return fb; |
2048e328 MY |
120 | } |
121 | ||
122 | void rockchip_drm_mode_config_init(struct drm_device *dev) | |
123 | { | |
124 | dev->mode_config.min_width = 0; | |
125 | dev->mode_config.min_height = 0; | |
126 | ||
127 | /* | |
128 | * set max width and height as default value(4096x4096). | |
129 | * this value would be used to check framebuffer size limitation | |
130 | * at drm_mode_addfb(). | |
131 | */ | |
132 | dev->mode_config.max_width = 4096; | |
133 | dev->mode_config.max_height = 4096; | |
134 | ||
135 | dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; | |
893b6cad | 136 | dev->mode_config.helper_private = &rockchip_mode_config_helpers; |
2048e328 | 137 | } |