Pixel Clock: PLLH_PIX

2021/10/14

This post investigates the programming of the HDMI pixel clock, performed by the RPi firmware to push the pixels into the HDMI encoder at that frequency.

Booting with the RPi firmware and the U-Boot, the actual resolution of the display is 1920x1080@60Hz. The resolution of the frame buffer might be lower - the HVS takes care of appropriately scaling and positioning the pixels.

Below is the Modeline details about the 1920x1080@60Hz resolution. These details were extracted out of the EDID information gathered from the monitor:

Modeline        "Mode 1" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync

The break-down of the fields:

Value Field Comment
148.500 clk The pixel clock frequency/rate, in MHz.
1920 hdisp The Width of the Active Video region of a scanline, in the units of pixels or pixel-clocks.
2008 hsyncstart The point in time, in the units of pixel or pixel-clock, when the HSync Pulse starts.
2052 hsyncend The point in time, in the units of pixel or pixel-clock, when the HSync Pulse ends.
2200 htotal The total time, in the units of pixels or pixel-clocks, of a scanline, including the blanking interval.
+hsync The HSync pulse is active high.

The sizes (in the units of pixels or pixel-clocks) of the various portions of a horizontal blanking interval can be calculated as follows:

Value Field Comment
88 hfp Horizontal Front Porch = hsyncstart - hdisp.
44 hsw Horizontal Sync Width = hsyncend - hsyncstart.
148 hbp Horizontal Back Porch = htotal - hsyncend.
Value Field Comment
1080 vdisp The Height of the Active Video region of a frame, in the units of scanline.
1084 vsyncstart The time, in the units of scanline, when the VSync Pulse starts.
1089 vsyncend The time, in the units of scanline, when the VSync Pulse ends.
1125 vtotal The total time, in the units of scanlines, of a frame, including the blanking intervals.
+vsync The VSync pulse is active high.

The sizes (in the units of scanlines) of the various portions of a vertical blanking interval can be calculated as follows:

Value Field Comment
4 vfp Vertical Front Porch = vsyncstart - vdisp.
5 vsw Vertical Sync Width = vsyncend - vsyncstart.
36 vbp Vertical Back Porch = vtotal - vsyncend.

The required pixel clock rate is given by htotal * vtotal * refreshrate, or 2200 * 1125 * 60 Hz = 148500000 Hz = 148.5 MHz.


Below is a snippet of bcm2708-rpi-b.dtb:

hdmi@7e902000 {
	compatible = "brcm,bcm2835-hdmi";
	. . .
	clocks = <0x07 0x10 0x07 0x19>;
	clock-names = "pixel\0hdmi";
	. . .
};

cprman@7e101000 {
	compatible = "brcm,bcm2835-cprman";
	#clock-cells = <0x01>;
	. . .
	phandle = <0x07>;
};

The hdmi node consumes two clocks, named pixel and hdmi. The hdmi clock identifies the clock which drives the HDMI State Machine (HSM). The pixel clock is the pixel clock.

The provider of the pixel clock is identified as the clock with ID 16 (0x10) under a phandle of 7, the CPRMAN, the Clock, Power, and Reset Manager.

Under Linux, the pixel clock is named PLLH_PIX. Its input/source is named PLLH, which is one of the 5 PLLs that themselves source from the main oscillator running at 19.2 MHz.

The RPi clock tree, and the details about the circuitry that generates the output for the PLLs, are listed here.

The Linux source code for the function bcm2835_pll_get_rate shows the register locations where the clock parameters for a PLL clock are stored; it also shows the method to calculate the PLL clock’s output frequency.

The register A2W_PLLH_CTRL has the value 0x2104d (placed in there by the RPi firmware). This value implies that NDIV is set to 0x4d, and PDIV is set to 1. The register A2W_PLLH_FRAC has the value 0x58000. The variable using_prediv has the value 0.

Then, the rate at which the PLLH clock runs is calculated as:

(19.2 MHz * ((0x4d << 20) + 0x58000)) >> 20 = 1485 MHz.

The PLLH_PIX clock is a divider clock, sourcing its input from the output of the PLLH clock. The PLLH_PIX clock has a fixed divider of 10, and another 8-bit integer divider stored in the register A2W_PLLH_PIX. Together, these dividers divide the input frequency to generate its output frequency. With the fixed divider of 10, and the 8-bit integer divider set to 1, the PLLH_PIX clock thus outputs a frequency of 1485 MHz / (10 * 1) = 148.5 MHz, which is exactly the desired frequency for the pixel clock.

The parameters set for the PLLH and the PLLH_PIX clocks, for a few more standard resolutions are:

Resolution Comment
640x480@60Hz PLLH: NDIV=0x1a, FDIV=0x40000.
PLLH_PIX: 8-bit integer divisor set to 2.
800x600@60Hz PLLH: NDIV=0x14, FDIV=0xd5556.
PLLH_PIX: 8-bit integer divisor set to 1.