hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
....@@ -1,24 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor
34 *
45 * Copyright (C) 2015 Renesas Electronics Corporation
56 *
67 * 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.
128 */
139
14
-#include <drm/drmP.h>
1510 #include <drm/drm_atomic_helper.h>
1611 #include <drm/drm_crtc.h>
17
-#include <drm/drm_crtc_helper.h>
1812 #include <drm/drm_fb_cma_helper.h>
13
+#include <drm/drm_fourcc.h>
1914 #include <drm/drm_gem_cma_helper.h>
2015 #include <drm/drm_gem_framebuffer_helper.h>
16
+#include <drm/drm_managed.h>
2117 #include <drm/drm_plane_helper.h>
18
+#include <drm/drm_vblank.h>
2219
2320 #include <linux/bitops.h>
2421 #include <linux/dma-mapping.h>
....@@ -31,16 +28,19 @@
3128 #include "rcar_du_drv.h"
3229 #include "rcar_du_kms.h"
3330 #include "rcar_du_vsp.h"
31
+#include "rcar_du_writeback.h"
3432
35
-static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
33
+static void rcar_du_vsp_complete(void *private, unsigned int status, u32 crc)
3634 {
3735 struct rcar_du_crtc *crtc = private;
3836
3937 if (crtc->vblank_enable)
4038 drm_crtc_handle_vblank(&crtc->crtc);
4139
42
- if (completed)
40
+ if (status & VSP1_DU_STATUS_COMPLETE)
4341 rcar_du_crtc_finish_page_flip(crtc);
42
+ if (status & VSP1_DU_STATUS_WRITEBACK)
43
+ rcar_du_writeback_complete(crtc);
4444
4545 drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc);
4646 }
....@@ -48,10 +48,11 @@
4848 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
4949 {
5050 const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
51
- struct rcar_du_device *rcdu = crtc->group->dev;
51
+ struct rcar_du_device *rcdu = crtc->dev;
5252 struct vsp1_du_lif_config cfg = {
5353 .width = mode->hdisplay,
5454 .height = mode->vdisplay,
55
+ .interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE,
5556 .callback = rcar_du_vsp_complete,
5657 .callback_data = crtc,
5758 };
....@@ -111,11 +112,12 @@
111112 state = to_rcar_crtc_state(crtc->crtc.state);
112113 cfg.crc = state->crc;
113114
115
+ rcar_du_writeback_setup(crtc, &cfg.writeback);
116
+
114117 vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
115118 }
116119
117
-/* Keep the two tables in sync. */
118
-static const u32 formats_kms[] = {
120
+static const u32 rcar_du_vsp_formats[] = {
119121 DRM_FORMAT_RGB332,
120122 DRM_FORMAT_ARGB4444,
121123 DRM_FORMAT_XRGB4444,
....@@ -129,7 +131,6 @@
129131 DRM_FORMAT_ARGB8888,
130132 DRM_FORMAT_XRGB8888,
131133 DRM_FORMAT_UYVY,
132
- DRM_FORMAT_VYUY,
133134 DRM_FORMAT_YUYV,
134135 DRM_FORMAT_YVYU,
135136 DRM_FORMAT_NV12,
....@@ -144,41 +145,13 @@
144145 DRM_FORMAT_YVU444,
145146 };
146147
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
-
176148 static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
177149 {
178150 struct rcar_du_vsp_plane_state *state =
179151 to_rcar_vsp_plane_state(plane->plane.state);
180152 struct rcar_du_crtc *crtc = to_rcar_crtc(state->state.crtc);
181153 struct drm_framebuffer *fb = plane->plane.state->fb;
154
+ const struct rcar_du_format_info *format;
182155 struct vsp1_du_atomic_config cfg = {
183156 .pixelformat = 0,
184157 .pitch = fb->pitches[0],
....@@ -201,15 +174,47 @@
201174 cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
202175 + fb->offsets[i];
203176
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
- }
177
+ format = rcar_du_format_info(state->format->fourcc);
178
+ cfg.pixelformat = format->v4l2;
210179
211180 vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe,
212181 plane->index, &cfg);
182
+}
183
+
184
+int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb,
185
+ struct sg_table sg_tables[3])
186
+{
187
+ struct rcar_du_device *rcdu = vsp->dev;
188
+ unsigned int i;
189
+ int ret;
190
+
191
+ for (i = 0; i < fb->format->num_planes; ++i) {
192
+ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
193
+ struct sg_table *sgt = &sg_tables[i];
194
+
195
+ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr,
196
+ gem->base.size);
197
+ if (ret)
198
+ goto fail;
199
+
200
+ ret = vsp1_du_map_sg(vsp->vsp, sgt);
201
+ if (ret) {
202
+ sg_free_table(sgt);
203
+ goto fail;
204
+ }
205
+ }
206
+
207
+ return 0;
208
+
209
+fail:
210
+ while (i--) {
211
+ struct sg_table *sgt = &sg_tables[i];
212
+
213
+ vsp1_du_unmap_sg(vsp->vsp, sgt);
214
+ sg_free_table(sgt);
215
+ }
216
+
217
+ return ret;
213218 }
214219
215220 static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
....@@ -217,8 +222,6 @@
217222 {
218223 struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
219224 struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
220
- struct rcar_du_device *rcdu = vsp->dev;
221
- unsigned int i;
222225 int ret;
223226
224227 /*
....@@ -228,39 +231,24 @@
228231 if (!state->visible)
229232 return 0;
230233
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];
234
+ ret = rcar_du_vsp_map_fb(vsp, state->fb, rstate->sg_tables);
235
+ if (ret < 0)
236
+ return ret;
235237
236
- ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr,
237
- gem->base.size);
238
- if (ret)
239
- goto fail;
238
+ return drm_gem_fb_prepare_fb(plane, state);
239
+}
240240
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
- }
241
+void rcar_du_vsp_unmap_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb,
242
+ struct sg_table sg_tables[3])
243
+{
244
+ unsigned int i;
248245
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];
246
+ for (i = 0; i < fb->format->num_planes; ++i) {
247
+ struct sg_table *sgt = &sg_tables[i];
258248
259249 vsp1_du_unmap_sg(vsp->vsp, sgt);
260250 sg_free_table(sgt);
261251 }
262
-
263
- return ret;
264252 }
265253
266254 static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
....@@ -268,17 +256,11 @@
268256 {
269257 struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
270258 struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
271
- unsigned int i;
272259
273260 if (!state->visible)
274261 return;
275262
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
- }
263
+ rcar_du_vsp_unmap_fb(vsp, state->fb, rstate->sg_tables);
282264 }
283265
284266 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
....@@ -297,7 +279,7 @@
297279
298280 if (plane->state->visible)
299281 rcar_du_vsp_plane_setup(rplane);
300
- else
282
+ else if (old_state->crtc)
301283 vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe,
302284 rplane->index, NULL);
303285 }
....@@ -346,11 +328,8 @@
346328 if (state == NULL)
347329 return;
348330
349
- state->state.alpha = DRM_BLEND_ALPHA_OPAQUE;
331
+ __drm_atomic_helper_plane_reset(plane, &state->state);
350332 state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
351
-
352
- plane->state = &state->state;
353
- plane->state->plane = plane;
354333 }
355334
356335 static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
....@@ -361,6 +340,13 @@
361340 .atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state,
362341 .atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state,
363342 };
343
+
344
+static void rcar_du_vsp_cleanup(struct drm_device *dev, void *res)
345
+{
346
+ struct rcar_du_vsp *vsp = res;
347
+
348
+ put_device(vsp->vsp);
349
+}
364350
365351 int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
366352 unsigned int crtcs)
....@@ -377,6 +363,10 @@
377363 return -ENXIO;
378364
379365 vsp->vsp = &pdev->dev;
366
+
367
+ ret = drmm_add_action(rcdu->ddev, rcar_du_vsp_cleanup, vsp);
368
+ if (ret < 0)
369
+ return ret;
380370
381371 ret = vsp1_du_init(vsp->vsp);
382372 if (ret < 0)
....@@ -404,8 +394,8 @@
404394
405395 ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
406396 &rcar_du_vsp_plane_funcs,
407
- formats_kms,
408
- ARRAY_SIZE(formats_kms),
397
+ rcar_du_vsp_formats,
398
+ ARRAY_SIZE(rcar_du_vsp_formats),
409399 NULL, type, NULL);
410400 if (ret < 0)
411401 return ret;
....@@ -413,12 +403,14 @@
413403 drm_plane_helper_add(&plane->plane,
414404 &rcar_du_vsp_plane_helper_funcs);
415405
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);
406
+ if (type == DRM_PLANE_TYPE_PRIMARY) {
407
+ drm_plane_create_zpos_immutable_property(&plane->plane,
408
+ 0);
409
+ } else {
410
+ drm_plane_create_alpha_property(&plane->plane);
411
+ drm_plane_create_zpos_property(&plane->plane, 1, 1,
412
+ vsp->num_planes - 1);
413
+ }
422414 }
423415
424416 return 0;