This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] SN65DSI86:TI SN65DSI86至 eDP 面板(NT156FHM-N41)-与 raspberrypi 计算模块4 (6.6.y Linux 内核)无 AUX 通信

Guru**** 2393725 points
Other Parts Discussed in Thread: SN65DSI86

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1513184/sn65dsi86-ti-sn65dsi86-to-edp-panel-nt156fhm-n41---no-aux-communication-with-raspberrypi-compute-module-4-6-6-y-linux-kernel

器件型号:SN65DSI86

工具/软件:

大家好:

我正在努力将 TI SN65DSI86 DSI 转 eDP 桥接芯片与 Raspberry Pi 计算模块4和 NT156FHM-N41 eDP 面板进行连接。

我已通过在面板上显示测试条图形成功验证了数据路径、因此基本连接似乎可以。 但是、我遇到了桥接芯片和面板之间的 AUX 通道通信问题。

具体情况如下:

  • eDP 协议使用 AUX 线路(AUX_P/N)进行控制通信、包括 EDID 和 DPCD 检索。
  • Raspberry Pi 上的 Linux 内核驱动程序尝试使用此 AUX 通道获取 EDID 信息以进行显示初始化。 这目前正在失败、并且显示流水线未设置。
  • 我编写了简单的脚本,通过网桥直接与面板通信,以读取 EDID 和 DPCD ,但这些也无法接收任何数据。 这强烈表明 AUX 通信本身存在问题。
  • 我已经尝试过毫无变化地交换 AUX_P 和 AUX_N 导线。

我使用的面板是 NT156FHM-N41 (数据表: BOE NT156FHM-N41)。 我正在寻找有关如何调查以使 AUX 通信正常工作的建议。

我是否应该考虑特定的硬件注意事项(如端接、上拉、信号完整性)? SN65DSI86上是否有任何对 AUX 通信至关重要的特定配置设置? 任何具有类似设置的见解或经验都将非常感谢!

提前感谢您的帮助!



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Bhavin、

    您是否在启动事务时探测并观察到 AUX 信道上的活动? 请检查波形以确认辅助通道上存在活动。

    请查看数据表中 I2C over AUX 的直接和间接方法:"8.4.5.3 I2C-over-AUX"一节。 您使用哪种方法?  您能否共享脚本以了解如何启动这些步骤?  

    您的系统使用哪种 DP 链路训练模式? AUX 是否在您设置的模式下用于链路训练?

    此致、
    Ikram

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尚未开始、我们想先确认我们的软件配置。 进行探测。

    是的、我们在测试脚本中遵循间接方法。 我将在下面添加脚本

    我们对测试模式使用了半自动链路训练、如 TI 的 SN65DSI86编程指南中所建议的那样。
    我们的目标是使用此桥接芯片、通过 DSI 端口将上述 eDP 面板连接到 Raspberry Pi。 从 Linux 内核驱动程序中、我们希望利用现有的 sn65dsi86.c (https://github.com/raspberrypi/linux/blob/rpi-6.6.y/drivers/gpu/drm/bridge/ti-sn65dsi86.c)驱动程序和 panel-edp.c (https://github.com/raspberrypi/linux/blob/rpi-6.6.y/drivers/gpu/drm/panel/panel-edp.c)驱动程序。 在配置这些驱动程序时、我们看到面板驱动程序无法读取 EDID、为了确认这一点、我们尝试使用测试脚本、测试脚本给出了相同的结果、EDID 读取为全零。
    我们的理解是、该驱动程序应采用器件树 文档(https://github.com/raspberrypi/linux/blob/rpi-6.6.y/Documentation/devicetree/bindings/display/bridge/ti%2Csn65dsi86.yaml)中建议的正确配置开箱即用。

    EDID_read2.sh
     

    #!/bin/bash
    
    I2C_DEV=1
    BRIDGE_ADDR=0x2c
    
    # 1. Enable EDID I2C address claim (0x50 with enable bit)
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x60 0x61 #0xA1  # 0xA1 = 0b10100001
    
    # 2. Set AUX_ADDR for I2C-over-AUX EDID address (high/mid = 0)
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x74 0x00  # AUX_ADDR[19:16]
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x75 0x00  # AUX_ADDR[15:8]
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x76 0x30 #0x50  # AUX_ADDR[7:0] — EDID address
    
    # 3. Set length to 16 bytes (0x10) — can read full EDID by looping
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x77 0x10
    
    # 4. Set command to I2C read (0x09 = I2C-over-AUX Read Request)
    #     Format: (CMD << 4) | 0x01 = 0x91
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x78 0x91
    
    # 5. Poll until SEND bit (bit 0 of 0x78) is cleared (max timeout 1s)
    timeout_ms=1000
    elapsed=0
    while true; do
        val=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR 0x78)
        if (( (val & 0x01) == 0 )); then
            break
        fi
        sleep 0.01
        elapsed=$((elapsed + 10))
        if (( elapsed >= timeout_ms )); then
            echo "ERROR: AUX transaction timed out"
            exit 1
        fi
    done
    
    # 6. Read back data (AUX_RDATA0 - AUX_RDATA15)
    echo "EDID chunk (16 bytes):"
    for i in $(seq 0 15); do
        reg=$((0x79 + i))
        byte=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR $reg)
        printf "%s " "$byte"
    done
    echo
    


    EDID_read.sh
    #!/bin/bash
    
    I2C_DEV=1        # Replace with correct I2C bus
    BRIDGE_ADDR=0x2c           # SN65DSI86 I2C address
    EDID_ADDR=0x50             # Standard EDID I2C address
    NUM_BLOCKS=1               # EDID block count (1 = 128 bytes)
    BYTES_PER_BLOCK=128
    
    # Enable I2C Claim1 for EDID address (0x50)
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x60 $((EDID_ADDR << 1 | 1)) # 7:1 address + EN bit
    
    # Function to read EDID block (16 bytes at a time)
    read_block() {
        local offset=$1
        for ((i=0; i<BYTES_PER_BLOCK; i+=16)); do
            # Set AUX_ADDR[7:0] to EDID address (0x50)
            i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x77 $EDID_ADDR
    
            # Set AUX_LENGTH (0x74) to 16
            i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x74 0x10
    
            # Set AUX_CMD (0x78) to 0x9 (I2C Read)
            # Set SEND bit (bit 0) to trigger transaction
            i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x78 0x91
    
            # Poll until SEND bit clears
            while true; do
                val=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR 0x78)
                if (( val & 0x01 == 0 )); then
                    break
                fi
                printf "Poll until SEND  bit clears"
                sleep 0.01
            done
    
            # Read 16 bytes from AUX_RDATA0–15 (0x79 to 0x88)
            printf "EDID offset 0x%02X: " $((offset + i))
            for ((j=0; j<16; j++)); do
                byte=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR $((0x79 + j)))
                printf "%s " "$byte"
            done
            echo
        done
    }
    
    # Read full EDID
    for ((block=0; block<NUM_BLOCKS; block++)); do
        read_block $((block * BYTES_PER_BLOCK))
    done
    


    DPCD_read.sh
    #!/bin/bash
    
    I2C_DEV=1               # Replace with correct I2C bus (e.g., /dev/i2c-2)
    BRIDGE_ADDR=0x2c        # SN65DSI86 I2C address
    DPCD_ADDR=(0x00 0x00 0x00)  # DPCD base address is 0x00000
    
    # Write DPCD address to AUX_ADDR registers (0x74, 0x75, 0x76)
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x74 ${DPCD_ADDR[0]} b
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x75 ${DPCD_ADDR[1]} b
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x76 ${DPCD_ADDR[2]} b
    
    # Set AUX length to 16 bytes
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x77 0x10 b
    
    # Set AUX_CMD to 0x2 (AUX read)
    # Set SEND = 1 to initiate transaction
    i2cset -y -f $I2C_DEV $BRIDGE_ADDR 0x78 0x21 b
    
    # Poll until SEND bit clears
    for i in {1..100}; do
        val=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR 0x78)
        if (( (val & 0x01) == 0 )); then
            break
        fi
        sleep 0.01
    done
    
    # Check if it timed out
    if (( (val & 0x01) != 0 )); then
        echo "Timeout waiting for AUX transaction to complete."
        exit 1
    fi
    
    # Read back 16 bytes from AUX_RDATA0–AUX_RDATA15 (0x79–0x88)
    echo "DPCD Response:"
    for ((i=0; i<16; i++)); do
        reg=$((0x79 + i))
        data=$(i2cget -y -f $I2C_DEV $BRIDGE_ADDR $reg)
        printf "0x%02x " $data
    done
    echo
    


    prog_guild_pattr.sh
    #!/bin/bash
    
    I2CBUS=1        # Adjust as per your I2C bus
    ADDR=0x2c       # SN65DSI86 I2C address
    
    if [ $# -gt 0 ]; then
    	ASSR=1
    else
    	ASSR=0
    fi
    
    echo "ASSR:$ASSR"
    
    raspi-gpio set 20 op dl
    sleep 1
    raspi-gpio set 20 op dh
    
    # Helper to write a register
    w() {
      i2cset -y $I2CBUS $ADDR $1 $2
    }
    
    echo "[INFO] Configuring SN65DSI86 for test pattern..."
    if [ "$ASSR" -eq 0 ]; then
    	echo "configuring Non ASSR"
    	w 0xff 0x07
    	w 0x16 0x01
    	w 0xff 0x00    
    fi
    
    # Configure REFCLK 27 MHz
    w 0x0a 0x06
    
    # DSI A 4 Lanes
    w 0x10 0x20
    
    #DSIA Freq 445MHz
    w 0x12 0x59
    
    if [ "$ASSR" -eq 1 ]; then
    	w 0x5a 0x05
    else
    	#Enhance framing NO ASSR
    	w 0x5a 0x04
    fi
    
    #DP link rate 2.7 Gbps
    w 0x94 0x80
    
    # DP Lanes 2, no SSC
    w 0x93 0x20
    
    # Enable PLL
    w 0x0d 0x01
    sleep 0.1
    
    if [ "$ASSR" -eq 1 ]; then
    	echo "configuring ASSR"
    	w 0x95 0x00
    	w 0x64 0x01
    	w 0x74 0x00
    	w 0x75 0x01
    	w 0x76 0x0a
    	w 0x77 0x01
    	w 0x78 0x81
    	sleep 0.10
    fi
    
    # Semi auto train
    w 0x96 0x0a
    sleep 0.2
    
    # Video Parameters
    # Horizontal active: 1920
    w 0x21 $(( (1920 >> 8) & 0xFF ))
    w 0x20 $(( 1920 & 0xFF ))
    
    # Vertical active: 1080
    w 0x25 $(( (1080 >> 8) & 0xFF ))
    w 0x24 $(( 1080 & 0xFF ))
    
    # Horizontal front porch and back porch
    w 0x38 207
    w 0x34 48
    
    # HSync width: 32
    w 0x2c 32
    
    # vertical front porch and back porch
    w 0x3a 71
    w 0x36 3
    
    # VSync width: 6
    w 0x30 6
    
    # Dp 24 bpp
    w 0x5b 0x00
    
    # Color Bar enable
    w 0x3c 0x14 #12 = 3 color working
    
    # enhanced framing, ASSR, and Vstream enable
    w 0x5a 0x0d
    
    echo "[DONE] Test pattern should now be visible on the panel."
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bhavin:

    1.我不熟悉您分享的驱动程序代码。 您能告诉我们您从哪里得到这个吗?

    我们为该器件提供的软件是:

    DSI 驱动程序代码: https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/bridge/ti-sn65dsi86.c

    DSI 寄存器计算器: https://e2e.ti.com/support/interface-group/interface/f/interface-forum/945404/faq-sn65dsi86-how-do-i-programming-the-sn65dsi86-registers?tisearch=e2e-sitesearch&keymatch=sn65dsi86#

    也可以使用上面的计算器工具输入配置并生成用于初始化的 I2C 脚本。

    2.有关 I2C over aux 步骤、请给我1-2天时间检查您共享的"EDID_READ"脚本、并将其与数据表匹配。

    让我知道您是否能够探测和检查 AUX 信道活动。 此外、您正在使用 TI EVM 来测试 DSI86器件、


    此致、
    Ikram

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请在下面找到我的内联回复、
    1.我不熟悉您分享的驱动程序代码。 您能告诉我们您从哪里得到这个吗?
    这是您指出的同一个驱动程序。 您分享的驱动程序引用来自主线 内核、我们使用的是 Raspberry Pi 的官方版本、该版本是根据 Linux 内核为 Raspberry Pi 用例创建的。
     
    2.有关 I2C over aux 步骤、请给我1-2天时间检查您共享的"EDID_READ"脚本、并将其与数据表匹配。
    是的、请查看并告知我们。 请注意、EDID_read.sh 和 EDID_read2.sh 有些相似;唯一的区别是在 EDID_read2.sh 中、我们仅读取前16个字节。
     
    此外、您正在使用 TI EVM 来测试 DSI86器件、
    不、我们的定制 PCB 具有与 Raspberry Pi CM4 DSI1端口连接的桥接芯片。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Bhavin ,我将检查脚本,并得到你.

    谢谢您、
    Ikram

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是否有任何更新?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bhavin:

    很抱歉耽误时间。 从"EDID_read2.sh"脚本中、似乎您将 AUX_ADDR 设置为0x30、而不是0x50。 这适用于您的应用吗?

    此外、您要将0x78设置为0x91、而不是0x41。  您是否可以 将 AUX_CMD = 0x4用作"I2C-over-Aux Write MOT = 1"选项?

    之前的 E2E 末尾包含一小部分代码: https://e2e.ti.com/support/interface-group/interface/f/interface-forum/957141/sn65dsi86-q1-i2c-detection-problem

    此外、如果您的系统允许时钟延展、则您可以考虑使用直接方法来简化序列。

    此致、
    Ikram

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    从"EDID_read2.sh"脚本中、似乎您将 AUX_ADDR 设置为0x30、而不是0x50。 这适用于您的应用吗?
    它也不适用于0x50。  在调试过程中、我们尝试了一个备用地址0x30、就像在互联网上的某个位置一样。 您可以注意到、0x50器件被注释到同一行中。
     
    此外、您要将0x78设置为0x91、而不是0x41。  您是否可以 将 AUX_CMD = 0x4用作"I2C-over-Aux Write MOT = 1"选项?
    肯定会试一下的。
     
    此外、如果您的系统允许时钟延展、则您可以考虑使用直接方法来简化序列。
    您能为我们提供直接通信方法的命令序列吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bhavin:

    以下是之前有关直接方法的 E2E 主题: https://e2e.ti.com/support/interface-group/interface/f/interface-forum/949449/sn65dsi86-i2c-over-aux-direct-method/3508159

    脚本语法来自 Aardvark I2C 适配器

    谢谢您、
    Ikram