Merge tag 'lsk-v3.10-15.10-android'
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / rockchip_drm_fb.c
1 /*
2  * Copyright (C) ROCKCHIP, Inc.
3  * Author:yzq<yzq@rock-chips.com>
4  *
5  * based on exynos_drm_fb.c
6  *
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.
10  *
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.
15  */
16 #include <drm/drmP.h>
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>
21
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"
27
28 #define to_rockchip_fb(x)       container_of(x, struct rockchip_drm_fb, fb)
29
30 /*
31  * rockchip specific framebuffer structure.
32  *
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.
36  */
37 struct rockchip_drm_fb {
38         struct drm_framebuffer          fb;
39         unsigned int                    buf_cnt;
40         struct rockchip_drm_gem_obj     *rockchip_gem_obj[MAX_FB_BUFFER];
41 };
42
43 static int check_fb_gem_memory_type(struct drm_device *drm_dev,
44                                 struct rockchip_drm_gem_obj *rockchip_gem_obj)
45 {
46         unsigned int flags;
47
48         /*
49          * if rockchip drm driver supports iommu then framebuffer can use
50          * all the buffer types.
51          */
52         if (is_drm_iommu_supported(drm_dev))
53                 return 0;
54
55         flags = rockchip_gem_obj->flags;
56
57         /*
58          * without iommu support, not support physically non-continuous memory
59          * for framebuffer.
60          */
61         if (IS_NONCONTIG_BUFFER(flags)) {
62                 DRM_ERROR("cannot use this gem memory type for fb.\n");
63                 return -EINVAL;
64         }
65
66         return 0;
67 }
68
69 static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
70 {
71         struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
72         unsigned int i;
73
74         DRM_DEBUG_KMS("%s\n", __FILE__);
75
76         /* make sure that overlay data are updated before relesing fb. */
77         rockchip_drm_encoder_complete_scanout(fb);
78
79         drm_framebuffer_cleanup(fb);
80
81         for (i = 0; i < ARRAY_SIZE(rockchip_fb->rockchip_gem_obj); i++) {
82                 struct drm_gem_object *obj;
83
84                 if (rockchip_fb->rockchip_gem_obj[i] == NULL)
85                         continue;
86
87                 obj = &rockchip_fb->rockchip_gem_obj[i]->base;
88                 drm_gem_object_unreference_unlocked(obj);
89         }
90
91         kfree(rockchip_fb);
92         rockchip_fb = NULL;
93 }
94
95 static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
96                                         struct drm_file *file_priv,
97                                         unsigned int *handle)
98 {
99         struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
100
101         DRM_DEBUG_KMS("%s\n", __FILE__);
102
103         /* This fb should have only one gem object. */
104         if (WARN_ON(rockchip_fb->buf_cnt != 1))
105                 return -EINVAL;
106
107         return drm_gem_handle_create(file_priv,
108                         &rockchip_fb->rockchip_gem_obj[0]->base, handle);
109 }
110
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,
114                                 unsigned num_clips)
115 {
116         DRM_DEBUG_KMS("%s\n", __FILE__);
117
118         /* TODO */
119
120         return 0;
121 }
122
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,
127 };
128
129 void rockchip_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
130                                                 unsigned int cnt)
131 {
132         struct rockchip_drm_fb *rockchip_fb;
133
134         rockchip_fb = to_rockchip_fb(fb);
135
136         rockchip_fb->buf_cnt = cnt;
137 }
138
139 unsigned int rockchip_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
140 {
141         struct rockchip_drm_fb *rockchip_fb;
142
143         rockchip_fb = to_rockchip_fb(fb);
144
145         return rockchip_fb->buf_cnt;
146 }
147
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)
152 {
153         struct rockchip_drm_fb *rockchip_fb;
154         struct rockchip_drm_gem_obj *rockchip_gem_obj;
155         int ret;
156
157         rockchip_gem_obj = to_rockchip_gem_obj(obj);
158
159         ret = check_fb_gem_memory_type(dev, rockchip_gem_obj);
160         if (ret < 0) {
161                 DRM_ERROR("cannot use this gem memory type for fb.\n");
162                 return ERR_PTR(-EINVAL);
163         }
164
165         rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
166         if (!rockchip_fb) {
167                 DRM_ERROR("failed to allocate rockchip drm framebuffer\n");
168                 return ERR_PTR(-ENOMEM);
169         }
170
171         drm_helper_mode_fill_fb_struct(&rockchip_fb->fb, mode_cmd);
172         rockchip_fb->rockchip_gem_obj[0] = rockchip_gem_obj;
173
174         ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs);
175         if (ret) {
176                 DRM_ERROR("failed to initialize framebuffer\n");
177                 return ERR_PTR(ret);
178         }
179
180         return &rockchip_fb->fb;
181 }
182
183 static u32 rockchip_drm_format_num_buffers(struct drm_mode_fb_cmd2 *mode_cmd)
184 {
185         unsigned int cnt = 0;
186
187         if (mode_cmd->pixel_format != DRM_FORMAT_NV12)
188                 return drm_format_num_planes(mode_cmd->pixel_format);
189
190         while (cnt != MAX_FB_BUFFER) {
191                 if (!mode_cmd->handles[cnt])
192                         break;
193                 cnt++;
194         }
195
196         /*
197          * check if NV12 or NV12M.
198          *
199          * NV12
200          * handles[0] = base1, offsets[0] = 0
201          * handles[1] = base1, offsets[1] = Y_size
202          *
203          * NV12M
204          * handles[0] = base1, offsets[0] = 0
205          * handles[1] = base2, offsets[1] = 0
206          */
207         if (cnt == 2) {
208                 /*
209                  * in case of NV12 format, offsets[1] is not 0 and
210                  * handles[0] is same as handles[1].
211                  */
212                 if (mode_cmd->offsets[1] &&
213                         mode_cmd->handles[0] == mode_cmd->handles[1])
214                         cnt = 1;
215         }
216
217         return cnt;
218 }
219
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)
223 {
224         struct drm_gem_object *obj;
225         struct rockchip_drm_gem_obj *rockchip_gem_obj;
226         struct rockchip_drm_fb *rockchip_fb;
227         int i, ret;
228
229         DRM_DEBUG_KMS("%s\n", __FILE__);
230
231         rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
232         if (!rockchip_fb) {
233                 DRM_ERROR("failed to allocate rockchip drm framebuffer\n");
234                 return ERR_PTR(-ENOMEM);
235         }
236
237         obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
238         if (!obj) {
239                 DRM_ERROR("failed to lookup gem object\n");
240                 ret = -ENOENT;
241                 goto err_free;
242         }
243
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);
247
248         DRM_DEBUG_KMS("buf_cnt = %d\n", rockchip_fb->buf_cnt);
249
250         for (i = 1; i < rockchip_fb->buf_cnt; i++) {
251                 obj = drm_gem_object_lookup(dev, file_priv,
252                                 mode_cmd->handles[i]);
253                 if (!obj) {
254                         DRM_ERROR("failed to lookup gem object\n");
255                         ret = -ENOENT;
256                         rockchip_fb->buf_cnt = i;
257                         goto err_unreference;
258                 }
259
260                 rockchip_gem_obj = to_rockchip_gem_obj(obj);
261                 rockchip_fb->rockchip_gem_obj[i] = rockchip_gem_obj;
262
263                 ret = check_fb_gem_memory_type(dev, rockchip_gem_obj);
264                 if (ret < 0) {
265                         DRM_ERROR("cannot use this gem memory type for fb.\n");
266                         goto err_unreference;
267                 }
268         }
269
270         ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs);
271         if (ret) {
272                 DRM_ERROR("failed to init framebuffer.\n");
273                 goto err_unreference;
274         }
275
276         return &rockchip_fb->fb;
277
278 err_unreference:
279         for (i = 0; i < rockchip_fb->buf_cnt; i++) {
280                 struct drm_gem_object *obj;
281
282                 obj = &rockchip_fb->rockchip_gem_obj[i]->base;
283                 if (obj)
284                         drm_gem_object_unreference_unlocked(obj);
285         }
286 err_free:
287         kfree(rockchip_fb);
288         return ERR_PTR(ret);
289 }
290
291 struct rockchip_drm_gem_buf *rockchip_drm_fb_buffer(struct drm_framebuffer *fb,
292                                                 int index)
293 {
294         struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
295         struct rockchip_drm_gem_buf *buffer;
296
297         DRM_DEBUG_KMS("%s\n", __FILE__);
298
299         if (index >= MAX_FB_BUFFER)
300                 return NULL;
301
302         buffer = rockchip_fb->rockchip_gem_obj[index]->buffer;
303         if (!buffer)
304                 return NULL;
305
306         DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
307
308         return buffer;
309 }
310
311 static void rockchip_drm_output_poll_changed(struct drm_device *dev)
312 {
313         struct rockchip_drm_private *private = dev->dev_private;
314         struct drm_fb_helper *fb_helper = private->fb_helper;
315
316         if (fb_helper)
317                 drm_fb_helper_hotplug_event(fb_helper);
318 }
319
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,
323 };
324
325 void rockchip_drm_mode_config_init(struct drm_device *dev)
326 {
327         dev->mode_config.min_width = 0;
328         dev->mode_config.min_height = 0;
329
330         /*
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().
334          */
335         dev->mode_config.max_width = 4096;
336         dev->mode_config.max_height = 4096;
337
338         dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
339 }