Display SerDes#

NVIDIA provides a reference driver for display serializer and deserializer known as nvdisp_serdes. It is for stakeholders who are using display serializer-deserializer hardware provided by different vendors. Such display serializer hardware is connected to display output connector of NVIDIA automotive platform.

Overall, Display serdes driver workflow is divided into two parts:

    1. serdes driver device tree node,

    1. serdes driver.

The device tree node contains basic properties to set up device driver and serdes configuration for underlying hardware. It is mentioned as display-serdes-config node and is required for programming the underlying serializer and deserializer hardware. Stakeholders must follow OPCODE specification and populate this node with required data.

The serdes reference driver reads this display-serdes-config node from device tree blob during probe. The driver has implementation of pre-defined action for each OPCODE. The driver then executes action for each corresponding OPCODE, which is read from this device node during different phases of functionality like initialization, suspend, resume, etc. So, in brief, the driver executes OPCODEs defined in field init-seq of display-serdes-config node during boot and resume. It executes OPCODEs defined in field errb-seq of display-serdes-config node during error interrupt handling. It executes OPCODEs defined in field deinit-seq of display-serdes-config node during suspend.

Configuring the Driver Device Tree Node#

There are various ways to configure the driver by using device tree node and its properties. As shown in the following example, a device tree node fragment is given that configures the serdes driver on i2c node with required device tree properties including mandatory display-serdes-config property.

 i2c@810c420000 {
    status = "okay";
    nvdisp_serdes_b: nvdisp_serdes@40 {
        compatible = "nvidia,nvdisp_serdes";
        reg = <0x40>;
        status = "okay";
        nvdisp-serdes-errb = <&gpio_main TEGRA264_MAIN_GPIO(T, 6) GPIO_ACTIVE_HIGH>;
        reg-bits = <0x10>;
        val-bits = <0x08>;
        display-serdes-config {
        description = "MAX96851 connected as SER B, GMSL2, SST";
        /* opcode sequence to initialize SerDes */
        init-seq =
        [50], [00 00 0F A0], [FF],
        /* debug: read link A and link B lock status registers */
        [F0], [40 00], [2A 00], [FF],
        [F0], [40 00], [34 00], [FF];
        deinit-seq =
        /* disable video link output at pipe X */
        [10], [40 00], [00 01], [60], [00], [FF];
        errb-seq =
        /*** start: detect and clear error for internal video crc */
        /* read error status register for internal video crc to clear pending error */
        [80], [40 00], [49 04], [04], [00], [04], [00], [FF],
        [80], [40 00], [49 05], [04], [00], [04], [00], [FF];
    };
};

A description of each of the preceding properties is as follows:

  • Required properties:

    • compatible: Must be nvidia,nvdisp_serdes.

    • reg: I2C address of the display serializer.

    • display-serdes-config:

      • This is parent node for configuration of display serdes hardware.

      • This contains different sequences like init-sequence, deinit-sequence, errb-sequence.

      • Each sequence is again set of OPCODEs (operation code).

      • OPCODE is set of bytes that starts with HEADER, then is followed by PAYLOAD and then terminated with TERMINATOR code.

      • Details of OPCODE are given in The OPCODE Specification section below.

      • init-seq

      • This is a mandatory property.

      • This property contains the OPCODE sequence that is executed by the driver during the initialization of serdes driver. It can contain I2C commands to program hardware and some OS specific operations as given in OPCODE specification.

      • This is executed during probe and resume of serdes driver.

      • deinit-seq

      • This property contains an OPCODE sequence that is executed during de-initialization of serdes hardware. This happens either during the removal of the driver or suspend operation of driver. This is an optional property as in some scenarios, there is no action required in case of deinitialization of serdes hardware.

      • errb-seq

      • This property contains an OPCODE sequence that gets executed as part of interrupt handling in response to interrupt reported on ERRB pin. It can contain I2C commands as given in OPCODE specification. This is an optional property as in some scenarios, there is no action required in case of absence of error interrupt pin from serdes hardware.

  • Optional properties:

    • reg-bits: Width of address register of serdes. Default is 16 bits if not mentioned.

    • val-bits: Width of value for register of serdes. Default is 8 bits if not mentioned.

    • nvdisp-serdes-errb: GPIO pin init level and pin number details for ERRB pin.

    • description: This is a one-line description that gives information in brief about what is this serdes configuration. This is also logged in dmesg debug logs.

Note

* If you want to override the above sequences, you can either change the content of the above sequences in default dtsi file; * Or you can create a new dtsi file, modify OPCODE sequences, and then include that dtsi file at end of your platform dtsi file. * In such case, the optional and not needed sequences also present in final dtb file, so such sequences can be removed using the delete-property approach. * For example, if you do not want de-init sequence in your overridden platform dtsi file, then you must include /delete-property/ deinit-seq; in display-serdes-config as the first line.

The OPCODE Specification#

This specification gives guidelines to stakeholders who are creating device tree property like init-seq, deinit-seq, or errb-seq, which is part of display-serdes-config property for underlying display serializers and deserializer hardware that is connected to display output connector of NVIDIA automotive platform.

These properties are a set of multiple OPCODEs. An OPCODE is sequence of bytes that begin with OPCODE_HEADER, then followed by OPCODE_DATA, and then followed by last byte as TERMINATOR. OPCODE_HEADER is a single byte value that is unique per OPCODE. OPCODE_DATA is a variable number of bytes that have some meaning for that OPCODE. Bytes that belong to same logical field in opcode sequence are included within [ and ] brackets.

For example:

The OPCODE sequence below is for I2C write of a single byte at two-byte address register at i2c device.

[10], [40 00], [29 00], [01], [00], [FF],

In the above example, the first data byte 10 is the OPCODE header. The second, third, up to sixth data bytes [40 00], [29 00], [01], [00] are part of OPCODE DATA, and the last data byte FF in the sequence is the TERMINATOR.

A few things to notice in OPCODE sequence are:

    1. All numbers are hex numbers.

    1. Hex numbers between brackets [ and ] are from same logical group. For example, [29 00] belongs to one logical field within opcode sequence.

OPCODE Details#

This section explains each OPCODE details with an example.

I2C_WRITE_8_SINGLE → [0x10]

Performs a single-byte I2C write to the specified I2C device.

Byte #

0

1

2

3

4

5

6

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Register Data

Padding

Value

[10]

[LO HI]

[LO HI]

[DATA]

[00]

Description

Performs a single-byte I2C write to the specified I2C device.

Size

6

Header

10

Example

[10], [40 00], [29 00], [01], [00], [FF]

Interpretation is to write data 0x01 at address 0x0029 for i2c device 0x0040.

I2C_READ_8_SINGLE → [0x30]

Performs a single-byte I2C addressed read from the specified I2C device.

Byte #

0

1

2

3

4

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Value

[30]

[LO HI]

[LO HI]

Description

Performs a single-byte I2C read from the specified I2C device.

Size

4

Header

30

Example

[30], [40 00], [21 00], [FF]

Interpretation is to read register 0x0021 from i2c device 0x0040.

I2C_READ_8_SINGLE_WITH_GOLDEN_VALUE → [0x80]

Performs a single-byte I2C addressed read with validation from the specified I2C device.

Byte #

0

1

2

3

4

5

6

7

8

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Golden Mask

Padding

Golden Value

Padding

Value

[80]

[LO HI]

[LO HI]

[MASK]

[00]

[DATA]

[00]

Description

Performs a single-byte I2C read and verify masked value.

Size

8

Header

80

Example

[80], [40 00], [49 04], [04], [00], [04], [00], [FF]

Interpretation is to read data from 0x0449 register, compare its golden mask of 0x04 with golden value 0x04.

This can also be achieved by OPCODE 0x90 where one can set polling count to 0 and polling delay to 0.

I2C_READ_8_SINGLE_WITH_POLLING → [0x90]

Performs an I2C single byte read with polling to the specified I2C device.

Byte #

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Polling Count

Padding

Polling Delay in µs (LSB)

Polling Mask (LSB)

Polling Value (LSB)

Value

[90]

[LO HI]

[LO HI]

[DATA]

[00]

[LO … … HI]

[LO HI]

[LO HI]

Description

Performs a single-byte I2C read and poll for value for specified duration.

Size

14

Header

90

Example

[90], [40 00], [2A 00], [0A], [00], [10 27 00 00], [01 00], [01 00], [FF]

Interpretation is to read data from 0x002A register, compare its mask of 0x0001 with value 0x0001 for duration of (0x2710 * 0xA) microsecond.

OS_DELAY_USEC → 0x50

Performs a delay specified in microseconds.

Byte #

0

1

2

3

4

Description

OpCode

Delay in µs (Cell)

Value

[0x50]

Description

Introduce delay

Size

4

Header

50

Example

[50], [00 00 0F A0], [FF]

Above example means introduce delay/sleep.

Note

This is required for AV + L driver for API “usleep_range” which is Linux specific function is usleep_range(min, max).

The above value is the min value. The max is calculated using min + 200.

If we need to support max value, we will have to come with new OPCODE.

At the writing of this, for AV + Q and DCE drivers, above opcode will introduce sleep/delay in their respective library.

I2C_UPDATE_SINGLE_BYTE – A2

Update field/mask of register.

Byte #

0

1

2

3

4

5

6

7

8

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Golden Mask

Padding

Golden Value

Padding

Value

[A2]

[LO HI]

[LO HI]

[MASK]

[00]

[DATA]

[00]

Description

Performs a single-byte I2C write with masked value

Size

8

Header

A2

Example

[A2], [40 00], [49 04], [10], [00], [00], [00], [FF]

Above means update value of 0x0449 register, so that mask of 0x10 is updated with value 0x00.

In short, update bit 5 with value 0 of this register.

I2C_READ_8_SINGLE_PRINT – F0

Read and print the value of the 8-bit register (debug purpose only).

Byte #

0

1

2

3

4

Description

OpCode

I2C Address (LSB)

Register Address (LSB)

Value

[F0]

[LO HI]

[LO HI]

Description

Read a single-byte I2C byte and print

Size

8

Header

A2

Example

[F0], [40 00], [2A 00], [FF]

Above means read value of 0x002A register and print it on console.

Configure MST IDs in the serializer opcode file#

In the MST serializer configuration file (e.g., tegra264-p3960-serdes-max96861-ser-c-gmsl2-mst.dtsi), ensure the MST IDs match the heads being routed to this serializer. According to the DisplayPort specification, the MST ID for each stream must be set correctly.

The MST ID value must follow the rule: MST ID = head_index + 1

For example, if you are configuring:

Native DP (connector 0) with head 0 Serializer B (connector 1) in SST mode with head 1 Serializer C (connector 2) in MST mode with heads 2 and 3 Then in the MST configuration for Serializer C, modify the MST payload ID opcodes to use values 3 and 4 for the first two payload IDs, and zero out the unused ones:

/* MST payload id 0 */
[10], [40 00], [04 79], [03], [00], [FF],  // Changed from 01 to 03
/* MST payload id 1 */
[10], [40 00], [08 79], [04], [00], [FF],  // Changed from 02 to 04
/* MST payload id 2 */
[10], [40 00], [0c 79], [00], [00], [FF],  // Changed from 03 to 00
/* MST payload id 3 */
[10], [40 00], [10 79], [00], [00], [FF],  // Changed from 04 to 00

Similarly, if Serializer B is configured for MST mode with heads 1 and 2, the MST IDs are 2 and 3.

Note

The display driver programs the MST IDs as head_index + 1, so you must ensure the MST IDs in the serializer opcode file match this pattern based on the heads being routed to that serializer.