drm/vc4: fkms: Add firmware-kms mode

This is a squash of all firmware-kms related patches from previous
branches, up to and including
"drm/vc4: Set the possible crtcs mask correctly for planes with FKMS"
plus a couple of minor fixups for the 5.9 branch.
Please refer to earlier branches for full history.

This patch includes work by Eric Anholt, James Hughes, Phil Elwell,
Dave Stevenson, Dom Cobley, and Jonathon Bell.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fixup firmware-kms after "drm/atomic: Pass the full state to CRTC atomic enable/disable"

Prototype for those calls changed, so amend fkms (which isn't
upstream) to match.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fixup fkms for API change

Atomic flush and check changed API, so fix up the downstream-only
FKMS driver.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Make normalize_zpos conditional on using fkms

Eric's view was that there was no point in having zpos
support on vc4 as all the planes had the same functionality.

Can be later squashed into (and fixes):
drm/vc4: Add firmware-kms mode

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

drm/vc4: FKMS: Change of Broadcast RGB mode needs a mode change

The Broadcast RGB (aka HDMI limited/full range) property is only
notified to the firmware on mode change, so this needs to be
signalled when set.

https://github.com/raspberrypi/firmware/issues/1580

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

vc4/drv: Only notify firmware of display done with kms

fkms driver still wants firmware display to be active

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

ydrm/vc4: fkms: Fix margin calculations for the right/bottom edges

The calculations clipped the right/bottom edge of the clipped
range based on the left/top margins.

https://github.com/raspberrypi/linux/issues/4447

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: Use new devm_rpi_firmware_get api

drm/kms: Add allow_fb_modifiers

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

drm/vc4: Add async update support for cursor planes

Now that cursors are implemented as regular planes, all cursor
movements result in atomic updates. As the firmware-kms driver
doesn't support asynchronous updates, these are synchronous, which
limits the update rate to the screen refresh rate. Xorg seems unaware
of this (or at least of the effect of this), because if the mouse is
configured with a higher update rate than the screen then continuous
mouse movement results in an increasing backlog of mouse events -
cue extreme lag.

Add minimal support for asynchronous updates - limited to cursor
planes - to eliminate the lag.

See: https://github.com/raspberrypi/linux/pull/4971
     https://github.com/raspberrypi/linux/issues/4988

Signed-off-by: Phil Elwell <phil@raspberrypi.com>

drivers/gpu/drm/vc4: Add missing 32-bit RGB formats

The missing 32-bit per pixel ABGR and various "RGB with an X value"
formats are added. Change sent by Dave Stevenson.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>

drm: vc4: Fixup duplicated macro definition in vc4_firmware_kms

Both vc4_drv.h and vc4_firmware_kms.c had definitions for
to_vc4_crtc.

Rename the fkms one to make it unique, and drop the magic
define vc4_crtc vc4_kms_crtc
define to_vc4_crtc to_vc4_kms_crtc
that renamed half the variable and function names in a slightly
unexpected way.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fix FKMS for when the YUV chroma planes are different buffers

The code was assuming that it was a single buffer with offsets,
when kmstest uses separate buffers and 0 offsets for each plane.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: Rename plane related functions

The name collide with the Full KMS functions that are going to be made
public.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

drm/vc4_fkms: Fix up interrupt handler for both 2835/2711 and 2712

2712 has switched from using the SMI peripheral to another interrupt
source for the vsync interrupt, so handle both sources cleanly.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: No SMI abuse needed on BCM2712

Since we don't use the (absent) SMI block to create interrupts on
BCM2712, there's no need to map any registers.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
This commit is contained in:
Dave Stevenson
2020-09-07 17:32:27 +01:00
committed by Dom Cobley
parent 7976487482
commit 0a4636e214
7 changed files with 2324 additions and 24 deletions

View File

@@ -9,6 +9,7 @@ vc4-y := \
vc4_dpi.o \
vc4_dsi.o \
vc4_fence.o \
vc4_firmware_kms.o \
vc4_kms.o \
vc4_gem.o \
vc4_hdmi.o \

View File

@@ -24,7 +24,8 @@ vc4_debugfs_init(struct drm_minor *minor)
struct vc4_dev *vc4 = to_vc4_dev(minor->dev);
struct drm_device *drm = &vc4->base;
drm_WARN_ON(drm, vc4_hvs_debugfs_init(minor));
if (vc4->hvs)
drm_WARN_ON(drm, vc4_hvs_debugfs_init(minor));
if (vc4->v3d) {
drm_WARN_ON(drm, vc4_bo_debugfs_init(minor));

View File

@@ -300,6 +300,18 @@ static const struct of_device_id vc4_dma_range_matches[] = {
{}
};
/*
* we need this helper function for determining presence of fkms
* before it's been bound
*/
static bool firmware_kms(void)
{
return of_device_is_available(of_find_compatible_node(NULL, NULL,
"raspberrypi,rpi-firmware-kms")) ||
of_device_is_available(of_find_compatible_node(NULL, NULL,
"raspberrypi,rpi-firmware-kms-2711"));
}
static int vc4_drm_bind(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -380,7 +392,7 @@ static int vc4_drm_bind(struct device *dev)
if (ret)
goto err;
if (firmware) {
if (firmware && !firmware_kms()) {
ret = rpi_firmware_property(firmware,
RPI_FIRMWARE_NOTIFY_DISPLAY_DONE,
NULL, 0);
@@ -398,16 +410,20 @@ static int vc4_drm_bind(struct device *dev)
if (ret)
goto err;
ret = vc4_plane_create_additional_planes(drm);
if (ret)
goto err;
if (!vc4->firmware_kms) {
ret = vc4_plane_create_additional_planes(drm);
if (ret)
goto err;
}
ret = vc4_kms_load(drm);
if (ret < 0)
goto err;
drm_for_each_crtc(crtc, drm)
vc4_crtc_disable_at_boot(crtc);
if (!vc4->firmware_kms) {
drm_for_each_crtc(crtc, drm)
vc4_crtc_disable_at_boot(crtc);
}
ret = drm_dev_register(drm, 0);
if (ret < 0)
@@ -453,6 +469,7 @@ static struct platform_driver *const component_drivers[] = {
&vc4_dsi_driver,
&vc4_txp_driver,
&vc4_crtc_driver,
&vc4_firmware_kms_driver,
&vc4_v3d_driver,
};

View File

@@ -96,8 +96,12 @@ struct vc4_dev {
unsigned int irq;
bool firmware_kms;
struct rpi_firmware *firmware;
struct vc4_hvs *hvs;
struct vc4_v3d *v3d;
struct vc4_fkms *fkms;
struct vc4_hang_state *hang_state;
@@ -1007,6 +1011,9 @@ extern struct platform_driver vc4_dsi_driver;
/* vc4_fence.c */
extern const struct dma_fence_ops vc4_fence_ops;
/* vc4_firmware_kms.c */
extern struct platform_driver vc4_firmware_kms_driver;
/* vc4_gem.c */
int vc4_gem_init(struct drm_device *dev);
int vc4_submit_cl_ioctl(struct drm_device *dev, void *data,

File diff suppressed because it is too large Load Diff

View File

@@ -138,6 +138,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state);
struct drm_color_ctm *ctm = ctm_state->ctm;
if (vc4->firmware_kms)
return;
WARN_ON_ONCE(vc4->gen > VC4_GEN_5);
if (ctm_state->fifo) {
@@ -406,9 +409,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
struct vc4_crtc_state *vc4_crtc_state;
if (!new_crtc_state->commit)
if (!new_crtc_state->commit || vc4->firmware_kms)
continue;
vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
vc4_hvs_mask_underrun(hvs, vc4_crtc_state->assigned_channel);
}
@@ -433,7 +437,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
old_hvs_state->fifo_state[channel].pending_commit = NULL;
}
if (vc4->gen == VC4_GEN_5) {
if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) {
unsigned long state_rate = max(old_hvs_state->core_clock_rate,
new_hvs_state->core_clock_rate);
unsigned long core_rate = clamp_t(unsigned long, state_rate,
@@ -454,23 +458,25 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
if (vc4->gen <= VC4_GEN_5)
vc4_ctm_commit(vc4, state);
switch (vc4->gen) {
case VC4_GEN_4:
vc4_hvs_pv_muxing_commit(vc4, state);
break;
if (!vc4->firmware_kms) {
switch (vc4->gen) {
case VC4_GEN_4:
vc4_hvs_pv_muxing_commit(vc4, state);
break;
case VC4_GEN_5:
vc5_hvs_pv_muxing_commit(vc4, state);
break;
case VC4_GEN_5:
vc5_hvs_pv_muxing_commit(vc4, state);
break;
case VC4_GEN_6_C:
case VC4_GEN_6_D:
vc6_hvs_pv_muxing_commit(vc4, state);
break;
case VC4_GEN_6_C:
case VC4_GEN_6_D:
vc6_hvs_pv_muxing_commit(vc4, state);
break;
default:
drm_err(dev, "Unknown VC4 generation: %d", vc4->gen);
break;
default:
drm_err(dev, "Unknown VC4 generation: %d", vc4->gen);
break;
}
}
drm_atomic_helper_commit_planes(dev, state,
@@ -486,7 +492,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_cleanup_planes(dev, state);
if (vc4->gen == VC4_GEN_5) {
if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) {
unsigned long core_rate = min_t(unsigned long,
hvs->max_core_rate,
new_hvs_state->core_clock_rate);
@@ -507,11 +513,21 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
static int vc4_atomic_commit_setup(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
struct drm_crtc_state *crtc_state;
struct vc4_hvs_state *hvs_state;
struct drm_crtc *crtc;
unsigned int i;
/* We know for sure we don't want an async update here. Set
* state->legacy_cursor_update to false to prevent
* drm_atomic_helper_setup_commit() from auto-completing
* commit->flip_done.
*/
if (!vc4->firmware_kms)
state->legacy_cursor_update = false;
hvs_state = vc4_hvs_get_new_global_state(state);
if (WARN_ON(IS_ERR(hvs_state)))
return PTR_ERR(hvs_state);
@@ -890,6 +906,7 @@ static int cmp_vc4_crtc_hvs_output(const void *a, const void *b)
static int vc4_pv_muxing_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct vc4_dev *vc4 = to_vc4_dev(state->dev);
struct vc4_hvs_state *hvs_new_state;
struct drm_crtc **sorted_crtcs;
struct drm_crtc *crtc;
@@ -897,6 +914,9 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev,
unsigned int i;
int ret;
if (vc4->firmware_kms)
return 0;
hvs_new_state = vc4_hvs_get_global_state(state);
if (IS_ERR(hvs_new_state))
return PTR_ERR(hvs_new_state);

View File

@@ -0,0 +1,175 @@
/*
* 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
* and vc_image_structs.h at
* https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.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 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,
/* 10-bit YUV 420 column image format */
VC_IMAGE_YUV10COL,
/* 32-bpp, 10-bit R/G/B, 2-bit Alpha */
VC_IMAGE_RGBA1010102,
VC_IMAGE_MAX, /* bounds for error checking */
VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
};
enum {
/* Unknown or unset - defaults to BT601 interstitial */
VC_IMAGE_YUVINFO_UNSPECIFIED = 0,
/* colour-space conversions data [4 bits] */
/* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */
VC_IMAGE_YUVINFO_CSC_ITUR_BT601 = 1,
/* ITU-R BT.709-3 [HDTV] */
VC_IMAGE_YUVINFO_CSC_ITUR_BT709 = 2,
/* JPEG JFIF */
VC_IMAGE_YUVINFO_CSC_JPEG_JFIF = 3,
/* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
VC_IMAGE_YUVINFO_CSC_FCC = 4,
/* Society of Motion Picture and Television Engineers 240M (1999) */
VC_IMAGE_YUVINFO_CSC_SMPTE_240M = 5,
/* ITU-R BT.470-2 System M */
VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M = 6,
/* ITU-R BT.470-2 System B,G */
VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7,
/* JPEG JFIF, but with 16..255 luma */
VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8,
/* Rec 2020 */
VC_IMAGE_YUVINFO_CSC_REC_2020 = 9,
};