#include "vc4_regs.h"
#include <soc/bcm2835/raspberrypi-firmware.h>
+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.
*/
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,
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.
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[] = {
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:
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,
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,
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,