Skip to content

Instantly share code, notes, and snippets.

@cleverca22
Last active December 8, 2023 17:01
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cleverca22/b602c32228ac9c0a051c37513cdddb50 to your computer and use it in GitHub Desktop.
Save cleverca22/b602c32228ac9c0a051c37513cdddb50 to your computer and use it in GitHub Desktop.

a display list is a series of planes in the dlist memory, followed by a SCALER_CTL0_END flag

for example: [CTL(valid,...), POS0, POS2, POS3, POINT0, POINTCTX, PITCH0, CTL(END)] would be a list containing just one plane

VC4 Control Word:

bits usage
0:3 pixel format
4 unity scaling
5:7 SCL0
8:10 SCL1
11:12 rgb expand
13:14 pixel order
15 vflip
16 hflip
17:18 key mode
19 alpha mask
20:21 tiling mode
24:29 number of words in this plane description
30 marks this as a valid control word
31 signals the end of a display list (must be its own control word, after a another plane)

VC6 Control Word:

bits usage
0:4 pixel format
5:7 SCL0
8:10 SCL1
11 rgb expand
12 alpha expand
13:14 pixel order
15 unity scaling
20:21 tiling mode
30 marks this as a valid control word
31 signals the end of a display list (must be its own control word, after a another plane)

VC6 Control Word 2:

bits usage
4:15 alpha
16 gamma
17:18 MAP_SEL
25 ALPHA_LOC
28 ALPHA_MIX
29 ALPHA_PREMULT
30:31 alpha mode

VC4 Position Word 0:

bits usage
0:11 x
12:23 y
24:31 fixed alpha

VC6 Position Word 0:

bits usage
0:13 x
15 hflip
16:27 y
31 yflip

VC4 Position Word 1:

only present when not using unity scaling

bits usage
0:11 scale width
16:27 scale height

VC6 Position Word 1:

only present when not using unity scaling

bits usage
0:12 scale width
16:28 scale height

VC4 Position Word 2:

bits usage
0:11 width
16:27 height
28 alpha mix
29 alpha pre-multiply
30:31 alpha mode

VC6 Position Word 2:

bits usage
0:12 width
16:28 height

Position Word 3:

the HVS will store some state in this slot when running, just fill it with any 32bit value when generating the display list

Pointer Word 0/1/2:

the address for each plane of image data RGB based formats only use Pointer Word 0, while YUV formats use 3

Pointer Context Word 0/1/2:

more internal state for the HVS, one per Pointer Word used

Pitch Word 0/1/2:

the pitch for each plane

more info:

Position Word 0 mainly describes where on the screen to render a given image

Position Word 1 describes the destination width/height, when scaling

Position word 2 mainly describes the source width/height, and if unity, that is also the destination size

example plane configs:

VC4 RGB unity scaling: Control Word, Position Word 0, Position Word 2, Position Word 3, Pointer Word 0, Pitch Word 0

VC6 RGB unity scaling: Control Word, Position Word 0, Control Word 2, Position Word 2, Position Word 3, Pointer Word 0, Pitch Word 0

there are 3 main stages to the video output pipeline in the rpi

first stage is the HVS, it will take a display list, convert it into scanlines, and feed them into a FIFO

second stage is the pixelvalve, it takes all of the video timing information, generates the hsync/vsync pulses, and throttles the flow of pixels from the HVS FIFO to the output PHY

the third stage is the various output PHY's

  • hdmi
  • VEC (ntsc/pal video)
  • DPI
  • SMI
  • DSI

all pi models have 3 HVS channels, and can drive a total of 3 screens at once (but the official firmware only supports a max of 2)

VC4 pi's have 3 pixelvalves:

  • PV0 can drive DSI0 or DPI
  • PV1 can drive DSI1 or SMI
  • PV2 can drive HDMI or VEC

VC6 pi's have 5 pixelvalves:

  • PV0 can drive DSI0/DPI
  • PV1 can drive DSI1/SMI
  • PV2 can drive HDMI0
  • PV3 can drive VEC
  • PV4 can drive HDMI1

on VC4, each PV is hard-wired to a certain HVS channel but on VC6, each PV has a mux to select between any HVS channel(todo, confirm that), but you cant share a channel between 2 PV's

+-----+  +----------+  +----+  +-----+
| HVS |->| HVS FIFO |->| PV |->| PHY |
+-----+  +----------+  +----+  +-----+

all 3 HVS channels share some FIFO ram, and the SCALER_DISPBASE[0-2] registers control which region of the ram each will be using

some example code:

  hvs_channels[2].dispbase = BASE_BASE(0)      | BASE_TOP(0xf00);
  hvs_channels[1].dispbase = BASE_BASE(0xf10)  | BASE_TOP(0x4b00);
  hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700);

under normal conditions, those ranges will have already been configured by the firmware, so the only reason to look at them is to know the latency between the HVS and the PV

https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/gpu/drm/vc4/vc4_crtc.c#L1136-L1150

https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/gpu/drm/vc4/vc4_crtc.c#L173-L196

the lower 12 bits of SCALER_DISPSTAT[0-2] say what scanline the HVS is currently on, but based on width and fifo depth, the PV+PHY will be lagging behind a certain number of scanlines

@erichester76
Copy link

you could take this information along with https://github.com/microsoft/graphics-driver-samples and likely get somewhere. I'd be willing to participate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment