blob: 2c5fd68a188da8009828b62694aa46bda787d2a4 [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"
chen.wang1d5483452024-02-28 06:18:16 +000018#include "meson_drm_log.h"
Ao Xu6747bbd2020-09-28 20:02:09 +080019
20#define MAX_OSD_PLANE 6
21#define MAX_VIDEO_PLANE 4
22#define MAX_CONNECTOR 3
23#define MAX_CRTC 3
24
25struct kms_display;
26
chen.wang1bace1312023-01-18 16:13:54 +080027
Ao Xu6747bbd2020-09-28 20:02:09 +080028#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
29#define container_of(ptr, type, member) \
30 (type *)((char *)(ptr) - (char *) &((type *)0)->member)
31
32#define to_kms_display(x) container_of(x, struct kms_display, base)
33
34struct property {
35 uint32_t id;
36 uint64_t value;
37};
38
39struct crtc_state {
40 uint32_t id;
41
42 struct property mode_id;
43 struct property active;
44 struct property out_fence;
45 struct property video_out_fence;
46};
47
48struct connector_state {
49 uint32_t id;
50 uint32_t crtc_mask;
51 drmModeModeInfo mode;
52
53 struct property crtc_id;
54};
55
56struct plane_state {
57 uint32_t id;
58 uint32_t crtc_mask;
59
60 struct property crtc_id;
61 struct property crtc_x;
62 struct property crtc_y;
63 struct property crtc_w;
64 struct property crtc_h;
65 struct property fb_id;
66 struct property src_x;
67 struct property src_y;
68 struct property src_w;
69 struct property src_h;
Ao Xu6747bbd2020-09-28 20:02:09 +080070 struct property type;
71 struct property in_fence_fd;
72 struct property in_formats;
73};
74
Ao Xu6747bbd2020-09-28 20:02:09 +080075struct kms_display {
76 struct drm_display base;
77
Ao Xu6747bbd2020-09-28 20:02:09 +080078 int num_crtc;
79 struct crtc_state *crtc_states[MAX_CRTC];
80 int num_connector;
81 struct connector_state *conn_states[MAX_CONNECTOR];
82 int num_osd_plane;
83 struct plane_state *osd_states[MAX_OSD_PLANE];
84 int num_vid_plane;
85 struct plane_state *vid_states[MAX_OSD_PLANE];
86
87 int mode_set;
88};
89
90static void kms_destroy_display(struct drm_display *drm_disp)
91{
Ao Xu70554242020-10-15 15:19:48 +080092 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +080093 struct kms_display *disp = to_kms_display(drm_disp);
Ao Xu70554242020-10-15 15:19:48 +080094 close(drm_disp->drm_fd);
limin.tian79bf2b12023-02-24 10:28:26 +000095 close(drm_disp->dev->render_fd);
Ao Xu70554242020-10-15 15:19:48 +080096 meson_device_destroy(drm_disp->dev);
97
98 for (i = 0; i < MAX_CRTC; i++) {
99 if (disp->crtc_states[i])
100 free(disp->crtc_states[i]);
101 }
102
103 for (i = 0; i < MAX_CONNECTOR; i++) {
104 if (disp->conn_states[i])
105 free(disp->conn_states[i]);
106 }
107
108 for (i = 0; i < MAX_OSD_PLANE; i++) {
109 if (disp->osd_states[i])
110 free(disp->osd_states[i]);
111 }
112
113 for (i = 0; i < MAX_OSD_PLANE; i++) {
114 if (disp->vid_states[i])
115 free(disp->vid_states[i]);
116 }
117
Ao Xu6747bbd2020-09-28 20:02:09 +0800118 free(disp);
119}
120
Ao Xu6747bbd2020-09-28 20:02:09 +0800121static int free_buf(struct drm_display *drm_disp, struct drm_buf *buf)
122{
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800123 int i, fd, ret;
Ao Xu6747bbd2020-09-28 20:02:09 +0800124 struct drm_mode_destroy_dumb destroy_dumb;
125
chen.wang1518f14f2023-04-12 09:53:10 +0000126 if (!buf)
127 return -1;
128
Ao Xu6747bbd2020-09-28 20:02:09 +0800129 for ( i = 0; i < buf->nbo; i++)
130 close(buf->fd[i]);
131
chen.wang1bace1312023-01-18 16:13:54 +0800132 fd = drm_disp->alloc_only ? drm_disp->dev->render_fd : drm_disp->dev->fd;
wenlong.zhang7d32ed92023-04-12 06:08:17 +0000133 if (drm_disp->freeze) {
134 ret = drmIoctl(drm_disp->drm_fd, DRM_IOCTL_MESON_RMFB, &buf->fb_id);
135 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000136 ERROR("%s %d Unable to rmfb: %s\n",__FUNCTION__,__LINE__,
wenlong.zhang7d32ed92023-04-12 06:08:17 +0000137 strerror(errno));
138 }
139 } else {
140 drmModeRmFB(drm_disp->drm_fd, buf->fb_id);
141 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800142 memset(&destroy_dumb, 0, sizeof(destroy_dumb));
143
144 for ( i = 0; i < buf->nbo; i++) {
chen.wang1518f14f2023-04-12 09:53:10 +0000145 if (!buf->bos[i])
146 continue;
147
Ao Xu6747bbd2020-09-28 20:02:09 +0800148 destroy_dumb.handle = meson_bo_handle(buf->bos[i]);
149
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800150 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
Ao Xu6747bbd2020-09-28 20:02:09 +0800151 if (ret < 0) {
152 /* If handle was from drmPrimeFDToHandle, then fd is connected
153 * as render, we have to use drm_gem_close to release it.
154 */
155 if (errno == EACCES) {
156 struct drm_gem_close close_req;
157 close_req.handle = destroy_dumb.handle;
wenlong.zhanga71a2e02022-06-14 15:58:53 +0800158 ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req);
Ao Xu6747bbd2020-09-28 20:02:09 +0800159 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000160 ERROR("%s %d Unable to destroy buffer: %s\n",__FUNCTION__,__LINE__,
Ao Xu6747bbd2020-09-28 20:02:09 +0800161 strerror(errno));
162 return -1;
163 }
164 }
165 }
chen.wang1518f14f2023-04-12 09:53:10 +0000166 free(buf->bos[i]);
167 buf->bos[i] = NULL;
Ao Xu6747bbd2020-09-28 20:02:09 +0800168 }
chen.wang1bace1312023-01-18 16:13:54 +0800169 free(buf);
chen.wang1518f14f2023-04-12 09:53:10 +0000170 buf = NULL;
Ao Xu6747bbd2020-09-28 20:02:09 +0800171 return 0;
172}
173static int kms_free_bufs(struct drm_display *drm_disp)
174{
175 int i;
176 struct drm_buf *buf;
Ao Xu6747bbd2020-09-28 20:02:09 +0800177 for ( i = 0; i < drm_disp->nbuf; i++ ) {
178 buf = &drm_disp->bufs[i];
179 free_buf(drm_disp, buf);
180 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800181 return 0;
182}
183
184static int kms_free_buf(struct drm_buf *buf)
185{
186 free_buf(buf->disp, buf);
187 return 0;
188}
189
Ao Xu70554242020-10-15 15:19:48 +0800190static struct meson_bo *alloc_bo(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t bpp, uint32_t width,
191 uint32_t height, uint32_t *bo_handle, uint32_t *pitch)
192{
193 uint32_t size;
194 struct meson_bo *bo;
195
196 size = width * height * bpp / 8;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800197 bo = meson_bo_create(drm_disp->dev, size, buf->flags, drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800198 if (bo) {
199 *bo_handle = meson_bo_handle(bo);
200 *pitch = width * bpp / 8;
201 return bo;
202 } else {
chen.wang1d5483452024-02-28 06:18:16 +0000203 ERROR("%s %d meson_bo_create fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800204 return NULL;
205 }
206}
207
208static int alloc_bos(struct drm_display *drm_disp, struct drm_buf *buf, uint32_t *bo_handles)
209{
210 uint32_t width = buf->width;
211 uint32_t height = buf->height;
212
213 switch (buf->fourcc) {
214 case DRM_FORMAT_ARGB8888:
215 buf->nbo = 1;
216 buf->bos[0] = alloc_bo(drm_disp, buf, 32, width, height, &bo_handles[0], &buf->pitches[0]);
217 if (!buf->bos[0]) {
chen.wang1d5483452024-02-28 06:18:16 +0000218 ERROR("%s %d alloc_bo argb888 fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800219 return -1;
220 }
221
222 buf->size = width * height * 4;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800223 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800224 break;
225 case DRM_FORMAT_UYVY:
226 case DRM_FORMAT_YUYV:
227 buf->nbo = 1;
228 buf->bos[0] = alloc_bo(drm_disp, buf, 16, width, height, &bo_handles[0], &buf->pitches[0]);
229 if (!buf->bos[0]) {
chen.wang1d5483452024-02-28 06:18:16 +0000230 ERROR("%s %d alloc_bo yuyv or uyvy fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800231 return -1;
232 }
233
234 buf->size = width * height * 2;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800235 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800236 buf->commit_to_video = 1;
237 break;
238 case DRM_FORMAT_NV12:
239 case DRM_FORMAT_NV21:
240 buf->nbo = 2;
241 buf->bos[0] = alloc_bo(drm_disp, buf, 8, width, height, &bo_handles[0], &buf->pitches[0]);
242 if (!buf->bos[0]) {
chen.wang1d5483452024-02-28 06:18:16 +0000243 ERROR("%s %d alloc_bo nv12 or nv21 fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800244 return -1;
245 }
246
wenlong.zhang4c011d42022-06-09 10:59:38 +0800247 buf->fd[0] = meson_bo_dmabuf(buf->bos[0], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800248
249 buf->bos[1] = alloc_bo(drm_disp, buf, 16, width/2, height/2, &bo_handles[1], &buf->pitches[1]);
250 if (!buf->bos[1]) {
chen.wang1d5483452024-02-28 06:18:16 +0000251 ERROR("%s %d alloc_bo argb888 fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800252 return -1;
253 }
wenlong.zhang4c011d42022-06-09 10:59:38 +0800254 buf->fd[1] = meson_bo_dmabuf(buf->bos[1], drm_disp->alloc_only);
Ao Xu70554242020-10-15 15:19:48 +0800255 buf->size = width * height * 3 / 2;
256 buf->commit_to_video = 1;
257 break;
258 default:
chen.wang1d5483452024-02-28 06:18:16 +0000259 ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__,buf->fourcc);
Ao Xu70554242020-10-15 15:19:48 +0800260 break;
261 }
262
263 return 0;
264}
265
266static int add_framebuffer(int fd, struct drm_buf *buf, uint32_t *bo_handles, uint64_t modifier)
267{
268 int i, ret;
269 uint64_t modifiers[4] = { 0, 0, 0, 0 };
270 uint32_t flags = 0;
271 uint32_t fb_id;
272
273 for ( i = 0; i < buf->nbo; i++) {
274 if (bo_handles[i] != 0 && modifier != DRM_FORMAT_MOD_NONE) {
275 flags |= DRM_MODE_FB_MODIFIERS;
276 modifiers[i] = modifier;
277 }
278 }
279
280 ret = drmModeAddFB2WithModifiers(fd, buf->width, buf->height, buf->fourcc,
281 bo_handles, buf->pitches, buf->offsets, modifiers, &fb_id, flags);
282 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000283 ERROR("%s %d Unable to add framebuffer for plane: %s\n",__FUNCTION__,__LINE__, strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800284 return -1;
285 }
286
287 buf->fb_id = fb_id;
288 return 0;
289}
290
291static struct drm_buf *kms_alloc_buf(struct drm_display *drm_disp, struct drm_buf_metadata *info)
292{
293 int ret;
294 struct drm_buf *buf = NULL;
295 uint32_t bo_handles[4] = {0};
296
297 buf = calloc(1, sizeof(*buf));
298 buf->fourcc = info->fourcc;
299 buf->width = info->width;
300 buf->height = info->height;
301 buf->flags = info->flags;
302 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000303 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800304 buf->disp = drm_disp;
305
306 ret = alloc_bos(drm_disp, buf, bo_handles);
307 if (ret) {
chen.wang1d5483452024-02-28 06:18:16 +0000308 ERROR("%s %d alloc_bos fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800309 free(buf);
310 return NULL;
311 }
312
chen.wang1bace1312023-01-18 16:13:54 +0800313 /*for non-root users, just need alloc buf and don't need to add framebuffer*/
314 if (drm_disp->alloc_only)
315 return buf;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800316
Ao Xu70554242020-10-15 15:19:48 +0800317 ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
318 if (ret) {
chen.wang1d5483452024-02-28 06:18:16 +0000319 ERROR("%s %d add_framebuffer fail, call free_buf\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800320 free_buf(drm_disp, buf);
Ao Xu70554242020-10-15 15:19:48 +0800321 return NULL;
322 }
323
324 return buf;
325}
326
327static int kms_alloc_bufs(struct drm_display *drm_disp, int num, struct drm_buf_metadata *info)
328{
329 int i, ret;
330 struct drm_buf *buf;
331 uint32_t bo_handles[4] = {0};
332
333 drm_disp->bufs = calloc(num, sizeof(*drm_disp->bufs));
334 drm_disp->nbuf = num;
335
336 for ( i = 0; i < num; i++) {
337 buf = &drm_disp->bufs[i];
338 buf->fourcc = info->fourcc;
339 buf->width = info->width;
340 buf->height = info->height;
341 buf->flags = info->flags;
342 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000343 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800344 buf->disp = drm_disp;
345
346 if (!info->fourcc)
347 buf->fourcc = DRM_FORMAT_ARGB8888;
348
349 switch (buf->fourcc) {
350 case DRM_FORMAT_ARGB8888:
351 buf->nbo = 1;
352 break;
353 case DRM_FORMAT_UYVY:
354 case DRM_FORMAT_YUYV:
355 buf->nbo = 1;
356 break;
357 case DRM_FORMAT_NV12:
358 case DRM_FORMAT_NV21:
359 buf->nbo = 2;
360 break;
361 default:
chen.wang1d5483452024-02-28 06:18:16 +0000362 ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__, buf->fourcc);
Ao Xu70554242020-10-15 15:19:48 +0800363 break;
364 }
365
366 ret = alloc_bos(drm_disp, buf, bo_handles);
367 if (ret) {
chen.wang1d5483452024-02-28 06:18:16 +0000368 ERROR("%s %d alloc_bos fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800369 return -1;
370 }
371
372 ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
373 if (ret) {
chen.wang1d5483452024-02-28 06:18:16 +0000374 ERROR("%s %d add_framebuffer fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800375 free_buf(drm_disp, buf);
376 return -1;
377 }
378 }
379 return 0;
380}
381
382static struct drm_buf *kms_import_buf(struct drm_display *disp, struct drm_buf_import *info)
383{
384 int i;
385 uint32_t size;
386 struct drm_buf *buf = NULL;
387 uint32_t bo_handles[4] = {0};
388
389 buf = calloc(1, sizeof(*buf));
390 buf->fourcc = info->fourcc;
391 buf->width = info->width;
392 buf->height = info->height;
393 buf->flags = info->flags;
394 buf->fence_fd = -1;
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000395 buf->disable_plane = 0;
Ao Xu70554242020-10-15 15:19:48 +0800396 buf->disp = disp;
397
398 if (!info->fourcc)
399 buf->fourcc = DRM_FORMAT_ARGB8888;
400
401 switch (buf->fourcc) {
402 case DRM_FORMAT_ARGB8888:
403 buf->nbo = 1;
404 break;
405 case DRM_FORMAT_UYVY:
406 case DRM_FORMAT_YUYV:
407 buf->nbo = 1;
408 break;
409 case DRM_FORMAT_NV12:
410 case DRM_FORMAT_NV21:
411 buf->nbo = 2;
412 break;
413 default:
chen.wang1d5483452024-02-28 06:18:16 +0000414 ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__,buf->fourcc);
Ao Xu70554242020-10-15 15:19:48 +0800415 break;
416 }
417
418 for (i = 0; i < buf->nbo; i++) {
419 if ( i == 0 )
420 size = info->width * info->height;
421 else
422 size = info->width * info->height / 2;
423
424 buf->size += size;
425 buf->fd[i] = info->fd[i];
426 buf->pitches[i] = buf->width;
427 buf->bos[i] = meson_bo_import(disp->dev, info->fd[i], size, info->flags);
428 if (!buf->bos[i]) {
chen.wang1d5483452024-02-28 06:18:16 +0000429 ERROR("%s %d meson_bo_import fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800430 return NULL;
431 }
432
433 bo_handles[i] = meson_bo_handle(buf->bos[i]);
434 }
435
436 add_framebuffer(disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE);
437
438 return buf;
439}
440
chen.wang1d5483452024-02-28 06:18:16 +0000441static int kms_set_plane(struct drm_display *drm_disp, struct drm_buf *buf)
442{
443 int ret;
444 uint32_t crtc_w, crtc_h;
445 struct kms_display *disp = to_kms_display(drm_disp);
446
447 struct plane_state *plane_state;
448 struct crtc_state *crtc_state;
449 struct connector_state *conn_state;
450
451 conn_state = disp->conn_states[0];
452 crtc_state = disp->crtc_states[0];
453
454 if (buf->flags & MESON_USE_VD1)
455 plane_state = disp->vid_states[0];
456 else if (buf->flags & MESON_USE_VD2)
457 plane_state = disp->vid_states[1];
458 else
459 plane_state = disp->osd_states[0];
460
461
462 if (buf->crtc_w == 0)
463 crtc_w = conn_state->mode.hdisplay;
464 else
465 crtc_w = buf->crtc_w;
466
467 if (buf->crtc_h == 0)
468 crtc_h = conn_state->mode.vdisplay;
469 else
470 crtc_h = buf->crtc_h;
471
mingyang.he2ba112a2024-03-25 07:56:58 +0000472 if (!drmIsMaster(drm_disp->drm_fd))
473 drmSetMaster(drm_disp->drm_fd);
474
chen.wang1d5483452024-02-28 06:18:16 +0000475 if (drmModeSetPlane(drm_disp->drm_fd, plane_state->id, crtc_state->id, buf->fb_id,
476 0, buf->crtc_x, buf->crtc_y, crtc_w, crtc_h,
477 buf->src_x << 16, buf->src_y << 16, buf->src_w << 16, buf->src_h << 16)) {
mingyang.he2ba112a2024-03-25 07:56:58 +0000478 ERROR("failed to set plane: %s\n", strerror(errno));
479 drmDropMaster(drm_disp->drm_fd);
chen.wang1d5483452024-02-28 06:18:16 +0000480 return -1;
481 }
mingyang.he2ba112a2024-03-25 07:56:58 +0000482 drmDropMaster(drm_disp->drm_fd);
chen.wang1d5483452024-02-28 06:18:16 +0000483
484 return ret;
485}
486
Ao Xu6747bbd2020-09-28 20:02:09 +0800487static int kms_post_buf(struct drm_display *drm_disp, struct drm_buf *buf)
488{
489 int ret;
490 drmModeAtomicReqPtr request;
Ao Xu6747bbd2020-09-28 20:02:09 +0800491 uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
492 struct kms_display *disp = to_kms_display(drm_disp);
493
494 struct plane_state *plane_state;
495 struct crtc_state *crtc_state;
496 struct connector_state *conn_state;
497
498 conn_state = disp->conn_states[0];
499 crtc_state = disp->crtc_states[0];
500
sky zhouf05ca462020-10-29 18:07:40 +0800501 if (buf->flags & MESON_USE_VD1)
Ao Xu6747bbd2020-09-28 20:02:09 +0800502 plane_state = disp->vid_states[0];
sky zhouf05ca462020-10-29 18:07:40 +0800503 else if (buf->flags & MESON_USE_VD2)
Ao Xu6747bbd2020-09-28 20:02:09 +0800504 plane_state = disp->vid_states[1];
505 else
506 plane_state = disp->osd_states[0];
507
508 request = drmModeAtomicAlloc();
509
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000510 if (buf->disable_plane) {
511 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_x.id, 0);
512 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_y.id, 0);
513 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, 0);
514 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, 0);
515 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_x.id, 0);
516 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_y.id, 0);
517 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_w.id, 0);
518 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_h.id, 0);
519 drmModeAtomicAddProperty(request, plane_state->id, plane_state->fb_id.id, 0);
520 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_id.id, 0);
521 } else {
522 #if 0
523 if (!disp->mode_set) {
524 flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
525 drmModeAtomicAddProperty(request, conn_state->id, conn_state->crtc_id.id, crtc_state->id);
Ao Xu6747bbd2020-09-28 20:02:09 +0800526
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000527 if (drmModeCreatePropertyBlob(drm_disp->drm_fd, &disp->conn_states[0]->mode,
528 sizeof(drmModeModeInfo), &blob_id) != 0 ) {
529 return -1;
530 }
531 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->mode_id.id, blob_id);
532 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->active.id, 1);
533
534 disp->mode_set = 1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800535 }
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000536 #else
537 /*No modeset needed in post buf, modeset will control by systemservice.*/
538 #endif
Ao Xu6747bbd2020-09-28 20:02:09 +0800539
wenlong.zhangcf8a5462023-04-10 03:25:19 +0000540 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_x.id, buf->crtc_x);
541 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_y.id, buf->crtc_y);
542 if (buf->crtc_w == 0) {
543 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, conn_state->mode.hdisplay);
544 } else {
545 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_w.id, buf->crtc_w);
546 }
547
548 if (buf->crtc_h == 0) {
549 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, conn_state->mode.vdisplay);
550 } else {
551 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_h.id, buf->crtc_h);
552 }
553
554 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_x.id, buf->src_x << 16);
555 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_y.id, buf->src_y << 16);
556 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_w.id, buf->src_w << 16);
557 drmModeAtomicAddProperty(request, plane_state->id, plane_state->src_h.id, buf->src_h << 16);
558 drmModeAtomicAddProperty(request, plane_state->id, plane_state->fb_id.id, buf->fb_id);
559 drmModeAtomicAddProperty(request, plane_state->id, plane_state->crtc_id.id, crtc_state->id);
560 #if 0
561 if (buf->flags | (MESON_USE_VD2 | MESON_USE_VD1))
562 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->video_out_fence.id, VOID2U64(&buf->fence_fd));
563 else
564 drmModeAtomicAddProperty(request, crtc_state->id, crtc_state->out_fence.id, VOID2U64(&buf->fence_fd));
565 #endif
Ao Xu6747bbd2020-09-28 20:02:09 +0800566 }
sky zhouf05ca462020-10-29 18:07:40 +0800567
568 ret = drmModeAsyncAtomicCommit(drm_disp->drm_fd, request, flags, NULL);
Ao Xu6747bbd2020-09-28 20:02:09 +0800569 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000570 ERROR("%s %d Unable to flip page: %s\n",__FUNCTION__,__LINE__,strerror(errno));
Ao Xu6747bbd2020-09-28 20:02:09 +0800571 goto error;
572 }
573
574 ret = 0;
575 goto complete;
576
577error:
578 ret = -1;
579complete:
580 drmModeAtomicFree(request);
581
582 return ret;
583}
584
585static void getproperty(int drm_fd, drmModeObjectProperties* props, const char *name,
586 struct property *p)
587{
588 int i;
589 drmModePropertyRes *res;
590 for (i = 0; i < props->count_props; i++) {
591 res = drmModeGetProperty(drm_fd, props->props[i]);
Ao Xu70554242020-10-15 15:19:48 +0800592 if (res && !strcmp(name, res->name)) {
593 p->id = res->prop_id;
594 p->value = props->prop_values[i];
595 //fprintf(stdout, "getproperty: %s, id: %u, value: %llu \n", res->name, p->id, p->value);
596 }
Ao Xu70554242020-10-15 15:19:48 +0800597 drmModeFreeProperty(res);
Ao Xu6747bbd2020-09-28 20:02:09 +0800598 }
599}
600
601static int populate_connectors(drmModeRes *resources, struct kms_display *disp)
602{
Ao Xu70554242020-10-15 15:19:48 +0800603 int i, j;
Ao Xu6747bbd2020-09-28 20:02:09 +0800604 int num_connector = 0;
605 struct connector_state *state;
606 drmModeConnector *connector;
607 drmModeEncoder *encoder;
608 drmModeObjectProperties *props;
609
610 for (i = 0; i < resources->count_connectors; i++) {
611 connector = drmModeGetConnector(disp->base.drm_fd, resources->connectors[i]);
Ao Xu70554242020-10-15 15:19:48 +0800612 if (!connector) {
chen.wang1d5483452024-02-28 06:18:16 +0000613 ERROR("%s %d drmModeGetConnector fail.\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800614 continue;
615 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800616
chen.wang1bace1312023-01-18 16:13:54 +0800617 if (connector->connector_type == DRM_MODE_CONNECTOR_TV) {
618 drmModeFreeConnector(connector);
Ao Xu6747bbd2020-09-28 20:02:09 +0800619 continue;
chen.wang1bace1312023-01-18 16:13:54 +0800620 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800621 state = calloc(1, sizeof(*state));
622 disp->conn_states[num_connector++] = state;
623 state->id = resources->connectors[i];
624
625 for (j = 0; j < connector->count_encoders; j++) {
626 encoder = drmModeGetEncoder(disp->base.drm_fd, connector->encoders[j]);
Ao Xu70554242020-10-15 15:19:48 +0800627 if (encoder) {
628 state->crtc_mask |= encoder->possible_crtcs;
629 drmModeFreeEncoder(encoder);
630 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800631 }
632
633 if (connector->count_modes)
634 state->mode = connector->modes[0];
635
636 for (j = 0; j < connector->count_modes; j++) {
637 if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED) {
638 state->mode = connector->modes[j];
639 break;
640 }
641 }
642
643 disp->base.width = state->mode.hdisplay;
644 disp->base.height = state->mode.vdisplay;
645 disp->base.vrefresh = state->mode.vrefresh;
646
647 props = drmModeObjectGetProperties(disp->base.drm_fd, resources->connectors[i], DRM_MODE_OBJECT_CONNECTOR);
Ao Xu6747bbd2020-09-28 20:02:09 +0800648 getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id);
Ao Xu70554242020-10-15 15:19:48 +0800649
650 if (props)
651 drmModeFreeObjectProperties(props);
652
653 if (connector)
654 drmModeFreeConnector(connector);
Ao Xu6747bbd2020-09-28 20:02:09 +0800655 }
656
657 disp->num_connector = num_connector;
chen.wang1d5483452024-02-28 06:18:16 +0000658 INFO("%s %d found %d connector\n",__FUNCTION__,__LINE__,num_connector);
Ao Xu70554242020-10-15 15:19:48 +0800659 return 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800660}
661
662static int populate_crtcs(drmModeRes *resources, struct kms_display *disp)
663{
Ao Xu70554242020-10-15 15:19:48 +0800664 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +0800665 int num_crtc = 0;
666 struct crtc_state *state;
667 drmModeObjectProperties *props;
668
669 for (i = 0; i < resources->count_crtcs; i++) {
670 state = calloc(1, sizeof(*state));
Ao Xu70554242020-10-15 15:19:48 +0800671 if (!state) {
chen.wang1d5483452024-02-28 06:18:16 +0000672 ERROR("%s %d calloc crtc state fail.\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800673 return -1;
674 }
675
Ao Xu6747bbd2020-09-28 20:02:09 +0800676 disp->crtc_states[num_crtc++] = state;
677 state->id = resources->crtcs[i];
678
679 props = drmModeObjectGetProperties(disp->base.drm_fd, resources->crtcs[i], DRM_MODE_OBJECT_CRTC);
Ao Xu70554242020-10-15 15:19:48 +0800680 if (props) {
681 getproperty(disp->base.drm_fd, props, "MODE_ID", &state->mode_id);
682 getproperty(disp->base.drm_fd, props, "ACTIVE", &state->active);
683 getproperty(disp->base.drm_fd, props, "OUT_FENCE_PTR", &state->out_fence);
684 getproperty(disp->base.drm_fd, props, "VIDEO_OUT_FENCE_PTR", &state->video_out_fence);
Ao Xu70554242020-10-15 15:19:48 +0800685 drmModeFreeObjectProperties(props);
686 } else {
chen.wang1d5483452024-02-28 06:18:16 +0000687 ERROR("%s %d get crtc obj property fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800688 return -1;
689 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800690 }
691
692 disp->num_crtc = num_crtc;
693
chen.wang1d5483452024-02-28 06:18:16 +0000694 DEBUG("%s %d found %d crtc\n",__FUNCTION__,__LINE__,num_crtc);
Ao Xu70554242020-10-15 15:19:48 +0800695 return 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800696}
697
698static int is_plane_support_yuv(drmModePlane * plane)
699{
700 int i;
701 for (i = 0; i < plane->count_formats; i++) {
702 switch (plane->formats[i]) {
703 case DRM_FORMAT_NV12:
704 case DRM_FORMAT_NV21:
705 return 1;
706 default:
707 return 0;
708 }
709 }
710
711 return 0;
712}
713
714static int populate_planes(drmModeRes *resources, struct kms_display *disp)
715{
Ao Xu70554242020-10-15 15:19:48 +0800716 int i;
Ao Xu6747bbd2020-09-28 20:02:09 +0800717 int num_osd_plane = 0;
718 int num_vid_plane = 0;
719 struct plane_state *state;
720 drmModePlane *plane;
721 drmModePlaneRes *plane_res;
722 drmModeObjectProperties *props;
723
724 plane_res = drmModeGetPlaneResources(disp->base.drm_fd);
Ao Xu70554242020-10-15 15:19:48 +0800725 if (!plane_res) {
chen.wang1d5483452024-02-28 06:18:16 +0000726 ERROR("%s %d drmModeGetPlaneResources fail.\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800727 goto error;
728 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800729
730 for (i = 0; i < plane_res->count_planes; i++) {
731 state = calloc(1, sizeof(*state));
Ao Xu70554242020-10-15 15:19:48 +0800732 if (!state) {
chen.wang1d5483452024-02-28 06:18:16 +0000733 ERROR("%s %d calloc plane state fail.\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800734 goto error;
735 }
736
Ao Xu6747bbd2020-09-28 20:02:09 +0800737 plane = drmModeGetPlane(disp->base.drm_fd, plane_res->planes[i]);
Ao Xu70554242020-10-15 15:19:48 +0800738 if (plane) {
739 if (is_plane_support_yuv(plane))
740 disp->vid_states[num_vid_plane++] = state;
741 else
742 disp->osd_states[num_osd_plane++] = state;
Ao Xu6747bbd2020-09-28 20:02:09 +0800743
Ao Xu70554242020-10-15 15:19:48 +0800744 state->id = plane_res->planes[i];
745 state->crtc_mask = plane->possible_crtcs;
Ao Xu6747bbd2020-09-28 20:02:09 +0800746
Ao Xu70554242020-10-15 15:19:48 +0800747 props = drmModeObjectGetProperties(disp->base.drm_fd, plane_res->planes[i], DRM_MODE_OBJECT_PLANE);
748 if (props) {
749 getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id);
750 getproperty(disp->base.drm_fd, props, "CRTC_X", &state->crtc_x);
751 getproperty(disp->base.drm_fd, props, "CRTC_Y", &state->crtc_y);
752 getproperty(disp->base.drm_fd, props, "CRTC_W", &state->crtc_w);
753 getproperty(disp->base.drm_fd, props, "CRTC_H", &state->crtc_h);
754 getproperty(disp->base.drm_fd, props, "FB_ID", &state->fb_id);
755 getproperty(disp->base.drm_fd, props, "SRC_X", &state->src_x);
756 getproperty(disp->base.drm_fd, props, "SRC_Y", &state->src_y);
757 getproperty(disp->base.drm_fd, props, "SRC_W", &state->src_w);
758 getproperty(disp->base.drm_fd, props, "SRC_H", &state->src_h);
759 getproperty(disp->base.drm_fd, props, "type", &state->type);
760 getproperty(disp->base.drm_fd, props, "IN_FENCE_FD", &state->in_fence_fd);
761 getproperty(disp->base.drm_fd, props, "IN_FORMATS", &state->in_formats);
762 }
763 }
764
765 if (props)
766 drmModeFreeObjectProperties(props);
767
768 if (plane)
769 drmModeFreePlane(plane);
Ao Xu6747bbd2020-09-28 20:02:09 +0800770 }
771
772 disp->num_osd_plane = num_osd_plane;
773 disp->num_vid_plane = num_vid_plane;
774
Ao Xu70554242020-10-15 15:19:48 +0800775 drmModeFreePlaneResources(plane_res);
776
chen.wang1d5483452024-02-28 06:18:16 +0000777 INFO("%s %d found %d osd, %d video\n",__FUNCTION__,__LINE__,num_osd_plane, num_vid_plane);
Ao Xu70554242020-10-15 15:19:48 +0800778 return 0;
779
780error:
781 drmModeFreePlaneResources(plane_res);
782
783 return -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800784}
785
786static int drm_kms_init_resource(struct kms_display *disp)
787{
788 int ret;
limin.tian79bf2b12023-02-24 10:28:26 +0000789 int drm_fd = -1;
790 int render_fd = -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800791 drmModeRes *resources;
792
793 drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
794 if (drm_fd < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000795 ERROR("%s %d Unable to open DRM node: %s\n",__FUNCTION__,__LINE__,
Ao Xu6747bbd2020-09-28 20:02:09 +0800796 strerror(errno));
797 return -1;
798 }
chen.wang1f5503ea2023-04-12 07:36:24 +0000799 drmDropMaster(drm_fd);
wenlong.zhang4c011d42022-06-09 10:59:38 +0800800 render_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
801 if (render_fd < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000802 ERROR("%s %d Unable to open renderD128 node: %s\n",__FUNCTION__,__LINE__,
wenlong.zhang4c011d42022-06-09 10:59:38 +0800803 strerror(errno));
limin.tian79bf2b12023-02-24 10:28:26 +0000804 goto error3;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800805 }
806
Ao Xu6747bbd2020-09-28 20:02:09 +0800807 disp->base.drm_fd = drm_fd;
wenlong.zhang4c011d42022-06-09 10:59:38 +0800808 disp->base.dev = meson_device_create(drm_fd, render_fd);
Ao Xu70554242020-10-15 15:19:48 +0800809 if (!disp->base.dev) {
chen.wang1d5483452024-02-28 06:18:16 +0000810 ERROR("%s %d meson_device_create fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800811 goto error3;
812 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800813
814 ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
815 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000816 ERROR("%s %d Unable to set DRM atomic capability: %s\n",__FUNCTION__,__LINE__,
Ao Xu6747bbd2020-09-28 20:02:09 +0800817 strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800818 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800819 }
820
821 ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
822 if (ret < 0) {
chen.wang1d5483452024-02-28 06:18:16 +0000823 ERROR("%s %d Unable to set DRM universal planes capability: %s\n",__FUNCTION__,__LINE__,
Ao Xu6747bbd2020-09-28 20:02:09 +0800824 strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800825 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800826 }
827
828 resources = drmModeGetResources(drm_fd);
829 if (!resources) {
chen.wang1d5483452024-02-28 06:18:16 +0000830 ERROR("%s %d drmModeGetResources failed: %s\n",__FUNCTION__,__LINE__, strerror(errno));
Ao Xu70554242020-10-15 15:19:48 +0800831 goto error2;
Ao Xu6747bbd2020-09-28 20:02:09 +0800832 }
833
Ao Xu70554242020-10-15 15:19:48 +0800834 ret = populate_connectors(resources, disp);
835 if (ret)
836 goto error1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800837
Ao Xu70554242020-10-15 15:19:48 +0800838 ret = populate_crtcs(resources, disp);
839 if (ret)
840 goto error1;
841
842 ret = populate_planes(resources, disp);
843 if (ret)
844 goto error1;
chen.wang1bace1312023-01-18 16:13:54 +0800845 drmModeFreeResources(resources);
Ao Xu6747bbd2020-09-28 20:02:09 +0800846 return 0;
Ao Xu70554242020-10-15 15:19:48 +0800847
848error1:
849 drmModeFreeResources(resources);
850error2:
851 meson_device_destroy(disp->base.dev);
852error3:
limin.tian79bf2b12023-02-24 10:28:26 +0000853 if (drm_fd >= 0)
854 close(drm_fd);
855 if (render_fd >= 0)
856 close(render_fd);
Ao Xu70554242020-10-15 15:19:48 +0800857
858 return -1;
Ao Xu6747bbd2020-09-28 20:02:09 +0800859}
860
861struct drm_display *drm_kms_init(void)
862{
Ao Xu70554242020-10-15 15:19:48 +0800863 int ret;
Ao Xu6747bbd2020-09-28 20:02:09 +0800864 struct kms_display *display;
865 struct drm_display *base;
866 display = calloc(1, sizeof(*display));
Ao Xu70554242020-10-15 15:19:48 +0800867 if (!display) {
chen.wang1d5483452024-02-28 06:18:16 +0000868 ERROR("%s %d calloc kms_display fail\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800869 return NULL;
870 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800871
872 base = &display->base;
873 base->destroy_display = kms_destroy_display;
874 base->alloc_bufs = kms_alloc_bufs;
875 base->free_bufs = kms_free_bufs;
876
877 base->alloc_buf = kms_alloc_buf;
Ao Xu70554242020-10-15 15:19:48 +0800878 base->import_buf = kms_import_buf;
Ao Xu6747bbd2020-09-28 20:02:09 +0800879 base->free_buf = kms_free_buf;
880 base->post_buf = kms_post_buf;
mingyang.he2ba112a2024-03-25 07:56:58 +0000881 base->set_plane = kms_set_plane;
chen.wang1bace1312023-01-18 16:13:54 +0800882 base->alloc_only = 0;
wenlong.zhang7d32ed92023-04-12 06:08:17 +0000883 base->freeze = 0;
Ao Xu6747bbd2020-09-28 20:02:09 +0800884
Ao Xu70554242020-10-15 15:19:48 +0800885 ret = drm_kms_init_resource(display);
886 if (ret) {
chen.wang1d5483452024-02-28 06:18:16 +0000887 ERROR("%s %d drm_kms_init_resource fail.\n",__FUNCTION__,__LINE__);
Ao Xu70554242020-10-15 15:19:48 +0800888 free(display);
889 return NULL;
890 }
Ao Xu6747bbd2020-09-28 20:02:09 +0800891
892 return base;
893}