DWC HDMI Controller

The A83t/H3/A64/(A80?) SoCs use a Synopsys DesignWare HDMI controller. A83t and A64 seem to use a PHY from Synopsys too, but H3 has an unknown PHY.

= Register Guide =

Base address: 0x01ee0000

Controller
0x01ee0000 - 0x01eeffff (only byte-accessible)

(A similar version of) the controller is publicly documented in the i.MX6 Reference Manual, chapter 33. The A83t/A64 PHY registers are documented in this manual too, the H3 PHY registers are undocumented. There also is a mainline Linux driver for the controller in drivers/gpu/drm/bridge/dw_hdmi.c. This driver also supports the A83t and A64 PHYs, but SoC specific parameters are needed for PHY configuration.

Now the hard part, the register addresses are obfuscated in sunxi for some silly reason. To use existing drivers/documentation the address bits have to be rearranged in the following way:

real <-> obfuscated address bits A1  <-> A15 A3  <-> A14 A5  <-> A13 A7  <-> A12 A9  <-> A11 A11 <-> A10 A13 <-> A9 A15  <-> A8 A14  <-> A7 A12  <-> A6 A10  <-> A5 A8   <-> A4 A6   <-> A3 A4   <-> A2 A2   <-> A1 A0   <-> A0

For example, to access register 0x100D (vsync width) one has to access 0x4043 on sunxi.

def dwc2sunxi(r): return (       ((r & (1 << 15)) >> 7) +        ((r & (1 << 14)) >> 7) +        ((r & (1 << 13)) >> 4) +        ((r & (1 << 12)) >> 6) +        ((r & (1 << 11)) >> 1) +        ((r & (1 << 10)) >> 5) +        ((r & (1 << 9)) << 2) +        ((r & (1 << 8)) >> 4) +        ((r & (1 << 7)) << 5) +        ((r & (1 << 6)) >> 3) +        ((r & (1 << 5)) << 8) +        ((r & (1 << 4)) >> 2) +        ((r & (1 << 3)) << 11) +        ((r & (1 << 2)) >> 1) +        ((r & (1 << 1)) << 14) +        ((r & (1 << 0)) >> 0)    )

def sunxi2dwc(r): return (       ((r & (1 << 15)) >> 14) +        ((r & (1 << 14)) >> 11) +        ((r & (1 << 13)) >> 8) +        ((r & (1 << 12)) >> 5) +        ((r & (1 << 11)) >> 2) +        ((r & (1 << 10)) << 1) +        ((r & (1 << 9)) << 4) +        ((r & (1 << 8)) << 7) +        ((r & (1 << 7)) << 7) +        ((r & (1 << 6)) << 6) +        ((r & (1 << 5)) << 5) +        ((r & (1 << 4)) << 4) +        ((r & (1 << 3)) << 3) +        ((r & (1 << 2)) << 2) +        ((r & (1 << 1)) << 1) +        ((r & (1 << 0)) >> 0)    )

General and PHY
0x01ef0000 - 0x01ef00ff

Some register guessing:

0x10 Some magic (write only 0x54524545 "TREE" and 0x57415452 "WATR")

H3 only (PHY related, A64 and A83t have the PHY connected to internal I2C)

0x20 Control register

0x24

0x28

0x2c

0x30 PLL/Clock register	(bit ?:0 clock divider, parent is PLL3, not HDMI_CLK)

0x34

0x38 Status register