K230_DRM_API_Reference#

1. Introduction to DRM#

DRM is the management architecture responsible for interacting with the graphics card in the Linux kernel, and user programs can easily use the API provided by DRM to achieve display control, 3D rendering, video encoding and decoding, GPU computing and other work

1.1 DRM architecture features#

DRM is the mainstream graphics display framework in the current Linux kernel, compared with the traditional FB architecture, it has the following characteristics:

  1. DRM architecture natively supports multi-layer synthesis, FB schema natively does not support multi-layer synthesis

  2. The DRM architecture natively supports VSYNC, DMA_BUF, and Fence mechanisms

  3. The DRM architecture manages rendering and display drivers in a unified manner, making software development and maintenance simpler

1.2 DRM architecture composition#

From the overall architecture, DRM is mainly divided into three parts:

  • libdrm

    libdrm encapsulates the underlying interface and provides a common API interface to user patterns

    libdrm also provides a modetest program internally for querying the details of DRM devices, as well as basic display testing

  • KMS

    KMS stands for Kernel Mode Settings, which mainly sets display resolution, color space, refresh rate, and display buffer switching and multilayer compositing

  • GEM

    Memory management, responsible for memory allocation and release

2. ModeTest instructions#

modetest is a test program provided by libdrm that can query the details of DRM devices while also performing basic display tests

2.1 Query K230 DRM details#

The specific instructions are as follows:

[root@canaan ~ ]#modetest -M canaan-drm
Encoders:
id      crtc    type    possible crtcs  possible clones
37      36      DSI     0x00000001      0x00000001

Connectors:
id      encoder status          name            size (mm)       modes   encoders
38      37      connected       DSI-1           68x120          1       37
  modes:
        index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 1080x1920 30.00 1080 1310 1330 1350 1920 1925 1931 1939 78529 flags: ; type: preferred, driver
  props:
        1 EDID:
                flags: immutable blob
                blobs:

                value:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 0
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0
        6 non-desktop:
                flags: immutable range
                values: 0 1
                value: 0
        4 TILE:
                flags: immutable blob
                blobs:

                value:

CRTCs:
id      fb      pos     size
36      0       (0,0)   (1080x1920)
  #0 1080x1920 30.00 1080 1310 1330 1350 1920 1925 1931 1939 78529 flags: ; type: preferred, driver
  props:
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0
        28 GAMMA_LUT:
                flags: blob
                blobs:

                value:
        29 GAMMA_LUT_SIZE:
                flags: immutable range
                values: 0 4294967295
                value: 256

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
31      0       0       0,0             0,0     0               0x00000001
  formats: NV12 NV21 NV16 NV61
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
32      0       0       0,0             0,0     0               0x00000001
  formats: AR24 AR12 AR15 RG24 RG16
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 1
33      0       0       0,0             0,0     0               0x00000001
  formats: AR24 AR12 AR15 RG24 RG16
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 2
34      0       0       0,0             0,0     0               0x00000001
  formats: AR24 AR12 AR15 RG24 RG16
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
35      0       0       0,0             0,0     0               0x00000001
  formats: AR24 AR12 AR15 RG24 RG16
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0

Frame buffers:
id      size    pitch

[root@canaan ~ ]#

The above information is the K230 DRM details, here is a brief description:

Module ID

Module name

Module description

37

Encoder

none

38

Connector

none

36

CRTC

Resolution support: 1080x1920

31

Video layer

Color space support: NV12, NV21, NV16, NV61

32

OSD layer

Color space support: AR24, AR12, AR15, RG24, RG16

33

OSD layer

Color space support: AR24, AR12, AR15, RG24, RG16

34

OSD layer

Color space support: AR24, AR12, AR15, RG24, RG16

35

OSD layer

Color space support: AR24, AR12, AR15, RG24, RG16

AR24 Display ARGB8888

AR12 Display ARGB4444

AR15 Display ARGB1555

RG24 means RGB888

RG16 stands for RGB565

The 2.2 video layer outputs smpte color bars with NV12 color space#

The specific instructions are as follows:

modetest -M canaan-drm -D 0 -a -s 38@36:1080x1920-30 -P 31@36:1080x1920@NV12 -v -F smpte

The following figure shows the LCD display:

Display content

2.3 The OSD layer outputs tiles color bars, and the color space is AR24(ARGB8888)#

The specific instructions are as follows

modetest -M canaan-drm -D 0 -a -s 38@36:1080x1920-30 -P 32@36:1080x1920@AR24 -v -F tiles

The following figure shows the LCD display:

Display content

2.4 OSD layer outputs tiles color bars with a color space of RG16(RGB565)#

The specific instructions are as follows:

modetest -M canaan-drm -D 0 -a -s 38@36:1080x1920-30 -P 32@36:1080x1920@RG16 -v -F tiles

The following figure shows the LCD display:

Display content

3. Introduction to DRM API#

3.1 Turn on the DRM device#

    fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
    if (fd < 0) {
        fprintf(stderr, "open card0 error \n");
        return -1;
    }

3.2 Retrieving DRM resources#

drmModeResPtr drmModeGetResources(int fd);

typedef struct _drmModeRes {

        int count_fbs;
        uint32_t *fbs;

        int count_crtcs;
        uint32_t *crtcs;

        int count_connectors;
        uint32_t *connectors;

        int count_encoders;
        uint32_t *encoders;

        uint32_t min_width, max_width;
        uint32_t min_height, max_height;
} drmModeRes, *drmModeResPtr;

An example of a code call is as follows:

    res = drmModeGetResources(fd);
    if (res == NULL) {
        fprintf(stderr, "drmModeGetResources error \n");
        return -1;
    }
    conn_id = res->connectors[0];
    crtc_id = res->crtcs[0];

3.4 Retrieving layer resources#

drmModePlaneResPtr drmModeGetPlaneResources(int fd);

typedef struct _drmModePlaneRes {
        uint32_t count_planes;
        uint32_t *planes;
} drmModePlaneRes, *drmModePlaneResPtr;

An example of a code call is as follows:

    plane_res = drmModeGetPlaneResources(fd);
    if (plane_res == NULL) {
        fprintf(stderr, "drmModeGetPlaneResources error \n");
        return -1;
    }
    plane_id = plane_res->planes[1];

In K230 DRM, the layer correspondence is as follows:

plane_res->plans[0] stand for Video layer

plane_res->plans[1] to plane_res->plans[4] stand for OSD layer

3.5 Obtaining Connectors#

drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id);

typedef struct _drmModeConnector {
        uint32_t connector_id;
        uint32_t encoder_id; /**< Encoder currently connected to */
        uint32_t connector_type;
        uint32_t connector_type_id;
        drmModeConnection connection;
        uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
        drmModeSubPixel subpixel;

        int count_modes;
        drmModeModeInfoPtr modes;

        int count_props;
        uint32_t *props; /**< List of property ids */
        uint64_t *prop_values; /**< List of property values */

        int count_encoders;
        uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;

An example of a code call is as follows:

    conn = drmModeGetConnector(fd, conn_id);
    if (conn == NULL) {
        fprintf(stderr, "drmModeGetConnector error \n");
        return -1;
    }

3.6 Apply for DRM DUMB buffer#

An example of a code call is as follows:

    creq.width = 1080;
    creq.height = 1920;
    creq.bpp = 32;
    creq.fourcc = DRM_FORMAT_ARGB8888;
    ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
    if (ret < 0) {
        fprintf(stderr, "cannot create dumb buffer (%d): %m\n",
            errno);
        return -errno;
    }

3.7 Submit DRM Requests#

An example of a code call is as follows:

int drmModeAtomicCommit(int fd,
                   drmModeAtomicReqPtr req,
                   uint32_t flags,
                   void *user_data);

4. Precautions#

  1. K230 DRM development and testing rely on LCD screens

  2. K230 DRM internal module ID is not static, we should according to the actual ID of each module