RK3399的HDMI双屏异显的有关问题

背景

  • Platform: RK3399
  • OS: Android7.1.2
  • Kernel: v4.4.103

问题及原因分析

项目中,我们使用Presentation开发了双屏异显功能。

不稳定问题

  • 在测试中,发现开机上电HDMI有时候有显示,有时候又没有,有时候甚至会一闪一闪的
    后面发现是硬件HPD脚不稳定,导致HDMI显示时好时坏。HPD为高时,主控才会通过DDC去读EDID。

    异显内容覆盖问题

  • 要显示在HDMI上的异显内容,覆盖显示在了本地的MIPI屏上,非必现。
    代码中,我们先调用了DisplayManagergetDisplays()获取屏幕的数量,只有2个才会调用Presentation去呈现异显内容。但因为上面的原因导致屏幕数量获取错误,从而出现了这个问题。
    后面我们改用使用广播监听的方式去检测HDMI的热插拔状态,而且硬件也修改,但获取的屏幕数量还是不对,
    最后我们使用DisplayManager.DisplayListeneronDisplayAddedonDisplayRemoved来监听屏幕的变化,监听到变化之后再调用getDisplays()方法来获取准确的屏幕信息,包括数量、Name等。使用广播的方式去监听热插拔然后马上去获取屏幕数量,可能这个时候HDMI还没有ready。

扩展

驱动代码

主要驱动代码:

  • dw-hdmi.c: HDMI驱动,包括内部I2C接口实现
  • drm_edid.c: edid相关
  • dw_hdmi-rockchip.c: drm框架部分
    插拔是否成功可以在check_hdmi_irq()@dw-hdmi.c中打印log

HDMI热插拔状态检测

比较常用的广播监听

注册一个动态广播来获取HDMI接口的插拔,它的Action的name为 “android.intent.action.HDMI_PLUGGED”,具体的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent receivedIt) {
String action = receivedIt.getAction();
if (action.equals("android.intent.action.HDMI_PLUGGED")) {
boolean state = receivedIt.getBooleanExtra("state", false);
if (state) {
isHdmiConnect = true;
} else {
isHdmiConnect = false;
}
}
}
};

直接获取状态:

通过直接读取:/sys/devices/virtual/switch/hdmi/state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static boolean isHdmiSwitchSet() {
// The file '/sys/devices/virtual/switch/hdmi/state' holds an int -- if it's 1 then an HDMI device is connected.
// An alternative file to check is '/sys/class/switch/hdmi/state' which exists instead on certain devices.
File switchFile = new File("/sys/devices/virtual/switch/hdmi/state");
if (!switchFile.exists()) {
switchFile = new File("/sys/class/switch/hdmi/state");
}
try {
Scanner switchFileScanner = new Scanner(switchFile);
int switchValue = switchFileScanner.nextInt();
switchFileScanner.close();
return switchValue > 0;
} catch (Exception e) {
return false;
}
}

但不能频繁操作

调试相关

/sys/class/drm/card0-HDMI-A-1

  • 设置drm的调试log等级:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    sys结点位置: /sys/module/drm/parameters/debug
    debug:Enable debug output, where each bit enables a debug category.
    Bit 0 (0x01) will enable CORE messages (drm core code)
    Bit 1 (0x02) will enable DRIVER messages (drm controller code)
    Bit 2 (0x04) will enable KMS messages (modesetting code)
    Bit 3 (0x08) will enable PRIME messages (prime code)
    Bit 4 (0x10) will enable ATOMIC messages (atomic code)
    Bit 5 (0x20) will enable VBL messages (vblank code) (int)
    示例: echo 0x0c > /sys/module/drm/parameters/debug
    打开了KMS, PRIME这些的打印, kernel驱动中使用DRM_DEBUG_KMS和
    DRM_DEBUG_PRIME打印的信息都可以打印出来

    一般设置为如下值:

    1
    echo 0x1f > /sys/module/drm/parameters/debug
  • 查看EDID有没有识别

    1
    dmesg | grep drm
  • 查看HDMI的状态

    1
    cat /d/dw-hdmi/status

参考

  1. https://www.cnblogs.com/fuccc/p/7676813.html
  2. 关于DisplayManager的Android官方文档
  3. https://blog.csdn.net/zhuyong006/article/details/81709520
Donate comment here