blob: 4c54cefd630113323cbe05db33a607f30580def5 [file] [log] [blame]
limin.tian79bf2b12023-02-24 10:28:26 +00001 /*
2 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
Ao Xu6747bbd2020-09-28 20:02:09 +08003 *
limin.tian79bf2b12023-02-24 10:28:26 +00004 * 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 Xu6747bbd2020-09-28 20:02:09 +08008 */
9
limin.tian79bf2b12023-02-24 10:28:26 +000010
Ao Xu6747bbd2020-09-28 20:02:09 +080011#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
24struct kms_display;
25
chen.wang1bace1312023-01-18 16:13:54 +080026
Ao Xu6747bbd2020-09-28 20:02:09 +080027#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
33struct property {
34 uint32_t id;
35 uint64_t value;
36};
37
38struct 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
47struct connector_state {
48 uint32_t id;
49 uint32_t crtc_mask;
50 drmModeModeInfo mode;
51
52 struct property crtc_id;
53};
54
55struct 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 Xu6747bbd2020-09-28 20:02:09 +080069 struct property type;
70 struct property in_fence_fd;
71 struct property in_formats;
72};
73
Ao Xu6747bbd2020-09-28 20:02:09 +080074struct kms_display {
75 struct drm_display base;
76
Ao Xu6747bbd2020-09-28 20:02:09 +080077 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
89static void kms_destroy_display(struct drm_display *drm_disp)
90{
Ao Xu70554242020-10-15 15:19:48 +080091 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +080092 struct kms_display *disp = to_kms_display(drm_disp);
Ao Xu70554242020-10-15 15:19:48 +080093 close(drm_disp->drm_fd);
limin.tian79bf2b12023-02-24 10:28:26 +000094 close(drm_disp->dev->render_fd);
Ao Xu70554242020-10-15 15:19:48 +080095 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 Xu6747bbd2020-09-28 20:02:09 +0800117 free(disp);
118}
119
Ao Xu6747bbd2020-09-28 20:02:09 +0800120static int free_buf(struct drm_display *drm_disp, struct drm_buf *buf)
121{
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800122 int i, fd, ret;
Ao Xu6747bbd2020-09-28 20:02:09 +0800123 struct drm_mode_destroy_dumb destroy_dumb;
124
chen.wang1518f14f2023-04-12 09:53:10 +0000125 if (!buf)
126 return -1;
127
Ao Xu6747bbd2020-09-28 20:02:09 +0800128 for ( i = 0; i < buf->nbo; i++)
129 close(buf->fd[i]);
130
chen.wang1bace1312023-01-18 16:13:54 +0800131 fd = drm_disp->alloc_only ? drm_disp->dev->render_fd : drm_disp->dev->fd;
Ao Xu6747bbd2020-09-28 20:02:09 +0800132 drmModeRmFB(drm_disp->drm_fd, buf->fb_id);
133 memset(&destroy_dumb, 0, sizeof(destroy_dumb));
134
135 for ( i = 0; i < buf->nbo; i++) {
chen.wang1518f14f2023-04-12 09:53:10 +0000136 if (!buf->bos[i])
137 continue;
138
Ao Xu6747bbd2020-09-28 20:02:09 +0800139 destroy_dumb.handle = meson_bo_handle(buf->bos[i]);
140
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800141 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
Ao Xu6747bbd2020-09-28 20:02:09 +0800142 if (ret < 0) {
143 /* If handle was from drmPrimeFDToHandle, then fd is connected
144 * as render, we have to use drm_gem_close to release it.
145 */
146 if (errno == EACCES) {
147 struct drm_gem_close close_req;
148 close_req.handle = destroy_dumb.handle;
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800149 ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req);
Ao Xu6747bbd2020-09-28 20:02:09 +0800150 if (ret < 0) {
151 fprintf(stderr, "Unable to destroy buffer: %s\n",
152 strerror(errno));
153 return -1;
154 }
155 }
156 }
chen.wang1518f14f2023-04-12 09:53:10 +0000157 free(buf->bos[i]);
158 buf->bos[i] = NULL;
Ao Xu6747bbd2020-09-28 20:02:09 +0800159 }
chen.wang1bace1312023-01-18 16:13:54 +0800160 free(buf);
chen.wang1518f14f2023-04-12 09:53:10 +0000161 buf = NULL;
Ao Xu6747bbd2020-09-28 20:02:09 +0800162 return 0;
163}
164static int kms_free_bufs(struct drm_display *drm_disp)
165{
166 int i;
167 struct drm_buf *buf;
Ao Xu6747bbd2020-09-28 20:02:09 +0800168 for ( i = 0; i < drm_disp->nbuf; i++ ) {
169 buf = &drm_disp->bufs[i];
170 free_buf(drm_disp, buf);
171 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800172 return 0;
173}
174
175static int kms_free_buf(struct drm_buf *buf)
176{
177 free_buf(buf->disp, buf);
178 return 0;
179}
180
Ao Xu70554242020-10-15 15:19:48 +0800181static struct meson_bo *alloc_bo(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t bpp, uint32_t width,
182 uint32_t height, uint32_t *bo_handle, uint32_t *pitch)
183{
184 uint32_t size;
185 struct meson_bo *bo;
186
187 size = width * height * bpp / 8;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800188 bo = meson_bo_create(drm_disp->dev, size, buf->flags, drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800189 if (bo) {
190 *bo_handle = meson_bo_handle(bo);
191 *pitch = width * bpp / 8;
192 return bo;
193 } else {
194 fprintf(stderr, "meson_bo_create fail\n");
195 return NULL;
196 }
197}
198
199static int alloc_bos(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t *bo_handles)
200{
201 uint32_t width = buf->width;
202 uint32_t height = buf->height;
203
204 switch (buf->fourcc) {
205 case DRM_FORMAT_ARGB8888:
206 buf->nbo = 1;
207 buf->bos[0] = alloc_bo(drm_disp, buf, 32, width, height, &bo_handles[0], &buf->pitches[0]);
208 if (!buf->bos[0]) {
209 fprintf(stderr, "alloc_bo argb888 fail\n");
210 return -1;
211 }
212
213 buf->size = width * height * 4;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800214 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800215 break;
216 case DRM_FORMAT_UYVY:
217 case DRM_FORMAT_YUYV:
218 buf->nbo = 1;
219 buf->bos[0] = alloc_bo(drm_disp, buf, 16, width, height, &bo_handles[0], &buf->pitches[0]);
220 if (!buf->bos[0]) {
221 fprintf(stderr, "alloc_bo yuyv or uyvy fail\n");
222 return -1;
223 }
224
225 buf->size = width * height * 2;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800226 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800227 buf->commit_to_video = 1;
228 break;
229 case DRM_FORMAT_NV12:
230 case DRM_FORMAT_NV21:
231 buf->nbo = 2;
232 buf->bos[0] = alloc_bo(drm_disp, buf, 8, width, height, &bo_handles[0], &buf->pitches[0]);
233 if (!buf->bos[0]) {
234 fprintf(stderr, "alloc_bo nv12 or nv21 fail\n");
235 return -1;
236 }
237
wenlong.zhang4c011d42022-06-09 10:59:38 +0800238 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800239
240 buf->bos[1] = alloc_bo(drm_disp, buf, 16, width/2, height/2, &bo_handles[1], &buf->pitches[1]);
241 if (!buf->bos[1]) {
242 fprintf(stderr, "alloc_bo argb888 fail\n");
243 return -1;
244 }
wenlong.zhang4c011d42022-06-09 10:59:38 +0800245 buf->fd[1] = meson_bo_dmabuf(buf->bos[1], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800246 buf->size = width * height * 3 / 2;
247 buf->commit_to_video = 1;
248 break;
249 default:
250 fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc);
251 break;
252 }
253
254 return 0;
255}
256
257static int add_framebuffer(int fd, struct drm_buf *buf, uint32_t *bo_handles, uint64_t modifier)
258{
259 int i, ret;
260 uint64_t modifiers[4] = { 0, 0, 0, 0 };
261 uint32_t flags = 0;
262 uint32_t fb_id;
263
264 for ( i = 0; i < buf->nbo; i++) {
265 if (bo_handles[i] != 0 && modifier != DRM_FORMAT_MOD_NONE) {
266 flags |= DRM_MODE_FB_MODIFIERS;
267 modifiers[i] = modifier;
268 }
269 }
270
271 ret = drmModeAddFB2WithModifiers(fd, buf->width, buf->height, buf->fourcc,
272 bo_handles, buf->pitches, buf->offsets, modifiers, &fb_id, flags);
273 if (ret < 0) {
274 fprintf(stderr, "Unable to add framebuffer for plane: %s\n", strerror(errno));
275 return -1;
276 }
277
278 buf->fb_id = fb_id;
279 return 0;
280}
281
282static struct drm_buf *kms_alloc_buf(struct drm_display *drm_disp, struct drm_buf_metadata *info)
283{
284 int ret;
285 struct drm_buf *buf = NULL;
286 uint32_t bo_handles[4] = {0};
287
288 buf = calloc(1, sizeof(*buf));
289 buf->fourcc = info->fourcc;
290 buf->width = info->width;
291 buf->height = info->height;
292 buf->flags = info->flags;
293 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000294 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800295 buf->disp = drm_disp;
296
297 ret = alloc_bos(drm_disp, buf, bo_handles);
298 if (ret) {
299 fprintf(stderr, "alloc_bos fail\n");
300 free(buf);
301 return NULL;
302 }
303
chen.wang1bace1312023-01-18 16:13:54 +0800304 /*for non-root users, just need alloc buf and don't need to add framebuffer*/
305 if (drm_disp->alloc_only)
306 return buf;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800307
Ao Xu70554242020-10-15 15:19:48 +0800308 ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
309 if (ret) {
chen.wang1bace1312023-01-18 16:13:54 +0800310 fprintf(stderr, "add_framebuffer fail, call free_buf\n");
Ao Xu70554242020-10-15 15:19:48 +0800311 free_buf(drm_disp, buf);
Ao Xu70554242020-10-15 15:19:48 +0800312 return NULL;
313 }
314
315 return buf;
316}
317
318static int kms_alloc_bufs(struct drm_display *drm_disp, int num, struct drm_buf_metadata *info)
319{
320 int i, ret;
321 struct drm_buf *buf;
322 uint32_t bo_handles[4] = {0};
323
324 drm_disp->bufs = calloc(num, sizeof(*drm_disp->bufs));
325 drm_disp->nbuf = num;
326
327 for ( i = 0; i < num; i++) {
328 buf = &drm_disp->bufs[i];
329 buf->fourcc = info->fourcc;
330 buf->width = info->width;
331 buf->height = info->height;
332 buf->flags = info->flags;
333 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000334 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800335 buf->disp = drm_disp;
336
337 if (!info->fourcc)
338 buf->fourcc = DRM_FORMAT_ARGB8888;
339
340 switch (buf->fourcc) {
341 case DRM_FORMAT_ARGB8888:
342 buf->nbo = 1;
343 break;
344 case DRM_FORMAT_UYVY:
345 case DRM_FORMAT_YUYV:
346 buf->nbo = 1;
347 break;
348 case DRM_FORMAT_NV12:
349 case DRM_FORMAT_NV21:
350 buf->nbo = 2;
351 break;
352 default:
353 fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc);
354 break;
355 }
356
357 ret = alloc_bos(drm_disp, buf, bo_handles);
358 if (ret) {
359 fprintf(stderr, "alloc_bos fail\n");
360 return -1;
361 }
362
363 ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
364 if (ret) {
365 fprintf(stderr, "add_framebuffer fail\n");
366 free_buf(drm_disp, buf);
367 return -1;
368 }
369 }
370 return 0;
371}
372
373static struct drm_buf *kms_import_buf(struct drm_display *disp, struct drm_buf_import *info)
374{
375 int i;
376 uint32_t size;
377 struct drm_buf *buf = NULL;
378 uint32_t bo_handles[4] = {0};
379
380 buf = calloc(1, sizeof(*buf));
381 buf->fourcc = info->fourcc;
382 buf->width = info->width;
383 buf->height = info->height;
384 buf->flags = info->flags;
385 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000386 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800387 buf->disp = disp;
388
389 if (!info->fourcc)
390 buf->fourcc = DRM_FORMAT_ARGB8888;
391
392 switch (buf->fourcc) {
393 case DRM_FORMAT_ARGB8888:
394 buf->nbo = 1;
395 break;
396 case DRM_FORMAT_UYVY:
397 case DRM_FORMAT_YUYV:
398 buf->nbo = 1;
399 break;
400 case DRM_FORMAT_NV12:
401 case DRM_FORMAT_NV21:
402 buf->nbo = 2;
403 break;
404 default:
405 fprintf(stderr, "unsupport format: 0x%08x\n", buf->fourcc);
406 break;
407 }
408
409 for (i = 0; i < buf->nbo; i++) {
410 if ( i == 0 )
411 size = info->width * info->height;
412 else
413 size = info->width * info->height / 2;
414
415 buf->size += size;
416 buf->fd[i] = info->fd[i];
417 buf->pitches[i] = buf->width;
418 buf->bos[i] = meson_bo_import(disp->dev, info->fd[i], size, info->flags);
419 if (!buf->bos[i]) {
420 fprintf(stderr, "meson_bo_import fail\n");
421 return NULL;
422 }
423
424 bo_handles[i] = meson_bo_handle(buf->bos[i]);
425 }
426
427 add_framebuffer(disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
428
429 return buf;
430}
431
Ao Xu6747bbd2020-09-28 20:02:09 +0800432static int kms_post_buf(struct drm_display *drm_disp, struct drm_buf *buf)
433{
434 int ret;
435 drmModeAtomicReqPtr request;
Ao Xu6747bbd2020-09-28 20:02:09 +0800436 uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
437 struct kms_display *disp = to_kms_display(drm_disp);
438
439 struct plane_state *plane_state;
440 struct crtc_state *crtc_state;
441 struct connector_state *conn_state;
442
443 conn_state = disp->conn_states[0];
444 crtc_state = disp->crtc_states[0];
445
sky zhouf05ca462020-10-29 18:07:40 +0800446 if (buf->flags & MESON_USE_VD1)
Ao Xu6747bbd2020-09-28 20:02:09 +0800447 plane_state = disp->vid_states[0];
sky zhouf05ca462020-10-29 18:07:40 +0800448 else if (buf->flags & MESON_USE_VD2)
Ao Xu6747bbd2020-09-28 20:02:09 +0800449 plane_state = disp->vid_states[1];
450 else
451 plane_state = disp->osd_states[0];
452
453 request = drmModeAtomicAlloc();
454
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000455 if (buf->disable_plane) {
456 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_x.id, 0);
457 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_y.id, 0);
458 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, 0);
459 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, 0);
460 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_x.id, 0);
461 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_y.id, 0);
462 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_w.id, 0);
463 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_h.id, 0);
464 drmModeAtomicAddProperty(request, plane_state->id, plane_state->fb_id.id, 0);
465 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_id.id, 0);
466 } else {
467 #if 0
468 if (!disp->mode_set) {
469 flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
470 drmModeAtomicAddProperty(request, conn_state->id, conn_state->crtc_id.id, crtc_state->id);
Ao Xu6747bbd2020-09-28 20:02:09 +0800471
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000472 if (drmModeCreatePropertyBlob(drm_disp->drm_fd, &disp->conn_states[0]->mode,
473 sizeof(drmModeModeInfo), &blob_id) != 0 ) {
474 return -1;
475 }
476 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->mode_id.id, blob_id);
477 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->active.id, 1);
478
479 disp->mode_set = 1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800480 }
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000481 #else
482 /*No modeset needed in post buf, modeset will control by systemservice.*/
483 #endif
Ao Xu6747bbd2020-09-28 20:02:09 +0800484
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000485 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_x.id, buf->crtc_x);
486 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_y.id, buf->crtc_y);
487 if (buf->crtc_w == 0) {
488 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, conn_state->mode.hdisplay);
489 } else {
490 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, buf->crtc_w);
491 }
492
493 if (buf->crtc_h == 0) {
494 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, conn_state->mode.vdisplay);
495 } else {
496 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, buf->crtc_h);
497 }
498
499 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_x.id, buf->src_x << 16);
500 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_y.id, buf->src_y << 16);
501 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_w.id, buf->src_w << 16);
502 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_h.id, buf->src_h << 16);
503 drmModeAtomicAddProperty(request, plane_state->id, plane_state->fb_id.id, buf->fb_id);
504 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_id.id, crtc_state->id);
505 #if 0
506 if (buf->flags | (MESON_USE_VD2 | MESON_USE_VD1))
507 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->video_out_fence.id, VOID2U64(&buf->fence_fd));
508 else
509 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->out_fence.id, VOID2U64(&buf->fence_fd));
510 #endif
Ao Xu6747bbd2020-09-28 20:02:09 +0800511 }
sky zhouf05ca462020-10-29 18:07:40 +0800512
513 ret = drmModeAsyncAtomicCommit(drm_disp->drm_fd, request, flags, NULL);
Ao Xu6747bbd2020-09-28 20:02:09 +0800514 if (ret < 0) {
515 fprintf(stderr, "Unable to flip page: %s\n", strerror(errno));
516 goto error;
517 }
518
519 ret = 0;
520 goto complete;
521
522error:
523 ret = -1;
524complete:
525 drmModeAtomicFree(request);
526
527 return ret;
528}
529
530static void getproperty(int drm_fd, drmModeObjectProperties* props, const char *name,
531 struct property *p)
532{
533 int i;
534 drmModePropertyRes *res;
535 for (i = 0; i < props->count_props; i++) {
536 res = drmModeGetProperty(drm_fd, props->props[i]);
Ao Xu70554242020-10-15 15:19:48 +0800537 if (res && !strcmp(name, res->name)) {
538 p->id = res->prop_id;
539 p->value = props->prop_values[i];
540 //fprintf(stdout, "getproperty: %s, id: %u, value: %llu \n", res->name, p->id, p->value);
541 }
Ao Xu70554242020-10-15 15:19:48 +0800542 drmModeFreeProperty(res);
Ao Xu6747bbd2020-09-28 20:02:09 +0800543 }
544}
545
546static int populate_connectors(drmModeRes *resources, struct kms_display *disp)
547{
Ao Xu70554242020-10-15 15:19:48 +0800548 int i, j;
Ao Xu6747bbd2020-09-28 20:02:09 +0800549 int num_connector = 0;
550 struct connector_state *state;
551 drmModeConnector *connector;
552 drmModeEncoder *encoder;
553 drmModeObjectProperties *props;
554
555 for (i = 0; i < resources->count_connectors; i++) {
556 connector = drmModeGetConnector(disp->base.drm_fd, resources->connectors[i]);
Ao Xu70554242020-10-15 15:19:48 +0800557 if (!connector) {
558 fprintf(stderr, "drmModeGetConnector fail.\n");
559 continue;
560 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800561
chen.wang1bace1312023-01-18 16:13:54 +0800562 if (connector->connector_type == DRM_MODE_CONNECTOR_TV) {
563 drmModeFreeConnector(connector);
Ao Xu6747bbd2020-09-28 20:02:09 +0800564 continue;
chen.wang1bace1312023-01-18 16:13:54 +0800565 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800566 state = calloc(1, sizeof(*state));
567 disp->conn_states[num_connector++] = state;
568 state->id = resources->connectors[i];
569
570 for (j = 0; j < connector->count_encoders; j++) {
571 encoder = drmModeGetEncoder(disp->base.drm_fd, connector->encoders[j]);
Ao Xu70554242020-10-15 15:19:48 +0800572 if (encoder) {
573 state->crtc_mask |= encoder->possible_crtcs;
574 drmModeFreeEncoder(encoder);
575 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800576 }
577
578 if (connector->count_modes)
579 state->mode = connector->modes[0];
580
581 for (j = 0; j < connector->count_modes; j++) {
582 if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED) {
583 state->mode = connector->modes[j];
584 break;
585 }
586 }
587
588 disp->base.width = state->mode.hdisplay;
589 disp->base.height = state->mode.vdisplay;
590 disp->base.vrefresh = state->mode.vrefresh;
591
592 props = drmModeObjectGetProperties(disp->base.drm_fd, resources->connectors[i], DRM_MODE_OBJECT_CONNECTOR);
Ao Xu6747bbd2020-09-28 20:02:09 +0800593 getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id);
Ao Xu70554242020-10-15 15:19:48 +0800594
595 if (props)
596 drmModeFreeObjectProperties(props);
597
598 if (connector)
599 drmModeFreeConnector(connector);
Ao Xu6747bbd2020-09-28 20:02:09 +0800600 }
601
602 disp->num_connector = num_connector;
603 fprintf(stdout, "found %d connector\n", num_connector);
Ao Xu70554242020-10-15 15:19:48 +0800604 return 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800605}
606
607static int populate_crtcs(drmModeRes *resources, struct kms_display *disp)
608{
Ao Xu70554242020-10-15 15:19:48 +0800609 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +0800610 int num_crtc = 0;
611 struct crtc_state *state;
612 drmModeObjectProperties *props;
613
614 for (i = 0; i < resources->count_crtcs; i++) {
615 state = calloc(1, sizeof(*state));
Ao Xu70554242020-10-15 15:19:48 +0800616 if (!state) {
617 fprintf(stderr, "calloc crtc state fail.\n");
618 return -1;
619 }
620
Ao Xu6747bbd2020-09-28 20:02:09 +0800621 disp->crtc_states[num_crtc++] = state;
622 state->id = resources->crtcs[i];
623
624 props = drmModeObjectGetProperties(disp->base.drm_fd, resources->crtcs[i], DRM_MODE_OBJECT_CRTC);
Ao Xu70554242020-10-15 15:19:48 +0800625 if (props) {
626 getproperty(disp->base.drm_fd, props, "MODE_ID", &state->mode_id);
627 getproperty(disp->base.drm_fd, props, "ACTIVE", &state->active);
628 getproperty(disp->base.drm_fd, props, "OUT_FENCE_PTR", &state->out_fence);
629 getproperty(disp->base.drm_fd, props, "VIDEO_OUT_FENCE_PTR", &state->video_out_fence);
Ao Xu70554242020-10-15 15:19:48 +0800630 drmModeFreeObjectProperties(props);
631 } else {
632 fprintf(stderr, "get crtc obj property fail\n");
633 return -1;
634 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800635 }
636
637 disp->num_crtc = num_crtc;
638
639 fprintf(stdout, "found %d crtc\n", num_crtc);
Ao Xu70554242020-10-15 15:19:48 +0800640 return 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800641}
642
643static int is_plane_support_yuv(drmModePlane * plane)
644{
645 int i;
646 for (i = 0; i < plane->count_formats; i++) {
647 switch (plane->formats[i]) {
648 case DRM_FORMAT_NV12:
649 case DRM_FORMAT_NV21:
650 return 1;
651 default:
652 return 0;
653 }
654 }
655
656 return 0;
657}
658
659static int populate_planes(drmModeRes *resources, struct kms_display *disp)
660{
Ao Xu70554242020-10-15 15:19:48 +0800661 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +0800662 int num_osd_plane = 0;
663 int num_vid_plane = 0;
664 struct plane_state *state;
665 drmModePlane *plane;
666 drmModePlaneRes *plane_res;
667 drmModeObjectProperties *props;
668
669 plane_res = drmModeGetPlaneResources(disp->base.drm_fd);
Ao Xu70554242020-10-15 15:19:48 +0800670 if (!plane_res) {
671 fprintf(stderr, "drmModeGetPlaneResources fail.\n");
672 goto error;
673 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800674
675 for (i = 0; i < plane_res->count_planes; i++) {
676 state = calloc(1, sizeof(*state));
Ao Xu70554242020-10-15 15:19:48 +0800677 if (!state) {
678 fprintf(stderr, "calloc plane state fail.\n");
679 goto error;
680 }
681
Ao Xu6747bbd2020-09-28 20:02:09 +0800682 plane = drmModeGetPlane(disp->base.drm_fd, plane_res->planes[i]);
Ao Xu70554242020-10-15 15:19:48 +0800683 if (plane) {
684 if (is_plane_support_yuv(plane))
685 disp->vid_states[num_vid_plane++] = state;
686 else
687 disp->osd_states[num_osd_plane++] = state;
Ao Xu6747bbd2020-09-28 20:02:09 +0800688
Ao Xu70554242020-10-15 15:19:48 +0800689 state->id = plane_res->planes[i];
690 state->crtc_mask = plane->possible_crtcs;
Ao Xu6747bbd2020-09-28 20:02:09 +0800691
Ao Xu70554242020-10-15 15:19:48 +0800692 props = drmModeObjectGetProperties(disp->base.drm_fd, plane_res->planes[i], DRM_MODE_OBJECT_PLANE);
693 if (props) {
694 getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id);
695 getproperty(disp->base.drm_fd, props, "CRTC_X", &state->crtc_x);
696 getproperty(disp->base.drm_fd, props, "CRTC_Y", &state->crtc_y);
697 getproperty(disp->base.drm_fd, props, "CRTC_W", &state->crtc_w);
698 getproperty(disp->base.drm_fd, props, "CRTC_H", &state->crtc_h);
699 getproperty(disp->base.drm_fd, props, "FB_ID", &state->fb_id);
700 getproperty(disp->base.drm_fd, props, "SRC_X", &state->src_x);
701 getproperty(disp->base.drm_fd, props, "SRC_Y", &state->src_y);
702 getproperty(disp->base.drm_fd, props, "SRC_W", &state->src_w);
703 getproperty(disp->base.drm_fd, props, "SRC_H", &state->src_h);
704 getproperty(disp->base.drm_fd, props, "type", &state->type);
705 getproperty(disp->base.drm_fd, props, "IN_FENCE_FD", &state->in_fence_fd);
706 getproperty(disp->base.drm_fd, props, "IN_FORMATS", &state->in_formats);
707 }
708 }
709
710 if (props)
711 drmModeFreeObjectProperties(props);
712
713 if (plane)
714 drmModeFreePlane(plane);
Ao Xu6747bbd2020-09-28 20:02:09 +0800715 }
716
717 disp->num_osd_plane = num_osd_plane;
718 disp->num_vid_plane = num_vid_plane;
719
Ao Xu70554242020-10-15 15:19:48 +0800720 drmModeFreePlaneResources(plane_res);
721
Ao Xu6747bbd2020-09-28 20:02:09 +0800722 fprintf(stdout, "found %d osd, %d video\n", num_osd_plane, num_vid_plane);
Ao Xu70554242020-10-15 15:19:48 +0800723 return 0;
724
725error:
726 drmModeFreePlaneResources(plane_res);
727
728 return -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800729}
730
731static int drm_kms_init_resource(struct kms_display *disp)
732{
733 int ret;
limin.tian79bf2b12023-02-24 10:28:26 +0000734 int drm_fd = -1;
735 int render_fd = -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800736 drmModeRes *resources;
737
738 drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
739 if (drm_fd < 0) {
740 fprintf(stderr, "Unable to open DRM node: %s\n",
741 strerror(errno));
742 return -1;
743 }
chen.wang1f5503ea2023-04-12 07:36:24 +0000744 drmDropMaster(drm_fd);
wenlong.zhang4c011d42022-06-09 10:59:38 +0800745 render_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
746 if (render_fd < 0) {
747 fprintf(stderr, "Unable to open renderD128 node: %s\n",
748 strerror(errno));
limin.tian79bf2b12023-02-24 10:28:26 +0000749 goto error3;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800750 }
751
Ao Xu6747bbd2020-09-28 20:02:09 +0800752 disp->base.drm_fd = drm_fd;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800753 disp->base.dev = meson_device_create(drm_fd, render_fd);
Ao Xu70554242020-10-15 15:19:48 +0800754 if (!disp->base.dev) {
755 fprintf(stderr, "meson_device_create fail\n");
756 goto error3;
757 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800758
759 ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
760 if (ret < 0) {
761 fprintf(stderr, "Unable to set DRM atomic capability: %s\n",
762 strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800763 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800764 }
765
766 ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
767 if (ret < 0) {
768 fprintf(stderr, "Unable to set DRM universal planes capability: %s\n",
769 strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800770 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800771 }
772
773 resources = drmModeGetResources(drm_fd);
774 if (!resources) {
775 fprintf(stderr, "drmModeGetResources failed: %s\n", strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800776 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800777 }
778
Ao Xu70554242020-10-15 15:19:48 +0800779 ret = populate_connectors(resources, disp);
780 if (ret)
781 goto error1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800782
Ao Xu70554242020-10-15 15:19:48 +0800783 ret = populate_crtcs(resources, disp);
784 if (ret)
785 goto error1;
786
787 ret = populate_planes(resources, disp);
788 if (ret)
789 goto error1;
chen.wang1bace1312023-01-18 16:13:54 +0800790 drmModeFreeResources(resources);
Ao Xu6747bbd2020-09-28 20:02:09 +0800791 return 0;
Ao Xu70554242020-10-15 15:19:48 +0800792
793error1:
794 drmModeFreeResources(resources);
795error2:
796 meson_device_destroy(disp->base.dev);
797error3:
limin.tian79bf2b12023-02-24 10:28:26 +0000798 if (drm_fd >= 0)
799 close(drm_fd);
800 if (render_fd >= 0)
801 close(render_fd);
Ao Xu70554242020-10-15 15:19:48 +0800802
803 return -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800804}
805
806struct drm_display *drm_kms_init(void)
807{
Ao Xu70554242020-10-15 15:19:48 +0800808 int ret;
Ao Xu6747bbd2020-09-28 20:02:09 +0800809 struct kms_display *display;
810 struct drm_display *base;
811 display = calloc(1, sizeof(*display));
Ao Xu70554242020-10-15 15:19:48 +0800812 if (!display) {
813 fprintf(stderr, "calloc kms_display fail\n");
814 return NULL;
815 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800816
817 base = &display->base;
818 base->destroy_display = kms_destroy_display;
819 base->alloc_bufs = kms_alloc_bufs;
820 base->free_bufs = kms_free_bufs;
821
822 base->alloc_buf = kms_alloc_buf;
Ao Xu70554242020-10-15 15:19:48 +0800823 base->import_buf = kms_import_buf;
Ao Xu6747bbd2020-09-28 20:02:09 +0800824 base->free_buf = kms_free_buf;
825 base->post_buf = kms_post_buf;
chen.wang1bace1312023-01-18 16:13:54 +0800826 base->alloc_only = 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800827
Ao Xu70554242020-10-15 15:19:48 +0800828 ret = drm_kms_init_resource(display);
829 if (ret) {
830 fprintf(stderr, "drm_kms_init_resource fail.\n");
831 free(display);
832 return NULL;
833 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800834
835 return base;
836}