Skip to content

The Graphics Synthesizer

frno7 edited this page May 17, 2022 · 21 revisions

There are currently 34 video modes, shown below, provided for convenience. All of them are calculated from first principles so one can adjust margins, clock speeds, and so on, and invent new modes.

# cat /sys/class/graphics/fb0/modes | column
V:1280x1024p-75	V:640x480p-60	S:1920x1080i-60	U:1688x964p-50	S:1280x720p-50
V:1280x1024p-60	U:1688x964p-60	S:1280x720p-60	U:1688x964i-50	S:720x576p-50
V:1024x768p-75	U:1688x964i-60	S:720x480p-60	U:1124x644p-50	S:720x576i-50
V:1024x768p-60	U:1124x644p-60	S:720x480i-60	U:576x460p-50	S:640x512i-50
V:800x600p-75	U:576x384p-60	S:640x448i-60	U:576x460i-50	S:720x288p-50
V:800x600p-60	U:576x384i-60	S:720x240p-60	S:1920x1080p-50	S:640x256p-50
V:640x480p-75	S:1920x1080p-60	S:640x224p-60	S:1920x1080i-50

There are three main methods to configure video modes:

  1. The current video mode can be shown with cat /sys/class/graphics/fb0/mode. Applying a preset video mode is very easy. One can for instance do echo S:720x576p-50 >/sys/class/graphics/fb0/mode, from the list of modes shown with cat /sys/class/graphics/fb0/modes.
  2. The fbset command can be used to configure advanced video modes.
  3. In addition, the video hardware registers can be examined and manipulated.

The kernel implements an early printk. The conventional putc prints to a serial port, that requires soldering on the PlayStation 2. This putc instead prints to a video frame buffer using the Graphics Synthesizer, which at the moment is fixed at the video resolution 1920×1080p for an HDMI adapter or component video. The following three lines are the first ones visible on the screen when the kernel boots:

zimage at:     00803BE0 00BDDE8C
Uncompressing Linux at load address 80010000
Now, booting the kernel...

The PlayStation 2 Graphics Synthesizer (GS) has a Linux frame buffer device driver drivers/video/fbdev/ps2fb.c for a fast and efficient text console. The ps2fb.ko kernel module will attempt a default video resolution, which can be configured with the following options, as an example:

modprobe ps2fb mode_option=1920x1080p@50 mode_margin=+48+0

It’s often convenient to load ps2fb.ko in a start-up script such as /sbin/init.

The GS has 4 MiB of local frame buffer video memory that is not directly accessible by the kernel due to its hardware design. No main memory is allocated for the frame buffer, which is a significant saving given that the PlayStation 2 is limited to 32 MiB of total main memory, and mmap is disabled.

The maximum practical resolution 1920×1080p at 16 bits per pixel is 4147200 bytes, which leaves 47104 bytes for a tiled font, which at 8×8 pixels and at a minimum of a 4 bits indexed texture palette is at most 1464 characters. The indexed palette makes it easy to switch colors. struct fb_tile_ops such as fb_tileblit, fb_fillrect and fb_copyarea are accelerated by GS hardware that is very fast for the kernel via simple DMA (GIF PATH3) GS commands. The GS has two CRT merge circuits made for picture-in-picture that are used to accelerate YWRAP in hardware, which is particularly effective for console text scrolling.

Console text operations are synchronous and therefore work properly in interrupt contexts, with kernel panics, etc. This is essential for debuggability (see also #27). Various optimisation techniques, such as buffering, can possibly be even faster, but one might want to implement that as a user space console driver via some kind of /dev/gs device, explained below, that can do zero-copying of GS commands, etc.

It’s possible to implement a virtual frame buffer mode, similar to the PlayStation 3 in that the whole visible main memory frame buffer is regularly copied to the GS via DMA at vertical blank intervals. This enables mmap, which is required for frame buffer compatibility, but it is otherwise very inefficient and slow. A complete copy of the whole frame buffer is allocated in main memory and GS hardware acceleration would be completely turned off.

The GS hardware is essentially a serial device that accepts a series of commands via DMA. A /dev/gs device could provide direct access to the GS hardware, which would be very efficient and enable most features of the GS to applications. The main drawback is that this kind of device driver is specific to the GS and the PlayStation 2.

Graphics Synthesizer registers are available symbolically via the gs-sysfs.ko sysfs kernel module:

# ls /sys/devices/platform/gs/registers
bgcolor   dispfb1   display2  extwrite  siglblid  srfsh     syncv
busdir    dispfb2   extbuf    imr       smode1    synch1
csr       display1  extdata   pmode     smode2    synch2

It’s simple to examine and try out new field value combinations, especially if one has access to an oscilloscope. To view SMODE1, for example, use the cat command, with the first line printing the hexadecimal value of the entire register:

# 0x13422004b1
rc 1
lc 22
t1248 1
slck 0
cmod vesa
ex 0
prst 0
sint 0
xpck 0
pck2 0
spml 1
gcont ycrcb
phs 0
pvs 0
pehs 0
pevs 0
clksel 1
nvck 1
slck2 1
vcksel 0
vhp 1

In relevant cases, register bit fields are symbolic:

# grep gcont /sys/devices/platform/gs/registers/smode1
gcont ycrcb

To update a register, use for example the echo command with the wanted field values, like so:

# echo "gcont rgbyc" >/sys/devices/platform/gs/registers/smode1

The updated SMODE1 register can be viewed with grep again:

# grep gcont /sys/devices/platform/gs/registers/smode1
gcont rgbyc

In this particular case, changing the gcont field from ycrcb to rgbyc corresponds to the PlayStation 2 System Configuration setting for Component Video Out, having the alternatives YCbCr and RGB.

Printing all registers in hexadecimal is easy with a small awk script:

# cd /sys/devices/platform/gs/registers
# awk '$1 == "#" { print FILENAME " " $2 }' *
csr 0x551b600c
dispfb1 0x11000000013c00
dispfb2 0x13c00
display1 0x21777f0002811b
display2 0x21f77f0024011b
imr 0x7f00
pmode 0x7
siglblid 0x0
smode1 0x13422004b1
smode2 0x4
srfsh 0x2
synch1 0x2c4d0160621b4
synch2 0x240300
syncv 0xb0e00002400004

There is an almost fully working Direct Rendering Manager (DRM) variant of the frame buffer console for the PlayStation 2 Graphics Synthesizer. The Graphics Synthesizer has the hardware to support two DRM planes. When completed, drivers/video/fbdev/ps2fb.c would be retired and removed.

However, there is apparently significant user space breakage with the generic DRM frame buffer subsystem. Many relevant video modes are missing in the generic DRM modes file (in fact, only one is shown), the vertical refresh value is wrong (0 instead of 60), and the mode type (U instead of S) is wrong too:

# cat /sys/class/graphics/fb0/modes
U:1920x1200p-0

The fbset tool no longer works properly, as its timing mode settings are ignored by the DRM subsystem, and so is attempts to set modes with /sys/class/graphics/fb0/mode. Moreover, it appears that the standard DRM video modes have mixed up the sync and front porch timings in struct drm_display_mode but this remains to be confirmed.

Some problems are due to breakage in drivers/gpu/drm/drm_fb_helper.c and others are due to DRM design choices, such as the abstraction of connectors, CRTs, planes and framebuffers. The DRM subsystem relies heavily on EDID to automatically choose an appropriate video resolution, which presumably explain why compatibility is lost and other mode setting methods are ignored.

There doesn’t seem to be any EDID capabilities with the PlayStation 2, and so it seems important to retain compatibility with sysfs and fbset. This means reimplementing some generic parts of drivers/gpu/drm/drm_fb_helper.c in the specific DRM driver for the Graphics Synthesizer, to obtain all proper modes and timings:

# column </sys/class/graphics/fb0/modes
V:1280x1024p-75	V:640x480p-60	S:1920x1080i-60	U:1688x964p-50	S:1280x720p-50
V:1280x1024p-60	U:1688x964p-60	S:1280x720p-60	U:1688x964i-50	S:720x576p-50
V:1024x768p-75	U:1688x964i-60	S:720x480p-60	U:1124x644p-50	S:720x576i-50
V:1024x768p-60	U:1124x644p-60	S:720x480i-60	U:576x460p-50	S:640x512i-50
V:800x600p-75	U:576x384p-60	S:640x448i-60	U:576x460i-50	S:720x288p-50
V:800x600p-60	U:576x384i-60	S:720x240p-60	S:1920x1080p-50	S:640x256p-50
V:640x480p-75	S:1920x1080p-60	S:640x224p-60	S:1920x1080i-50
# fbset
mode "1920x1080-50"
	# D: 148.500 MHz, H: 56.250 kHz, V: 50.000 Hz
	geometry 1920 1080 1920 1080 16
	timings 6734 148 484 36 4 88 5
	accel false
	rgba 5/0,5/5,5/10,1/15
endmode

The PlayStation 2 video connector is called AV-MULTI-OUT by the DRM driver. It remains to be decided whether the DRM concept of subconnectors ought to be applied, as in DRM_MODE_SUBCONNECTOR_Composite, DRM_MODE_SUBCONNECTOR_SVIDEO, DRM_MODE_SUBCONNECTOR_SCART, DRM_MODE_SUBCONNECTOR_VGA, DRM_MODE_SUBCONNECTOR_Component and possibly a new variant DRM_MODE_SUBCONNECTOR_DTerminal for D-Terminal that is popular in Japan.

Example of DRM video configuration:

# cat /sys/kernel/debug/dri/0/state
plane[32]: plane-0
	crtc=crtc-0
	fb=35
		allocated by = [fbcon]
		refcount=2
		format=RA15 little-endian (0x35314152)
		modifier=0x0
		size=1280x720
		layers:
			size[0]=1280x720
			pitch[0]=5120
			offset[0]=0
			obj[0]:(null)
	crtc-pos=1280x720+0+0
	src-pos=1280.000000x720.000000+0.000000+0.000000
	rotation=1
	normalized-zpos=0
	color-encoding=ITU-R BT.601 YCbCr
	color-range=YCbCr limited range
crtc[33]: crtc-0
	enable=1
	active=1
	self_refresh_active=0
	planes_changed=1
	mode_changed=0
	active_changed=0
	connectors_changed=0
	color_mgmt_changed=0
	plane_mask=1
	connector_mask=1
	encoder_mask=1
	mode: "1280x720@60": 60 74178 1280 1350 1430 1650 720 726 731 750 0x48 0x400
connector[31]: AV-MULTI-OUT
	crtc=crtc-0
	self_refresh_aware=0
# fbset
mode "1280x720-60"
	# D: 74.178 MHz, H: 44.957 kHz, V: 59.942 Hz
	geometry 1280 720 1280 720 16
	timings 13481 220 70 19 6 80 5
	accel false
	rgba 5/0,5/5,5/10,1/15
endmode
  • EE User’s Manual, version 6.0, Sony Computer Entertainment Inc.
  • GS User’s Manual, version 6.0, Sony Computer Entertainment Inc.

See #10 and #30.