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" |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 18 | #include "meson_drm_log.h" |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 19 | |
| 20 | #define MAX_OSD_PLANE 6 |
| 21 | #define MAX_VIDEO_PLANE 4 |
| 22 | #define MAX_CONNECTOR 3 |
| 23 | #define MAX_CRTC 3 |
| 24 | |
| 25 | struct kms_display; |
| 26 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 27 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 28 | #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 | |
| 34 | struct property { |
| 35 | uint32_t id; |
| 36 | uint64_t value; |
| 37 | }; |
| 38 | |
| 39 | struct 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 | |
| 48 | struct connector_state { |
| 49 | uint32_t id; |
| 50 | uint32_t crtc_mask; |
| 51 | drmModeModeInfo mode; |
| 52 | |
| 53 | struct property crtc_id; |
| 54 | }; |
| 55 | |
| 56 | struct 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 70 | struct property type; |
| 71 | struct property in_fence_fd; |
| 72 | struct property in_formats; |
| 73 | }; |
| 74 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 75 | struct kms_display { |
| 76 | struct drm_display base; |
| 77 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 78 | 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 | |
| 90 | static void kms_destroy_display(struct drm_display *drm_disp) |
| 91 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 92 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 93 | struct kms_display *disp = to_kms_display(drm_disp); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 94 | close(drm_disp->drm_fd); |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 95 | close(drm_disp->dev->render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 96 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 118 | free(disp); |
| 119 | } |
| 120 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 121 | static int free_buf(struct drm_display *drm_disp, struct drm_buf *buf) |
| 122 | { |
wenlong.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 123 | int i, fd, ret; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 124 | struct drm_mode_destroy_dumb destroy_dumb; |
| 125 | |
chen.wang1 | 518f14f | 2023-04-12 09:53:10 +0000 | [diff] [blame] | 126 | if (!buf) |
| 127 | return -1; |
| 128 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 129 | for ( i = 0; i < buf->nbo; i++) |
| 130 | close(buf->fd[i]); |
| 131 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 132 | fd = drm_disp->alloc_only ? drm_disp->dev->render_fd : drm_disp->dev->fd; |
wenlong.zhang | 7d32ed9 | 2023-04-12 06:08:17 +0000 | [diff] [blame] | 133 | if (drm_disp->freeze) { |
| 134 | ret = drmIoctl(drm_disp->drm_fd, DRM_IOCTL_MESON_RMFB, &buf->fb_id); |
| 135 | if (ret < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 136 | ERROR("%s %d Unable to rmfb: %s\n",__FUNCTION__,__LINE__, |
wenlong.zhang | 7d32ed9 | 2023-04-12 06:08:17 +0000 | [diff] [blame] | 137 | strerror(errno)); |
| 138 | } |
| 139 | } else { |
| 140 | drmModeRmFB(drm_disp->drm_fd, buf->fb_id); |
| 141 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 142 | memset(&destroy_dumb, 0, sizeof(destroy_dumb)); |
| 143 | |
| 144 | for ( i = 0; i < buf->nbo; i++) { |
chen.wang1 | 518f14f | 2023-04-12 09:53:10 +0000 | [diff] [blame] | 145 | if (!buf->bos[i]) |
| 146 | continue; |
| 147 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 148 | destroy_dumb.handle = meson_bo_handle(buf->bos[i]); |
| 149 | |
wenlong.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 150 | ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 151 | 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.zhang | a71a2e0 | 2022-06-14 15:58:53 +0800 | [diff] [blame] | 158 | ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 159 | if (ret < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 160 | ERROR("%s %d Unable to destroy buffer: %s\n",__FUNCTION__,__LINE__, |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 161 | strerror(errno)); |
| 162 | return -1; |
| 163 | } |
| 164 | } |
| 165 | } |
chen.wang1 | 518f14f | 2023-04-12 09:53:10 +0000 | [diff] [blame] | 166 | free(buf->bos[i]); |
| 167 | buf->bos[i] = NULL; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 168 | } |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 169 | free(buf); |
chen.wang1 | 518f14f | 2023-04-12 09:53:10 +0000 | [diff] [blame] | 170 | buf = NULL; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 171 | return 0; |
| 172 | } |
| 173 | static int kms_free_bufs(struct drm_display *drm_disp) |
| 174 | { |
| 175 | int i; |
| 176 | struct drm_buf *buf; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 177 | for ( i = 0; i < drm_disp->nbuf; i++ ) { |
| 178 | buf = &drm_disp->bufs[i]; |
| 179 | free_buf(drm_disp, buf); |
| 180 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 181 | return 0; |
| 182 | } |
| 183 | |
| 184 | static int kms_free_buf(struct drm_buf *buf) |
| 185 | { |
| 186 | free_buf(buf->disp, buf); |
| 187 | return 0; |
| 188 | } |
| 189 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 190 | static 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.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 197 | 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] | 198 | if (bo) { |
| 199 | *bo_handle = meson_bo_handle(bo); |
| 200 | *pitch = width * bpp / 8; |
| 201 | return bo; |
| 202 | } else { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 203 | ERROR("%s %d meson_bo_create fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 204 | return NULL; |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | static 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 218 | ERROR("%s %d alloc_bo argb888 fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 219 | return -1; |
| 220 | } |
| 221 | |
| 222 | buf->size = width * height * 4; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 223 | 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] | 224 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 230 | ERROR("%s %d alloc_bo yuyv or uyvy fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 231 | return -1; |
| 232 | } |
| 233 | |
| 234 | buf->size = width * height * 2; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 235 | 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] | 236 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 243 | ERROR("%s %d alloc_bo nv12 or nv21 fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 244 | return -1; |
| 245 | } |
| 246 | |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 247 | 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] | 248 | |
| 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 251 | ERROR("%s %d alloc_bo argb888 fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 252 | return -1; |
| 253 | } |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 254 | 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] | 255 | buf->size = width * height * 3 / 2; |
| 256 | buf->commit_to_video = 1; |
| 257 | break; |
| 258 | default: |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 259 | ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__,buf->fourcc); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 260 | break; |
| 261 | } |
| 262 | |
| 263 | return 0; |
| 264 | } |
| 265 | |
| 266 | static 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 283 | ERROR("%s %d Unable to add framebuffer for plane: %s\n",__FUNCTION__,__LINE__, strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 284 | return -1; |
| 285 | } |
| 286 | |
| 287 | buf->fb_id = fb_id; |
| 288 | return 0; |
| 289 | } |
| 290 | |
| 291 | static 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.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 303 | buf->disable_plane = 0; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 304 | buf->disp = drm_disp; |
| 305 | |
| 306 | ret = alloc_bos(drm_disp, buf, bo_handles); |
| 307 | if (ret) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 308 | ERROR("%s %d alloc_bos fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 309 | free(buf); |
| 310 | return NULL; |
| 311 | } |
| 312 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 313 | /*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.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 316 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 317 | ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE); |
| 318 | if (ret) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 319 | ERROR("%s %d add_framebuffer fail, call free_buf\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 320 | free_buf(drm_disp, buf); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 321 | return NULL; |
| 322 | } |
| 323 | |
| 324 | return buf; |
| 325 | } |
| 326 | |
| 327 | static 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.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 343 | buf->disable_plane = 0; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 344 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 362 | ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__, buf->fourcc); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 363 | break; |
| 364 | } |
| 365 | |
| 366 | ret = alloc_bos(drm_disp, buf, bo_handles); |
| 367 | if (ret) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 368 | ERROR("%s %d alloc_bos fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 369 | return -1; |
| 370 | } |
| 371 | |
| 372 | ret = add_framebuffer(drm_disp->drm_fd, buf, bo_handles, DRM_FORMAT_MOD_NONE); |
| 373 | if (ret) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 374 | ERROR("%s %d add_framebuffer fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 375 | free_buf(drm_disp, buf); |
| 376 | return -1; |
| 377 | } |
| 378 | } |
| 379 | return 0; |
| 380 | } |
| 381 | |
| 382 | static 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.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 395 | buf->disable_plane = 0; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 396 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 414 | ERROR("%s %d unsupport format: 0x%08x\n",__FUNCTION__,__LINE__,buf->fourcc); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 415 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 429 | ERROR("%s %d meson_bo_import fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 430 | 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.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 441 | static 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.he | 2ba112a | 2024-03-25 07:56:58 +0000 | [diff] [blame^] | 472 | if (!drmIsMaster(drm_disp->drm_fd)) |
| 473 | drmSetMaster(drm_disp->drm_fd); |
| 474 | |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 475 | 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.he | 2ba112a | 2024-03-25 07:56:58 +0000 | [diff] [blame^] | 478 | ERROR("failed to set plane: %s\n", strerror(errno)); |
| 479 | drmDropMaster(drm_disp->drm_fd); |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 480 | return -1; |
| 481 | } |
mingyang.he | 2ba112a | 2024-03-25 07:56:58 +0000 | [diff] [blame^] | 482 | drmDropMaster(drm_disp->drm_fd); |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 483 | |
| 484 | return ret; |
| 485 | } |
| 486 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 487 | static int kms_post_buf(struct drm_display *drm_disp, struct drm_buf *buf) |
| 488 | { |
| 489 | int ret; |
| 490 | drmModeAtomicReqPtr request; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 491 | 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 zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 501 | if (buf->flags & MESON_USE_VD1) |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 502 | plane_state = disp->vid_states[0]; |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 503 | else if (buf->flags & MESON_USE_VD2) |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 504 | plane_state = disp->vid_states[1]; |
| 505 | else |
| 506 | plane_state = disp->osd_states[0]; |
| 507 | |
| 508 | request = drmModeAtomicAlloc(); |
| 509 | |
wenlong.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 510 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 526 | |
wenlong.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 527 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 535 | } |
wenlong.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 536 | #else |
| 537 | /*No modeset needed in post buf, modeset will control by systemservice.*/ |
| 538 | #endif |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 539 | |
wenlong.zhang | cf8a546 | 2023-04-10 03:25:19 +0000 | [diff] [blame] | 540 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 566 | } |
sky zhou | f05ca46 | 2020-10-29 18:07:40 +0800 | [diff] [blame] | 567 | |
| 568 | ret = drmModeAsyncAtomicCommit(drm_disp->drm_fd, request, flags, NULL); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 569 | if (ret < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 570 | ERROR("%s %d Unable to flip page: %s\n",__FUNCTION__,__LINE__,strerror(errno)); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 571 | goto error; |
| 572 | } |
| 573 | |
| 574 | ret = 0; |
| 575 | goto complete; |
| 576 | |
| 577 | error: |
| 578 | ret = -1; |
| 579 | complete: |
| 580 | drmModeAtomicFree(request); |
| 581 | |
| 582 | return ret; |
| 583 | } |
| 584 | |
| 585 | static 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 592 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 597 | drmModeFreeProperty(res); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 598 | } |
| 599 | } |
| 600 | |
| 601 | static int populate_connectors(drmModeRes *resources, struct kms_display *disp) |
| 602 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 603 | int i, j; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 604 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 612 | if (!connector) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 613 | ERROR("%s %d drmModeGetConnector fail.\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 614 | continue; |
| 615 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 616 | |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 617 | if (connector->connector_type == DRM_MODE_CONNECTOR_TV) { |
| 618 | drmModeFreeConnector(connector); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 619 | continue; |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 620 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 621 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 627 | if (encoder) { |
| 628 | state->crtc_mask |= encoder->possible_crtcs; |
| 629 | drmModeFreeEncoder(encoder); |
| 630 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 631 | } |
| 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 648 | getproperty(disp->base.drm_fd, props, "CRTC_ID", &state->crtc_id); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 649 | |
| 650 | if (props) |
| 651 | drmModeFreeObjectProperties(props); |
| 652 | |
| 653 | if (connector) |
| 654 | drmModeFreeConnector(connector); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | disp->num_connector = num_connector; |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 658 | INFO("%s %d found %d connector\n",__FUNCTION__,__LINE__,num_connector); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 659 | return 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 660 | } |
| 661 | |
| 662 | static int populate_crtcs(drmModeRes *resources, struct kms_display *disp) |
| 663 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 664 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 665 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 671 | if (!state) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 672 | ERROR("%s %d calloc crtc state fail.\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 673 | return -1; |
| 674 | } |
| 675 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 676 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 680 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 685 | drmModeFreeObjectProperties(props); |
| 686 | } else { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 687 | ERROR("%s %d get crtc obj property fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 688 | return -1; |
| 689 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 690 | } |
| 691 | |
| 692 | disp->num_crtc = num_crtc; |
| 693 | |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 694 | DEBUG("%s %d found %d crtc\n",__FUNCTION__,__LINE__,num_crtc); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 695 | return 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 696 | } |
| 697 | |
| 698 | static 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 | |
| 714 | static int populate_planes(drmModeRes *resources, struct kms_display *disp) |
| 715 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 716 | int i; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 717 | 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 725 | if (!plane_res) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 726 | ERROR("%s %d drmModeGetPlaneResources fail.\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 727 | goto error; |
| 728 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 729 | |
| 730 | for (i = 0; i < plane_res->count_planes; i++) { |
| 731 | state = calloc(1, sizeof(*state)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 732 | if (!state) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 733 | ERROR("%s %d calloc plane state fail.\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 734 | goto error; |
| 735 | } |
| 736 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 737 | plane = drmModeGetPlane(disp->base.drm_fd, plane_res->planes[i]); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 738 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 743 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 744 | state->id = plane_res->planes[i]; |
| 745 | state->crtc_mask = plane->possible_crtcs; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 746 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 747 | 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 Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 770 | } |
| 771 | |
| 772 | disp->num_osd_plane = num_osd_plane; |
| 773 | disp->num_vid_plane = num_vid_plane; |
| 774 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 775 | drmModeFreePlaneResources(plane_res); |
| 776 | |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 777 | INFO("%s %d found %d osd, %d video\n",__FUNCTION__,__LINE__,num_osd_plane, num_vid_plane); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 778 | return 0; |
| 779 | |
| 780 | error: |
| 781 | drmModeFreePlaneResources(plane_res); |
| 782 | |
| 783 | return -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 784 | } |
| 785 | |
| 786 | static int drm_kms_init_resource(struct kms_display *disp) |
| 787 | { |
| 788 | int ret; |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 789 | int drm_fd = -1; |
| 790 | int render_fd = -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 791 | drmModeRes *resources; |
| 792 | |
| 793 | drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); |
| 794 | if (drm_fd < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 795 | ERROR("%s %d Unable to open DRM node: %s\n",__FUNCTION__,__LINE__, |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 796 | strerror(errno)); |
| 797 | return -1; |
| 798 | } |
chen.wang1 | f5503ea | 2023-04-12 07:36:24 +0000 | [diff] [blame] | 799 | drmDropMaster(drm_fd); |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 800 | render_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC); |
| 801 | if (render_fd < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 802 | ERROR("%s %d Unable to open renderD128 node: %s\n",__FUNCTION__,__LINE__, |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 803 | strerror(errno)); |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 804 | goto error3; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 805 | } |
| 806 | |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 807 | disp->base.drm_fd = drm_fd; |
wenlong.zhang | 4c011d4 | 2022-06-09 10:59:38 +0800 | [diff] [blame] | 808 | disp->base.dev = meson_device_create(drm_fd, render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 809 | if (!disp->base.dev) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 810 | ERROR("%s %d meson_device_create fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 811 | goto error3; |
| 812 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 813 | |
| 814 | ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1); |
| 815 | if (ret < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 816 | ERROR("%s %d Unable to set DRM atomic capability: %s\n",__FUNCTION__,__LINE__, |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 817 | strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 818 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 819 | } |
| 820 | |
| 821 | ret = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); |
| 822 | if (ret < 0) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 823 | ERROR("%s %d Unable to set DRM universal planes capability: %s\n",__FUNCTION__,__LINE__, |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 824 | strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 825 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 826 | } |
| 827 | |
| 828 | resources = drmModeGetResources(drm_fd); |
| 829 | if (!resources) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 830 | ERROR("%s %d drmModeGetResources failed: %s\n",__FUNCTION__,__LINE__, strerror(errno)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 831 | goto error2; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 832 | } |
| 833 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 834 | ret = populate_connectors(resources, disp); |
| 835 | if (ret) |
| 836 | goto error1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 837 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 838 | 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.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 845 | drmModeFreeResources(resources); |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 846 | return 0; |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 847 | |
| 848 | error1: |
| 849 | drmModeFreeResources(resources); |
| 850 | error2: |
| 851 | meson_device_destroy(disp->base.dev); |
| 852 | error3: |
limin.tian | 79bf2b1 | 2023-02-24 10:28:26 +0000 | [diff] [blame] | 853 | if (drm_fd >= 0) |
| 854 | close(drm_fd); |
| 855 | if (render_fd >= 0) |
| 856 | close(render_fd); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 857 | |
| 858 | return -1; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 859 | } |
| 860 | |
| 861 | struct drm_display *drm_kms_init(void) |
| 862 | { |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 863 | int ret; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 864 | struct kms_display *display; |
| 865 | struct drm_display *base; |
| 866 | display = calloc(1, sizeof(*display)); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 867 | if (!display) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 868 | ERROR("%s %d calloc kms_display fail\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 869 | return NULL; |
| 870 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 871 | |
| 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 Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 878 | base->import_buf = kms_import_buf; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 879 | base->free_buf = kms_free_buf; |
| 880 | base->post_buf = kms_post_buf; |
mingyang.he | 2ba112a | 2024-03-25 07:56:58 +0000 | [diff] [blame^] | 881 | base->set_plane = kms_set_plane; |
chen.wang1 | bace131 | 2023-01-18 16:13:54 +0800 | [diff] [blame] | 882 | base->alloc_only = 0; |
wenlong.zhang | 7d32ed9 | 2023-04-12 06:08:17 +0000 | [diff] [blame] | 883 | base->freeze = 0; |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 884 | |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 885 | ret = drm_kms_init_resource(display); |
| 886 | if (ret) { |
chen.wang1 | d548345 | 2024-02-28 06:18:16 +0000 | [diff] [blame] | 887 | ERROR("%s %d drm_kms_init_resource fail.\n",__FUNCTION__,__LINE__); |
Ao Xu | 7055424 | 2020-10-15 15:19:48 +0800 | [diff] [blame] | 888 | free(display); |
| 889 | return NULL; |
| 890 | } |
Ao Xu | 6747bbd | 2020-09-28 20:02:09 +0800 | [diff] [blame] | 891 | |
| 892 | return base; |
| 893 | } |