diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c index eed391f1d160..6e90be13338c 100644 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c @@ -28,6 +28,25 @@ #include "vc4_regs.h" #include +struct fb_alloc_tags { + struct rpi_firmware_property_tag_header tag1; + u32 xres, yres; + struct rpi_firmware_property_tag_header tag2; + u32 xres_virtual, yres_virtual; + struct rpi_firmware_property_tag_header tag3; + u32 bpp; + struct rpi_firmware_property_tag_header tag4; + u32 xoffset, yoffset; + struct rpi_firmware_property_tag_header tag5; + u32 base, screen_size; + struct rpi_firmware_property_tag_header tag6; + u32 pitch; + struct rpi_firmware_property_tag_header tag7; + u32 alpha_mode; + struct rpi_firmware_property_tag_header tag8; + u32 layer; +}; + /* The firmware delivers a vblank interrupt to us through the SMI * hardware, which has only this one register. */ @@ -121,45 +140,39 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct vc4_dev *vc4 = to_vc4_dev(plane->dev); - struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); 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); - volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo; + 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; - fbinfo->xres = state->crtc_w; - fbinfo->yres = state->crtc_h; - fbinfo->xres_virtual = state->crtc_w; - fbinfo->yres_virtual = state->crtc_h; - fbinfo->bpp = bpp; - fbinfo->xoffset = state->crtc_x; - fbinfo->yoffset = state->crtc_y; - fbinfo->base = bo->paddr + fb->offsets[0]; - fbinfo->pitch = fb->pitches[0]; - if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED) - fbinfo->bpp |= BIT(31); - - /* A bug in the firmware makes it so that if the fb->base is - * set to nonzero, the configured pitch gets overwritten with - * the previous pitch. So, to get the configured pitch - * recomputed, we have to make it allocate itself a new buffer - * in VC memory, first. - */ - if (vc4_plane->pitch != fb->pitches[0]) { - u32 saved_base = fbinfo->base; - fbinfo->base = 0; - - ret = rpi_firmware_transaction(vc4->firmware, - RPI_FIRMWARE_CHAN_FB, - vc4_plane->fbinfo_bus_addr); - fbinfo->base = saved_base; - - vc4_plane->pitch = fbinfo->pitch; - WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); - } + fbinfo.bpp |= BIT(31); DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n", plane->base.id, plane->name, @@ -168,14 +181,13 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane, bpp, state->crtc_x, state->crtc_y, - &fbinfo->base, + &fbinfo.base, fb->pitches[0]); - ret = rpi_firmware_transaction(vc4->firmware, - RPI_FIRMWARE_CHAN_FB, - vc4_plane->fbinfo_bus_addr); - WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]); - WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[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, * then unblank. Otherwise, stay blank until CRTC enable. @@ -332,10 +344,10 @@ static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = { static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, enum drm_plane_type type) { + /* Primary and cursor planes only */ struct drm_plane *plane = NULL; struct vc4_fkms_plane *vc4_plane; - u32 xrgb8888 = DRM_FORMAT_XRGB8888; - u32 argb8888 = DRM_FORMAT_ARGB8888; + u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; int ret = 0; bool primary = (type == DRM_PLANE_TYPE_PRIMARY); static const uint64_t modifiers[] = { @@ -357,22 +369,15 @@ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, plane = &vc4_plane->base; ret = drm_universal_plane_init(dev, plane, 0xff, &vc4_plane_funcs, - primary ? &xrgb8888 : &argb8888, 1, - modifiers, + formats, primary ? 2 : 1, modifiers, type, primary ? "primary" : "cursor"); - if (type == DRM_PLANE_TYPE_PRIMARY) { - vc4_plane->fbinfo = - dma_alloc_coherent(dev->dev, - sizeof(*vc4_plane->fbinfo), - &vc4_plane->fbinfo_bus_addr, - GFP_KERNEL); - memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo)); - + if (type == DRM_PLANE_TYPE_PRIMARY) drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs); - } else { + else drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs); - } + + drm_plane_create_alpha_property(plane); return plane; fail: diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index 23b9d356537f..b54035b15b57 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -111,9 +111,15 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c, + RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d, + RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, + RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013, + RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013, + RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014, RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005, @@ -122,6 +128,8 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c, + RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d, RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, @@ -134,6 +142,8 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c, + RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d, RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,