Chapter 55H: RGB-to-HDMI bridge (sii902x)

What: the Silicon Image SiI902x family of RGB-parallel-to-HDMI transmitter chips, and the kernel’s DRM bridge subsystem. The i.MX6ULL has no native HDMI. An SiI9022/SiI9024 chip on the LCDIF parallel output gives you HDMI. The mainline sii902x.c DRM bridge driver handles config and EDID parsing.

Why: any product that needs an external display (HMI, kiosk, signage) usually wants HDMI compatibility. SiI902x is a small, low-cost (~$2) chip that takes 24-bit RGB + HSYNC/VSYNC/PCLK and outputs HDMI 1.4 at up to 1080p60. It works on any i.MX6ULL board with LCDIF pinmux available.

Focus: the bridge concept. A DRM “bridge” sits between a CRTC (LCDIF) and a connector (HDMI port). DRM chains bridges automatically. You describe the chain in DT and the driver does the rest.

55H.1 Hardware

SiI902x has:

  • Input: 24 parallel RGB + HSYNC + VSYNC + PCLK + DE. From i.MX6ULL LCDIF.

  • Output: 4 differential pairs + DDC (HPD + I²C). To HDMI connector.

  • I²C control: 0x39 typically.

  • HPD (Hot Plug Detect) interrupt: tells the bridge when an HDMI cable is attached.

Connect LCDIF parallel out → SiI902x in, HDMI cable → SiI902x out, I²C2 + HPD-IRQ → host. The bridge handles EDID negotiation with the sink (TV/monitor).

MCU bridge: Think of an IRQ like an EXTI/NVIC interrupt path, except Linux splits the hard interrupt from deferred work and must share lines across drivers. IRQ: interrupt request, the signal path that tells the CPU or interrupt controller that hardware needs service.

55H.2 Device tree

&i2c2 {
    sii902x: hdmi@39 {
        compatible = "sil,sii9022";
        reg = <0x39>;
        reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
        interrupt-parent = <&gpio2>;
        interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
        #sound-dai-cells = <0>;

        ports {
            #address-cells = <1>;
            #size-cells = <0>;

            port@0 {
                reg = <0>;
                sii902x_in: endpoint {
                    remote-endpoint = <&lcdif_out>;
                };
            };

            port@1 {
                reg = <1>;
                sii902x_out: endpoint {
                    remote-endpoint = <&hdmi_connector_in>;
                };
            };
        };
    };
};

&lcdif {
    status = "okay";
    port {
        lcdif_out: endpoint {
            remote-endpoint = <&sii902x_in>;
        };
    };
};

hdmi_connector: hdmi-connector {
    compatible = "hdmi-connector";
    type = "a";
    port {
        hdmi_connector_in: endpoint {
            remote-endpoint = <&sii902x_out>;
        };
    };
};

Three DT nodes form the graph: LCDIF, SiI902x, and the HDMI connector. The DRM bridge chain wires them together.

55H.3 How it works

At boot:

  1. SiI902x’s sii902x_probe registers a DRM bridge.

  2. LCDIF’s DRM driver sees a downstream bridge instead of a panel.

  3. SiI902x’s attach callback runs. It queries the connector for HPD state.

  4. If HPD is asserted (cable plugged), it reads EDID from the sink (via DDC I²C on the HDMI connector).

  5. Available modes derived from EDID become valid DRM modes.

modetest shows the modes:

[root@pa-mini:~]# modetest -M mxsfb
Connectors:
id      encoder status          name            size (mm)       modes   encoders
42      40      connected       HDMI-A-1        598x336         18      40
        modes:
            #0 1920x1080 60.00 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: preferred
            #1 1280x720 60.00 1280 1390 1430 1650 720 725 730 750 74250 flags: phsync, pvsync;
            ...

Set a mode:

[root@pa-mini:~]# modetest -M mxsfb -s 42:1920x1080

However, the i.MX6ULL LCDIF tops out at about 80 MHz pixel clock. 1080p60 is 148.5 MHz. Doesn’t work. Practical max on i.MX6ULL via SiI902x is 720p (74.25 MHz). 480p, 576p, 720p all work.

55H.4 Audio over HDMI

SiI902x also carries audio. With #sound-dai-cells = <0>;, the chip exposes an audio DAI. Build an ASoC machine driver (Ch 53) that connects SAI → SiI902x → HDMI. Most products skip this and use HDMI for video only.

ASoC: ALSA System-on-Chip, the embedded audio layer that connects CPU audio ports, codecs, and board wiring.

55H.5 Lab

  1. Add SiI902x to your DT. Boot. Check dmesg | grep sil for “SiI902x bridge ready” or similar.

  2. Plug an HDMI monitor. modetest -M mxsfb -c lists connected outputs. HDMI-A-1 should be connected with valid modes.

  3. Set 720p. modetest -M mxsfb -s <id>:1280x720. Verify monitor displays.

  4. /dev/fb0 painting. Default fbdev emulation shows it. cat /dev/urandom > /dev/fb0 paints noise on the HDMI output.

  5. HPD detection. Unplug cable. Observe disconnected event in dmesg / modetest -c.

  6. Try 1080p. Confirm it fails (LCDIF pixel clock limit). Read drm.debug=15 dmesg for the rejection.

55H.6 Pitfalls

  • No HPD wiring. Bridge thinks nothing connected. Mode list is empty.

  • Reset-gpios polarity wrong. Chip held in reset forever.

  • DDC pull-ups missing. EDID read fails. Schematic check.

  • Pixel clock > 80 MHz. LCDIF chokes. Stay ≤ 720p on i.MX6ULL.

  • No frame-rate match. Some monitors require specific timings. The EDID list filters out invalid ones but check the kernel debug output.

  • Modeset reports OK but the screen stays blank. Often the HDMI sink is expecting a different pixel format than the bridge sends. SiI902x defaults to RGB. Some old TVs want YCbCr. Force RGB via property if needed.

55H.7 Going deeper

  • drivers/gpu/drm/bridge/sii902x.c: the SiI902x DRM bridge driver.

  • Documentation/gpu/drm-kms.rst: KMS bridge chain.

  • SiI9022 datasheet: register map, EDID handling, audio config.

Next chapter: Chapter 55I: Rust-for-Linux. A small kernel-module written in Rust, demonstrating the upcoming second kernel language.