linux-5.4.18内核强制输出图形显示信号 并通过firmware文件指定分辨率

目录

1 简介

2 设置 connector 的状态为“connector_status_connected”

2.1 connector的状态

2.2 强制设置connector 的状态为“connector_status_connected”

2.2.1 简介

2.2.2 获取connector的名称

2.2.3 在启动参数里添加:video=DP-1:D

3 通过firmware方式设置分辨率

3.1 创建firmware 文件(以1920x1200分辨率为例)

3.2 将 1920x1200.bin 文件编译到内核镜像里

3.3 添加启动参数

参考:Documentation/driver-api/edid.rst


1 简介

        常见的个人电脑显示接口(如HDMI)都有探测信号,可以检测有没有连接显示器。当探测到连接新的显示器的时候,linux内核会通过I2C通道来获取显示器的分辨率、刷新率等信息,然后内核会根据显示器支持的分辨率设置输出的图像显示信号。

        在平板电脑上,屏幕是固定的,所以不需要探测的过程,同时可以直接固定一个分辨率。

2 设置 connector 的状态为“connector_status_connected”

2.1 connector的状态

        linux内核使用DRM框架来管理显示功能。在DRM框架中使用“struct drm_connector”来抽象化表示是VGA、HDMI等接口。struct drm_connector结构体中有一个成员变量“enum drm_connector_status status”来表示是否有连接显示器,有以下3中状态:

/**
 * enum drm_connector_status - status for a &drm_connector
 *
 * This enum is used to track the connector status. There are no separate
 * #defines for the uapi!
 */
enum drm_connector_status {
    /**  
     * @connector_status_connected: The connector is definitely connected to
     * a sink device, and can be enabled.
     */
    connector_status_connected = 1, 
    /**  
     * @connector_status_disconnected: The connector isn't connected to a
     * sink device which can be autodetect. For digital outputs like DP or
     * HDMI (which can be realiable probed) this means there's really
     * nothing there. It is driver-dependent whether a connector with this
     * status can be lit up or not.
     */
    connector_status_disconnected = 2, 
    /**  
     * @connector_status_unknown: The connector's status could not be
     * reliably detected. This happens when probing would either cause
     * flicker (like load-detection when the connector is in use), or when a
     * hardware resource isn't available (like when load-detection needs a
     * free CRTC). It should be possible to light up the connector with one
     * of the listed fallback modes. For default configuration userspace
     * should only try to light up connectors with unknown status when
     * there's not connector with @connector_status_connected.
     */
    connector_status_unknown = 3, 
};

2.2 强制设置connector 的状态为“connector_status_connected”

2.2.1 简介

        在某些平板电脑硬件上,因为屏幕是固定的,不需要动态探测是否有新屏幕连接,所以显示接口中的探测信号被省略了。在这种情况下就要通过其他方式告知linux内核当前屏幕已连接。

2.2.2 获取connector的名称

打开drm的调试信息

        在启动参数里添加:drm.debug=0xfff

然后重启

查看dmesg信息,可以看到如下信息:

[ 0.824831] [drm] Connector 0:
[ 0.824833] [drm] DP-1
[ 0.824835] [drm] HPD1
[ 0.824837] [drm] DDC: 0x4868 0x4868 0x4869 0x4869 0x486a 0x486a 0x486b 0x486b
[ 0.824839] [drm] Encoders:
[ 0.824841] [drm] DFP1: INTERNAL_UNIPHY

上面显示的connector名称是“DP-1

2.2.3 在启动参数里添加:video=DP-1:D

对应的内核处理函数

//drivers/gpu/drm/drm_modes.c
static int drm_mode_parse_cmdline_extra(const char *str, int length,
                    bool freestanding,
                    const struct drm_connector *connector,
                    struct drm_cmdline_mode *mode)
{
        ......
        case 'D': 
            if (mode->force != DRM_FORCE_UNSPECIFIED)
                return -EINVAL;

            if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
                (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
                mode->force = DRM_FORCE_ON;
            else 
                mode->force = DRM_FORCE_ON_DIGITAL;
            break;
        ......
}

重启系统后,可以在dmesg信息中看到如下信息

[ 8.274745] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:53:DP-1]
[ 8.274749] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:53:DP-1] status updated from unknown to connected

3 通过firmware方式设置分辨率

3.1 创建firmware 文件(以1920x1200分辨率为例)

在获取了屏幕的具体显示参数后,在 linux-5.4.18/Documentation/EDID/目录下创建文件“1920x1200.S”,文件内容如下:

/* EDID */
#define VERSION 1
#define REVISION 3

#define XPIX 1920
#define XBLANK 160
#define XOFFSET 48
#define XPULSE 32

#define YPIX 1200
#define YBLANK 35
#define YOFFSET 3
#define YPULSE 6

#define DPI 72
/* Display */
#define CLOCK 77000 /* kHz */
#define XY_RATIO XY_RATIO_16_10
#define VFREQ 30 /* Hz */
#define TIMING_NAME "Linux XGA"
#define HSYNC_POL 1
#define VSYNC_POL 1

#include "edid.S"

将“1920x1200.S”文件编译成 bin 文件

cd linux-5.4.18/Documentation/EDID/
make
编译成功后,会在 linux-5.4.18/Documentation/EDID/目录下生成 1920x1200.bin

3.2 将 1920x1200.bin 文件编译到内核镜像里

修改下面 2 个内核配置来指定文件 1920x1200.bin
        CONFIG_EXTRA_FIRMWARE
        CONFIG_EXTRA_FIRMWARE_DIR

然后编译内核

3.3 添加启动参数

增加以下启动参数:drm.edid_firmware=DP-1:1920x1200.bin                (对应的内核处理函数:drm_add_override_edid_modes();)

然后重启系统。

以上操作成功后,可以在 dmesg 信息里看到以下内容:

[ 9.219533] [drm] Got external EDID base block and 0 extensions from "1920x1200.bin" for connector "DP-1"
......
[ 9.240652] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:53:DP-1] probed modes :
[ 9.240657] [drm:drm_mode_debug_printmodeline] Modeline "1920x1200": 30 77000 1920 1968 2000 2080 1200 1203 1209 1235 0x48 0x5

参考:Documentation/driver-api/edid.rst

猜你喜欢

转载自blog.csdn.net/u010936265/article/details/134227945