Mention branches and keyring.
[releases.git] / gpu / drm / rcar-du / rcar_du_vsp.c
1 /*
2  * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
3  *
4  * Copyright (C) 2015 Renesas Electronics Corporation
5  *
6  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <drm/drmP.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_crtc.h>
17 #include <drm/drm_crtc_helper.h>
18 #include <drm/drm_fb_cma_helper.h>
19 #include <drm/drm_gem_cma_helper.h>
20 #include <drm/drm_gem_framebuffer_helper.h>
21 #include <drm/drm_plane_helper.h>
22
23 #include <linux/bitops.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/of_platform.h>
26 #include <linux/scatterlist.h>
27 #include <linux/videodev2.h>
28
29 #include <media/vsp1.h>
30
31 #include "rcar_du_drv.h"
32 #include "rcar_du_kms.h"
33 #include "rcar_du_vsp.h"
34
35 static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
36 {
37         struct rcar_du_crtc *crtc = private;
38
39         if (crtc->vblank_enable)
40                 drm_crtc_handle_vblank(&crtc->crtc);
41
42         if (completed)
43                 rcar_du_crtc_finish_page_flip(crtc);
44
45         drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc);
46 }
47
48 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
49 {
50         const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
51         struct rcar_du_device *rcdu = crtc->group->dev;
52         struct vsp1_du_lif_config cfg = {
53                 .width = mode->hdisplay,
54                 .height = mode->vdisplay,
55                 .callback = rcar_du_vsp_complete,
56                 .callback_data = crtc,
57         };
58         struct rcar_du_plane_state state = {
59                 .state = {
60                         .alpha = DRM_BLEND_ALPHA_OPAQUE,
61                         .crtc = &crtc->crtc,
62                         .dst.x1 = 0,
63                         .dst.y1 = 0,
64                         .dst.x2 = mode->hdisplay,
65                         .dst.y2 = mode->vdisplay,
66                         .src.x1 = 0,
67                         .src.y1 = 0,
68                         .src.x2 = mode->hdisplay << 16,
69                         .src.y2 = mode->vdisplay << 16,
70                         .zpos = 0,
71                 },
72                 .format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
73                 .source = RCAR_DU_PLANE_VSPD1,
74                 .colorkey = 0,
75         };
76
77         if (rcdu->info->gen >= 3)
78                 state.hwindex = (crtc->index % 2) ? 2 : 0;
79         else
80                 state.hwindex = crtc->index % 2;
81
82         __rcar_du_plane_setup(crtc->group, &state);
83
84         /*
85          * Ensure that the plane source configuration takes effect by requesting
86          * a restart of the group. See rcar_du_plane_atomic_update() for a more
87          * detailed explanation.
88          *
89          * TODO: Check whether this is still needed on Gen3.
90          */
91         crtc->group->need_restart = true;
92
93         vsp1_du_setup_lif(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
94 }
95
96 void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
97 {
98         vsp1_du_setup_lif(crtc->vsp->vsp, crtc->vsp_pipe, NULL);
99 }
100
101 void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
102 {
103         vsp1_du_atomic_begin(crtc->vsp->vsp, crtc->vsp_pipe);
104 }
105
106 void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
107 {
108         struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
109         struct rcar_du_crtc_state *state;
110
111         state = to_rcar_crtc_state(crtc->crtc.state);
112         cfg.crc = state->crc;
113
114         vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
115 }
116
117 /* Keep the two tables in sync. */
118 static const u32 formats_kms[] = {
119         DRM_FORMAT_RGB332,
120         DRM_FORMAT_ARGB4444,
121         DRM_FORMAT_XRGB4444,
122         DRM_FORMAT_ARGB1555,
123         DRM_FORMAT_XRGB1555,
124         DRM_FORMAT_RGB565,
125         DRM_FORMAT_BGR888,
126         DRM_FORMAT_RGB888,
127         DRM_FORMAT_BGRA8888,
128         DRM_FORMAT_BGRX8888,
129         DRM_FORMAT_ARGB8888,
130         DRM_FORMAT_XRGB8888,
131         DRM_FORMAT_UYVY,
132         DRM_FORMAT_VYUY,
133         DRM_FORMAT_YUYV,
134         DRM_FORMAT_YVYU,
135         DRM_FORMAT_NV12,
136         DRM_FORMAT_NV21,
137         DRM_FORMAT_NV16,
138         DRM_FORMAT_NV61,
139         DRM_FORMAT_YUV420,
140         DRM_FORMAT_YVU420,
141         DRM_FORMAT_YUV422,
142         DRM_FORMAT_YVU422,
143         DRM_FORMAT_YUV444,
144         DRM_FORMAT_YVU444,
145 };
146
147 static const u32 formats_v4l2[] = {
148         V4L2_PIX_FMT_RGB332,
149         V4L2_PIX_FMT_ARGB444,
150         V4L2_PIX_FMT_XRGB444,
151         V4L2_PIX_FMT_ARGB555,
152         V4L2_PIX_FMT_XRGB555,
153         V4L2_PIX_FMT_RGB565,
154         V4L2_PIX_FMT_RGB24,
155         V4L2_PIX_FMT_BGR24,
156         V4L2_PIX_FMT_ARGB32,
157         V4L2_PIX_FMT_XRGB32,
158         V4L2_PIX_FMT_ABGR32,
159         V4L2_PIX_FMT_XBGR32,
160         V4L2_PIX_FMT_UYVY,
161         V4L2_PIX_FMT_VYUY,
162         V4L2_PIX_FMT_YUYV,
163         V4L2_PIX_FMT_YVYU,
164         V4L2_PIX_FMT_NV12M,
165         V4L2_PIX_FMT_NV21M,
166         V4L2_PIX_FMT_NV16M,
167         V4L2_PIX_FMT_NV61M,
168         V4L2_PIX_FMT_YUV420M,
169         V4L2_PIX_FMT_YVU420M,
170         V4L2_PIX_FMT_YUV422M,
171         V4L2_PIX_FMT_YVU422M,
172         V4L2_PIX_FMT_YUV444M,
173         V4L2_PIX_FMT_YVU444M,
174 };
175
176 static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
177 {
178         struct rcar_du_vsp_plane_state *state =
179                 to_rcar_vsp_plane_state(plane->plane.state);
180         struct rcar_du_crtc *crtc = to_rcar_crtc(state->state.crtc);
181         struct drm_framebuffer *fb = plane->plane.state->fb;
182         struct vsp1_du_atomic_config cfg = {
183                 .pixelformat = 0,
184                 .pitch = fb->pitches[0],
185                 .alpha = state->state.alpha >> 8,
186                 .zpos = state->state.zpos,
187         };
188         unsigned int i;
189
190         cfg.src.left = state->state.src.x1 >> 16;
191         cfg.src.top = state->state.src.y1 >> 16;
192         cfg.src.width = drm_rect_width(&state->state.src) >> 16;
193         cfg.src.height = drm_rect_height(&state->state.src) >> 16;
194
195         cfg.dst.left = state->state.dst.x1;
196         cfg.dst.top = state->state.dst.y1;
197         cfg.dst.width = drm_rect_width(&state->state.dst);
198         cfg.dst.height = drm_rect_height(&state->state.dst);
199
200         for (i = 0; i < state->format->planes; ++i)
201                 cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
202                            + fb->offsets[i];
203
204         for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {
205                 if (formats_kms[i] == state->format->fourcc) {
206                         cfg.pixelformat = formats_v4l2[i];
207                         break;
208                 }
209         }
210
211         vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe,
212                               plane->index, &cfg);
213 }
214
215 static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
216                                         struct drm_plane_state *state)
217 {
218         struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
219         struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
220         struct rcar_du_device *rcdu = vsp->dev;
221         unsigned int i;
222         int ret;
223
224         /*
225          * There's no need to prepare (and unprepare) the framebuffer when the
226          * plane is not visible, as it will not be displayed.
227          */
228         if (!state->visible)
229                 return 0;
230
231         for (i = 0; i < rstate->format->planes; ++i) {
232                 struct drm_gem_cma_object *gem =
233                         drm_fb_cma_get_gem_obj(state->fb, i);
234                 struct sg_table *sgt = &rstate->sg_tables[i];
235
236                 ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr,
237                                       gem->base.size);
238                 if (ret)
239                         goto fail;
240
241                 ret = vsp1_du_map_sg(vsp->vsp, sgt);
242                 if (!ret) {
243                         sg_free_table(sgt);
244                         ret = -ENOMEM;
245                         goto fail;
246                 }
247         }
248
249         ret = drm_gem_fb_prepare_fb(plane, state);
250         if (ret)
251                 goto fail;
252
253         return 0;
254
255 fail:
256         while (i--) {
257                 struct sg_table *sgt = &rstate->sg_tables[i];
258
259                 vsp1_du_unmap_sg(vsp->vsp, sgt);
260                 sg_free_table(sgt);
261         }
262
263         return ret;
264 }
265
266 static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
267                                          struct drm_plane_state *state)
268 {
269         struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
270         struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
271         unsigned int i;
272
273         if (!state->visible)
274                 return;
275
276         for (i = 0; i < rstate->format->planes; ++i) {
277                 struct sg_table *sgt = &rstate->sg_tables[i];
278
279                 vsp1_du_unmap_sg(vsp->vsp, sgt);
280                 sg_free_table(sgt);
281         }
282 }
283
284 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
285                                           struct drm_plane_state *state)
286 {
287         struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
288
289         return __rcar_du_plane_atomic_check(plane, state, &rstate->format);
290 }
291
292 static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
293                                         struct drm_plane_state *old_state)
294 {
295         struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
296         struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc);
297
298         if (plane->state->visible)
299                 rcar_du_vsp_plane_setup(rplane);
300         else
301                 vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe,
302                                       rplane->index, NULL);
303 }
304
305 static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
306         .prepare_fb = rcar_du_vsp_plane_prepare_fb,
307         .cleanup_fb = rcar_du_vsp_plane_cleanup_fb,
308         .atomic_check = rcar_du_vsp_plane_atomic_check,
309         .atomic_update = rcar_du_vsp_plane_atomic_update,
310 };
311
312 static struct drm_plane_state *
313 rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
314 {
315         struct rcar_du_vsp_plane_state *copy;
316
317         if (WARN_ON(!plane->state))
318                 return NULL;
319
320         copy = kzalloc(sizeof(*copy), GFP_KERNEL);
321         if (copy == NULL)
322                 return NULL;
323
324         __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
325
326         return &copy->state;
327 }
328
329 static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
330                                                    struct drm_plane_state *state)
331 {
332         __drm_atomic_helper_plane_destroy_state(state);
333         kfree(to_rcar_vsp_plane_state(state));
334 }
335
336 static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
337 {
338         struct rcar_du_vsp_plane_state *state;
339
340         if (plane->state) {
341                 rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state);
342                 plane->state = NULL;
343         }
344
345         state = kzalloc(sizeof(*state), GFP_KERNEL);
346         if (state == NULL)
347                 return;
348
349         state->state.alpha = DRM_BLEND_ALPHA_OPAQUE;
350         state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
351
352         plane->state = &state->state;
353         plane->state->plane = plane;
354 }
355
356 static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
357         .update_plane = drm_atomic_helper_update_plane,
358         .disable_plane = drm_atomic_helper_disable_plane,
359         .reset = rcar_du_vsp_plane_reset,
360         .destroy = drm_plane_cleanup,
361         .atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state,
362         .atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state,
363 };
364
365 int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
366                      unsigned int crtcs)
367 {
368         struct rcar_du_device *rcdu = vsp->dev;
369         struct platform_device *pdev;
370         unsigned int num_crtcs = hweight32(crtcs);
371         unsigned int i;
372         int ret;
373
374         /* Find the VSP device and initialize it. */
375         pdev = of_find_device_by_node(np);
376         if (!pdev)
377                 return -ENXIO;
378
379         vsp->vsp = &pdev->dev;
380
381         ret = vsp1_du_init(vsp->vsp);
382         if (ret < 0)
383                 return ret;
384
385          /*
386           * The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
387           * 4 RPFs.
388           */
389         vsp->num_planes = rcdu->info->gen >= 3 ? 5 : 4;
390
391         vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
392                                    sizeof(*vsp->planes), GFP_KERNEL);
393         if (!vsp->planes)
394                 return -ENOMEM;
395
396         for (i = 0; i < vsp->num_planes; ++i) {
397                 enum drm_plane_type type = i < num_crtcs
398                                          ? DRM_PLANE_TYPE_PRIMARY
399                                          : DRM_PLANE_TYPE_OVERLAY;
400                 struct rcar_du_vsp_plane *plane = &vsp->planes[i];
401
402                 plane->vsp = vsp;
403                 plane->index = i;
404
405                 ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
406                                                &rcar_du_vsp_plane_funcs,
407                                                formats_kms,
408                                                ARRAY_SIZE(formats_kms),
409                                                NULL, type, NULL);
410                 if (ret < 0)
411                         return ret;
412
413                 drm_plane_helper_add(&plane->plane,
414                                      &rcar_du_vsp_plane_helper_funcs);
415
416                 if (type == DRM_PLANE_TYPE_PRIMARY)
417                         continue;
418
419                 drm_plane_create_alpha_property(&plane->plane);
420                 drm_plane_create_zpos_property(&plane->plane, 1, 1,
421                                                vsp->num_planes - 1);
422         }
423
424         return 0;
425 }