2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author:Mark Yao <mark.yao@rock-chips.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/kernel.h>
18 #include <drm/drm_atomic.h>
19 #include <drm/drm_fb_helper.h>
20 #include <drm/drm_gem_framebuffer_helper.h>
21 #include <drm/drm_probe_helper.h>
23 #include "rockchip_drm_drv.h"
24 #include "rockchip_drm_fb.h"
25 #include "rockchip_drm_gem.h"
26 #include "rockchip_drm_psr.h"
28 static int rockchip_drm_fb_dirty(struct drm_framebuffer
*fb
,
29 struct drm_file
*file
,
30 unsigned int flags
, unsigned int color
,
31 struct drm_clip_rect
*clips
,
32 unsigned int num_clips
)
34 rockchip_drm_psr_flush_all(fb
->dev
);
38 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs
= {
39 .destroy
= drm_gem_fb_destroy
,
40 .create_handle
= drm_gem_fb_create_handle
,
41 .dirty
= rockchip_drm_fb_dirty
,
44 static struct drm_framebuffer
*
45 rockchip_fb_alloc(struct drm_device
*dev
, const struct drm_mode_fb_cmd2
*mode_cmd
,
46 struct drm_gem_object
**obj
, unsigned int num_planes
)
48 struct drm_framebuffer
*fb
;
52 fb
= kzalloc(sizeof(*fb
), GFP_KERNEL
);
54 return ERR_PTR(-ENOMEM
);
56 drm_helper_mode_fill_fb_struct(dev
, fb
, mode_cmd
);
58 for (i
= 0; i
< num_planes
; i
++)
61 ret
= drm_framebuffer_init(dev
, fb
, &rockchip_drm_fb_funcs
);
63 DRM_DEV_ERROR(dev
->dev
,
64 "Failed to initialize framebuffer: %d\n",
73 static struct drm_framebuffer
*
74 rockchip_user_fb_create(struct drm_device
*dev
, struct drm_file
*file_priv
,
75 const struct drm_mode_fb_cmd2
*mode_cmd
)
77 struct drm_framebuffer
*fb
;
78 struct drm_gem_object
*objs
[ROCKCHIP_MAX_FB_BUFFER
];
79 struct drm_gem_object
*obj
;
86 hsub
= drm_format_horz_chroma_subsampling(mode_cmd
->pixel_format
);
87 vsub
= drm_format_vert_chroma_subsampling(mode_cmd
->pixel_format
);
88 num_planes
= min(drm_format_num_planes(mode_cmd
->pixel_format
),
89 ROCKCHIP_MAX_FB_BUFFER
);
91 for (i
= 0; i
< num_planes
; i
++) {
92 unsigned int width
= mode_cmd
->width
/ (i
? hsub
: 1);
93 unsigned int height
= mode_cmd
->height
/ (i
? vsub
: 1);
94 unsigned int min_size
;
96 obj
= drm_gem_object_lookup(file_priv
, mode_cmd
->handles
[i
]);
98 DRM_DEV_ERROR(dev
->dev
,
99 "Failed to lookup GEM object\n");
101 goto err_gem_object_unreference
;
104 min_size
= (height
- 1) * mode_cmd
->pitches
[i
] +
105 mode_cmd
->offsets
[i
] +
106 width
* drm_format_plane_cpp(mode_cmd
->pixel_format
, i
);
108 if (obj
->size
< min_size
) {
109 drm_gem_object_put_unlocked(obj
);
111 goto err_gem_object_unreference
;
116 fb
= rockchip_fb_alloc(dev
, mode_cmd
, objs
, i
);
119 goto err_gem_object_unreference
;
124 err_gem_object_unreference
:
125 for (i
--; i
>= 0; i
--)
126 drm_gem_object_put_unlocked(objs
[i
]);
131 rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state
*old_state
)
133 struct drm_device
*dev
= old_state
->dev
;
135 rockchip_drm_psr_inhibit_get_state(old_state
);
137 drm_atomic_helper_commit_modeset_disables(dev
, old_state
);
139 drm_atomic_helper_commit_modeset_enables(dev
, old_state
);
141 drm_atomic_helper_commit_planes(dev
, old_state
,
142 DRM_PLANE_COMMIT_ACTIVE_ONLY
);
144 rockchip_drm_psr_inhibit_put_state(old_state
);
146 drm_atomic_helper_commit_hw_done(old_state
);
148 drm_atomic_helper_wait_for_vblanks(dev
, old_state
);
150 drm_atomic_helper_cleanup_planes(dev
, old_state
);
153 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers
= {
154 .atomic_commit_tail
= rockchip_atomic_helper_commit_tail_rpm
,
157 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs
= {
158 .fb_create
= rockchip_user_fb_create
,
159 .output_poll_changed
= drm_fb_helper_output_poll_changed
,
160 .atomic_check
= drm_atomic_helper_check
,
161 .atomic_commit
= drm_atomic_helper_commit
,
164 struct drm_framebuffer
*
165 rockchip_drm_framebuffer_init(struct drm_device
*dev
,
166 const struct drm_mode_fb_cmd2
*mode_cmd
,
167 struct drm_gem_object
*obj
)
169 struct drm_framebuffer
*fb
;
171 fb
= rockchip_fb_alloc(dev
, mode_cmd
, &obj
, 1);
178 void rockchip_drm_mode_config_init(struct drm_device
*dev
)
180 dev
->mode_config
.min_width
= 0;
181 dev
->mode_config
.min_height
= 0;
184 * set max width and height as default value(4096x4096).
185 * this value would be used to check framebuffer size limitation
186 * at drm_mode_addfb().
188 dev
->mode_config
.max_width
= 4096;
189 dev
->mode_config
.max_height
= 4096;
191 dev
->mode_config
.funcs
= &rockchip_drm_mode_config_funcs
;
192 dev
->mode_config
.helper_private
= &rockchip_mode_config_helpers
;