limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 3 | * |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 4 | * This source code is subject to the terms and conditions defined in the |
| 5 | * file 'LICENSE' which is part of this source code package. |
| 6 | * |
| 7 | * Description: |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 8 | */ |
| 9 | |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 10 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 11 | #include <stdio.h> |
| 12 | #include <fcntl.h> |
| 13 | #include <sys/types.h> |
| 14 | #include <sys/stat.h> |
| 15 | #include <stddef.h> |
| 16 | #include <drm_fourcc.h> |
| 17 | #include "meson_drm_util.h" |
| 18 | |
| 19 | #define MAX_OSD_PLANE 6 |
| 20 | #define MAX_VIDEO_PLANE 4 |
| 21 | #define MAX_CONNECTOR 3 |
| 22 | #define MAX_CRTC 3 |
| 23 | |
| 24 | struct kms_display; |
| 25 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 26 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 27 | #define VOID2U64(x) ((uint64_t)(unsigned long)(x)) |
| 28 | #define container_of(ptr, type, member) \ |
| 29 | (type *)((char *)(ptr) - (char *) &((type *)0)->member) |
| 30 | |
| 31 | #define to_kms_display(x) container_of(x, struct kms_display, base) |
| 32 | |
| 33 | struct property { |
| 34 | uint32_t id; |
| 35 | uint64_t value; |
| 36 | }; |
| 37 | |
| 38 | struct crtc_state { |
| 39 | uint32_t id; |
| 40 | |
| 41 | struct property mode_id; |
| 42 | struct property active; |
| 43 | struct property out_fence; |
| 44 | struct property video_out_fence; |
| 45 | }; |
| 46 | |
| 47 | struct connector_state { |
| 48 | uint32_t id; |
| 49 | uint32_t crtc_mask; |
| 50 | drmModeModeInfo mode; |
| 51 | |
| 52 | struct property crtc_id; |
| 53 | }; |
| 54 | |
| 55 | struct plane_state { |
| 56 | uint32_t id; |
| 57 | uint32_t crtc_mask; |
| 58 | |
| 59 | struct property crtc_id; |
| 60 | struct property crtc_x; |
| 61 | struct property crtc_y; |
| 62 | struct property crtc_w; |
| 63 | struct property crtc_h; |
| 64 | struct property fb_id; |
| 65 | struct property src_x; |
| 66 | struct property src_y; |
| 67 | struct property src_w; |
| 68 | struct property src_h; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 69 | struct property type; |
| 70 | struct property in_fence_fd; |
| 71 | struct property in_formats; |
| 72 | }; |
| 73 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 74 | struct kms_display { |
| 75 | struct drm_display base; |
| 76 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 77 | int num_crtc; |
| 78 | struct crtc_state *crtc_states[MAX_CRTC]; |
| 79 | int num_connector; |
| 80 | struct connector_state *conn_states[MAX_CONNECTOR]; |
| 81 | int num_osd_plane; |
| 82 | struct plane_state *osd_states[MAX_OSD_PLANE]; |
| 83 | int num_vid_plane; |
| 84 | struct plane_state *vid_states[MAX_OSD_PLANE]; |
| 85 | |
| 86 | int mode_set; |
| 87 | }; |
| 88 | |
| 89 | static void kms_destroy_display(struct drm_display *drm_disp) |
| 90 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 91 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 92 | struct kms_display *disp = to_kms_display(drm_disp); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 93 | close(drm_disp->drm_fd); |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 94 | close(drm_disp->dev->render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 95 | meson_device_destroy(drm_disp->dev); |
| 96 | |
| 97 | for (i = 0; i < MAX_CRTC; i++) { |
| 98 | if (disp->crtc_states[i]) |
| 99 | free(disp->crtc_states[i]); |
| 100 | } |
| 101 | |
| 102 | for (i = 0; i < MAX_CONNECTOR; i++) { |
| 103 | if (disp->conn_states[i]) |
| 104 | free(disp->conn_states[i]); |
| 105 | } |
| 106 | |
| 107 | for (i = 0; i < MAX_OSD_PLANE; i++) { |
| 108 | if (disp->osd_states[i]) |
| 109 | free(disp->osd_states[i]); |
| 110 | } |
| 111 | |
| 112 | for (i = 0; i < MAX_OSD_PLANE; i++) { |
| 113 | if (disp->vid_states[i]) |
| 114 | free(disp->vid_states[i]); |
| 115 | } |
| 116 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 117 | free(disp); |
| 118 | } |
| 119 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 120 | static int free_buf(struct drm_display *drm_disp, struct drm_buf *buf) |
| 121 | { |
wenlong.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 122 | int i, fd, ret; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 123 | struct drm_mode_destroy_dumb destroy_dumb; |
| 124 | |
| 125 | for ( i = 0; i < buf->nbo; i++) |
| 126 | close(buf->fd[i]); |
| 127 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 128 | fd = drm_disp->alloc_only ? drm_disp->dev->render_fd : drm_disp->dev->fd; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 129 | drmModeRmFB(drm_disp->drm_fd, buf->fb_id); |
| 130 | memset(&destroy_dumb, 0, sizeof(destroy_dumb)); |
| 131 | |
| 132 | for ( i = 0; i < buf->nbo; i++) { |
| 133 | destroy_dumb.handle = meson_bo_handle(buf->bos[i]); |
| 134 | |
wenlong.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 135 | ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 136 | if (ret < 0) { |
| 137 | /* If handle was from drmPrimeFDToHandle, then fd is connected |
| 138 | * as render, we have to use drm_gem_close to release it. |
| 139 | */ |
| 140 | if (errno == EACCES) { |
| 141 | struct drm_gem_close close_req; |
| 142 | close_req.handle = destroy_dumb.handle; |
wenlong.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 143 | ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 144 | if (ret < 0) { |
| 145 | fprintf(stderr, "Unable to destroy buffer: %s\n", |
| 146 | strerror(errno)); |
| 147 | return -1; |
| 148 | } |
| 149 | } |
| 150 | } |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 151 | meson_bo_destroy(buf->bos[i]); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 152 | } |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 153 | free(buf); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 154 | return 0; |
| 155 | } |
| 156 | static int kms_free_bufs(struct drm_display *drm_disp) |
| 157 | { |
| 158 | int i; |
| 159 | struct drm_buf *buf; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 160 | for ( i = 0; i < drm_disp->nbuf; i++ ) { |
| 161 | buf = &drm_disp->bufs[i]; |
| 162 | free_buf(drm_disp, buf); |
| 163 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 164 | return 0; |
| 165 | } |
| 166 | |
| 167 | static int kms_free_buf(struct drm_buf *buf) |
| 168 | { |
| 169 | free_buf(buf->disp, buf); |
| 170 | return 0; |
| 171 | } |
| 172 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 173 | static struct meson_bo *alloc_bo(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t bpp, uint32_t width, |
| 174 | uint32_t height, uint32_t *bo_handle, uint32_t *pitch) |
| 175 | { |
| 176 | uint32_t size; |
| 177 | struct meson_bo *bo; |
| 178 | |
| 179 | size = width * height * bpp / 8; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 180 | bo = meson_bo_create(drm_disp->dev, size, buf->flags, drm_disp->alloc_only); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 181 | if (bo) { |
| 182 | *bo_handle = meson_bo_handle(bo); |
| 183 | *pitch = width * bpp / 8; |
| 184 | return bo; |
| 185 | } else { |
| 186 | fprintf(stderr, "meson_bo_create fail\n"); |
| 187 | return NULL; |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | static int alloc_bos(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t *bo_handles) |
| 192 | { |
| 193 | uint32_t width = buf->width; |
| 194 | uint32_t height = buf->height; |
| 195 | |
| 196 | switch (buf->fourcc) { |
| 197 | case DRM_FORMAT_ARGB8888: |
| 198 | buf->nbo = 1; |
| 199 | buf->bos[0] = alloc_bo(drm_disp, buf, 32, width, height, &bo_handles[0], &buf->pitches[0]); |
| 200 | if (!buf->bos[0]) { |
| 201 | fprintf(stderr, "alloc_bo argb888 fail\n"); |
| 202 | return -1; |
| 203 | } |
| 204 | |
| 205 | buf->size = width * height * 4; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 206 | buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 207 | break; |
| 208 | case DRM_FORMAT_UYVY: |
| 209 | case DRM_FORMAT_YUYV: |
| 210 | buf->nbo = 1; |
| 211 | buf->bos[0] = alloc_bo(drm_disp, buf, 16, width, height, &bo_handles[0], &buf->pitches[0]); |
| 212 | if (!buf->bos[0]) { |
| 213 | fprintf(stderr, "alloc_bo yuyv or uyvy fail\n"); |
| 214 | return -1; |
| 215 | } |
| 216 | |
| 217 | buf->size = width * height * 2; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 218 | buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 219 | buf->commit_to_video = 1; |
| 220 | break; |
| 221 | case DRM_FORMAT_NV12: |
| 222 | case DRM_FORMAT_NV21: |
| 223 | buf->nbo = 2; |
| 224 | buf->bos[0] = alloc_bo(drm_disp, buf, 8, width, height, &bo_handles[0], &buf->pitches[0]); |
| 225 | if (!buf->bos[0]) { |
| 226 | fprintf(stderr, "alloc_bo nv12 or nv21 fail\n"); |
| 227 | return -1; |
| 228 | } |
| 229 | |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 230 | buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 231 | |
| 232 | buf->bos[1] = alloc_bo(drm_disp, buf, 16, width/2, height/2, &bo_handles[1], &buf->pitches[1]); |
| 233 | if (!buf->bos[1]) { |
| 234 | fprintf(stderr, "alloc_bo argb888 fail\n"); |
| 235 | return -1; |
| 236 | } |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 237 | buf->fd[1] = meson_bo_dmabuf(buf->bos[1], drm_disp->alloc_only); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 238 | buf->size = width * height * 3 / 2; |
| 239 | buf->commit_to_video = 1; |
| 240 | break; |
| 241 | default: |
| 242 | fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc); |
| 243 | break; |
| 244 | } |
| 245 | |
| 246 | return 0; |
| 247 | } |
| 248 | |
| 249 | static int add_framebuffer(int fd, struct drm_buf *buf, uint32_t *bo_handles, uint64_t modifier) |
| 250 | { |
| 251 | int i, ret; |
| 252 | uint64_t modifiers[4] = { 0, 0, 0, 0 }; |
| 253 | uint32_t flags = 0; |
| 254 | uint32_t fb_id; |
| 255 | |
| 256 | for ( i = 0; i < buf->nbo; i++) { |
| 257 | if (bo_handles[i] != 0 && modifier != DRM_FORMAT_MOD_NONE) { |
| 258 | flags |= DRM_MODE_FB_MODIFIERS; |
| 259 | modifiers[i] = modifier; |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | ret = drmModeAddFB2WithModifiers(fd, buf->width, buf->height, buf->fourcc, |
| 264 | bo_handles, buf->pitches, buf->offsets, modifiers, &fb_id, flags); |
| 265 | if (ret < 0) { |
| 266 | fprintf(stderr, "Unable to add framebuffer for plane: %s\n", strerror(errno)); |
| 267 | return -1; |
| 268 | } |
| 269 | |
| 270 | buf->fb_id = fb_id; |
| 271 | return 0; |
| 272 | } |
| 273 | |
| 274 | static struct drm_buf *kms_alloc_buf(struct drm_display *drm_disp, struct drm_buf_metadata *info) |
| 275 | { |
| 276 | int ret; |
| 277 | struct drm_buf *buf = NULL; |
| 278 | uint32_t bo_handles[4] = {0}; |
| 279 | |
| 280 | buf = calloc(1, sizeof(*buf)); |
| 281 | buf->fourcc = info->fourcc; |
| 282 | buf->width = info->width; |
| 283 | buf->height = info->height; |
| 284 | buf->flags = info->flags; |
| 285 | buf->fence_fd = -1; |
| 286 | buf->disp = drm_disp; |
| 287 | |
| 288 | ret = alloc_bos(drm_disp, buf, bo_handles); |
| 289 | if (ret) { |
| 290 | fprintf(stderr, "alloc_bos fail\n"); |
| 291 | free(buf); |
| 292 | return NULL; |
| 293 | } |
| 294 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 295 | /*for non-root users, just need alloc buf and don't need to add framebuffer*/ |
| 296 | if (drm_disp->alloc_only) |
| 297 | return buf; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 298 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 299 | ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE); |
| 300 | if (ret) { |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 301 | fprintf(stderr, "add_framebuffer fail, call free_buf\n"); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 302 | free_buf(drm_disp, buf); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 303 | return NULL; |
| 304 | } |
| 305 | |
| 306 | return buf; |
| 307 | } |
| 308 | |
| 309 | static int kms_alloc_bufs(struct drm_display *drm_disp, int num, struct drm_buf_metadata *info) |
| 310 | { |
| 311 | int i, ret; |
| 312 | struct drm_buf *buf; |
| 313 | uint32_t bo_handles[4] = {0}; |
| 314 | |
| 315 | drm_disp->bufs = calloc(num, sizeof(*drm_disp->bufs)); |
| 316 | drm_disp->nbuf = num; |
| 317 | |
| 318 | for ( i = 0; i < num; i++) { |
| 319 | buf = &drm_disp->bufs[i]; |
| 320 | buf->fourcc = info->fourcc; |
| 321 | buf->width = info->width; |
| 322 | buf->height = info->height; |
| 323 | buf->flags = info->flags; |
| 324 | buf->fence_fd = -1; |
| 325 | buf->disp = drm_disp; |
| 326 | |
| 327 | if (!info->fourcc) |
| 328 | buf->fourcc = DRM_FORMAT_ARGB8888; |
| 329 | |
| 330 | switch (buf->fourcc) { |
| 331 | case DRM_FORMAT_ARGB8888: |
| 332 | buf->nbo = 1; |
| 333 | break; |
| 334 | case DRM_FORMAT_UYVY: |
| 335 | case DRM_FORMAT_YUYV: |
| 336 | buf->nbo = 1; |
| 337 | break; |
| 338 | case DRM_FORMAT_NV12: |
| 339 | case DRM_FORMAT_NV21: |
| 340 | buf->nbo = 2; |
| 341 | break; |
| 342 | default: |
| 343 | fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc); |
| 344 | break; |
| 345 | } |
| 346 | |
| 347 | ret = alloc_bos(drm_disp, buf, bo_handles); |
| 348 | if (ret) { |
| 349 | fprintf(stderr, "alloc_bos fail\n"); |
| 350 | return -1; |
| 351 | } |
| 352 | |
| 353 | ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE); |
| 354 | if (ret) { |
| 355 | fprintf(stderr, "add_framebuffer fail\n"); |
| 356 | free_buf(drm_disp, buf); |
| 357 | return -1; |
| 358 | } |
| 359 | } |
| 360 | return 0; |
| 361 | } |
| 362 | |
| 363 | static struct drm_buf *kms_import_buf(struct drm_display *disp, struct drm_buf_import *info) |
| 364 | { |
| 365 | int i; |
| 366 | uint32_t size; |
| 367 | struct drm_buf *buf = NULL; |
| 368 | uint32_t bo_handles[4] = {0}; |
| 369 | |
| 370 | buf = calloc(1, sizeof(*buf)); |
| 371 | buf->fourcc = info->fourcc; |
| 372 | buf->width = info->width; |
| 373 | buf->height = info->height; |
| 374 | buf->flags = info->flags; |
| 375 | buf->fence_fd = -1; |
| 376 | buf->disp = disp; |
| 377 | |
| 378 | if (!info->fourcc) |
| 379 | buf->fourcc = DRM_FORMAT_ARGB8888; |
| 380 | |
| 381 | switch (buf->fourcc) { |
| 382 | case DRM_FORMAT_ARGB8888: |
| 383 | buf->nbo = 1; |
| 384 | break; |
| 385 | case DRM_FORMAT_UYVY: |
| 386 | case DRM_FORMAT_YUYV: |
| 387 | buf->nbo = 1; |
| 388 | break; |
| 389 | case DRM_FORMAT_NV12: |
| 390 | case DRM_FORMAT_NV21: |
| 391 | buf->nbo = 2; |
| 392 | break; |
| 393 | default: |
| 394 | fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc); |
| 395 | break; |
| 396 | } |
| 397 | |
| 398 | for (i = 0; i < buf->nbo; i++) { |
| 399 | if ( i == 0 ) |
| 400 | size = info->width * info->height; |
| 401 | else |
| 402 | size = info->width * info->height / 2; |
| 403 | |
| 404 | buf->size += size; |
| 405 | buf->fd[i] = info->fd[i]; |
| 406 | buf->pitches[i] = buf->width; |
| 407 | buf->bos[i] = meson_bo_import(disp->dev, info->fd[i], size, info->flags); |
| 408 | if (!buf->bos[i]) { |
| 409 | fprintf(stderr, "meson_bo_import fail\n"); |
| 410 | return NULL; |
| 411 | } |
| 412 | |
| 413 | bo_handles[i] = meson_bo_handle(buf->bos[i]); |
| 414 | } |
| 415 | |
| 416 | add_framebuffer(disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE); |
| 417 | |
| 418 | return buf; |
| 419 | } |
| 420 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 421 | static int kms_post_buf(struct drm_display *drm_disp, struct drm_buf *buf) |
| 422 | { |
| 423 | int ret; |
| 424 | drmModeAtomicReqPtr request; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 425 | uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; |
| 426 | struct kms_display *disp = to_kms_display(drm_disp); |
| 427 | |
| 428 | struct plane_state *plane_state; |
| 429 | struct crtc_state *crtc_state; |
| 430 | struct connector_state *conn_state; |
| 431 | |
| 432 | conn_state = disp->conn_states[0]; |
| 433 | crtc_state = disp->crtc_states[0]; |
| 434 | |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 435 | if (buf->flags & MESON_USE_VD1) |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 436 | plane_state = disp->vid_states[0]; |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 437 | else if (buf->flags & MESON_USE_VD2) |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 438 | plane_state = disp->vid_states[1]; |
| 439 | else |
| 440 | plane_state = disp->osd_states[0]; |
| 441 | |
| 442 | request = drmModeAtomicAlloc(); |
| 443 | |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 444 | #if 0 |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 445 | if (!disp->mode_set) { |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 446 | flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; |
| 447 | drmModeAtomicAddProperty(request, conn_state->id, conn_state->crtc_id.id, crtc_state->id); |
| 448 | |
| 449 | if (drmModeCreatePropertyBlob(drm_disp->drm_fd, &disp->conn_states[0]->mode, |
| 450 | sizeof(drmModeModeInfo), &blob_id) != 0 ) { |
| 451 | return -1; |
| 452 | } |
| 453 | drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->mode_id.id, blob_id); |
| 454 | drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->active.id, 1); |
| 455 | |
| 456 | disp->mode_set = 1; |
| 457 | } |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 458 | #else |
| 459 | /*No modeset needed in post buf, modeset will control by systemservice.*/ |
| 460 | #endif |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 461 | |
Ao Xu | b368989 | 2020-11-09 18:57:56 +0800 | [diff] [blame] | 462 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_x.id, buf->crtc_x); |
| 463 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_y.id, buf->crtc_y); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 464 | if (buf->crtc_w == 0) { |
| 465 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, conn_state->mode.hdisplay); |
| 466 | } else { |
| 467 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, buf->crtc_w); |
| 468 | } |
| 469 | |
| 470 | if (buf->crtc_h == 0) { |
| 471 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, conn_state->mode.vdisplay); |
| 472 | } else { |
| 473 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, buf->crtc_h); |
| 474 | } |
| 475 | |
Ao Xu | 2b6aec5 | 2020-12-15 14:24:21 +0800 | [diff] [blame] | 476 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_x.id, buf->src_x << 16); |
| 477 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_y.id, buf->src_y << 16); |
yujun.zhang | 54c6eda | 2021-12-30 12:24:49 +0800 | [diff] [blame] | 478 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_w.id, buf->src_w << 16); |
| 479 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_h.id, buf->src_h << 16); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 480 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->fb_id.id, buf->fb_id); |
| 481 | drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_id.id, crtc_state->id); |
| 482 | #if 0 |
| 483 | if (buf->flags | (MESON_USE_VD2 | MESON_USE_VD1)) |
| 484 | drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->video_out_fence.id, VOID2U64(&buf->fence_fd)); |
| 485 | else |
| 486 | drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->out_fence.id, VOID2U64(&buf->fence_fd)); |
| 487 | #endif |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 488 | |
| 489 | ret = drmModeAsyncAtomicCommit(drm_disp->drm_fd, request, flags, NULL); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 490 | if (ret < 0) { |
| 491 | fprintf(stderr, "Unable to flip page: %s\n", strerror(errno)); |
| 492 | goto error; |
| 493 | } |
| 494 | |
| 495 | ret = 0; |
| 496 | goto complete; |
| 497 | |
| 498 | error: |
| 499 | ret = -1; |
| 500 | complete: |
| 501 | drmModeAtomicFree(request); |
| 502 | |
| 503 | return ret; |
| 504 | } |
| 505 | |
| 506 | static void getproperty(int drm_fd, drmModeObjectProperties* props, const char *name, |
| 507 | struct property *p) |
| 508 | { |
| 509 | int i; |
| 510 | drmModePropertyRes *res; |
| 511 | for (i = 0; i < props->count_props; i++) { |
| 512 | res = drmModeGetProperty(drm_fd, props->props[i]); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 513 | if (res && !strcmp(name, res->name)) { |
| 514 | p->id = res->prop_id; |
| 515 | p->value = props->prop_values[i]; |
| 516 | //fprintf(stdout, "getproperty: %s, id: %u, value: %llu \n", res->name, p->id, p->value); |
| 517 | } |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 518 | drmModeFreeProperty(res); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 519 | } |
| 520 | } |
| 521 | |
| 522 | static int populate_connectors(drmModeRes *resources, struct kms_display *disp) |
| 523 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 524 | int i, j; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 525 | int num_connector = 0; |
| 526 | struct connector_state *state; |
| 527 | drmModeConnector *connector; |
| 528 | drmModeEncoder *encoder; |
| 529 | drmModeObjectProperties *props; |
| 530 | |
| 531 | for (i = 0; i < resources->count_connectors; i++) { |
| 532 | connector = drmModeGetConnector(disp->base.drm_fd, resources->connectors[i]); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 533 | if (!connector) { |
| 534 | fprintf(stderr, "drmModeGetConnector fail.\n"); |
| 535 | continue; |
| 536 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 537 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 538 | if (connector->connector_type == DRM_MODE_CONNECTOR_TV) { |
| 539 | drmModeFreeConnector(connector); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 540 | continue; |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 541 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 542 | state = calloc(1, sizeof(*state)); |
| 543 | disp->conn_states[num_connector++] = state; |
| 544 | state->id = resources->connectors[i]; |
| 545 | |
| 546 | for (j = 0; j < connector->count_encoders; j++) { |
| 547 | encoder = drmModeGetEncoder(disp->base.drm_fd, connector->encoders[j]); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 548 | if (encoder) { |
| 549 | state->crtc_mask |= encoder->possible_crtcs; |
| 550 | drmModeFreeEncoder(encoder); |
| 551 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 552 | } |
| 553 | |
| 554 | if (connector->count_modes) |
| 555 | state->mode = connector->modes[0]; |
| 556 | |
| 557 | for (j = 0; j < connector->count_modes; j++) { |
| 558 | if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED) { |
| 559 | state->mode = connector->modes[j]; |
| 560 | break; |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | disp->base.width = state->mode.hdisplay; |
| 565 | disp->base.height = state->mode.vdisplay; |
| 566 | disp->base.vrefresh = state->mode.vrefresh; |
| 567 | |
| 568 | props = drmModeObjectGetProperties(disp->base.drm_fd, resources->connectors[i], DRM_MODE_OBJECT_CONNECTOR); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 569 | getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 570 | |
| 571 | if (props) |
| 572 | drmModeFreeObjectProperties(props); |
| 573 | |
| 574 | if (connector) |
| 575 | drmModeFreeConnector(connector); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 576 | } |
| 577 | |
| 578 | disp->num_connector = num_connector; |
| 579 | fprintf(stdout, "found %d connector\n", num_connector); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 580 | return 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 581 | } |
| 582 | |
| 583 | static int populate_crtcs(drmModeRes *resources, struct kms_display *disp) |
| 584 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 585 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 586 | int num_crtc = 0; |
| 587 | struct crtc_state *state; |
| 588 | drmModeObjectProperties *props; |
| 589 | |
| 590 | for (i = 0; i < resources->count_crtcs; i++) { |
| 591 | state = calloc(1, sizeof(*state)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 592 | if (!state) { |
| 593 | fprintf(stderr, "calloc crtc state fail.\n"); |
| 594 | return -1; |
| 595 | } |
| 596 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 597 | disp->crtc_states[num_crtc++] = state; |
| 598 | state->id = resources->crtcs[i]; |
| 599 | |
| 600 | props = drmModeObjectGetProperties(disp->base.drm_fd, resources->crtcs[i], DRM_MODE_OBJECT_CRTC); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 601 | if (props) { |
| 602 | getproperty(disp->base.drm_fd, props, "MODE_ID", &state->mode_id); |
| 603 | getproperty(disp->base.drm_fd, props, "ACTIVE", &state->active); |
| 604 | getproperty(disp->base.drm_fd, props, "OUT_FENCE_PTR", &state->out_fence); |
| 605 | getproperty(disp->base.drm_fd, props, "VIDEO_OUT_FENCE_PTR", &state->video_out_fence); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 606 | drmModeFreeObjectProperties(props); |
| 607 | } else { |
| 608 | fprintf(stderr, "get crtc obj property fail\n"); |
| 609 | return -1; |
| 610 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 611 | } |
| 612 | |
| 613 | disp->num_crtc = num_crtc; |
| 614 | |
| 615 | fprintf(stdout, "found %d crtc\n", num_crtc); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 616 | return 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 617 | } |
| 618 | |
| 619 | static int is_plane_support_yuv(drmModePlane * plane) |
| 620 | { |
| 621 | int i; |
| 622 | for (i = 0; i < plane->count_formats; i++) { |
| 623 | switch (plane->formats[i]) { |
| 624 | case DRM_FORMAT_NV12: |
| 625 | case DRM_FORMAT_NV21: |
| 626 | return 1; |
| 627 | default: |
| 628 | return 0; |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | return 0; |
| 633 | } |
| 634 | |
| 635 | static int populate_planes(drmModeRes *resources, struct kms_display *disp) |
| 636 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 637 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 638 | int num_osd_plane = 0; |
| 639 | int num_vid_plane = 0; |
| 640 | struct plane_state *state; |
| 641 | drmModePlane *plane; |
| 642 | drmModePlaneRes *plane_res; |
| 643 | drmModeObjectProperties *props; |
| 644 | |
| 645 | plane_res = drmModeGetPlaneResources(disp->base.drm_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 646 | if (!plane_res) { |
| 647 | fprintf(stderr, "drmModeGetPlaneResources fail.\n"); |
| 648 | goto error; |
| 649 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 650 | |
| 651 | for (i = 0; i < plane_res->count_planes; i++) { |
| 652 | state = calloc(1, sizeof(*state)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 653 | if (!state) { |
| 654 | fprintf(stderr, "calloc plane state fail.\n"); |
| 655 | goto error; |
| 656 | } |
| 657 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 658 | plane = drmModeGetPlane(disp->base.drm_fd, plane_res->planes[i]); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 659 | if (plane) { |
| 660 | if (is_plane_support_yuv(plane)) |
| 661 | disp->vid_states[num_vid_plane++] = state; |
| 662 | else |
| 663 | disp->osd_states[num_osd_plane++] = state; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 664 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 665 | state->id = plane_res->planes[i]; |
| 666 | state->crtc_mask = plane->possible_crtcs; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 667 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 668 | props = drmModeObjectGetProperties(disp->base.drm_fd, plane_res->planes[i], DRM_MODE_OBJECT_PLANE); |
| 669 | if (props) { |
| 670 | getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id); |
| 671 | getproperty(disp->base.drm_fd, props, "CRTC_X", &state->crtc_x); |
| 672 | getproperty(disp->base.drm_fd, props, "CRTC_Y", &state->crtc_y); |
| 673 | getproperty(disp->base.drm_fd, props, "CRTC_W", &state->crtc_w); |
| 674 | getproperty(disp->base.drm_fd, props, "CRTC_H", &state->crtc_h); |
| 675 | getproperty(disp->base.drm_fd, props, "FB_ID", &state->fb_id); |
| 676 | getproperty(disp->base.drm_fd, props, "SRC_X", &state->src_x); |
| 677 | getproperty(disp->base.drm_fd, props, "SRC_Y", &state->src_y); |
| 678 | getproperty(disp->base.drm_fd, props, "SRC_W", &state->src_w); |
| 679 | getproperty(disp->base.drm_fd, props, "SRC_H", &state->src_h); |
| 680 | getproperty(disp->base.drm_fd, props, "type", &state->type); |
| 681 | getproperty(disp->base.drm_fd, props, "IN_FENCE_FD", &state->in_fence_fd); |
| 682 | getproperty(disp->base.drm_fd, props, "IN_FORMATS", &state->in_formats); |
| 683 | } |
| 684 | } |
| 685 | |
| 686 | if (props) |
| 687 | drmModeFreeObjectProperties(props); |
| 688 | |
| 689 | if (plane) |
| 690 | drmModeFreePlane(plane); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 691 | } |
| 692 | |
| 693 | disp->num_osd_plane = num_osd_plane; |
| 694 | disp->num_vid_plane = num_vid_plane; |
| 695 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 696 | drmModeFreePlaneResources(plane_res); |
| 697 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 698 | fprintf(stdout, "found %d osd, %d video\n", num_osd_plane, num_vid_plane); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 699 | return 0; |
| 700 | |
| 701 | error: |
| 702 | drmModeFreePlaneResources(plane_res); |
| 703 | |
| 704 | return -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 705 | } |
| 706 | |
| 707 | static int drm_kms_init_resource(struct kms_display *disp) |
| 708 | { |
| 709 | int ret; |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 710 | int drm_fd = -1; |
| 711 | int render_fd = -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 712 | drmModeRes *resources; |
| 713 | |
| 714 | drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); |
| 715 | if (drm_fd < 0) { |
| 716 | fprintf(stderr, "Unable to open DRM node: %s\n", |
| 717 | strerror(errno)); |
| 718 | return -1; |
| 719 | } |
chen.wang1 | f5503ea | 2023-04-12 07:36:24 +0000 | [diff] [blame^] | 720 | drmDropMaster(drm_fd); |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 721 | render_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC); |
| 722 | if (render_fd < 0) { |
| 723 | fprintf(stderr, "Unable to open renderD128 node: %s\n", |
| 724 | strerror(errno)); |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 725 | goto error3; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 726 | } |
| 727 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 728 | disp->base.drm_fd = drm_fd; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 729 | disp->base.dev = meson_device_create(drm_fd, render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 730 | if (!disp->base.dev) { |
| 731 | fprintf(stderr, "meson_device_create fail\n"); |
| 732 | goto error3; |
| 733 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 734 | |
| 735 | ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1); |
| 736 | if (ret < 0) { |
| 737 | fprintf(stderr, "Unable to set DRM atomic capability: %s\n", |
| 738 | strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 739 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 740 | } |
| 741 | |
| 742 | ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); |
| 743 | if (ret < 0) { |
| 744 | fprintf(stderr, "Unable to set DRM universal planes capability: %s\n", |
| 745 | strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 746 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 747 | } |
| 748 | |
| 749 | resources = drmModeGetResources(drm_fd); |
| 750 | if (!resources) { |
| 751 | fprintf(stderr, "drmModeGetResources failed: %s\n", strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 752 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 753 | } |
| 754 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 755 | ret = populate_connectors(resources, disp); |
| 756 | if (ret) |
| 757 | goto error1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 758 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 759 | ret = populate_crtcs(resources, disp); |
| 760 | if (ret) |
| 761 | goto error1; |
| 762 | |
| 763 | ret = populate_planes(resources, disp); |
| 764 | if (ret) |
| 765 | goto error1; |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 766 | drmModeFreeResources(resources); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 767 | return 0; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 768 | |
| 769 | error1: |
| 770 | drmModeFreeResources(resources); |
| 771 | error2: |
| 772 | meson_device_destroy(disp->base.dev); |
| 773 | error3: |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 774 | if (drm_fd >= 0) |
| 775 | close(drm_fd); |
| 776 | if (render_fd >= 0) |
| 777 | close(render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 778 | |
| 779 | return -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 780 | } |
| 781 | |
| 782 | struct drm_display *drm_kms_init(void) |
| 783 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 784 | int ret; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 785 | struct kms_display *display; |
| 786 | struct drm_display *base; |
| 787 | display = calloc(1, sizeof(*display)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 788 | if (!display) { |
| 789 | fprintf(stderr, "calloc kms_display fail\n"); |
| 790 | return NULL; |
| 791 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 792 | |
| 793 | base = &display->base; |
| 794 | base->destroy_display = kms_destroy_display; |
| 795 | base->alloc_bufs = kms_alloc_bufs; |
| 796 | base->free_bufs = kms_free_bufs; |
| 797 | |
| 798 | base->alloc_buf = kms_alloc_buf; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 799 | base->import_buf = kms_import_buf; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 800 | base->free_buf = kms_free_buf; |
| 801 | base->post_buf = kms_post_buf; |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 802 | base->alloc_only = 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 803 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 804 | ret = drm_kms_init_resource(display); |
| 805 | if (ret) { |
| 806 | fprintf(stderr, "drm_kms_init_resource fail.\n"); |
| 807 | free(display); |
| 808 | return NULL; |
| 809 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 810 | |
| 811 | return base; |
| 812 | } |