1 From 953d85d97f59691dccbbca743c478a8b01f92b59 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Wed, 27 Mar 2019 17:45:01 +0000
4 Subject: [PATCH 592/806] drm: vc4: Add an overlay plane to vc4-firmware-kms
6 This uses a new API that is exposed via the mailbox service
7 to stick an element straight on the screen using DispmanX.
9 The primary and cursor planes have also been switched to using
10 the new plane API, and it supports layering based on the DRM
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
15 drivers/gpu/drm/vc4/vc4_firmware_kms.c | 518 ++++++++++++++-------
16 drivers/gpu/drm/vc4/vc4_kms.c | 1 +
17 drivers/gpu/drm/vc4/vc_image_types.h | 143 ++++++
18 include/soc/bcm2835/raspberrypi-firmware.h | 2 +
19 4 files changed, 495 insertions(+), 169 deletions(-)
20 create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h
22 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
23 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
25 #include "linux/of_device.h"
28 +#include "vc_image_types.h"
29 #include <soc/bcm2835/raspberrypi-firmware.h>
43 + u32 src_x; /* 16p16 */
44 + u32 src_y; /* 16p16 */
46 + u32 src_w; /* 16p16 */
47 + u32 src_h; /* 16p16 */
60 + u32 planes[4]; /* DMA address of each plane */
63 +struct mailbox_set_plane {
64 + struct rpi_firmware_property_tag_header tag;
65 + struct set_plane plane;
68 struct fb_alloc_tags {
69 struct rpi_firmware_property_tag_header tag1;
71 @@ -47,6 +85,79 @@ struct fb_alloc_tags {
75 +static const struct vc_image_format {
76 + u32 drm; /* DRM_FORMAT_* */
77 + u32 vc_image; /* VC_IMAGE_* */
79 +} vc_image_formats[] = {
81 + .drm = DRM_FORMAT_XRGB8888,
82 + .vc_image = VC_IMAGE_XRGB8888,
85 + .drm = DRM_FORMAT_ARGB8888,
86 + .vc_image = VC_IMAGE_ARGB8888,
89 + * FIXME: Need to resolve which DRM format goes to which vc_image format
90 + * for the remaining RGBA and RGBX formats.
92 + * .drm = DRM_FORMAT_ABGR8888,
93 + * .vc_image = VC_IMAGE_RGBA8888,
96 + * .drm = DRM_FORMAT_XBGR8888,
97 + * .vc_image = VC_IMAGE_RGBA8888,
101 + .drm = DRM_FORMAT_RGB565,
102 + .vc_image = VC_IMAGE_RGB565,
105 + .drm = DRM_FORMAT_RGB888,
106 + .vc_image = VC_IMAGE_BGR888,
109 + .drm = DRM_FORMAT_BGR888,
110 + .vc_image = VC_IMAGE_RGB888,
113 + .drm = DRM_FORMAT_YUV422,
114 + .vc_image = VC_IMAGE_YUV422PLANAR,
117 + .drm = DRM_FORMAT_YUV420,
118 + .vc_image = VC_IMAGE_YUV420,
121 + .drm = DRM_FORMAT_YVU420,
122 + .vc_image = VC_IMAGE_YUV420,
126 + .drm = DRM_FORMAT_NV12,
127 + .vc_image = VC_IMAGE_YUV420SP,
130 + .drm = DRM_FORMAT_NV21,
131 + .vc_image = VC_IMAGE_YUV420SP,
136 +static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
140 + for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
141 + if (vc_image_formats[i].drm == drm_format)
142 + return &vc_image_formats[i];
148 /* The firmware delivers a vblank interrupt to us through the SMI
149 * hardware, which has only this one register.
151 @@ -113,6 +224,7 @@ struct vc4_fkms_plane {
152 struct fbinfo_s *fbinfo;
153 dma_addr_t fbinfo_bus_addr;
155 + struct mailbox_set_plane mb;
158 static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
159 @@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_
160 return (struct vc4_fkms_plane *)plane;
163 -/* Turns the display on/off. */
164 -static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank)
165 +static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
167 struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
168 + struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
169 + struct mailbox_set_plane blank_mb = {
170 + .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
172 + .display = vc4_plane->mb.plane.display,
173 + .plane_id = vc4_plane->mb.plane.plane_id,
178 - u32 packet = blank;
180 - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s",
181 + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
182 plane->base.id, plane->name,
183 blank ? "blank" : "unblank");
185 - return rpi_firmware_property(vc4->firmware,
186 - RPI_FIRMWARE_FRAMEBUFFER_BLANK,
187 - &packet, sizeof(packet));
189 + ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
192 + ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
193 + sizeof(vc4_plane->mb));
195 + WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
200 -static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
201 - struct drm_plane_state *old_state)
202 +static void vc4_plane_atomic_update(struct drm_plane *plane,
203 + struct drm_plane_state *old_state)
205 - struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
206 struct drm_plane_state *state = plane->state;
207 struct drm_framebuffer *fb = state->fb;
208 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
209 - u32 format = fb->format->format;
210 - struct fb_alloc_tags fbinfo = {
211 - .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
213 - .xres = state->crtc_w,
214 - .yres = state->crtc_h,
215 - .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
217 - .xres_virtual = state->crtc_w,
218 - .yres_virtual = state->crtc_h,
219 - .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
221 - .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
224 - .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
225 - .base = bo->paddr + fb->offsets[0],
226 - .screen_size = state->crtc_w * state->crtc_h * 4,
227 - .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
228 - .pitch = fb->pitches[0],
229 - .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
230 - .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
231 - .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
236 + const struct drm_format_info *drm_fmt = fb->format;
237 + const struct vc_image_format *vc_fmt =
238 + vc4_get_vc_image_fmt(drm_fmt->format);
239 + struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
240 + struct mailbox_set_plane *mb = &vc4_plane->mb;
241 + struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
242 + int num_planes = fb->format->num_planes;
243 + struct drm_display_mode *mode = &state->crtc->mode;
245 - if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
246 - fbinfo.bpp |= BIT(31);
247 + mb->plane.vc_image_type = vc_fmt->vc_image;
248 + mb->plane.width = fb->width;
249 + mb->plane.height = fb->height;
250 + mb->plane.pitch = fb->pitches[0];
251 + mb->plane.src_w = state->src_w;
252 + mb->plane.src_h = state->src_h;
253 + mb->plane.src_x = state->src_x;
254 + mb->plane.src_y = state->src_y;
255 + mb->plane.dst_w = state->crtc_w;
256 + mb->plane.dst_h = state->crtc_h;
257 + mb->plane.dst_x = state->crtc_x;
258 + mb->plane.dst_y = state->crtc_y;
259 + mb->plane.alpha = state->alpha >> 8;
260 + mb->plane.layer = state->normalized_zpos ?
261 + state->normalized_zpos : -127;
262 + mb->plane.num_planes = num_planes;
263 + mb->plane.is_vu = vc_fmt->is_vu;
264 + mb->plane.planes[0] = bo->paddr + fb->offsets[0];
266 - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
267 + /* FIXME: If the dest rect goes off screen then clip the src rect so we
268 + * don't have off-screen pixels.
270 + if (plane->type == DRM_PLANE_TYPE_CURSOR) {
271 + /* There is no scaling on the cursor plane, therefore the calcs
272 + * to alter the source crop as the cursor goes off the screen
275 + if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
276 + mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
277 + mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
280 + if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
281 + mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
282 + mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
287 + if (num_planes > 1) {
288 + /* Assume this must be YUV */
289 + /* Makes assumptions on the stride for the chroma planes as we
290 + * can't easily plumb in non-standard pitches.
292 + mb->plane.planes[1] = bo->paddr + fb->offsets[1];
293 + if (num_planes > 2)
294 + mb->plane.planes[2] = bo->paddr + fb->offsets[2];
296 + mb->plane.planes[2] = 0;
298 + /* Special case the YUV420 with U and V as line interleaved
299 + * planes as we have special handling for that case.
301 + if (num_planes == 3 &&
302 + (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
303 + mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
305 + mb->plane.planes[1] = 0;
306 + mb->plane.planes[2] = 0;
308 + mb->plane.planes[3] = 0;
310 + switch (fb->modifier) {
311 + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
312 + switch (mb->plane.vc_image_type) {
313 + case VC_IMAGE_RGBX32:
314 + mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
316 + case VC_IMAGE_RGBA32:
317 + mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
319 + case VC_IMAGE_RGB565:
320 + mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
324 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
325 + mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
326 + mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
331 + mb->plane.dst_x += vc4_crtc->overscan[0];
332 + mb->plane.dst_y += vc4_crtc->overscan[1];
335 + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
336 plane->base.id, plane->name,
342 + mb->plane.vc_image_type,
348 - ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
350 - WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
351 - WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
353 - /* If the CRTC is on (or going to be on) and we're enabled,
360 + mb->plane.planes[0],
361 + mb->plane.planes[1],
362 + mb->plane.planes[2],
365 + state->normalized_zpos);
368 + * Do NOT set now, as we haven't checked if the crtc is active or not.
369 + * Set from vc4_plane_set_blank instead.
371 + * If the CRTC is on (or going to be on) and we're enabled,
372 * then unblank. Otherwise, stay blank until CRTC enable.
375 if (state->crtc->state->active)
376 - vc4_plane_set_primary_blank(plane, false);
377 + vc4_plane_set_blank(plane, false);
380 -static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
381 - struct drm_plane_state *old_state)
382 +static void vc4_plane_atomic_disable(struct drm_plane *plane,
383 + struct drm_plane_state *old_state)
385 - vc4_plane_set_primary_blank(plane, true);
388 -static void vc4_cursor_plane_atomic_update(struct drm_plane *plane,
389 - struct drm_plane_state *old_state)
391 - struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
392 + //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
393 struct drm_plane_state *state = plane->state;
394 - struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
395 - struct drm_framebuffer *fb = state->fb;
396 - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
397 - dma_addr_t addr = bo->paddr + fb->offsets[0];
399 - u32 packet_state[] = {
400 - state->crtc->state->active,
405 - WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
406 + struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
408 - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
409 + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
410 plane->base.id, plane->name,
413 + vc4_plane->mb.plane.vc_image_type,
419 - /* add on the top/left offsets when overscan is active */
421 - packet_state[1] += vc4_crtc->overscan[0];
422 - packet_state[2] += vc4_crtc->overscan[1];
425 - ret = rpi_firmware_property(vc4->firmware,
426 - RPI_FIRMWARE_SET_CURSOR_STATE,
428 - sizeof(packet_state));
429 - if (ret || packet_state[0] != 0)
430 - DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
432 - /* Note: When the cursor contents change, the modesetting
433 - * driver calls drm_mode_cursor_univeral() with
434 - * DRM_MODE_CURSOR_BO, which means a new fb will be allocated.
437 - state->crtc_w != old_state->crtc_w ||
438 - state->crtc_h != old_state->crtc_h ||
439 - fb != old_state->fb) {
440 - u32 packet_info[] = { state->crtc_w, state->crtc_h,
443 - 0, 0, /* hotx, hoty */};
445 - ret = rpi_firmware_property(vc4->firmware,
446 - RPI_FIRMWARE_SET_CURSOR_INFO,
448 - sizeof(packet_info));
449 - if (ret || packet_info[0] != 0)
450 - DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]);
454 -static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane,
455 - struct drm_plane_state *old_state)
457 - struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
458 - u32 packet_state[] = { false, 0, 0, 0 };
461 - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name);
463 - ret = rpi_firmware_property(vc4->firmware,
464 - RPI_FIRMWARE_SET_CURSOR_STATE,
466 - sizeof(packet_state));
467 - if (ret || packet_state[0] != 0)
468 - DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
470 + vc4_plane_set_blank(plane, true);
473 static int vc4_plane_atomic_check(struct drm_plane *plane,
474 @@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte
476 case DRM_FORMAT_XRGB8888:
477 case DRM_FORMAT_ARGB8888:
478 + case DRM_FORMAT_RGB565:
480 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
481 case DRM_FORMAT_MOD_LINEAR:
482 @@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte
486 + case DRM_FORMAT_NV12:
487 + case DRM_FORMAT_NV21:
488 + switch (fourcc_mod_broadcom_mod(modifier)) {
489 + case DRM_FORMAT_MOD_LINEAR:
490 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
495 + case DRM_FORMAT_RGB888:
496 + case DRM_FORMAT_BGR888:
497 + case DRM_FORMAT_YUV422:
498 + case DRM_FORMAT_YUV420:
499 + case DRM_FORMAT_YVU420:
502 + return (modifier == DRM_FORMAT_MOD_LINEAR);
506 @@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_
507 .format_mod_supported = vc4_fkms_format_mod_supported,
510 -static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
511 - .prepare_fb = drm_gem_fb_prepare_fb,
512 - .cleanup_fb = NULL,
513 - .atomic_check = vc4_plane_atomic_check,
514 - .atomic_update = vc4_primary_plane_atomic_update,
515 - .atomic_disable = vc4_primary_plane_atomic_disable,
518 -static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
519 +static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
520 .prepare_fb = drm_gem_fb_prepare_fb,
522 .atomic_check = vc4_plane_atomic_check,
523 - .atomic_update = vc4_cursor_plane_atomic_update,
524 - .atomic_disable = vc4_cursor_plane_atomic_disable,
525 + .atomic_update = vc4_plane_atomic_update,
526 + .atomic_disable = vc4_plane_atomic_disable,
529 static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
530 - enum drm_plane_type type)
531 + enum drm_plane_type type,
534 - /* Primary and cursor planes only */
535 struct drm_plane *plane = NULL;
536 struct vc4_fkms_plane *vc4_plane;
537 - u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
538 + u32 formats[ARRAY_SIZE(vc_image_formats)];
539 + unsigned int default_zpos;
540 + u32 num_formats = 0;
542 - bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
543 static const uint64_t modifiers[] = {
544 DRM_FORMAT_MOD_LINEAR,
545 /* VC4_T_TILED should come after linear, because we
546 @@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_
547 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
548 DRM_FORMAT_MOD_INVALID,
552 vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
554 @@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_
558 + for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
559 + formats[num_formats++] = vc_image_formats[i].drm;
561 plane = &vc4_plane->base;
562 ret = drm_universal_plane_init(dev, plane, 0xff,
564 - formats, primary ? 2 : 1, modifiers,
565 - type, primary ? "primary" : "cursor");
566 + formats, num_formats, modifiers,
569 - if (type == DRM_PLANE_TYPE_PRIMARY)
570 - drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
572 - drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
573 + drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
575 drm_plane_create_alpha_property(plane);
578 + * Default frame buffer setup is with FB on -127, and raspistill etc
579 + * tend to drop overlays on layer 2. Cursor plane was on layer +127.
581 + * For F-KMS the mailbox call allows for a s8.
582 + * Remap zpos 0 to -127 for the background layer, but leave all the
583 + * other layers as requested by KMS.
586 + case DRM_PLANE_TYPE_PRIMARY:
589 + case DRM_PLANE_TYPE_OVERLAY:
592 + case DRM_PLANE_TYPE_CURSOR:
596 + drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
598 + /* Prepare the static elements of the mailbox structure */
599 + vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
600 + vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
601 + vc4_plane->mb.tag.req_resp_size = 0;
602 + vc4_plane->mb.plane.display = 0;
603 + vc4_plane->mb.plane.plane_id = plane_id;
604 + vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
609 @@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_
610 * whether anything scans out at all, but the firmware doesn't
611 * give us a CRTC-level control for that.
613 - vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
614 - vc4_plane_set_primary_blank(crtc->primary, true);
616 + vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
617 + vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
619 + /* FIXME: Disable overlay planes */
622 static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
624 /* Unblank the planes (if they're supposed to be displayed). */
626 if (crtc->primary->state->fb)
627 - vc4_plane_set_primary_blank(crtc->primary, false);
628 - if (crtc->cursor->state->fb) {
629 - vc4_cursor_plane_atomic_update(crtc->cursor,
630 - crtc->cursor->state);
632 + vc4_plane_set_blank(crtc->primary, false);
633 + if (crtc->cursor->state->fb)
634 + vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
636 + /* FIXME: Enable overlay planes */
639 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
640 @@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device *
641 struct vc4_crtc *vc4_crtc;
642 struct vc4_fkms_encoder *vc4_encoder;
643 struct drm_crtc *crtc;
644 - struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp;
645 + struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
646 + struct drm_plane *destroy_plane, *temp;
647 struct device_node *firmware_node;
651 vc4->firmware_kms = true;
652 @@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device *
653 if (IS_ERR(vc4_crtc->regs))
654 return PTR_ERR(vc4_crtc->regs);
656 - /* For now, we create just the primary and the legacy cursor
657 - * planes. We should be able to stack more planes on easily,
658 - * but to do that we would need to compute the bandwidth
659 - * requirement of the plane configuration, and reject ones
660 - * that will take too much.
662 - primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
663 + /* Blank the firmware provided framebuffer */
664 + rpi_firmware_property(vc4->firmware,
665 + RPI_FIRMWARE_FRAMEBUFFER_BLANK,
666 + &blank, sizeof(blank));
668 + primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
669 if (IS_ERR(primary_plane)) {
670 dev_err(dev, "failed to construct primary plane\n");
671 ret = PTR_ERR(primary_plane);
675 - cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
676 + overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
677 + if (IS_ERR(overlay_plane)) {
678 + dev_err(dev, "failed to construct overlay plane\n");
679 + ret = PTR_ERR(overlay_plane);
683 + cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2);
684 if (IS_ERR(cursor_plane)) {
685 dev_err(dev, "failed to construct cursor plane\n");
686 ret = PTR_ERR(cursor_plane);
687 --- a/drivers/gpu/drm/vc4/vc4_kms.c
688 +++ b/drivers/gpu/drm/vc4/vc4_kms.c
689 @@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev)
690 dev->mode_config.preferred_depth = 24;
691 dev->mode_config.async_page_flip = true;
692 dev->mode_config.allow_fb_modifiers = true;
693 + dev->mode_config.normalize_zpos = true;
695 drm_modeset_lock_init(&vc4->ctm_state_lock);
698 +++ b/drivers/gpu/drm/vc4/vc_image_types.h
702 + * Copyright (c) 2012, Broadcom Europe Ltd
704 + * Values taken from vc_image_types.h released by Broadcom at
705 + * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
707 + * This program is free software; you can redistribute it and/or modify
708 + * it under the terms of the GNU General Public License version 2 as
709 + * published by the Free Software Foundation.
713 + VC_IMAGE_MIN = 0, //bounds for error checking
715 + VC_IMAGE_RGB565 = 1,
721 + /* 4bpp palettised image */
723 + /* A separated format of 16 colour/light shorts followed by 16 z
727 + /* 16 colours followed by 16 z values */
729 + /* A separated format of 16 material/colour/light shorts followed by
733 + /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
735 + /* 32-bit format holding 18 bits of 6.6.6 RGB */
737 + /* 4bpp palettised image with embedded palette */
738 + VC_IMAGE_PAL4_OBSOLETE,
739 + /* 8bpp palettised image with embedded palette */
740 + VC_IMAGE_PAL8_OBSOLETE,
741 + /* RGB888 with an alpha byte after each pixel */
743 + /* a line of Y (32-byte padded), a line of U (16-byte padded), and a
744 + * line of V (16-byte padded)
747 + /* RGB565 with a transparent patch */
749 + /* Compressed (4444) version of RGBA32 */
751 + /* VCIII codec format */
753 + /* VCIII T-format RGBA8888 */
754 + VC_IMAGE_TF_RGBA32,
755 + /* VCIII T-format RGBx8888 */
756 + VC_IMAGE_TF_RGBX32,
757 + /* VCIII T-format float */
759 + /* VCIII T-format RGBA4444 */
760 + VC_IMAGE_TF_RGBA16,
761 + /* VCIII T-format RGB5551 */
762 + VC_IMAGE_TF_RGBA5551,
763 + /* VCIII T-format RGB565 */
764 + VC_IMAGE_TF_RGB565,
765 + /* VCIII T-format 8-bit luma and 8-bit alpha */
767 + /* VCIII T-format 8 bit generic sample */
769 + /* VCIII T-format 8-bit palette */
771 + /* VCIII T-format 4-bit palette */
773 + /* VCIII T-format Ericsson Texture Compressed */
775 + /* RGB888 with R & B swapped */
777 + /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after
778 + * each row of pixels
780 + VC_IMAGE_BGR888_NP,
781 + /* Bayer image, extra defines which variant is being used */
783 + /* General wrapper for codec images e.g. JPEG from camera */
785 + /* VCIII codec format */
787 + /* VCIII T-format 8-bit luma */
789 + /* VCIII T-format 8-bit alpha */
791 + /* VCIII T-format 16-bit generic sample */
793 + /* VCIII T-format 1bpp black/white */
796 + /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
798 + /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on
799 + * a per line basis)
801 + VC_IMAGE_YUV422PLANAR,
802 + /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
804 + /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
807 + /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */
808 + VC_IMAGE_YUV422YUYV,
809 + VC_IMAGE_YUV422YVYU,
810 + VC_IMAGE_YUV422UYVY,
811 + VC_IMAGE_YUV422VYUY,
813 + /* 32bpp like RGBA32 but with unused alpha */
815 + /* 32bpp, corresponding to RGBA with unused alpha */
817 + /* 32bpp, corresponding to BGRA with unused alpha */
820 + /* Y as a plane, then UV byte interleaved in plane with with same pitch,
825 + /* Y, U, & V planes separately 4:4:4 */
826 + VC_IMAGE_YUV444PLANAR,
828 + /* T-format 8-bit U - same as TF_Y8 buf from U plane */
830 + /* T-format 8-bit U - same as TF_Y8 buf from V plane */
833 + /* YUV4:2:0 planar, 16bit values */
834 + VC_IMAGE_YUV420_16,
835 + /* YUV4:2:0 codec format, 16bit values */
836 + VC_IMAGE_YUV_UV_16,
837 + /* YUV4:2:0 with U,V in side-by-side format */
840 + VC_IMAGE_MAX, /* bounds for error checking */
841 + VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
843 --- a/include/soc/bcm2835/raspberrypi-firmware.h
844 +++ b/include/soc/bcm2835/raspberrypi-firmware.h
845 @@ -148,6 +148,8 @@ enum rpi_firmware_property_tag {
847 RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
849 + RPI_FIRMWARE_SET_PLANE = 0x00048015,
851 RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
852 RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,