2 * Copyright (C) ROCKCHIP, Inc.
3 * Author:yzq<yzq@rock-chips.com>
5 * based on exynos_drm_fb.c
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <drm/drm_crtc.h>
18 #include <drm/drm_crtc_helper.h>
19 #include <drm/drm_fb_helper.h>
20 #include <uapi/drm/rockchip_drm.h>
22 #include "rockchip_drm_drv.h"
23 #include "rockchip_drm_fb.h"
24 #include "rockchip_drm_gem.h"
25 #include "rockchip_drm_iommu.h"
26 #include "rockchip_drm_encoder.h"
28 #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
31 * rockchip specific framebuffer structure.
33 * @fb: drm framebuffer obejct.
34 * @buf_cnt: a buffer count to drm framebuffer.
35 * @rockchip_gem_obj: array of rockchip specific gem object containing a gem object.
37 struct rockchip_drm_fb {
38 struct drm_framebuffer fb;
40 struct rockchip_drm_gem_obj *rockchip_gem_obj[MAX_FB_BUFFER];
43 static int check_fb_gem_memory_type(struct drm_device *drm_dev,
44 struct rockchip_drm_gem_obj *rockchip_gem_obj)
49 * if rockchip drm driver supports iommu then framebuffer can use
50 * all the buffer types.
52 if (is_drm_iommu_supported(drm_dev))
55 flags = rockchip_gem_obj->flags;
58 * without iommu support, not support physically non-continuous memory
61 if (IS_NONCONTIG_BUFFER(flags)) {
62 DRM_ERROR("cannot use this gem memory type for fb.\n");
69 static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
71 struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
74 DRM_DEBUG_KMS("%s\n", __FILE__);
76 /* make sure that overlay data are updated before relesing fb. */
77 rockchip_drm_encoder_complete_scanout(fb);
79 drm_framebuffer_cleanup(fb);
81 for (i = 0; i < ARRAY_SIZE(rockchip_fb->rockchip_gem_obj); i++) {
82 struct drm_gem_object *obj;
84 if (rockchip_fb->rockchip_gem_obj[i] == NULL)
87 obj = &rockchip_fb->rockchip_gem_obj[i]->base;
88 drm_gem_object_unreference_unlocked(obj);
95 static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
96 struct drm_file *file_priv,
99 struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
101 DRM_DEBUG_KMS("%s\n", __FILE__);
103 /* This fb should have only one gem object. */
104 if (WARN_ON(rockchip_fb->buf_cnt != 1))
107 return drm_gem_handle_create(file_priv,
108 &rockchip_fb->rockchip_gem_obj[0]->base, handle);
111 static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
112 struct drm_file *file_priv, unsigned flags,
113 unsigned color, struct drm_clip_rect *clips,
116 DRM_DEBUG_KMS("%s\n", __FILE__);
123 static struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
124 .destroy = rockchip_drm_fb_destroy,
125 .create_handle = rockchip_drm_fb_create_handle,
126 .dirty = rockchip_drm_fb_dirty,
129 void rockchip_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
132 struct rockchip_drm_fb *rockchip_fb;
134 rockchip_fb = to_rockchip_fb(fb);
136 rockchip_fb->buf_cnt = cnt;
139 unsigned int rockchip_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
141 struct rockchip_drm_fb *rockchip_fb;
143 rockchip_fb = to_rockchip_fb(fb);
145 return rockchip_fb->buf_cnt;
148 struct drm_framebuffer *
149 rockchip_drm_framebuffer_init(struct drm_device *dev,
150 struct drm_mode_fb_cmd2 *mode_cmd,
151 struct drm_gem_object *obj)
153 struct rockchip_drm_fb *rockchip_fb;
154 struct rockchip_drm_gem_obj *rockchip_gem_obj;
157 rockchip_gem_obj = to_rockchip_gem_obj(obj);
159 ret = check_fb_gem_memory_type(dev, rockchip_gem_obj);
161 DRM_ERROR("cannot use this gem memory type for fb.\n");
162 return ERR_PTR(-EINVAL);
165 rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
167 DRM_ERROR("failed to allocate rockchip drm framebuffer\n");
168 return ERR_PTR(-ENOMEM);
171 drm_helper_mode_fill_fb_struct(&rockchip_fb->fb, mode_cmd);
172 rockchip_fb->rockchip_gem_obj[0] = rockchip_gem_obj;
174 ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs);
176 DRM_ERROR("failed to initialize framebuffer\n");
180 return &rockchip_fb->fb;
183 static u32 rockchip_drm_format_num_buffers(struct drm_mode_fb_cmd2 *mode_cmd)
185 unsigned int cnt = 0;
187 if (mode_cmd->pixel_format != DRM_FORMAT_NV12)
188 return drm_format_num_planes(mode_cmd->pixel_format);
190 while (cnt != MAX_FB_BUFFER) {
191 if (!mode_cmd->handles[cnt])
197 * check if NV12 or NV12M.
200 * handles[0] = base1, offsets[0] = 0
201 * handles[1] = base1, offsets[1] = Y_size
204 * handles[0] = base1, offsets[0] = 0
205 * handles[1] = base2, offsets[1] = 0
209 * in case of NV12 format, offsets[1] is not 0 and
210 * handles[0] is same as handles[1].
212 if (mode_cmd->offsets[1] &&
213 mode_cmd->handles[0] == mode_cmd->handles[1])
220 static struct drm_framebuffer *
221 rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
222 struct drm_mode_fb_cmd2 *mode_cmd)
224 struct drm_gem_object *obj;
225 struct rockchip_drm_gem_obj *rockchip_gem_obj;
226 struct rockchip_drm_fb *rockchip_fb;
229 DRM_DEBUG_KMS("%s\n", __FILE__);
231 rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
233 DRM_ERROR("failed to allocate rockchip drm framebuffer\n");
234 return ERR_PTR(-ENOMEM);
237 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
239 DRM_ERROR("failed to lookup gem object\n");
244 drm_helper_mode_fill_fb_struct(&rockchip_fb->fb, mode_cmd);
245 rockchip_fb->rockchip_gem_obj[0] = to_rockchip_gem_obj(obj);
246 rockchip_fb->buf_cnt = rockchip_drm_format_num_buffers(mode_cmd);
248 DRM_DEBUG_KMS("buf_cnt = %d\n", rockchip_fb->buf_cnt);
250 for (i = 1; i < rockchip_fb->buf_cnt; i++) {
251 obj = drm_gem_object_lookup(dev, file_priv,
252 mode_cmd->handles[i]);
254 DRM_ERROR("failed to lookup gem object\n");
256 rockchip_fb->buf_cnt = i;
257 goto err_unreference;
260 rockchip_gem_obj = to_rockchip_gem_obj(obj);
261 rockchip_fb->rockchip_gem_obj[i] = rockchip_gem_obj;
263 ret = check_fb_gem_memory_type(dev, rockchip_gem_obj);
265 DRM_ERROR("cannot use this gem memory type for fb.\n");
266 goto err_unreference;
270 ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs);
272 DRM_ERROR("failed to init framebuffer.\n");
273 goto err_unreference;
276 return &rockchip_fb->fb;
279 for (i = 0; i < rockchip_fb->buf_cnt; i++) {
280 struct drm_gem_object *obj;
282 obj = &rockchip_fb->rockchip_gem_obj[i]->base;
284 drm_gem_object_unreference_unlocked(obj);
291 struct rockchip_drm_gem_buf *rockchip_drm_fb_buffer(struct drm_framebuffer *fb,
294 struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
295 struct rockchip_drm_gem_buf *buffer;
297 DRM_DEBUG_KMS("%s\n", __FILE__);
299 if (index >= MAX_FB_BUFFER)
302 buffer = rockchip_fb->rockchip_gem_obj[index]->buffer;
306 DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
311 static void rockchip_drm_output_poll_changed(struct drm_device *dev)
313 struct rockchip_drm_private *private = dev->dev_private;
314 struct drm_fb_helper *fb_helper = private->fb_helper;
317 drm_fb_helper_hotplug_event(fb_helper);
320 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
321 .fb_create = rockchip_user_fb_create,
322 .output_poll_changed = rockchip_drm_output_poll_changed,
325 void rockchip_drm_mode_config_init(struct drm_device *dev)
327 dev->mode_config.min_width = 0;
328 dev->mode_config.min_height = 0;
331 * set max width and height as default value(4096x4096).
332 * this value would be used to check framebuffer size limitation
333 * at drm_mode_addfb().
335 dev->mode_config.max_width = 4096;
336 dev->mode_config.max_height = 4096;
338 dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;