X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0545-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch;fp=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0545-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch;h=0000000000000000000000000000000000000000;hb=c2308a7e4adbb2acc8ff149f91d1ca46801c135e;hp=f3e2851087df3c30f3615d4d102664c5ff42f327;hpb=67dcc43f3a22dc3a7ac07a7065971b426feeb043;p=openwrt%2Fstaging%2Fchunkeey.git diff --git a/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch b/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch deleted file mode 100644 index f3e2851087..0000000000 --- a/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch +++ /dev/null @@ -1,853 +0,0 @@ -From 953d85d97f59691dccbbca743c478a8b01f92b59 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 27 Mar 2019 17:45:01 +0000 -Subject: [PATCH] drm: vc4: Add an overlay plane to vc4-firmware-kms - -This uses a new API that is exposed via the mailbox service -to stick an element straight on the screen using DispmanX. - -The primary and cursor planes have also been switched to using -the new plane API, and it supports layering based on the DRM -zpos parameter. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 518 ++++++++++++++------- - drivers/gpu/drm/vc4/vc4_kms.c | 1 + - drivers/gpu/drm/vc4/vc_image_types.h | 143 ++++++ - include/soc/bcm2835/raspberrypi-firmware.h | 2 + - 4 files changed, 495 insertions(+), 169 deletions(-) - create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h - ---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -26,8 +26,46 @@ - #include "linux/of_device.h" - #include "vc4_drv.h" - #include "vc4_regs.h" -+#include "vc_image_types.h" - #include - -+struct set_plane { -+ u8 display; -+ u8 plane_id; -+ u8 vc_image_type; -+ s8 layer; -+ -+ u16 width; -+ u16 height; -+ -+ u16 pitch; -+ u16 vpitch; -+ -+ u32 src_x; /* 16p16 */ -+ u32 src_y; /* 16p16 */ -+ -+ u32 src_w; /* 16p16 */ -+ u32 src_h; /* 16p16 */ -+ -+ s16 dst_x; -+ s16 dst_y; -+ -+ u16 dst_w; -+ u16 dst_h; -+ -+ u8 alpha; -+ u8 num_planes; -+ u8 is_vu; -+ u8 padding; -+ -+ u32 planes[4]; /* DMA address of each plane */ -+}; -+ -+struct mailbox_set_plane { -+ struct rpi_firmware_property_tag_header tag; -+ struct set_plane plane; -+}; -+ - struct fb_alloc_tags { - struct rpi_firmware_property_tag_header tag1; - u32 xres, yres; -@@ -47,6 +85,79 @@ struct fb_alloc_tags { - u32 layer; - }; - -+static const struct vc_image_format { -+ u32 drm; /* DRM_FORMAT_* */ -+ u32 vc_image; /* VC_IMAGE_* */ -+ u32 is_vu; -+} vc_image_formats[] = { -+ { -+ .drm = DRM_FORMAT_XRGB8888, -+ .vc_image = VC_IMAGE_XRGB8888, -+ }, -+ { -+ .drm = DRM_FORMAT_ARGB8888, -+ .vc_image = VC_IMAGE_ARGB8888, -+ }, -+/* -+ * FIXME: Need to resolve which DRM format goes to which vc_image format -+ * for the remaining RGBA and RGBX formats. -+ * { -+ * .drm = DRM_FORMAT_ABGR8888, -+ * .vc_image = VC_IMAGE_RGBA8888, -+ * }, -+ * { -+ * .drm = DRM_FORMAT_XBGR8888, -+ * .vc_image = VC_IMAGE_RGBA8888, -+ * }, -+ */ -+ { -+ .drm = DRM_FORMAT_RGB565, -+ .vc_image = VC_IMAGE_RGB565, -+ }, -+ { -+ .drm = DRM_FORMAT_RGB888, -+ .vc_image = VC_IMAGE_BGR888, -+ }, -+ { -+ .drm = DRM_FORMAT_BGR888, -+ .vc_image = VC_IMAGE_RGB888, -+ }, -+ { -+ .drm = DRM_FORMAT_YUV422, -+ .vc_image = VC_IMAGE_YUV422PLANAR, -+ }, -+ { -+ .drm = DRM_FORMAT_YUV420, -+ .vc_image = VC_IMAGE_YUV420, -+ }, -+ { -+ .drm = DRM_FORMAT_YVU420, -+ .vc_image = VC_IMAGE_YUV420, -+ .is_vu = 1, -+ }, -+ { -+ .drm = DRM_FORMAT_NV12, -+ .vc_image = VC_IMAGE_YUV420SP, -+ }, -+ { -+ .drm = DRM_FORMAT_NV21, -+ .vc_image = VC_IMAGE_YUV420SP, -+ .is_vu = 1, -+ }, -+}; -+ -+static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) { -+ if (vc_image_formats[i].drm == drm_format) -+ return &vc_image_formats[i]; -+ } -+ -+ return NULL; -+} -+ - /* The firmware delivers a vblank interrupt to us through the SMI - * hardware, which has only this one register. - */ -@@ -113,6 +224,7 @@ struct vc4_fkms_plane { - struct fbinfo_s *fbinfo; - dma_addr_t fbinfo_bus_addr; - u32 pitch; -+ struct mailbox_set_plane mb; - }; - - static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane) -@@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_ - return (struct vc4_fkms_plane *)plane; - } - --/* Turns the display on/off. */ --static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank) -+static int vc4_plane_set_blank(struct drm_plane *plane, bool blank) - { - struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ struct mailbox_set_plane blank_mb = { -+ .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 }, -+ .plane = { -+ .display = vc4_plane->mb.plane.display, -+ .plane_id = vc4_plane->mb.plane.plane_id, -+ } -+ }; -+ int ret; - -- u32 packet = blank; -- -- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s", -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s", - plane->base.id, plane->name, - blank ? "blank" : "unblank"); - -- return rpi_firmware_property(vc4->firmware, -- RPI_FIRMWARE_FRAMEBUFFER_BLANK, -- &packet, sizeof(packet)); -+ if (blank) -+ ret = rpi_firmware_property_list(vc4->firmware, &blank_mb, -+ sizeof(blank_mb)); -+ else -+ ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb, -+ sizeof(vc4_plane->mb)); -+ -+ WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware", -+ __func__); -+ return ret; - } - --static void vc4_primary_plane_atomic_update(struct drm_plane *plane, -- struct drm_plane_state *old_state) -+static void vc4_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *old_state) - { -- struct vc4_dev *vc4 = to_vc4_dev(plane->dev); - struct drm_plane_state *state = plane->state; - struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -- u32 format = fb->format->format; -- struct fb_alloc_tags fbinfo = { -- .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT, -- 8, 0, }, -- .xres = state->crtc_w, -- .yres = state->crtc_h, -- .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT, -- 8, 0, }, -- .xres_virtual = state->crtc_w, -- .yres_virtual = state->crtc_h, -- .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 }, -- .bpp = 32, -- .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 }, -- .xoffset = 0, -- .yoffset = 0, -- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 }, -- .base = bo->paddr + fb->offsets[0], -- .screen_size = state->crtc_w * state->crtc_h * 4, -- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 }, -- .pitch = fb->pitches[0], -- .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 }, -- .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2, -- .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 }, -- .layer = -127, -- }; -- u32 bpp = 32; -- int ret; -+ const struct drm_format_info *drm_fmt = fb->format; -+ const struct vc_image_format *vc_fmt = -+ vc4_get_vc_image_fmt(drm_fmt->format); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ struct mailbox_set_plane *mb = &vc4_plane->mb; -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc); -+ int num_planes = fb->format->num_planes; -+ struct drm_display_mode *mode = &state->crtc->mode; - -- if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED) -- fbinfo.bpp |= BIT(31); -+ mb->plane.vc_image_type = vc_fmt->vc_image; -+ mb->plane.width = fb->width; -+ mb->plane.height = fb->height; -+ mb->plane.pitch = fb->pitches[0]; -+ mb->plane.src_w = state->src_w; -+ mb->plane.src_h = state->src_h; -+ mb->plane.src_x = state->src_x; -+ mb->plane.src_y = state->src_y; -+ mb->plane.dst_w = state->crtc_w; -+ mb->plane.dst_h = state->crtc_h; -+ mb->plane.dst_x = state->crtc_x; -+ mb->plane.dst_y = state->crtc_y; -+ mb->plane.alpha = state->alpha >> 8; -+ mb->plane.layer = state->normalized_zpos ? -+ state->normalized_zpos : -127; -+ mb->plane.num_planes = num_planes; -+ mb->plane.is_vu = vc_fmt->is_vu; -+ mb->plane.planes[0] = bo->paddr + fb->offsets[0]; - -- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n", -+ /* FIXME: If the dest rect goes off screen then clip the src rect so we -+ * don't have off-screen pixels. -+ */ -+ if (plane->type == DRM_PLANE_TYPE_CURSOR) { -+ /* There is no scaling on the cursor plane, therefore the calcs -+ * to alter the source crop as the cursor goes off the screen -+ * are simple. -+ */ -+ if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) { -+ mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x; -+ mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x) -+ << 16; -+ } -+ if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) { -+ mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y; -+ mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y) -+ << 16; -+ } -+ } -+ -+ if (num_planes > 1) { -+ /* Assume this must be YUV */ -+ /* Makes assumptions on the stride for the chroma planes as we -+ * can't easily plumb in non-standard pitches. -+ */ -+ mb->plane.planes[1] = bo->paddr + fb->offsets[1]; -+ if (num_planes > 2) -+ mb->plane.planes[2] = bo->paddr + fb->offsets[2]; -+ else -+ mb->plane.planes[2] = 0; -+ -+ /* Special case the YUV420 with U and V as line interleaved -+ * planes as we have special handling for that case. -+ */ -+ if (num_planes == 3 && -+ (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1]) -+ mb->plane.vc_image_type = VC_IMAGE_YUV420_S; -+ } else { -+ mb->plane.planes[1] = 0; -+ mb->plane.planes[2] = 0; -+ } -+ mb->plane.planes[3] = 0; -+ -+ switch (fb->modifier) { -+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: -+ switch (mb->plane.vc_image_type) { -+ case VC_IMAGE_RGBX32: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32; -+ break; -+ case VC_IMAGE_RGBA32: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32; -+ break; -+ case VC_IMAGE_RGB565: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGB565; -+ break; -+ } -+ break; -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ mb->plane.vc_image_type = VC_IMAGE_YUV_UV; -+ mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier); -+ break; -+ } -+ -+ if (vc4_crtc) { -+ mb->plane.dst_x += vc4_crtc->overscan[0]; -+ mb->plane.dst_y += vc4_crtc->overscan[1]; -+ } -+ -+ 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", - plane->base.id, plane->name, -- state->crtc_w, -- state->crtc_h, -- bpp, -+ mb->plane.width, -+ mb->plane.height, -+ mb->plane.vc_image_type, - state->crtc_x, - state->crtc_y, -- &fbinfo.base, -- fb->pitches[0]); -- -- ret = rpi_firmware_property_list(vc4->firmware, &fbinfo, -- sizeof(fbinfo)); -- WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]); -- WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]); -- -- /* If the CRTC is on (or going to be on) and we're enabled, -+ state->crtc_w, -+ state->crtc_h, -+ mb->plane.src_x, -+ mb->plane.src_y, -+ mb->plane.src_w, -+ mb->plane.src_h, -+ mb->plane.planes[0], -+ mb->plane.planes[1], -+ mb->plane.planes[2], -+ fb->pitches[0], -+ state->alpha, -+ state->normalized_zpos); -+ -+ /* -+ * Do NOT set now, as we haven't checked if the crtc is active or not. -+ * Set from vc4_plane_set_blank instead. -+ * -+ * If the CRTC is on (or going to be on) and we're enabled, - * then unblank. Otherwise, stay blank until CRTC enable. -- */ -+ */ - if (state->crtc->state->active) -- vc4_plane_set_primary_blank(plane, false); -+ vc4_plane_set_blank(plane, false); - } - --static void vc4_primary_plane_atomic_disable(struct drm_plane *plane, -- struct drm_plane_state *old_state) -+static void vc4_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_plane_state *old_state) - { -- vc4_plane_set_primary_blank(plane, true); --} -- --static void vc4_cursor_plane_atomic_update(struct drm_plane *plane, -- struct drm_plane_state *old_state) --{ -- struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ //struct vc4_dev *vc4 = to_vc4_dev(plane->dev); - struct drm_plane_state *state = plane->state; -- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc); -- struct drm_framebuffer *fb = state->fb; -- struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -- dma_addr_t addr = bo->paddr + fb->offsets[0]; -- int ret; -- u32 packet_state[] = { -- state->crtc->state->active, -- state->crtc_x, -- state->crtc_y, -- 0 -- }; -- WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); - -- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)", -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n", - plane->base.id, plane->name, - state->crtc_w, - state->crtc_h, -+ vc4_plane->mb.plane.vc_image_type, - state->crtc_x, -- state->crtc_y, -- &addr, -- fb->pitches[0]); -- -- /* add on the top/left offsets when overscan is active */ -- if (vc4_crtc) { -- packet_state[1] += vc4_crtc->overscan[0]; -- packet_state[2] += vc4_crtc->overscan[1]; -- } -- -- ret = rpi_firmware_property(vc4->firmware, -- RPI_FIRMWARE_SET_CURSOR_STATE, -- &packet_state, -- sizeof(packet_state)); -- if (ret || packet_state[0] != 0) -- DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -- -- /* Note: When the cursor contents change, the modesetting -- * driver calls drm_mode_cursor_univeral() with -- * DRM_MODE_CURSOR_BO, which means a new fb will be allocated. -- */ -- if (!old_state || -- state->crtc_w != old_state->crtc_w || -- state->crtc_h != old_state->crtc_h || -- fb != old_state->fb) { -- u32 packet_info[] = { state->crtc_w, state->crtc_h, -- 0, /* unused */ -- addr, -- 0, 0, /* hotx, hoty */}; -- -- ret = rpi_firmware_property(vc4->firmware, -- RPI_FIRMWARE_SET_CURSOR_INFO, -- &packet_info, -- sizeof(packet_info)); -- if (ret || packet_info[0] != 0) -- DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]); -- } --} -- --static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane, -- struct drm_plane_state *old_state) --{ -- struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -- u32 packet_state[] = { false, 0, 0, 0 }; -- int ret; -- -- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name); -- -- ret = rpi_firmware_property(vc4->firmware, -- RPI_FIRMWARE_SET_CURSOR_STATE, -- &packet_state, -- sizeof(packet_state)); -- if (ret || packet_state[0] != 0) -- DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -+ state->crtc_y); -+ vc4_plane_set_blank(plane, true); - } - - static int vc4_plane_atomic_check(struct drm_plane *plane, -@@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte - switch (format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: -+ case DRM_FORMAT_RGB565: - switch (modifier) { - case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: - case DRM_FORMAT_MOD_LINEAR: -@@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte - default: - return false; - } -+ case DRM_FORMAT_NV12: -+ case DRM_FORMAT_NV21: -+ switch (fourcc_mod_broadcom_mod(modifier)) { -+ case DRM_FORMAT_MOD_LINEAR: -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ return true; -+ default: -+ return false; -+ } -+ case DRM_FORMAT_RGB888: -+ case DRM_FORMAT_BGR888: -+ case DRM_FORMAT_YUV422: -+ case DRM_FORMAT_YUV420: -+ case DRM_FORMAT_YVU420: - default: -- return false; -+ return (modifier == DRM_FORMAT_MOD_LINEAR); - } - } - -@@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_ - .format_mod_supported = vc4_fkms_format_mod_supported, - }; - --static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = { -- .prepare_fb = drm_gem_fb_prepare_fb, -- .cleanup_fb = NULL, -- .atomic_check = vc4_plane_atomic_check, -- .atomic_update = vc4_primary_plane_atomic_update, -- .atomic_disable = vc4_primary_plane_atomic_disable, --}; -- --static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = { -+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { - .prepare_fb = drm_gem_fb_prepare_fb, - .cleanup_fb = NULL, - .atomic_check = vc4_plane_atomic_check, -- .atomic_update = vc4_cursor_plane_atomic_update, -- .atomic_disable = vc4_cursor_plane_atomic_disable, -+ .atomic_update = vc4_plane_atomic_update, -+ .atomic_disable = vc4_plane_atomic_disable, - }; - - static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, -- enum drm_plane_type type) -+ enum drm_plane_type type, -+ u8 plane_id) - { -- /* Primary and cursor planes only */ - struct drm_plane *plane = NULL; - struct vc4_fkms_plane *vc4_plane; -- u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; -+ u32 formats[ARRAY_SIZE(vc_image_formats)]; -+ unsigned int default_zpos; -+ u32 num_formats = 0; - int ret = 0; -- bool primary = (type == DRM_PLANE_TYPE_PRIMARY); - static const uint64_t modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - /* VC4_T_TILED should come after linear, because we -@@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_ - DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, - DRM_FORMAT_MOD_INVALID, - }; -+ int i; - - vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), - GFP_KERNEL); -@@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_ - goto fail; - } - -+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) -+ formats[num_formats++] = vc_image_formats[i].drm; -+ - plane = &vc4_plane->base; - ret = drm_universal_plane_init(dev, plane, 0xff, - &vc4_plane_funcs, -- formats, primary ? 2 : 1, modifiers, -- type, primary ? "primary" : "cursor"); -+ formats, num_formats, modifiers, -+ type, NULL); - -- if (type == DRM_PLANE_TYPE_PRIMARY) -- drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs); -- else -- drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs); -+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs); - - drm_plane_create_alpha_property(plane); - -+ /* -+ * Default frame buffer setup is with FB on -127, and raspistill etc -+ * tend to drop overlays on layer 2. Cursor plane was on layer +127. -+ * -+ * For F-KMS the mailbox call allows for a s8. -+ * Remap zpos 0 to -127 for the background layer, but leave all the -+ * other layers as requested by KMS. -+ */ -+ switch (type) { -+ case DRM_PLANE_TYPE_PRIMARY: -+ default_zpos = 0; -+ break; -+ case DRM_PLANE_TYPE_OVERLAY: -+ default_zpos = 1; -+ break; -+ case DRM_PLANE_TYPE_CURSOR: -+ default_zpos = 2; -+ break; -+ } -+ drm_plane_create_zpos_property(plane, default_zpos, 0, 127); -+ -+ /* Prepare the static elements of the mailbox structure */ -+ vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE; -+ vc4_plane->mb.tag.buf_size = sizeof(struct set_plane); -+ vc4_plane->mb.tag.req_resp_size = 0; -+ vc4_plane->mb.plane.display = 0; -+ vc4_plane->mb.plane.plane_id = plane_id; -+ vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127; -+ - return plane; - fail: - if (plane) -@@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_ - * whether anything scans out at all, but the firmware doesn't - * give us a CRTC-level control for that. - */ -- vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state); -- vc4_plane_set_primary_blank(crtc->primary, true); -+ -+ vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state); -+ vc4_plane_atomic_disable(crtc->primary, crtc->primary->state); -+ -+ /* FIXME: Disable overlay planes */ - } - - static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) - { - /* Unblank the planes (if they're supposed to be displayed). */ -+ - if (crtc->primary->state->fb) -- vc4_plane_set_primary_blank(crtc->primary, false); -- if (crtc->cursor->state->fb) { -- vc4_cursor_plane_atomic_update(crtc->cursor, -- crtc->cursor->state); -- } -+ vc4_plane_set_blank(crtc->primary, false); -+ if (crtc->cursor->state->fb) -+ vc4_plane_set_blank(crtc->cursor, crtc->cursor->state); -+ -+ /* FIXME: Enable overlay planes */ - } - - static int vc4_crtc_atomic_check(struct drm_crtc *crtc, -@@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device * - struct vc4_crtc *vc4_crtc; - struct vc4_fkms_encoder *vc4_encoder; - struct drm_crtc *crtc; -- struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp; -+ struct drm_plane *primary_plane, *overlay_plane, *cursor_plane; -+ struct drm_plane *destroy_plane, *temp; - struct device_node *firmware_node; -+ u32 blank = 1; - int ret; - - vc4->firmware_kms = true; -@@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device * - if (IS_ERR(vc4_crtc->regs)) - return PTR_ERR(vc4_crtc->regs); - -- /* For now, we create just the primary and the legacy cursor -- * planes. We should be able to stack more planes on easily, -- * but to do that we would need to compute the bandwidth -- * requirement of the plane configuration, and reject ones -- * that will take too much. -- */ -- primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); -+ /* Blank the firmware provided framebuffer */ -+ rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_BLANK, -+ &blank, sizeof(blank)); -+ -+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0); - if (IS_ERR(primary_plane)) { - dev_err(dev, "failed to construct primary plane\n"); - ret = PTR_ERR(primary_plane); - goto err; - } - -- cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR); -+ overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1); -+ if (IS_ERR(overlay_plane)) { -+ dev_err(dev, "failed to construct overlay plane\n"); -+ ret = PTR_ERR(overlay_plane); -+ goto err; -+ } -+ -+ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2); - if (IS_ERR(cursor_plane)) { - dev_err(dev, "failed to construct cursor plane\n"); - ret = PTR_ERR(cursor_plane); ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev) - dev->mode_config.preferred_depth = 24; - dev->mode_config.async_page_flip = true; - dev->mode_config.allow_fb_modifiers = true; -+ dev->mode_config.normalize_zpos = true; - - drm_modeset_lock_init(&vc4->ctm_state_lock); - ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc_image_types.h -@@ -0,0 +1,143 @@ -+ -+/* -+ * Copyright (c) 2012, Broadcom Europe Ltd -+ * -+ * Values taken from vc_image_types.h released by Broadcom at -+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+enum { -+ VC_IMAGE_MIN = 0, //bounds for error checking -+ -+ VC_IMAGE_RGB565 = 1, -+ VC_IMAGE_1BPP, -+ VC_IMAGE_YUV420, -+ VC_IMAGE_48BPP, -+ VC_IMAGE_RGB888, -+ VC_IMAGE_8BPP, -+ /* 4bpp palettised image */ -+ VC_IMAGE_4BPP, -+ /* A separated format of 16 colour/light shorts followed by 16 z -+ * values -+ */ -+ VC_IMAGE_3D32, -+ /* 16 colours followed by 16 z values */ -+ VC_IMAGE_3D32B, -+ /* A separated format of 16 material/colour/light shorts followed by -+ * 16 z values -+ */ -+ VC_IMAGE_3D32MAT, -+ /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */ -+ VC_IMAGE_RGB2X9, -+ /* 32-bit format holding 18 bits of 6.6.6 RGB */ -+ VC_IMAGE_RGB666, -+ /* 4bpp palettised image with embedded palette */ -+ VC_IMAGE_PAL4_OBSOLETE, -+ /* 8bpp palettised image with embedded palette */ -+ VC_IMAGE_PAL8_OBSOLETE, -+ /* RGB888 with an alpha byte after each pixel */ -+ VC_IMAGE_RGBA32, -+ /* a line of Y (32-byte padded), a line of U (16-byte padded), and a -+ * line of V (16-byte padded) -+ */ -+ VC_IMAGE_YUV422, -+ /* RGB565 with a transparent patch */ -+ VC_IMAGE_RGBA565, -+ /* Compressed (4444) version of RGBA32 */ -+ VC_IMAGE_RGBA16, -+ /* VCIII codec format */ -+ VC_IMAGE_YUV_UV, -+ /* VCIII T-format RGBA8888 */ -+ VC_IMAGE_TF_RGBA32, -+ /* VCIII T-format RGBx8888 */ -+ VC_IMAGE_TF_RGBX32, -+ /* VCIII T-format float */ -+ VC_IMAGE_TF_FLOAT, -+ /* VCIII T-format RGBA4444 */ -+ VC_IMAGE_TF_RGBA16, -+ /* VCIII T-format RGB5551 */ -+ VC_IMAGE_TF_RGBA5551, -+ /* VCIII T-format RGB565 */ -+ VC_IMAGE_TF_RGB565, -+ /* VCIII T-format 8-bit luma and 8-bit alpha */ -+ VC_IMAGE_TF_YA88, -+ /* VCIII T-format 8 bit generic sample */ -+ VC_IMAGE_TF_BYTE, -+ /* VCIII T-format 8-bit palette */ -+ VC_IMAGE_TF_PAL8, -+ /* VCIII T-format 4-bit palette */ -+ VC_IMAGE_TF_PAL4, -+ /* VCIII T-format Ericsson Texture Compressed */ -+ VC_IMAGE_TF_ETC1, -+ /* RGB888 with R & B swapped */ -+ VC_IMAGE_BGR888, -+ /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after -+ * each row of pixels -+ */ -+ VC_IMAGE_BGR888_NP, -+ /* Bayer image, extra defines which variant is being used */ -+ VC_IMAGE_BAYER, -+ /* General wrapper for codec images e.g. JPEG from camera */ -+ VC_IMAGE_CODEC, -+ /* VCIII codec format */ -+ VC_IMAGE_YUV_UV32, -+ /* VCIII T-format 8-bit luma */ -+ VC_IMAGE_TF_Y8, -+ /* VCIII T-format 8-bit alpha */ -+ VC_IMAGE_TF_A8, -+ /* VCIII T-format 16-bit generic sample */ -+ VC_IMAGE_TF_SHORT, -+ /* VCIII T-format 1bpp black/white */ -+ VC_IMAGE_TF_1BPP, -+ VC_IMAGE_OPENGL, -+ /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */ -+ VC_IMAGE_YUV444I, -+ /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on -+ * a per line basis) -+ */ -+ VC_IMAGE_YUV422PLANAR, -+ /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */ -+ VC_IMAGE_ARGB8888, -+ /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */ -+ VC_IMAGE_XRGB8888, -+ -+ /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */ -+ VC_IMAGE_YUV422YUYV, -+ VC_IMAGE_YUV422YVYU, -+ VC_IMAGE_YUV422UYVY, -+ VC_IMAGE_YUV422VYUY, -+ -+ /* 32bpp like RGBA32 but with unused alpha */ -+ VC_IMAGE_RGBX32, -+ /* 32bpp, corresponding to RGBA with unused alpha */ -+ VC_IMAGE_RGBX8888, -+ /* 32bpp, corresponding to BGRA with unused alpha */ -+ VC_IMAGE_BGRX8888, -+ -+ /* Y as a plane, then UV byte interleaved in plane with with same pitch, -+ * half height -+ */ -+ VC_IMAGE_YUV420SP, -+ -+ /* Y, U, & V planes separately 4:4:4 */ -+ VC_IMAGE_YUV444PLANAR, -+ -+ /* T-format 8-bit U - same as TF_Y8 buf from U plane */ -+ VC_IMAGE_TF_U8, -+ /* T-format 8-bit U - same as TF_Y8 buf from V plane */ -+ VC_IMAGE_TF_V8, -+ -+ /* YUV4:2:0 planar, 16bit values */ -+ VC_IMAGE_YUV420_16, -+ /* YUV4:2:0 codec format, 16bit values */ -+ VC_IMAGE_YUV_UV_16, -+ /* YUV4:2:0 with U,V in side-by-side format */ -+ VC_IMAGE_YUV420_S, -+ -+ VC_IMAGE_MAX, /* bounds for error checking */ -+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff, -+}; ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -148,6 +148,8 @@ enum rpi_firmware_property_tag { - - RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, - -+ RPI_FIRMWARE_SET_PLANE = 0x00048015, -+ - RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, - RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, - };