The linux-5.4.18 kernel forces the output of graphics display signals and specifies the resolution through the firmware file.

Table of Contents

1 Introduction

2 Set the connector status to “connector_status_connected”

2.1 Connector status

2.2 Forcibly set the connector status to “connector_status_connected”

2.2.1 Introduction

2.2.2 Get the name of the connector

2.2.3 Add: video=DP-1:D to the startup parameters

3 Set the resolution through firmware

3.1 Create firmware file (take 1920×1200 resolution as an example)

3.2 Compile the 1920×1200.bin file into the kernel image

3.3 Add startup parameters

Reference: Documentation/driver-api/edid.rst


1 Introduction

Common personal computer display interfaces (such as HDMI) have detection signals that can detect whether a monitor is connected. When a new display is detected, the Linux kernel will obtain the display’s resolution, refresh rate and other information through the I2C channel, and then the kernel will set the output image display signal according to the resolution supported by the display.

On a tablet computer, the screen is fixed, so there is no need for a detection process, and a resolution can be fixed directly.

2 Set the connector’s status to “connector_status_connected”

2.1 connector status

The linux kernel uses the DRM framework to manage display functionality. In the DRM framework, “struct drm_connector” is used to abstractly represent interfaces such as VGA and HDMI. There is a member variable “enum drm_connector_status status” in the struct drm_connector structure to indicate whether a monitor is connected. There are three statuses:

/**
 * enum drm_connector_status - status for a & amp;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 Forcibly set the connector status to “connector_status_connected”

2.2.1 Introduction

On some tablet hardware, because the screen is fixed and there is no need to dynamically detect whether a new screen is connected, the detection signal in the display interface is omitted. In this case, it is necessary to inform the Linux kernel that the current screen is connected through other methods.

2.2.2 Get the name of the connector

Turn on debugging information for drm

Add in the startup parameters: drm.debug=0xfff

then restart

Check the dmesg information and you can see the following information:

[ 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

The connector name shown above is “DP-1

2.2.3 Add: video=DP-1:D in the startup parameters

Corresponding kernel processing function

//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) & amp; & amp;
                (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
                mode->force = DRM_FORCE_ON;
            else
                mode->force = DRM_FORCE_ON_DIGITAL;
            break;
        ...
}

After restarting the system, you can see the following information in the dmesg information

[ 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 Set the resolution through firmware

3.1 Create firmware files (take 1920×1200 resolution as an example)

After obtaining the specific display parameters of the screen, create the file “1920×1200.S” in the linux-5.4.18/Documentation/EDID/ directory. The file content is as follows:

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

#defineXPIX 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"

Compile the “1920×1200.S” file into a bin file

cd linux-5.4.18/Documentation/EDID/
make
After successful compilation, 1920×1200.bin will be generated in the linux-5.4.18/Documentation/EDID/ directory

3.2 Compile the 1920×1200.bin file into the kernel image

Modify the following 2 kernel configurations to specify the file 1920×1200.bin
CONFIG_EXTRA_FIRMWARE
CONFIG_EXTRA_FIRMWARE_DIR

Then compile the kernel

3.3 Add startup parameters

Add the following startup parameters: drm.edid_firmware=DP-1:1920×1200.bin (corresponding kernel processing function: drm_add_override_edid_modes();)

Then restart the system.

After the above operation is successful, you can see the following content in the dmesg information:

[ 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

Reference: Documentation/driver-api/edid.rst