1*4882a593SmuzhiyunFrom bbe6d49bdcb7b6a53044f494e31a90f4eed65b0e Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: ZiHan Huang <zack.huang@rock-chips.com> 3*4882a593SmuzhiyunDate: Fri, 6 Jan 2023 10:17:22 +0800 4*4882a593SmuzhiyunSubject: [PATCH 6/8] drm: Reconstructs the drm display driver 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunSigned-off-by: ZiHan Huang <zack.huang@rock-chips.com> 7*4882a593Smuzhiyun--- 8*4882a593Smuzhiyun display/drm.c | 1488 +++++++++++++++++++++++++++---------------------- 9*4882a593Smuzhiyun display/drm.h | 7 +- 10*4882a593Smuzhiyun 2 files changed, 832 insertions(+), 663 deletions(-) 11*4882a593Smuzhiyun 12*4882a593Smuzhiyundiff --git a/display/drm.c b/display/drm.c 13*4882a593Smuzhiyunindex 9cec6e3..17af072 100644 14*4882a593Smuzhiyun--- a/display/drm.c 15*4882a593Smuzhiyun+++ b/display/drm.c 16*4882a593Smuzhiyun@@ -22,780 +22,950 @@ 17*4882a593Smuzhiyun #include <errno.h> 18*4882a593Smuzhiyun #include <sys/mman.h> 19*4882a593Smuzhiyun #include <inttypes.h> 20*4882a593Smuzhiyun+#include <poll.h> 21*4882a593Smuzhiyun+#include <malloc.h> 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun+#include <drm_fourcc.h> 24*4882a593Smuzhiyun+#include <drm_mode.h> 25*4882a593Smuzhiyun+#include <lvgl/lvgl.h> 26*4882a593Smuzhiyun #include <xf86drm.h> 27*4882a593Smuzhiyun #include <xf86drmMode.h> 28*4882a593Smuzhiyun-#include <drm_fourcc.h> 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun #define DBG_TAG "drm" 31*4882a593Smuzhiyun+#define NUM_DUMB_BO 3 32*4882a593Smuzhiyun+#define VIDEO_PLANE_ENABLE 1 33*4882a593Smuzhiyun+#define DEBUG 34*4882a593Smuzhiyun+#ifdef DEBUG 35*4882a593Smuzhiyun+#define DRM_DEBUG(fmt, ...) \ 36*4882a593Smuzhiyun+ if (getenv("MJPG_DRM_DEBUG")) \ 37*4882a593Smuzhiyun+ printf("DRM_DEBUG: %s(%d) " fmt, __func__, __LINE__, ##__VA_ARGS__) 38*4882a593Smuzhiyun+#else 39*4882a593Smuzhiyun+#define DRM_DEBUG(fmt, ...) 40*4882a593Smuzhiyun+#endif 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 43*4882a593Smuzhiyun- 44*4882a593Smuzhiyun-#define print(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__); 45*4882a593Smuzhiyun-#define err(msg, ...) print("error: " msg "\n", ##__VA_ARGS__) 46*4882a593Smuzhiyun-#define info(msg, ...) print(msg "\n", ##__VA_ARGS__) 47*4882a593Smuzhiyun-#define dbg(msg, ...) {} //print(DBG_TAG ": " msg "\n", ##__VA_ARGS__) 48*4882a593Smuzhiyun- 49*4882a593Smuzhiyun-struct drm_buffer { 50*4882a593Smuzhiyun- uint32_t handle; 51*4882a593Smuzhiyun- uint32_t pitch; 52*4882a593Smuzhiyun- uint32_t offset; 53*4882a593Smuzhiyun- unsigned long int size; 54*4882a593Smuzhiyun- void * map; 55*4882a593Smuzhiyun- uint32_t fb_handle; 56*4882a593Smuzhiyun+#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1)) 57*4882a593Smuzhiyun+ 58*4882a593Smuzhiyun+struct drm_bo { 59*4882a593Smuzhiyun+ int fd; 60*4882a593Smuzhiyun+ void *ptr; 61*4882a593Smuzhiyun+ size_t size; 62*4882a593Smuzhiyun+ size_t offset; 63*4882a593Smuzhiyun+ size_t pitch; 64*4882a593Smuzhiyun+ unsigned int handle; 65*4882a593Smuzhiyun+ int fb_id; 66*4882a593Smuzhiyun+ int buf_fd; 67*4882a593Smuzhiyun+ int w; 68*4882a593Smuzhiyun+ int h; 69*4882a593Smuzhiyun }; 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun-struct drm_dev { 72*4882a593Smuzhiyun- int fd; 73*4882a593Smuzhiyun- uint32_t conn_id, enc_id, crtc_id, plane_id, crtc_idx; 74*4882a593Smuzhiyun- uint32_t width, height; 75*4882a593Smuzhiyun- uint32_t mmWidth, mmHeight; 76*4882a593Smuzhiyun- uint32_t fourcc; 77*4882a593Smuzhiyun- drmModeModeInfo mode; 78*4882a593Smuzhiyun- uint32_t blob_id; 79*4882a593Smuzhiyun- drmModeCrtc *saved_crtc; 80*4882a593Smuzhiyun- drmModeAtomicReq *req; 81*4882a593Smuzhiyun- drmEventContext drm_event_ctx; 82*4882a593Smuzhiyun- drmModePlane *plane; 83*4882a593Smuzhiyun- drmModeCrtc *crtc; 84*4882a593Smuzhiyun- drmModeConnector *conn; 85*4882a593Smuzhiyun- uint32_t count_plane_props; 86*4882a593Smuzhiyun- uint32_t count_crtc_props; 87*4882a593Smuzhiyun- uint32_t count_conn_props; 88*4882a593Smuzhiyun- drmModePropertyPtr plane_props[128]; 89*4882a593Smuzhiyun- drmModePropertyPtr crtc_props[128]; 90*4882a593Smuzhiyun- drmModePropertyPtr conn_props[128]; 91*4882a593Smuzhiyun- struct drm_buffer drm_bufs[2]; /* DUMB buffers */ 92*4882a593Smuzhiyun- struct drm_buffer *cur_bufs[2]; /* double buffering handling */ 93*4882a593Smuzhiyun-} drm_dev; 94*4882a593Smuzhiyun+struct device { 95*4882a593Smuzhiyun+ int fd; 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun-static uint32_t get_plane_property_id(const char *name) 98*4882a593Smuzhiyun-{ 99*4882a593Smuzhiyun- uint32_t i; 100*4882a593Smuzhiyun+ struct { 101*4882a593Smuzhiyun+ int width; 102*4882a593Smuzhiyun+ int height; 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun- dbg("Find plane property: %s", name); 105*4882a593Smuzhiyun+ int hdisplay; 106*4882a593Smuzhiyun+ int vdisplay; 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun- for (i = 0; i < drm_dev.count_plane_props; ++i) 109*4882a593Smuzhiyun- if (!strcmp(drm_dev.plane_props[i]->name, name)) 110*4882a593Smuzhiyun- return drm_dev.plane_props[i]->prop_id; 111*4882a593Smuzhiyun+ int current; 112*4882a593Smuzhiyun+ int fb_num; 113*4882a593Smuzhiyun+ int bpp; 114*4882a593Smuzhiyun+ } mode; 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun- dbg("Unknown plane property: %s", name); 117*4882a593Smuzhiyun+ drmModeResPtr res; 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun- return 0; 120*4882a593Smuzhiyun-} 121*4882a593Smuzhiyun+ int connector_id; 122*4882a593Smuzhiyun+ int encoder_id; 123*4882a593Smuzhiyun+ int crtc_id; 124*4882a593Smuzhiyun+ int plane_id; 125*4882a593Smuzhiyun+ int last_fb_id; 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun-static uint32_t get_crtc_property_id(const char *name) 128*4882a593Smuzhiyun-{ 129*4882a593Smuzhiyun- uint32_t i; 130*4882a593Smuzhiyun+ int waiting_for_flip; 131*4882a593Smuzhiyun+ struct pollfd drm_pollfd; 132*4882a593Smuzhiyun+ drmEventContext drm_evctx; 133*4882a593Smuzhiyun+}; 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun- dbg("Find crtc property: %s", name); 136*4882a593Smuzhiyun+static int lcd_w; 137*4882a593Smuzhiyun+static int lcd_h; 138*4882a593Smuzhiyun+static int lcd_sw; 139*4882a593Smuzhiyun+static char* drm_buff; 140*4882a593Smuzhiyun+static lv_color_t *buf_1; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun- for (i = 0; i < drm_dev.count_crtc_props; ++i) 143*4882a593Smuzhiyun- if (!strcmp(drm_dev.crtc_props[i]->name, name)) 144*4882a593Smuzhiyun- return drm_dev.crtc_props[i]->prop_id; 145*4882a593Smuzhiyun+static int quit = 0; 146*4882a593Smuzhiyun+static pthread_t drm_thread_pid; 147*4882a593Smuzhiyun+static pthread_mutex_t draw_mutex; 148*4882a593Smuzhiyun+static int draw_update = 0; 149*4882a593Smuzhiyun+static struct drm_bo *gbo; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun- dbg("Unknown crtc property: %s", name); 152*4882a593Smuzhiyun+struct device *pdev; 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun- return 0; 155*4882a593Smuzhiyun+static int bo_map(struct device *dev, struct drm_bo *bo) 156*4882a593Smuzhiyun+{ 157*4882a593Smuzhiyun+ struct drm_mode_map_dumb arg = { 158*4882a593Smuzhiyun+ .handle = bo->handle, 159*4882a593Smuzhiyun+ }; 160*4882a593Smuzhiyun+ struct drm_prime_handle fd_args = { 161*4882a593Smuzhiyun+ .fd = -1, 162*4882a593Smuzhiyun+ .handle = bo->handle, 163*4882a593Smuzhiyun+ .flags = 0, 164*4882a593Smuzhiyun+ }; 165*4882a593Smuzhiyun+ int ret; 166*4882a593Smuzhiyun+ 167*4882a593Smuzhiyun+ ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); 168*4882a593Smuzhiyun+ if (ret) 169*4882a593Smuzhiyun+ return ret; 170*4882a593Smuzhiyun+ 171*4882a593Smuzhiyun+ ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); 172*4882a593Smuzhiyun+ if (ret) 173*4882a593Smuzhiyun+ { 174*4882a593Smuzhiyun+ printf("handle_to_fd failed ret=%d, handle=%x \n", ret ,fd_args.handle); 175*4882a593Smuzhiyun+ return -1; 176*4882a593Smuzhiyun+ } 177*4882a593Smuzhiyun+ bo->buf_fd = fd_args.fd; 178*4882a593Smuzhiyun+ 179*4882a593Smuzhiyun+ bo->ptr = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 180*4882a593Smuzhiyun+ dev->fd, arg.offset); 181*4882a593Smuzhiyun+ if (bo->ptr == MAP_FAILED) { 182*4882a593Smuzhiyun+ bo->ptr = NULL; 183*4882a593Smuzhiyun+ return -1; 184*4882a593Smuzhiyun+ } 185*4882a593Smuzhiyun+ 186*4882a593Smuzhiyun+ return 0; 187*4882a593Smuzhiyun } 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun-static uint32_t get_conn_property_id(const char *name) 190*4882a593Smuzhiyun+static void bo_unmap(struct device *dev, struct drm_bo *bo) 191*4882a593Smuzhiyun { 192*4882a593Smuzhiyun- uint32_t i; 193*4882a593Smuzhiyun+ if (dev == NULL) 194*4882a593Smuzhiyun+ return; 195*4882a593Smuzhiyun+ if (!bo->ptr) 196*4882a593Smuzhiyun+ return; 197*4882a593Smuzhiyun+ 198*4882a593Smuzhiyun+ drmUnmap(bo->ptr, bo->size); 199*4882a593Smuzhiyun+ if (bo->buf_fd > 0) 200*4882a593Smuzhiyun+ close(bo->buf_fd); 201*4882a593Smuzhiyun+ bo->ptr = NULL; 202*4882a593Smuzhiyun+} 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun- dbg("Find conn property: %s", name); 205*4882a593Smuzhiyun+void bo_destroy(struct device *dev, struct drm_bo *bo) 206*4882a593Smuzhiyun+{ 207*4882a593Smuzhiyun+ struct drm_mode_destroy_dumb arg = { 208*4882a593Smuzhiyun+ .handle = bo->handle, 209*4882a593Smuzhiyun+ }; 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun- for (i = 0; i < drm_dev.count_conn_props; ++i) 212*4882a593Smuzhiyun- if (!strcmp(drm_dev.conn_props[i]->name, name)) 213*4882a593Smuzhiyun- return drm_dev.conn_props[i]->prop_id; 214*4882a593Smuzhiyun+ if (bo->fb_id) 215*4882a593Smuzhiyun+ drmModeRmFB(dev->fd, bo->fb_id); 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun- dbg("Unknown conn property: %s", name); 218*4882a593Smuzhiyun+ bo_unmap(dev, bo); 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun- return 0; 221*4882a593Smuzhiyun-} 222*4882a593Smuzhiyun+ if (bo->handle) 223*4882a593Smuzhiyun+ drmIoctl(dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun-static void page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, 226*4882a593Smuzhiyun- unsigned int tv_usec, void *user_data) 227*4882a593Smuzhiyun-{ 228*4882a593Smuzhiyun- dbg("flip"); 229*4882a593Smuzhiyun+ free(bo); 230*4882a593Smuzhiyun } 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun-static int drm_get_plane_props(void) 233*4882a593Smuzhiyun+static struct drm_bo * 234*4882a593Smuzhiyun+bo_create(struct device *dev, int width, int height, int format) 235*4882a593Smuzhiyun { 236*4882a593Smuzhiyun- uint32_t i; 237*4882a593Smuzhiyun- 238*4882a593Smuzhiyun- drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev.fd, drm_dev.plane_id, 239*4882a593Smuzhiyun- DRM_MODE_OBJECT_PLANE); 240*4882a593Smuzhiyun- if (!props) { 241*4882a593Smuzhiyun- err("drmModeObjectGetProperties failed"); 242*4882a593Smuzhiyun- return -1; 243*4882a593Smuzhiyun- } 244*4882a593Smuzhiyun- dbg("Found %u plane props", props->count_props); 245*4882a593Smuzhiyun- drm_dev.count_plane_props = props->count_props; 246*4882a593Smuzhiyun- for (i = 0; i < props->count_props; i++) { 247*4882a593Smuzhiyun- drm_dev.plane_props[i] = drmModeGetProperty(drm_dev.fd, props->props[i]); 248*4882a593Smuzhiyun- dbg("Added plane prop %u:%s", drm_dev.plane_props[i]->prop_id, drm_dev.plane_props[i]->name); 249*4882a593Smuzhiyun- } 250*4882a593Smuzhiyun- drmModeFreeObjectProperties(props); 251*4882a593Smuzhiyun- 252*4882a593Smuzhiyun- return 0; 253*4882a593Smuzhiyun+ struct drm_mode_create_dumb arg = { 254*4882a593Smuzhiyun+ .bpp = 32, 255*4882a593Smuzhiyun+ .width = ALIGN(width, 16), 256*4882a593Smuzhiyun+ .height = ALIGN(height, 16), 257*4882a593Smuzhiyun+ }; 258*4882a593Smuzhiyun+ struct drm_bo *bo; 259*4882a593Smuzhiyun+ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; 260*4882a593Smuzhiyun+ int ret; 261*4882a593Smuzhiyun+ 262*4882a593Smuzhiyun+ bo = malloc(sizeof(struct drm_bo)); 263*4882a593Smuzhiyun+ if (bo == NULL) { 264*4882a593Smuzhiyun+ fprintf(stderr, "allocate bo failed\n"); 265*4882a593Smuzhiyun+ return NULL; 266*4882a593Smuzhiyun+ } 267*4882a593Smuzhiyun+ memset(bo, 0, sizeof(*bo)); 268*4882a593Smuzhiyun+ if (format == DRM_FORMAT_NV12) { 269*4882a593Smuzhiyun+ arg.bpp = 8; 270*4882a593Smuzhiyun+ arg.height = height * 3 / 2; 271*4882a593Smuzhiyun+ } 272*4882a593Smuzhiyun+ 273*4882a593Smuzhiyun+ ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg); 274*4882a593Smuzhiyun+ if (ret) { 275*4882a593Smuzhiyun+ fprintf(stderr, "create dumb failed\n"); 276*4882a593Smuzhiyun+ goto err; 277*4882a593Smuzhiyun+ } 278*4882a593Smuzhiyun+ 279*4882a593Smuzhiyun+ bo->fd = dev->fd; 280*4882a593Smuzhiyun+ bo->handle = arg.handle; 281*4882a593Smuzhiyun+ bo->size = arg.size; 282*4882a593Smuzhiyun+ bo->pitch = arg.pitch; 283*4882a593Smuzhiyun+ bo->w = width; 284*4882a593Smuzhiyun+ bo->h = height; 285*4882a593Smuzhiyun+ 286*4882a593Smuzhiyun+ ret = bo_map(dev, bo); 287*4882a593Smuzhiyun+ if (ret) { 288*4882a593Smuzhiyun+ fprintf(stderr, "map bo failed\n"); 289*4882a593Smuzhiyun+ goto err; 290*4882a593Smuzhiyun+ } 291*4882a593Smuzhiyun+ 292*4882a593Smuzhiyun+ switch (format) { 293*4882a593Smuzhiyun+ case DRM_FORMAT_NV12: 294*4882a593Smuzhiyun+ case DRM_FORMAT_NV16: 295*4882a593Smuzhiyun+ handles[0] = bo->handle; 296*4882a593Smuzhiyun+ pitches[0] = bo->pitch ; 297*4882a593Smuzhiyun+ offsets[0] = 0; 298*4882a593Smuzhiyun+ handles[1] = bo->handle; 299*4882a593Smuzhiyun+ pitches[1] = pitches[0]; 300*4882a593Smuzhiyun+ offsets[1] = pitches[0] * height; 301*4882a593Smuzhiyun+ break; 302*4882a593Smuzhiyun+ case DRM_FORMAT_RGB332: 303*4882a593Smuzhiyun+ handles[0] = bo->handle; 304*4882a593Smuzhiyun+ pitches[0] = bo->pitch; 305*4882a593Smuzhiyun+ offsets[0] = 0; 306*4882a593Smuzhiyun+ break; 307*4882a593Smuzhiyun+ case DRM_FORMAT_RGB565: 308*4882a593Smuzhiyun+ case DRM_FORMAT_BGR565: 309*4882a593Smuzhiyun+ handles[0] = bo->handle; 310*4882a593Smuzhiyun+ pitches[0] = bo->pitch ; 311*4882a593Smuzhiyun+ offsets[0] = 0; 312*4882a593Smuzhiyun+ break; 313*4882a593Smuzhiyun+ case DRM_FORMAT_RGB888: 314*4882a593Smuzhiyun+ case DRM_FORMAT_BGR888: 315*4882a593Smuzhiyun+ handles[0] = bo->handle; 316*4882a593Smuzhiyun+ pitches[0] = bo->pitch ; 317*4882a593Smuzhiyun+ offsets[0] = 0; 318*4882a593Smuzhiyun+ break; 319*4882a593Smuzhiyun+ case DRM_FORMAT_ARGB8888: 320*4882a593Smuzhiyun+ case DRM_FORMAT_ABGR8888: 321*4882a593Smuzhiyun+ case DRM_FORMAT_RGBA8888: 322*4882a593Smuzhiyun+ case DRM_FORMAT_BGRA8888: 323*4882a593Smuzhiyun+ handles[0] = bo->handle; 324*4882a593Smuzhiyun+ pitches[0] = bo->pitch ; 325*4882a593Smuzhiyun+ offsets[0] = 0; 326*4882a593Smuzhiyun+ break; 327*4882a593Smuzhiyun+ } 328*4882a593Smuzhiyun+ 329*4882a593Smuzhiyun+ ret = drmModeAddFB2(dev->fd, width, height, format, handles, 330*4882a593Smuzhiyun+ pitches, offsets, (uint32_t *)&bo->fb_id, 0); 331*4882a593Smuzhiyun+ if (ret) { 332*4882a593Smuzhiyun+ fprintf(stderr, "add fb failed\n"); 333*4882a593Smuzhiyun+ goto err; 334*4882a593Smuzhiyun+ } 335*4882a593Smuzhiyun+ DRM_DEBUG("Created bo: %d, %dx%d\n", bo->fb_id, width, height); 336*4882a593Smuzhiyun+ 337*4882a593Smuzhiyun+ return bo; 338*4882a593Smuzhiyun+err: 339*4882a593Smuzhiyun+ bo_destroy(dev, bo); 340*4882a593Smuzhiyun+ return NULL; 341*4882a593Smuzhiyun } 342*4882a593Smuzhiyun 343*4882a593Smuzhiyun-static int drm_get_crtc_props(void) 344*4882a593Smuzhiyun+struct drm_bo *malloc_drm_bo(int width, int height, int format) 345*4882a593Smuzhiyun { 346*4882a593Smuzhiyun- uint32_t i; 347*4882a593Smuzhiyun- 348*4882a593Smuzhiyun- drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev.fd, drm_dev.crtc_id, 349*4882a593Smuzhiyun- DRM_MODE_OBJECT_CRTC); 350*4882a593Smuzhiyun- if (!props) { 351*4882a593Smuzhiyun- err("drmModeObjectGetProperties failed"); 352*4882a593Smuzhiyun- return -1; 353*4882a593Smuzhiyun- } 354*4882a593Smuzhiyun- dbg("Found %u crtc props", props->count_props); 355*4882a593Smuzhiyun- drm_dev.count_crtc_props = props->count_props; 356*4882a593Smuzhiyun- for (i = 0; i < props->count_props; i++) { 357*4882a593Smuzhiyun- drm_dev.crtc_props[i] = drmModeGetProperty(drm_dev.fd, props->props[i]); 358*4882a593Smuzhiyun- dbg("Added crtc prop %u:%s", drm_dev.crtc_props[i]->prop_id, drm_dev.crtc_props[i]->name); 359*4882a593Smuzhiyun- } 360*4882a593Smuzhiyun- drmModeFreeObjectProperties(props); 361*4882a593Smuzhiyun- 362*4882a593Smuzhiyun- return 0; 363*4882a593Smuzhiyun+ struct device *dev = pdev; 364*4882a593Smuzhiyun+ return bo_create(dev, width, height, format); 365*4882a593Smuzhiyun } 366*4882a593Smuzhiyun 367*4882a593Smuzhiyun-static int drm_get_conn_props(void) 368*4882a593Smuzhiyun+void free_drm_bo(struct drm_bo *bo) 369*4882a593Smuzhiyun { 370*4882a593Smuzhiyun- uint32_t i; 371*4882a593Smuzhiyun- 372*4882a593Smuzhiyun- drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev.fd, drm_dev.conn_id, 373*4882a593Smuzhiyun- DRM_MODE_OBJECT_CONNECTOR); 374*4882a593Smuzhiyun- if (!props) { 375*4882a593Smuzhiyun- err("drmModeObjectGetProperties failed"); 376*4882a593Smuzhiyun- return -1; 377*4882a593Smuzhiyun- } 378*4882a593Smuzhiyun- dbg("Found %u connector props", props->count_props); 379*4882a593Smuzhiyun- drm_dev.count_conn_props = props->count_props; 380*4882a593Smuzhiyun- for (i = 0; i < props->count_props; i++) { 381*4882a593Smuzhiyun- drm_dev.conn_props[i] = drmModeGetProperty(drm_dev.fd, props->props[i]); 382*4882a593Smuzhiyun- dbg("Added connector prop %u:%s", drm_dev.conn_props[i]->prop_id, drm_dev.conn_props[i]->name); 383*4882a593Smuzhiyun- } 384*4882a593Smuzhiyun- drmModeFreeObjectProperties(props); 385*4882a593Smuzhiyun- 386*4882a593Smuzhiyun- return 0; 387*4882a593Smuzhiyun+ struct device *dev = pdev; 388*4882a593Smuzhiyun+ if (bo) 389*4882a593Smuzhiyun+ bo_destroy(dev, bo); 390*4882a593Smuzhiyun } 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun-static int drm_add_plane_property(const char *name, uint64_t value) 393*4882a593Smuzhiyun+static void free_fb(struct device *dev) 394*4882a593Smuzhiyun { 395*4882a593Smuzhiyun- int ret; 396*4882a593Smuzhiyun- uint32_t prop_id = get_plane_property_id(name); 397*4882a593Smuzhiyun- 398*4882a593Smuzhiyun- if (!prop_id) { 399*4882a593Smuzhiyun- err("Couldn't find plane prop %s", name); 400*4882a593Smuzhiyun- return -1; 401*4882a593Smuzhiyun- } 402*4882a593Smuzhiyun+ DRM_DEBUG("Free fb, num: %d, bpp: %d\n", dev->mode.fb_num, dev->mode.bpp); 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun- ret = drmModeAtomicAddProperty(drm_dev.req, drm_dev.plane_id, get_plane_property_id(name), value); 405*4882a593Smuzhiyun- if (ret < 0) { 406*4882a593Smuzhiyun- err("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); 407*4882a593Smuzhiyun- return ret; 408*4882a593Smuzhiyun- } 409*4882a593Smuzhiyun- 410*4882a593Smuzhiyun- return 0; 411*4882a593Smuzhiyun+ dev->mode.fb_num = 0; 412*4882a593Smuzhiyun+ dev->mode.bpp = 0; 413*4882a593Smuzhiyun+ dev->mode.current = 0; 414*4882a593Smuzhiyun } 415*4882a593Smuzhiyun 416*4882a593Smuzhiyun-static int drm_add_crtc_property(const char *name, uint64_t value) 417*4882a593Smuzhiyun+static int alloc_fb(struct device *dev, int num, int bpp) 418*4882a593Smuzhiyun { 419*4882a593Smuzhiyun- int ret; 420*4882a593Smuzhiyun- uint32_t prop_id = get_crtc_property_id(name); 421*4882a593Smuzhiyun- 422*4882a593Smuzhiyun- if (!prop_id) { 423*4882a593Smuzhiyun- err("Couldn't find crtc prop %s", name); 424*4882a593Smuzhiyun- return -1; 425*4882a593Smuzhiyun- } 426*4882a593Smuzhiyun+ DRM_DEBUG("Alloc fb num: %d, bpp: %d\n", num, bpp); 427*4882a593Smuzhiyun 428*4882a593Smuzhiyun- ret = drmModeAtomicAddProperty(drm_dev.req, drm_dev.crtc_id, get_crtc_property_id(name), value); 429*4882a593Smuzhiyun- if (ret < 0) { 430*4882a593Smuzhiyun- err("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); 431*4882a593Smuzhiyun- return ret; 432*4882a593Smuzhiyun- } 433*4882a593Smuzhiyun+ dev->mode.fb_num = num; 434*4882a593Smuzhiyun+ dev->mode.bpp = bpp; 435*4882a593Smuzhiyun+ dev->mode.current = 0; 436*4882a593Smuzhiyun 437*4882a593Smuzhiyun- return 0; 438*4882a593Smuzhiyun+ return 0; 439*4882a593Smuzhiyun } 440*4882a593Smuzhiyun 441*4882a593Smuzhiyun-static int drm_add_conn_property(const char *name, uint64_t value) 442*4882a593Smuzhiyun+static int drm_get_preferred_connector(void) 443*4882a593Smuzhiyun { 444*4882a593Smuzhiyun- int ret; 445*4882a593Smuzhiyun- uint32_t prop_id = get_conn_property_id(name); 446*4882a593Smuzhiyun- 447*4882a593Smuzhiyun- if (!prop_id) { 448*4882a593Smuzhiyun- err("Couldn't find conn prop %s", name); 449*4882a593Smuzhiyun- return -1; 450*4882a593Smuzhiyun- } 451*4882a593Smuzhiyun- 452*4882a593Smuzhiyun- ret = drmModeAtomicAddProperty(drm_dev.req, drm_dev.conn_id, get_conn_property_id(name), value); 453*4882a593Smuzhiyun- if (ret < 0) { 454*4882a593Smuzhiyun- err("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); 455*4882a593Smuzhiyun- return ret; 456*4882a593Smuzhiyun- } 457*4882a593Smuzhiyun- 458*4882a593Smuzhiyun- return 0; 459*4882a593Smuzhiyun+ const char *path; 460*4882a593Smuzhiyun+ char buf[256] = "\0"; 461*4882a593Smuzhiyun+ int fd; 462*4882a593Smuzhiyun+ 463*4882a593Smuzhiyun+#define DRM_CONNECTOR_CFG_PATH_ENV "DRM_CONNECTOR_CFG_PATH" 464*4882a593Smuzhiyun+#define DRM_CONNECTOR_CFG_PATH_DEFAULT "/tmp/drm_connector.cfg" 465*4882a593Smuzhiyun+ path = getenv(DRM_CONNECTOR_CFG_PATH_ENV); 466*4882a593Smuzhiyun+ if (!path) 467*4882a593Smuzhiyun+ path = DRM_CONNECTOR_CFG_PATH_DEFAULT; 468*4882a593Smuzhiyun+ 469*4882a593Smuzhiyun+ fd = open(path, O_RDONLY); 470*4882a593Smuzhiyun+ if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { 471*4882a593Smuzhiyun+ DRM_DEBUG("Warning: read failed\n"); 472*4882a593Smuzhiyun+ } 473*4882a593Smuzhiyun+ close(fd); 474*4882a593Smuzhiyun+ 475*4882a593Smuzhiyun+ if (!buf[0]) 476*4882a593Smuzhiyun+ return -1; 477*4882a593Smuzhiyun+ 478*4882a593Smuzhiyun+ return atoi(buf); 479*4882a593Smuzhiyun } 480*4882a593Smuzhiyun 481*4882a593Smuzhiyun-static int drm_dmabuf_set_plane(struct drm_buffer *buf) 482*4882a593Smuzhiyun+static int drm_get_preferred_mode(int *width, int *height) 483*4882a593Smuzhiyun { 484*4882a593Smuzhiyun- int ret; 485*4882a593Smuzhiyun- static int first = 1; 486*4882a593Smuzhiyun- uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT; 487*4882a593Smuzhiyun- 488*4882a593Smuzhiyun- drm_dev.req = drmModeAtomicAlloc(); 489*4882a593Smuzhiyun+ const char *path; 490*4882a593Smuzhiyun+ char buf[256] = "\0"; 491*4882a593Smuzhiyun+ int fd, w, h; 492*4882a593Smuzhiyun 493*4882a593Smuzhiyun- /* On first Atomic commit, do a modeset */ 494*4882a593Smuzhiyun- if (first) { 495*4882a593Smuzhiyun- drm_add_conn_property("CRTC_ID", drm_dev.crtc_id); 496*4882a593Smuzhiyun+#define DRM_MODE_CFG_PATH_ENV "DRM_CONNECTOR_CFG_PATH" 497*4882a593Smuzhiyun+#define DRM_MODE_CFG_PATH_DEFAULT "/tmp/drm_mode.cfg" 498*4882a593Smuzhiyun+ path = getenv(DRM_MODE_CFG_PATH_ENV); 499*4882a593Smuzhiyun+ if (!path) 500*4882a593Smuzhiyun+ path = DRM_MODE_CFG_PATH_DEFAULT; 501*4882a593Smuzhiyun 502*4882a593Smuzhiyun- drm_add_crtc_property("MODE_ID", drm_dev.blob_id); 503*4882a593Smuzhiyun- drm_add_crtc_property("ACTIVE", 1); 504*4882a593Smuzhiyun+ fd = open(path, O_RDONLY); 505*4882a593Smuzhiyun+ if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { 506*4882a593Smuzhiyun+ DRM_DEBUG("Warning: read failed\n"); 507*4882a593Smuzhiyun+ } 508*4882a593Smuzhiyun+ close(fd); 509*4882a593Smuzhiyun 510*4882a593Smuzhiyun- flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; 511*4882a593Smuzhiyun+ if (!buf[0]) 512*4882a593Smuzhiyun+ return -1; 513*4882a593Smuzhiyun 514*4882a593Smuzhiyun- first = 0; 515*4882a593Smuzhiyun- } 516*4882a593Smuzhiyun+ if (2 != sscanf(buf, "%dx%d", &w, &h)) 517*4882a593Smuzhiyun+ return -1; 518*4882a593Smuzhiyun 519*4882a593Smuzhiyun- drm_add_plane_property("FB_ID", buf->fb_handle); 520*4882a593Smuzhiyun- drm_add_plane_property("CRTC_ID", drm_dev.crtc_id); 521*4882a593Smuzhiyun- drm_add_plane_property("SRC_X", 0); 522*4882a593Smuzhiyun- drm_add_plane_property("SRC_Y", 0); 523*4882a593Smuzhiyun- drm_add_plane_property("SRC_W", drm_dev.width << 16); 524*4882a593Smuzhiyun- drm_add_plane_property("SRC_H", drm_dev.height << 16); 525*4882a593Smuzhiyun- drm_add_plane_property("CRTC_X", 0); 526*4882a593Smuzhiyun- drm_add_plane_property("CRTC_Y", 0); 527*4882a593Smuzhiyun- drm_add_plane_property("CRTC_W", drm_dev.width); 528*4882a593Smuzhiyun- drm_add_plane_property("CRTC_H", drm_dev.height); 529*4882a593Smuzhiyun+ *width = w; 530*4882a593Smuzhiyun+ *height = h; 531*4882a593Smuzhiyun 532*4882a593Smuzhiyun- ret = drmModeAtomicCommit(drm_dev.fd, drm_dev.req, flags, NULL); 533*4882a593Smuzhiyun- if (ret) { 534*4882a593Smuzhiyun- err("drmModeAtomicCommit failed: %s", strerror(errno)); 535*4882a593Smuzhiyun- drmModeAtomicFree(drm_dev.req); 536*4882a593Smuzhiyun- return ret; 537*4882a593Smuzhiyun- } 538*4882a593Smuzhiyun- 539*4882a593Smuzhiyun- return 0; 540*4882a593Smuzhiyun+ return 0; 541*4882a593Smuzhiyun } 542*4882a593Smuzhiyun 543*4882a593Smuzhiyun-static int find_plane(unsigned int fourcc, uint32_t *plane_id, uint32_t crtc_id, uint32_t crtc_idx) 544*4882a593Smuzhiyun+static drmModeConnectorPtr 545*4882a593Smuzhiyun+drm_get_connector(struct device *dev, int connector_id) 546*4882a593Smuzhiyun { 547*4882a593Smuzhiyun- drmModePlaneResPtr planes; 548*4882a593Smuzhiyun- drmModePlanePtr plane; 549*4882a593Smuzhiyun- unsigned int i; 550*4882a593Smuzhiyun- unsigned int j; 551*4882a593Smuzhiyun- int ret = 0; 552*4882a593Smuzhiyun- unsigned int format = fourcc; 553*4882a593Smuzhiyun- 554*4882a593Smuzhiyun- planes = drmModeGetPlaneResources(drm_dev.fd); 555*4882a593Smuzhiyun- if (!planes) { 556*4882a593Smuzhiyun- err("drmModeGetPlaneResources failed"); 557*4882a593Smuzhiyun- return -1; 558*4882a593Smuzhiyun- } 559*4882a593Smuzhiyun- 560*4882a593Smuzhiyun- dbg("drm: found planes %u", planes->count_planes); 561*4882a593Smuzhiyun- 562*4882a593Smuzhiyun- for (i = 0; i < planes->count_planes; ++i) { 563*4882a593Smuzhiyun- plane = drmModeGetPlane(drm_dev.fd, planes->planes[i]); 564*4882a593Smuzhiyun- if (!plane) { 565*4882a593Smuzhiyun- err("drmModeGetPlane failed: %s", strerror(errno)); 566*4882a593Smuzhiyun- break; 567*4882a593Smuzhiyun- } 568*4882a593Smuzhiyun- 569*4882a593Smuzhiyun- if (!(plane->possible_crtcs & (1 << crtc_idx))) { 570*4882a593Smuzhiyun- drmModeFreePlane(plane); 571*4882a593Smuzhiyun- continue; 572*4882a593Smuzhiyun- } 573*4882a593Smuzhiyun- 574*4882a593Smuzhiyun- for (j = 0; j < plane->count_formats; ++j) { 575*4882a593Smuzhiyun- if (plane->formats[j] == format) 576*4882a593Smuzhiyun- break; 577*4882a593Smuzhiyun- } 578*4882a593Smuzhiyun+ drmModeConnectorPtr conn; 579*4882a593Smuzhiyun 580*4882a593Smuzhiyun- if (j == plane->count_formats) { 581*4882a593Smuzhiyun- drmModeFreePlane(plane); 582*4882a593Smuzhiyun- continue; 583*4882a593Smuzhiyun- } 584*4882a593Smuzhiyun+ conn = drmModeGetConnector(dev->fd, connector_id); 585*4882a593Smuzhiyun+ if (!conn) 586*4882a593Smuzhiyun+ return NULL; 587*4882a593Smuzhiyun 588*4882a593Smuzhiyun- *plane_id = plane->plane_id; 589*4882a593Smuzhiyun- drmModeFreePlane(plane); 590*4882a593Smuzhiyun+ DRM_DEBUG("Connector id: %d, %sconnected, modes: %d\n", connector_id, 591*4882a593Smuzhiyun+ (conn->connection == DRM_MODE_CONNECTED) ? "" : "dis", 592*4882a593Smuzhiyun+ conn->count_modes); 593*4882a593Smuzhiyun+ if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes) 594*4882a593Smuzhiyun+ return conn; 595*4882a593Smuzhiyun 596*4882a593Smuzhiyun- dbg("found plane %d", *plane_id); 597*4882a593Smuzhiyun+ drmModeFreeConnector(conn); 598*4882a593Smuzhiyun+ return NULL; 599*4882a593Smuzhiyun+} 600*4882a593Smuzhiyun 601*4882a593Smuzhiyun- break; 602*4882a593Smuzhiyun- } 603*4882a593Smuzhiyun+static drmModeConnectorPtr 604*4882a593Smuzhiyun+drm_find_best_connector(struct device *dev) 605*4882a593Smuzhiyun+{ 606*4882a593Smuzhiyun+ drmModeResPtr res = dev->res; 607*4882a593Smuzhiyun+ drmModeConnectorPtr conn; 608*4882a593Smuzhiyun+ int i, preferred_connector_id = drm_get_preferred_connector(); 609*4882a593Smuzhiyun+ 610*4882a593Smuzhiyun+ DRM_DEBUG("Preferred connector id: %d\n", preferred_connector_id); 611*4882a593Smuzhiyun+ conn = drm_get_connector(dev, preferred_connector_id); 612*4882a593Smuzhiyun+ if (conn) 613*4882a593Smuzhiyun+ return conn; 614*4882a593Smuzhiyun+ 615*4882a593Smuzhiyun+ for (i = 0; i < res->count_connectors; i++) { 616*4882a593Smuzhiyun+ conn = drm_get_connector(dev, res->connectors[i]); 617*4882a593Smuzhiyun+ if (conn) 618*4882a593Smuzhiyun+ return conn; 619*4882a593Smuzhiyun+ } 620*4882a593Smuzhiyun+ return NULL; 621*4882a593Smuzhiyun+} 622*4882a593Smuzhiyun 623*4882a593Smuzhiyun- if (i == planes->count_planes) 624*4882a593Smuzhiyun- ret = -1; 625*4882a593Smuzhiyun+static drmModeCrtcPtr 626*4882a593Smuzhiyun+drm_find_best_crtc(struct device *dev, drmModeConnectorPtr conn) 627*4882a593Smuzhiyun+{ 628*4882a593Smuzhiyun+ drmModeResPtr res = dev->res; 629*4882a593Smuzhiyun+ drmModeEncoderPtr encoder; 630*4882a593Smuzhiyun+ drmModeCrtcPtr crtc; 631*4882a593Smuzhiyun+ int i, preferred_crtc_id = 0; 632*4882a593Smuzhiyun+ int crtcs_for_connector = 0; 633*4882a593Smuzhiyun+ 634*4882a593Smuzhiyun+ encoder = drmModeGetEncoder(dev->fd, conn->encoder_id); 635*4882a593Smuzhiyun+ if (encoder) { 636*4882a593Smuzhiyun+ preferred_crtc_id = encoder->crtc_id; 637*4882a593Smuzhiyun+ drmModeFreeEncoder(encoder); 638*4882a593Smuzhiyun+ } 639*4882a593Smuzhiyun+ DRM_DEBUG("Preferred crtc: %d\n", preferred_crtc_id); 640*4882a593Smuzhiyun+ 641*4882a593Smuzhiyun+ crtc = drmModeGetCrtc(dev->fd, preferred_crtc_id); 642*4882a593Smuzhiyun+ if (crtc) 643*4882a593Smuzhiyun+ return crtc; 644*4882a593Smuzhiyun+ 645*4882a593Smuzhiyun+ for (i = 0; i < res->count_encoders; i++) { 646*4882a593Smuzhiyun+ encoder = drmModeGetEncoder(dev->fd, res->encoders[i]); 647*4882a593Smuzhiyun+ if (encoder) 648*4882a593Smuzhiyun+ crtcs_for_connector |= encoder->possible_crtcs; 649*4882a593Smuzhiyun+ drmModeFreeEncoder(encoder); 650*4882a593Smuzhiyun+ } 651*4882a593Smuzhiyun+ DRM_DEBUG("Possible crtcs: %x\n", crtcs_for_connector); 652*4882a593Smuzhiyun+ if (!crtcs_for_connector) 653*4882a593Smuzhiyun+ return NULL; 654*4882a593Smuzhiyun+ 655*4882a593Smuzhiyun+ return drmModeGetCrtc(dev->fd, res->crtcs[ffs(crtcs_for_connector) - 1]); 656*4882a593Smuzhiyun+} 657*4882a593Smuzhiyun 658*4882a593Smuzhiyun- drmModeFreePlaneResources(planes); 659*4882a593Smuzhiyun+int 660*4882a593Smuzhiyun+drm_plane_is_primary(struct device *dev, int plane_id) 661*4882a593Smuzhiyun+{ 662*4882a593Smuzhiyun+ drmModeObjectPropertiesPtr props; 663*4882a593Smuzhiyun+ drmModePropertyPtr prop; 664*4882a593Smuzhiyun+ unsigned int i; 665*4882a593Smuzhiyun+ int type = 0; 666*4882a593Smuzhiyun+ 667*4882a593Smuzhiyun+ props = drmModeObjectGetProperties(dev->fd, plane_id, 668*4882a593Smuzhiyun+ DRM_MODE_OBJECT_PLANE); 669*4882a593Smuzhiyun+ if (!props) 670*4882a593Smuzhiyun+ return 0; 671*4882a593Smuzhiyun+ 672*4882a593Smuzhiyun+ for (i = 0; i < props->count_props; i++) { 673*4882a593Smuzhiyun+ prop = drmModeGetProperty(dev->fd, props->props[i]); 674*4882a593Smuzhiyun+ if (prop && !strcmp(prop->name, "type")) 675*4882a593Smuzhiyun+ type = props->prop_values[i]; 676*4882a593Smuzhiyun+ drmModeFreeProperty(prop); 677*4882a593Smuzhiyun+ } 678*4882a593Smuzhiyun+ DRM_DEBUG("Plane: %d, type: %d\n", plane_id, type); 679*4882a593Smuzhiyun+ 680*4882a593Smuzhiyun+ drmModeFreeObjectProperties(props); 681*4882a593Smuzhiyun+ return type == DRM_PLANE_TYPE_PRIMARY; 682*4882a593Smuzhiyun+} 683*4882a593Smuzhiyun 684*4882a593Smuzhiyun- return ret; 685*4882a593Smuzhiyun+int 686*4882a593Smuzhiyun+drm_plane_is_overlay(struct device *dev, int plane_id) 687*4882a593Smuzhiyun+{ 688*4882a593Smuzhiyun+ drmModeObjectPropertiesPtr props; 689*4882a593Smuzhiyun+ drmModePropertyPtr prop; 690*4882a593Smuzhiyun+ unsigned int i; 691*4882a593Smuzhiyun+ int type = 0; 692*4882a593Smuzhiyun+ 693*4882a593Smuzhiyun+ props = drmModeObjectGetProperties(dev->fd, plane_id, 694*4882a593Smuzhiyun+ DRM_MODE_OBJECT_PLANE); 695*4882a593Smuzhiyun+ if (!props) 696*4882a593Smuzhiyun+ return 0; 697*4882a593Smuzhiyun+ 698*4882a593Smuzhiyun+ for (i = 0; i < props->count_props; i++) { 699*4882a593Smuzhiyun+ prop = drmModeGetProperty(dev->fd, props->props[i]); 700*4882a593Smuzhiyun+ if (prop && !strcmp(prop->name, "type")) 701*4882a593Smuzhiyun+ type = props->prop_values[i]; 702*4882a593Smuzhiyun+ drmModeFreeProperty(prop); 703*4882a593Smuzhiyun+ } 704*4882a593Smuzhiyun+ DRM_DEBUG("Plane: %d, type: %d\n", plane_id, type); 705*4882a593Smuzhiyun+ 706*4882a593Smuzhiyun+ drmModeFreeObjectProperties(props); 707*4882a593Smuzhiyun+ return type == DRM_PLANE_TYPE_OVERLAY; 708*4882a593Smuzhiyun } 709*4882a593Smuzhiyun 710*4882a593Smuzhiyun-static int drm_find_connector(void) 711*4882a593Smuzhiyun+static drmModePlanePtr 712*4882a593Smuzhiyun+drm_get_plane(struct device *dev, int plane_id, int pipe) 713*4882a593Smuzhiyun { 714*4882a593Smuzhiyun- drmModeConnector *conn = NULL; 715*4882a593Smuzhiyun- drmModeEncoder *enc = NULL; 716*4882a593Smuzhiyun- drmModeRes *res; 717*4882a593Smuzhiyun- int i; 718*4882a593Smuzhiyun+ drmModePlanePtr plane; 719*4882a593Smuzhiyun 720*4882a593Smuzhiyun- if ((res = drmModeGetResources(drm_dev.fd)) == NULL) { 721*4882a593Smuzhiyun- err("drmModeGetResources() failed"); 722*4882a593Smuzhiyun- return -1; 723*4882a593Smuzhiyun- } 724*4882a593Smuzhiyun+ plane = drmModeGetPlane(dev->fd, plane_id); 725*4882a593Smuzhiyun+ if (!plane) 726*4882a593Smuzhiyun+ return NULL; 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun- if (res->count_crtcs <= 0) { 729*4882a593Smuzhiyun- err("no Crtcs"); 730*4882a593Smuzhiyun- goto free_res; 731*4882a593Smuzhiyun- } 732*4882a593Smuzhiyun- 733*4882a593Smuzhiyun- /* find all available connectors */ 734*4882a593Smuzhiyun- for (i = 0; i < res->count_connectors; i++) { 735*4882a593Smuzhiyun- conn = drmModeGetConnector(drm_dev.fd, res->connectors[i]); 736*4882a593Smuzhiyun- if (!conn) 737*4882a593Smuzhiyun- continue; 738*4882a593Smuzhiyun- 739*4882a593Smuzhiyun-#if DRM_CONNECTOR_ID >= 0 740*4882a593Smuzhiyun- if (conn->connector_id != DRM_CONNECTOR_ID) { 741*4882a593Smuzhiyun- drmModeFreeConnector(conn); 742*4882a593Smuzhiyun- continue; 743*4882a593Smuzhiyun- } 744*4882a593Smuzhiyun-#endif 745*4882a593Smuzhiyun+ DRM_DEBUG("Check plane: %d, possible_crtcs: %x\n", plane_id, 746*4882a593Smuzhiyun+ plane->possible_crtcs); 747*4882a593Smuzhiyun+ if (drm_plane_is_primary(dev, plane_id)) { 748*4882a593Smuzhiyun+ if (plane->possible_crtcs & (1 << pipe)) 749*4882a593Smuzhiyun+ return plane; 750*4882a593Smuzhiyun+ } 751*4882a593Smuzhiyun 752*4882a593Smuzhiyun- if (conn->connection == DRM_MODE_CONNECTED) { 753*4882a593Smuzhiyun- dbg("drm: connector %d: connected", conn->connector_id); 754*4882a593Smuzhiyun- } else if (conn->connection == DRM_MODE_DISCONNECTED) { 755*4882a593Smuzhiyun- dbg("drm: connector %d: disconnected", conn->connector_id); 756*4882a593Smuzhiyun- } else if (conn->connection == DRM_MODE_UNKNOWNCONNECTION) { 757*4882a593Smuzhiyun- dbg("drm: connector %d: unknownconnection", conn->connector_id); 758*4882a593Smuzhiyun- } else { 759*4882a593Smuzhiyun- dbg("drm: connector %d: unknown", conn->connector_id); 760*4882a593Smuzhiyun- } 761*4882a593Smuzhiyun- 762*4882a593Smuzhiyun- if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes > 0) 763*4882a593Smuzhiyun- break; 764*4882a593Smuzhiyun- 765*4882a593Smuzhiyun- drmModeFreeConnector(conn); 766*4882a593Smuzhiyun- conn = NULL; 767*4882a593Smuzhiyun- }; 768*4882a593Smuzhiyun- 769*4882a593Smuzhiyun- if (!conn) { 770*4882a593Smuzhiyun- err("suitable connector not found"); 771*4882a593Smuzhiyun- goto free_res; 772*4882a593Smuzhiyun- } 773*4882a593Smuzhiyun+ drmModeFreePlane(plane); 774*4882a593Smuzhiyun+ return NULL; 775*4882a593Smuzhiyun+} 776*4882a593Smuzhiyun 777*4882a593Smuzhiyun- drm_dev.conn_id = conn->connector_id; 778*4882a593Smuzhiyun- dbg("conn_id: %d", drm_dev.conn_id); 779*4882a593Smuzhiyun- drm_dev.mmWidth = conn->mmWidth; 780*4882a593Smuzhiyun- drm_dev.mmHeight = conn->mmHeight; 781*4882a593Smuzhiyun+static drmModePlanePtr 782*4882a593Smuzhiyun+drm_find_best_plane(struct device *dev, drmModeCrtcPtr crtc) 783*4882a593Smuzhiyun+{ 784*4882a593Smuzhiyun+ drmModeResPtr res = dev->res; 785*4882a593Smuzhiyun+ drmModePlaneResPtr pres; 786*4882a593Smuzhiyun+ drmModePlanePtr plane; 787*4882a593Smuzhiyun+ unsigned int i; 788*4882a593Smuzhiyun+ int pipe; 789*4882a593Smuzhiyun+ 790*4882a593Smuzhiyun+ for (pipe = 0; pipe < res->count_crtcs; pipe++) { 791*4882a593Smuzhiyun+ if (crtc->crtc_id == res->crtcs[pipe]) 792*4882a593Smuzhiyun+ break; 793*4882a593Smuzhiyun+ } 794*4882a593Smuzhiyun+ if (pipe == res->count_crtcs) 795*4882a593Smuzhiyun+ return NULL; 796*4882a593Smuzhiyun+ 797*4882a593Smuzhiyun+ pres = drmModeGetPlaneResources(dev->fd); 798*4882a593Smuzhiyun+ if (!pres) 799*4882a593Smuzhiyun+ return NULL; 800*4882a593Smuzhiyun+ 801*4882a593Smuzhiyun+ for (i = 0; i < pres->count_planes; i++) { 802*4882a593Smuzhiyun+ plane = drm_get_plane(dev, pres->planes[i], pipe); 803*4882a593Smuzhiyun+ if (plane) { 804*4882a593Smuzhiyun+ drmModeFreePlaneResources(pres); 805*4882a593Smuzhiyun+ return plane; 806*4882a593Smuzhiyun+ } 807*4882a593Smuzhiyun+ drmModeFreePlane(plane); 808*4882a593Smuzhiyun+ } 809*4882a593Smuzhiyun+ 810*4882a593Smuzhiyun+ drmModeFreePlaneResources(pres); 811*4882a593Smuzhiyun+ return NULL; 812*4882a593Smuzhiyun+} 813*4882a593Smuzhiyun 814*4882a593Smuzhiyun- memcpy(&drm_dev.mode, &conn->modes[0], sizeof(drmModeModeInfo)); 815*4882a593Smuzhiyun+static drmModeModeInfoPtr 816*4882a593Smuzhiyun+drm_find_best_mode(struct device *dev, drmModeConnectorPtr conn) 817*4882a593Smuzhiyun+{ 818*4882a593Smuzhiyun+ drmModeModeInfoPtr mode; 819*4882a593Smuzhiyun+ int i, preferred_width = 1920, preferred_height = 1080; 820*4882a593Smuzhiyun+ 821*4882a593Smuzhiyun+ if (dev == NULL) 822*4882a593Smuzhiyun+ return 0; 823*4882a593Smuzhiyun+ drm_get_preferred_mode(&preferred_width, &preferred_height); 824*4882a593Smuzhiyun+ DRM_DEBUG("Preferred mode: %dx%d\n", preferred_width, preferred_height); 825*4882a593Smuzhiyun+ 826*4882a593Smuzhiyun+ mode = &conn->modes[0]; 827*4882a593Smuzhiyun+ for (i = 0; i < conn->count_modes; i++) { 828*4882a593Smuzhiyun+ DRM_DEBUG("Check mode: %dx%d\n", 829*4882a593Smuzhiyun+ conn->modes[i].hdisplay, conn->modes[i].vdisplay); 830*4882a593Smuzhiyun+ if (conn->modes[i].hdisplay == preferred_width && 831*4882a593Smuzhiyun+ conn->modes[i].vdisplay == preferred_height) { 832*4882a593Smuzhiyun+ mode = &conn->modes[i]; 833*4882a593Smuzhiyun+ break; 834*4882a593Smuzhiyun+ } 835*4882a593Smuzhiyun+ } 836*4882a593Smuzhiyun+ 837*4882a593Smuzhiyun+ return mode; 838*4882a593Smuzhiyun+} 839*4882a593Smuzhiyun 840*4882a593Smuzhiyun- if (drmModeCreatePropertyBlob(drm_dev.fd, &drm_dev.mode, sizeof(drm_dev.mode), 841*4882a593Smuzhiyun- &drm_dev.blob_id)) { 842*4882a593Smuzhiyun- err("error creating mode blob"); 843*4882a593Smuzhiyun- goto free_res; 844*4882a593Smuzhiyun- } 845*4882a593Smuzhiyun+static int drm_get_preferred_fb_mode(int *width, int *height) 846*4882a593Smuzhiyun+{ 847*4882a593Smuzhiyun+ char *buf; 848*4882a593Smuzhiyun+ int w, h; 849*4882a593Smuzhiyun 850*4882a593Smuzhiyun- drm_dev.width = conn->modes[0].hdisplay; 851*4882a593Smuzhiyun- drm_dev.height = conn->modes[0].vdisplay; 852*4882a593Smuzhiyun+ buf = getenv("MINIGUI_DRM_FB_MODE"); 853*4882a593Smuzhiyun+ if (!buf) 854*4882a593Smuzhiyun+ return -1; 855*4882a593Smuzhiyun 856*4882a593Smuzhiyun- for (i = 0 ; i < res->count_encoders; i++) { 857*4882a593Smuzhiyun- enc = drmModeGetEncoder(drm_dev.fd, res->encoders[i]); 858*4882a593Smuzhiyun- if (!enc) 859*4882a593Smuzhiyun- continue; 860*4882a593Smuzhiyun- 861*4882a593Smuzhiyun- dbg("enc%d enc_id %d conn enc_id %d", i, enc->encoder_id, conn->encoder_id); 862*4882a593Smuzhiyun- 863*4882a593Smuzhiyun- if (enc->encoder_id == conn->encoder_id) 864*4882a593Smuzhiyun- break; 865*4882a593Smuzhiyun- 866*4882a593Smuzhiyun- drmModeFreeEncoder(enc); 867*4882a593Smuzhiyun- enc = NULL; 868*4882a593Smuzhiyun- } 869*4882a593Smuzhiyun- 870*4882a593Smuzhiyun- if (enc) { 871*4882a593Smuzhiyun- drm_dev.enc_id = enc->encoder_id; 872*4882a593Smuzhiyun- dbg("enc_id: %d", drm_dev.enc_id); 873*4882a593Smuzhiyun- drm_dev.crtc_id = enc->crtc_id; 874*4882a593Smuzhiyun- dbg("crtc_id: %d", drm_dev.crtc_id); 875*4882a593Smuzhiyun- drmModeFreeEncoder(enc); 876*4882a593Smuzhiyun- } else { 877*4882a593Smuzhiyun- /* Encoder hasn't been associated yet, look it up */ 878*4882a593Smuzhiyun- for (i = 0; i < conn->count_encoders; i++) { 879*4882a593Smuzhiyun- int crtc, crtc_id = -1; 880*4882a593Smuzhiyun- 881*4882a593Smuzhiyun- enc = drmModeGetEncoder(drm_dev.fd, conn->encoders[i]); 882*4882a593Smuzhiyun- if (!enc) 883*4882a593Smuzhiyun- continue; 884*4882a593Smuzhiyun- 885*4882a593Smuzhiyun- for (crtc = 0 ; crtc < res->count_crtcs; crtc++) { 886*4882a593Smuzhiyun- uint32_t crtc_mask = 1 << crtc; 887*4882a593Smuzhiyun- 888*4882a593Smuzhiyun- crtc_id = res->crtcs[crtc]; 889*4882a593Smuzhiyun- 890*4882a593Smuzhiyun- dbg("enc_id %d crtc%d id %d mask %x possible %x", enc->encoder_id, crtc, crtc_id, crtc_mask, enc->possible_crtcs); 891*4882a593Smuzhiyun- 892*4882a593Smuzhiyun- if (enc->possible_crtcs & crtc_mask) 893*4882a593Smuzhiyun- break; 894*4882a593Smuzhiyun- } 895*4882a593Smuzhiyun- 896*4882a593Smuzhiyun- if (crtc_id > 0) { 897*4882a593Smuzhiyun- drm_dev.enc_id = enc->encoder_id; 898*4882a593Smuzhiyun- dbg("enc_id: %d", drm_dev.enc_id); 899*4882a593Smuzhiyun- drm_dev.crtc_id = crtc_id; 900*4882a593Smuzhiyun- dbg("crtc_id: %d", drm_dev.crtc_id); 901*4882a593Smuzhiyun- break; 902*4882a593Smuzhiyun- } 903*4882a593Smuzhiyun- 904*4882a593Smuzhiyun- drmModeFreeEncoder(enc); 905*4882a593Smuzhiyun- enc = NULL; 906*4882a593Smuzhiyun- } 907*4882a593Smuzhiyun- 908*4882a593Smuzhiyun- if (!enc) { 909*4882a593Smuzhiyun- err("suitable encoder not found"); 910*4882a593Smuzhiyun- goto free_res; 911*4882a593Smuzhiyun- } 912*4882a593Smuzhiyun- 913*4882a593Smuzhiyun- drmModeFreeEncoder(enc); 914*4882a593Smuzhiyun- } 915*4882a593Smuzhiyun- 916*4882a593Smuzhiyun- drm_dev.crtc_idx = -1; 917*4882a593Smuzhiyun- 918*4882a593Smuzhiyun- for (i = 0; i < res->count_crtcs; ++i) { 919*4882a593Smuzhiyun- if (drm_dev.crtc_id == res->crtcs[i]) { 920*4882a593Smuzhiyun- drm_dev.crtc_idx = i; 921*4882a593Smuzhiyun- break; 922*4882a593Smuzhiyun- } 923*4882a593Smuzhiyun- } 924*4882a593Smuzhiyun- 925*4882a593Smuzhiyun- if (drm_dev.crtc_idx == -1) { 926*4882a593Smuzhiyun- err("drm: CRTC not found"); 927*4882a593Smuzhiyun- goto free_res; 928*4882a593Smuzhiyun- } 929*4882a593Smuzhiyun+ if (2 != sscanf(buf, "%dx%d", &w, &h)) 930*4882a593Smuzhiyun+ return -1; 931*4882a593Smuzhiyun 932*4882a593Smuzhiyun- dbg("crtc_idx: %d", drm_dev.crtc_idx); 933*4882a593Smuzhiyun- 934*4882a593Smuzhiyun- return 0; 935*4882a593Smuzhiyun+ DRM_DEBUG("Preferred fb mode: %dx%d\n", w, h); 936*4882a593Smuzhiyun+ *width = w; 937*4882a593Smuzhiyun+ *height = h; 938*4882a593Smuzhiyun 939*4882a593Smuzhiyun-free_res: 940*4882a593Smuzhiyun- drmModeFreeResources(res); 941*4882a593Smuzhiyun- 942*4882a593Smuzhiyun- return -1; 943*4882a593Smuzhiyun+ return 0; 944*4882a593Smuzhiyun } 945*4882a593Smuzhiyun 946*4882a593Smuzhiyun-static int drm_open(const char *path) 947*4882a593Smuzhiyun+static void drm_setup_fb_mode(struct device *dev) 948*4882a593Smuzhiyun { 949*4882a593Smuzhiyun- int fd, flags; 950*4882a593Smuzhiyun- uint64_t has_dumb; 951*4882a593Smuzhiyun- int ret; 952*4882a593Smuzhiyun- 953*4882a593Smuzhiyun- fd = open(path, O_RDWR); 954*4882a593Smuzhiyun- if (fd < 0) { 955*4882a593Smuzhiyun- err("cannot open \"%s\"", path); 956*4882a593Smuzhiyun- return -1; 957*4882a593Smuzhiyun- } 958*4882a593Smuzhiyun+ drmModeResPtr res = dev->res; 959*4882a593Smuzhiyun+ drmModeConnectorPtr conn; 960*4882a593Smuzhiyun+ drmModeModeInfoPtr mode; 961*4882a593Smuzhiyun+ int i; 962*4882a593Smuzhiyun+ 963*4882a593Smuzhiyun+ if (dev->mode.width && dev->mode.height) 964*4882a593Smuzhiyun+ return; 965*4882a593Smuzhiyun+ 966*4882a593Smuzhiyun+ if (!drm_get_preferred_fb_mode(&dev->mode.width, &dev->mode.height)) 967*4882a593Smuzhiyun+ return; 968*4882a593Smuzhiyun+ 969*4882a593Smuzhiyun+ dev->mode.width = dev->mode.hdisplay; 970*4882a593Smuzhiyun+ dev->mode.height = dev->mode.vdisplay; 971*4882a593Smuzhiyun+ 972*4882a593Smuzhiyun+ for (i = 0; i < res->count_connectors; i++) { 973*4882a593Smuzhiyun+ conn = drm_get_connector(dev, res->connectors[i]); 974*4882a593Smuzhiyun+ if (!conn) 975*4882a593Smuzhiyun+ continue; 976*4882a593Smuzhiyun+ 977*4882a593Smuzhiyun+ mode = drm_find_best_mode(dev, conn); 978*4882a593Smuzhiyun+ if (mode) { 979*4882a593Smuzhiyun+ DRM_DEBUG("Best mode for connector(%d): %dx%d\n", 980*4882a593Smuzhiyun+ conn->connector_id, mode->hdisplay, mode->vdisplay); 981*4882a593Smuzhiyun+ if (dev->mode.width > mode->hdisplay || 982*4882a593Smuzhiyun+ dev->mode.height > mode->vdisplay) { 983*4882a593Smuzhiyun+ dev->mode.width = mode->hdisplay; 984*4882a593Smuzhiyun+ dev->mode.height = mode->vdisplay; 985*4882a593Smuzhiyun+ } 986*4882a593Smuzhiyun+ } 987*4882a593Smuzhiyun+ drmModeFreeConnector(conn); 988*4882a593Smuzhiyun+ } 989*4882a593Smuzhiyun+} 990*4882a593Smuzhiyun 991*4882a593Smuzhiyun- /* set FD_CLOEXEC flag */ 992*4882a593Smuzhiyun- if ((flags = fcntl(fd, F_GETFD)) < 0 || 993*4882a593Smuzhiyun- fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { 994*4882a593Smuzhiyun- err("fcntl FD_CLOEXEC failed"); 995*4882a593Smuzhiyun- goto err; 996*4882a593Smuzhiyun- } 997*4882a593Smuzhiyun+static void drm_free(struct device *dev) 998*4882a593Smuzhiyun+{ 999*4882a593Smuzhiyun+ int i; 1000*4882a593Smuzhiyun+ 1001*4882a593Smuzhiyun+ if (dev->res) { 1002*4882a593Smuzhiyun+ drmModeFreeResources(dev->res); 1003*4882a593Smuzhiyun+ dev->res = NULL; 1004*4882a593Smuzhiyun+ } 1005*4882a593Smuzhiyun+ 1006*4882a593Smuzhiyun+ dev->connector_id = 0; 1007*4882a593Smuzhiyun+ dev->crtc_id = 0; 1008*4882a593Smuzhiyun+ dev->plane_id = 0; 1009*4882a593Smuzhiyun+ dev->mode.hdisplay = 0; 1010*4882a593Smuzhiyun+ dev->mode.vdisplay = 0; 1011*4882a593Smuzhiyun+} 1012*4882a593Smuzhiyun 1013*4882a593Smuzhiyun- /* check capability */ 1014*4882a593Smuzhiyun- ret = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb); 1015*4882a593Smuzhiyun- if (ret < 0 || has_dumb == 0) { 1016*4882a593Smuzhiyun- err("drmGetCap DRM_CAP_DUMB_BUFFER failed or \"%s\" doesn't have dumb " 1017*4882a593Smuzhiyun- "buffer", path); 1018*4882a593Smuzhiyun- goto err; 1019*4882a593Smuzhiyun- } 1020*4882a593Smuzhiyun- 1021*4882a593Smuzhiyun- return fd; 1022*4882a593Smuzhiyun-err: 1023*4882a593Smuzhiyun- close(fd); 1024*4882a593Smuzhiyun- return -1; 1025*4882a593Smuzhiyun-} 1026*4882a593Smuzhiyun- 1027*4882a593Smuzhiyun-static int drm_setup(unsigned int fourcc) 1028*4882a593Smuzhiyun-{ 1029*4882a593Smuzhiyun- int ret; 1030*4882a593Smuzhiyun- const char *device_path = NULL; 1031*4882a593Smuzhiyun- 1032*4882a593Smuzhiyun- device_path = getenv("DRM_CARD"); 1033*4882a593Smuzhiyun- if (!device_path) 1034*4882a593Smuzhiyun- device_path = DRM_CARD; 1035*4882a593Smuzhiyun- 1036*4882a593Smuzhiyun- drm_dev.fd = drm_open(device_path); 1037*4882a593Smuzhiyun- if (drm_dev.fd < 0) 1038*4882a593Smuzhiyun- return -1; 1039*4882a593Smuzhiyun- 1040*4882a593Smuzhiyun- ret = drmSetClientCap(drm_dev.fd, DRM_CLIENT_CAP_ATOMIC, 1); 1041*4882a593Smuzhiyun- if (ret) { 1042*4882a593Smuzhiyun- err("No atomic modesetting support: %s", strerror(errno)); 1043*4882a593Smuzhiyun- goto err; 1044*4882a593Smuzhiyun- } 1045*4882a593Smuzhiyun- 1046*4882a593Smuzhiyun- ret = drm_find_connector(); 1047*4882a593Smuzhiyun- if (ret) { 1048*4882a593Smuzhiyun- err("available drm devices not found"); 1049*4882a593Smuzhiyun- goto err; 1050*4882a593Smuzhiyun- } 1051*4882a593Smuzhiyun- 1052*4882a593Smuzhiyun- ret = find_plane(fourcc, &drm_dev.plane_id, drm_dev.crtc_id, drm_dev.crtc_idx); 1053*4882a593Smuzhiyun- if (ret) { 1054*4882a593Smuzhiyun- err("Cannot find plane"); 1055*4882a593Smuzhiyun- goto err; 1056*4882a593Smuzhiyun- } 1057*4882a593Smuzhiyun- 1058*4882a593Smuzhiyun- drm_dev.plane = drmModeGetPlane(drm_dev.fd, drm_dev.plane_id); 1059*4882a593Smuzhiyun- if (!drm_dev.plane) { 1060*4882a593Smuzhiyun- err("Cannot get plane"); 1061*4882a593Smuzhiyun- goto err; 1062*4882a593Smuzhiyun- } 1063*4882a593Smuzhiyun- 1064*4882a593Smuzhiyun- drm_dev.crtc = drmModeGetCrtc(drm_dev.fd, drm_dev.crtc_id); 1065*4882a593Smuzhiyun- if (!drm_dev.crtc) { 1066*4882a593Smuzhiyun- err("Cannot get crtc"); 1067*4882a593Smuzhiyun- goto err; 1068*4882a593Smuzhiyun- } 1069*4882a593Smuzhiyun- 1070*4882a593Smuzhiyun- drm_dev.conn = drmModeGetConnector(drm_dev.fd, drm_dev.conn_id); 1071*4882a593Smuzhiyun- if (!drm_dev.conn) { 1072*4882a593Smuzhiyun- err("Cannot get connector"); 1073*4882a593Smuzhiyun- goto err; 1074*4882a593Smuzhiyun- } 1075*4882a593Smuzhiyun- 1076*4882a593Smuzhiyun- ret = drm_get_plane_props(); 1077*4882a593Smuzhiyun- if (ret) { 1078*4882a593Smuzhiyun- err("Cannot get plane props"); 1079*4882a593Smuzhiyun- goto err; 1080*4882a593Smuzhiyun- } 1081*4882a593Smuzhiyun- 1082*4882a593Smuzhiyun- ret = drm_get_crtc_props(); 1083*4882a593Smuzhiyun- if (ret) { 1084*4882a593Smuzhiyun- err("Cannot get crtc props"); 1085*4882a593Smuzhiyun- goto err; 1086*4882a593Smuzhiyun- } 1087*4882a593Smuzhiyun- 1088*4882a593Smuzhiyun- ret = drm_get_conn_props(); 1089*4882a593Smuzhiyun- if (ret) { 1090*4882a593Smuzhiyun- err("Cannot get connector props"); 1091*4882a593Smuzhiyun- goto err; 1092*4882a593Smuzhiyun- } 1093*4882a593Smuzhiyun- 1094*4882a593Smuzhiyun- drm_dev.drm_event_ctx.version = DRM_EVENT_CONTEXT_VERSION; 1095*4882a593Smuzhiyun- drm_dev.drm_event_ctx.page_flip_handler = page_flip_handler; 1096*4882a593Smuzhiyun- drm_dev.fourcc = fourcc; 1097*4882a593Smuzhiyun- 1098*4882a593Smuzhiyun- info("drm: Found plane_id: %u connector_id: %d crtc_id: %d", 1099*4882a593Smuzhiyun- drm_dev.plane_id, drm_dev.conn_id, drm_dev.crtc_id); 1100*4882a593Smuzhiyun- 1101*4882a593Smuzhiyun- info("drm: %dx%d (%dmm X% dmm) pixel format %c%c%c%c", 1102*4882a593Smuzhiyun- drm_dev.width, drm_dev.height, drm_dev.mmWidth, drm_dev.mmHeight, 1103*4882a593Smuzhiyun- (fourcc>>0)&0xff, (fourcc>>8)&0xff, (fourcc>>16)&0xff, (fourcc>>24)&0xff); 1104*4882a593Smuzhiyun- 1105*4882a593Smuzhiyun- return 0; 1106*4882a593Smuzhiyun+static void configure_plane_zpos(struct device *self, int plane_id, uint64_t zpos) 1107*4882a593Smuzhiyun+{ 1108*4882a593Smuzhiyun+ drmModeObjectPropertiesPtr props = NULL; 1109*4882a593Smuzhiyun+ drmModePropertyPtr prop = NULL; 1110*4882a593Smuzhiyun+ char *buf; 1111*4882a593Smuzhiyun+ unsigned int i; 1112*4882a593Smuzhiyun+ 1113*4882a593Smuzhiyun+ if (plane_id <= 0) 1114*4882a593Smuzhiyun+ return; 1115*4882a593Smuzhiyun+ 1116*4882a593Smuzhiyun+ if (drmSetClientCap (self->fd, DRM_CLIENT_CAP_ATOMIC, 1)) 1117*4882a593Smuzhiyun+ return; 1118*4882a593Smuzhiyun+ 1119*4882a593Smuzhiyun+ props = drmModeObjectGetProperties (self->fd, plane_id, 1120*4882a593Smuzhiyun+ DRM_MODE_OBJECT_PLANE); 1121*4882a593Smuzhiyun+ if (!props) 1122*4882a593Smuzhiyun+ goto out; 1123*4882a593Smuzhiyun+ 1124*4882a593Smuzhiyun+ for (i = 0; i < props->count_props; i++) { 1125*4882a593Smuzhiyun+ prop = drmModeGetProperty (self->fd, props->props[i]); 1126*4882a593Smuzhiyun+ if (prop && !strcmp (prop->name, "ZPOS")) 1127*4882a593Smuzhiyun+ break; 1128*4882a593Smuzhiyun+ drmModeFreeProperty (prop); 1129*4882a593Smuzhiyun+ prop = NULL; 1130*4882a593Smuzhiyun+ } 1131*4882a593Smuzhiyun+ 1132*4882a593Smuzhiyun+ if (!prop) 1133*4882a593Smuzhiyun+ goto out; 1134*4882a593Smuzhiyun+ 1135*4882a593Smuzhiyun+ drmModeObjectSetProperty (self->fd, plane_id, 1136*4882a593Smuzhiyun+ DRM_MODE_OBJECT_PLANE, props->props[i], zpos); 1137*4882a593Smuzhiyun+out: 1138*4882a593Smuzhiyun+ drmModeFreeProperty (prop); 1139*4882a593Smuzhiyun+ drmModeFreeObjectProperties (props); 1140*4882a593Smuzhiyun+} 1141*4882a593Smuzhiyun 1142*4882a593Smuzhiyun+static int drm_setup(struct device *dev) 1143*4882a593Smuzhiyun+{ 1144*4882a593Smuzhiyun+ drmModeConnectorPtr conn = NULL; 1145*4882a593Smuzhiyun+ drmModeModeInfoPtr mode; 1146*4882a593Smuzhiyun+ drmModePlanePtr plane = NULL; 1147*4882a593Smuzhiyun+ drmModeCrtcPtr crtc = NULL; 1148*4882a593Smuzhiyun+ //int ret; 1149*4882a593Smuzhiyun+ int i, success = 0; 1150*4882a593Smuzhiyun+ 1151*4882a593Smuzhiyun+ dev->res = drmModeGetResources(dev->fd); 1152*4882a593Smuzhiyun+ if (!dev->res) { 1153*4882a593Smuzhiyun+ fprintf(stderr, "drm get resource failed\n"); 1154*4882a593Smuzhiyun+ goto err; 1155*4882a593Smuzhiyun+ } 1156*4882a593Smuzhiyun+ 1157*4882a593Smuzhiyun+ conn = drm_find_best_connector(dev); 1158*4882a593Smuzhiyun+ if (!conn) { 1159*4882a593Smuzhiyun+ fprintf(stderr, "drm find connector failed\n"); 1160*4882a593Smuzhiyun+ goto err; 1161*4882a593Smuzhiyun+ } 1162*4882a593Smuzhiyun+ DRM_DEBUG("Best connector id: %d\n", conn->connector_id); 1163*4882a593Smuzhiyun+ 1164*4882a593Smuzhiyun+ mode = drm_find_best_mode(dev, conn); 1165*4882a593Smuzhiyun+ if (!mode) { 1166*4882a593Smuzhiyun+ fprintf(stderr, "drm find mode failed\n"); 1167*4882a593Smuzhiyun+ goto err; 1168*4882a593Smuzhiyun+ } 1169*4882a593Smuzhiyun+ DRM_DEBUG("Best mode: %dx%d\n", mode->hdisplay, mode->vdisplay); 1170*4882a593Smuzhiyun+ 1171*4882a593Smuzhiyun+ crtc = drm_find_best_crtc(dev, conn); 1172*4882a593Smuzhiyun+ if (!crtc) { 1173*4882a593Smuzhiyun+ fprintf(stderr, "drm find crtc failed\n"); 1174*4882a593Smuzhiyun+ goto err; 1175*4882a593Smuzhiyun+ } 1176*4882a593Smuzhiyun+ DRM_DEBUG("Best crtc: %d\n", crtc->crtc_id); 1177*4882a593Smuzhiyun+ 1178*4882a593Smuzhiyun+ plane = drm_find_best_plane(dev, crtc); 1179*4882a593Smuzhiyun+ if (!plane) { 1180*4882a593Smuzhiyun+ fprintf(stderr, "drm find plane failed\n"); 1181*4882a593Smuzhiyun+ goto err; 1182*4882a593Smuzhiyun+ } 1183*4882a593Smuzhiyun+ configure_plane_zpos(dev, plane->plane_id, 1); 1184*4882a593Smuzhiyun+ printf("Best plane: %d\n", plane->plane_id); 1185*4882a593Smuzhiyun+ dev->connector_id = conn->connector_id; 1186*4882a593Smuzhiyun+ dev->crtc_id = crtc->crtc_id; 1187*4882a593Smuzhiyun+ dev->plane_id = plane->plane_id; 1188*4882a593Smuzhiyun+ dev->last_fb_id = 0; 1189*4882a593Smuzhiyun+ dev->mode.hdisplay = mode->hdisplay; 1190*4882a593Smuzhiyun+ dev->mode.vdisplay = mode->vdisplay; 1191*4882a593Smuzhiyun+ 1192*4882a593Smuzhiyun+ drm_setup_fb_mode(dev); 1193*4882a593Smuzhiyun+ DRM_DEBUG("Drm fb mode: %dx%d\n", dev->mode.width, dev->mode.height); 1194*4882a593Smuzhiyun+ 1195*4882a593Smuzhiyun+ success = 1; 1196*4882a593Smuzhiyun err: 1197*4882a593Smuzhiyun- close(drm_dev.fd); 1198*4882a593Smuzhiyun- return -1; 1199*4882a593Smuzhiyun-} 1200*4882a593Smuzhiyun- 1201*4882a593Smuzhiyun-static int drm_allocate_dumb(struct drm_buffer *buf) 1202*4882a593Smuzhiyun-{ 1203*4882a593Smuzhiyun- struct drm_mode_create_dumb creq; 1204*4882a593Smuzhiyun- struct drm_mode_map_dumb mreq; 1205*4882a593Smuzhiyun- uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; 1206*4882a593Smuzhiyun- int ret; 1207*4882a593Smuzhiyun- 1208*4882a593Smuzhiyun- /* create dumb buffer */ 1209*4882a593Smuzhiyun- memset(&creq, 0, sizeof(creq)); 1210*4882a593Smuzhiyun- creq.width = drm_dev.width; 1211*4882a593Smuzhiyun- creq.height = drm_dev.height; 1212*4882a593Smuzhiyun- creq.bpp = LV_COLOR_DEPTH; 1213*4882a593Smuzhiyun- ret = drmIoctl(drm_dev.fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); 1214*4882a593Smuzhiyun- if (ret < 0) { 1215*4882a593Smuzhiyun- err("DRM_IOCTL_MODE_CREATE_DUMB fail"); 1216*4882a593Smuzhiyun- return -1; 1217*4882a593Smuzhiyun- } 1218*4882a593Smuzhiyun- 1219*4882a593Smuzhiyun- buf->handle = creq.handle; 1220*4882a593Smuzhiyun- buf->pitch = creq.pitch; 1221*4882a593Smuzhiyun- dbg("pitch %d", buf->pitch); 1222*4882a593Smuzhiyun- buf->size = creq.size; 1223*4882a593Smuzhiyun- dbg("size %d", buf->size); 1224*4882a593Smuzhiyun- 1225*4882a593Smuzhiyun- /* prepare buffer for memory mapping */ 1226*4882a593Smuzhiyun- memset(&mreq, 0, sizeof(mreq)); 1227*4882a593Smuzhiyun- mreq.handle = creq.handle; 1228*4882a593Smuzhiyun- ret = drmIoctl(drm_dev.fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); 1229*4882a593Smuzhiyun- if (ret) { 1230*4882a593Smuzhiyun- err("DRM_IOCTL_MODE_MAP_DUMB fail"); 1231*4882a593Smuzhiyun- return -1; 1232*4882a593Smuzhiyun- } 1233*4882a593Smuzhiyun- 1234*4882a593Smuzhiyun- buf->offset = mreq.offset; 1235*4882a593Smuzhiyun- 1236*4882a593Smuzhiyun- /* perform actual memory mapping */ 1237*4882a593Smuzhiyun- buf->map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_dev.fd, mreq.offset); 1238*4882a593Smuzhiyun- if (buf->map == MAP_FAILED) { 1239*4882a593Smuzhiyun- err("mmap fail"); 1240*4882a593Smuzhiyun- return -1; 1241*4882a593Smuzhiyun- } 1242*4882a593Smuzhiyun- 1243*4882a593Smuzhiyun- /* clear the framebuffer to 0 (= full transparency in ARGB8888) */ 1244*4882a593Smuzhiyun- memset(buf->map, 0, creq.size); 1245*4882a593Smuzhiyun- 1246*4882a593Smuzhiyun- /* create framebuffer object for the dumb-buffer */ 1247*4882a593Smuzhiyun- handles[0] = creq.handle; 1248*4882a593Smuzhiyun- pitches[0] = creq.pitch; 1249*4882a593Smuzhiyun- offsets[0] = 0; 1250*4882a593Smuzhiyun- ret = drmModeAddFB2(drm_dev.fd, drm_dev.width, drm_dev.height, drm_dev.fourcc, 1251*4882a593Smuzhiyun- handles, pitches, offsets, &buf->fb_handle, 0); 1252*4882a593Smuzhiyun- if (ret) { 1253*4882a593Smuzhiyun- err("drmModeAddFB fail"); 1254*4882a593Smuzhiyun- return -1; 1255*4882a593Smuzhiyun- } 1256*4882a593Smuzhiyun- 1257*4882a593Smuzhiyun- return 0; 1258*4882a593Smuzhiyun+ drmModeFreeConnector(conn); 1259*4882a593Smuzhiyun+ drmModeFreePlane(plane); 1260*4882a593Smuzhiyun+ drmModeFreeCrtc(crtc); 1261*4882a593Smuzhiyun+ if (!success) { 1262*4882a593Smuzhiyun+ drm_free(dev); 1263*4882a593Smuzhiyun+ return -1; 1264*4882a593Smuzhiyun+ } 1265*4882a593Smuzhiyun+ return 0; 1266*4882a593Smuzhiyun } 1267*4882a593Smuzhiyun 1268*4882a593Smuzhiyun-static int drm_setup_buffers(void) 1269*4882a593Smuzhiyun+static void drm_flip_handler(int fd, unsigned frame, unsigned sec, 1270*4882a593Smuzhiyun+ unsigned usec, void *data) 1271*4882a593Smuzhiyun { 1272*4882a593Smuzhiyun- int ret; 1273*4882a593Smuzhiyun- 1274*4882a593Smuzhiyun- /* Allocate DUMB buffers */ 1275*4882a593Smuzhiyun- ret = drm_allocate_dumb(&drm_dev.drm_bufs[0]); 1276*4882a593Smuzhiyun- if (ret) 1277*4882a593Smuzhiyun- return ret; 1278*4882a593Smuzhiyun- 1279*4882a593Smuzhiyun- ret = drm_allocate_dumb(&drm_dev.drm_bufs[1]); 1280*4882a593Smuzhiyun- if (ret) 1281*4882a593Smuzhiyun- return ret; 1282*4882a593Smuzhiyun- 1283*4882a593Smuzhiyun- /* Set buffering handling */ 1284*4882a593Smuzhiyun- drm_dev.cur_bufs[0] = NULL; 1285*4882a593Smuzhiyun- drm_dev.cur_bufs[1] = &drm_dev.drm_bufs[0]; 1286*4882a593Smuzhiyun- 1287*4882a593Smuzhiyun- return 0; 1288*4882a593Smuzhiyun+ // data is &dev->waiting_for_flip 1289*4882a593Smuzhiyun+ DRM_DEBUG("Page flip received(%d)!, %d, %d, %d, %d\n", *(int*)data, fd, frame, sec, usec); 1290*4882a593Smuzhiyun+ *(int*)data = 0; 1291*4882a593Smuzhiyun } 1292*4882a593Smuzhiyun 1293*4882a593Smuzhiyun-void drm_wait_vsync(lv_disp_drv_t *disp_drv) 1294*4882a593Smuzhiyun+int drm_init(int bpp) 1295*4882a593Smuzhiyun { 1296*4882a593Smuzhiyun- int ret; 1297*4882a593Smuzhiyun- fd_set fds; 1298*4882a593Smuzhiyun- FD_ZERO(&fds); 1299*4882a593Smuzhiyun- FD_SET(drm_dev.fd, &fds); 1300*4882a593Smuzhiyun- 1301*4882a593Smuzhiyun- do { 1302*4882a593Smuzhiyun- ret = select(drm_dev.fd + 1, &fds, NULL, NULL, NULL); 1303*4882a593Smuzhiyun- } while (ret == -1 && errno == EINTR); 1304*4882a593Smuzhiyun- 1305*4882a593Smuzhiyun- if (ret < 0) { 1306*4882a593Smuzhiyun- err("select failed: %s", strerror(errno)); 1307*4882a593Smuzhiyun- drmModeAtomicFree(drm_dev.req); 1308*4882a593Smuzhiyun- drm_dev.req = NULL; 1309*4882a593Smuzhiyun- return; 1310*4882a593Smuzhiyun- } 1311*4882a593Smuzhiyun- 1312*4882a593Smuzhiyun- if (FD_ISSET(drm_dev.fd, &fds)) 1313*4882a593Smuzhiyun- drmHandleEvent(drm_dev.fd, &drm_dev.drm_event_ctx); 1314*4882a593Smuzhiyun- 1315*4882a593Smuzhiyun- drmModeAtomicFree(drm_dev.req); 1316*4882a593Smuzhiyun- drm_dev.req = NULL; 1317*4882a593Smuzhiyun+ int ret; 1318*4882a593Smuzhiyun+ 1319*4882a593Smuzhiyun+ pdev = malloc(sizeof(struct device)); 1320*4882a593Smuzhiyun+ if (pdev == NULL) { 1321*4882a593Smuzhiyun+ fprintf(stderr, "allocate device failed\n"); 1322*4882a593Smuzhiyun+ return -1; 1323*4882a593Smuzhiyun+ } 1324*4882a593Smuzhiyun+ memset(pdev, 0, sizeof(*pdev)); 1325*4882a593Smuzhiyun+ 1326*4882a593Smuzhiyun+ //drm_install_sighandler(pdev); 1327*4882a593Smuzhiyun+ 1328*4882a593Smuzhiyun+ pdev->fd = drmOpen(NULL, NULL); 1329*4882a593Smuzhiyun+ if (pdev->fd < 0) 1330*4882a593Smuzhiyun+ pdev->fd = open("/dev/dri/card0", O_RDWR); 1331*4882a593Smuzhiyun+ if (pdev->fd < 0) { 1332*4882a593Smuzhiyun+ fprintf(stderr, "drm open failed\n"); 1333*4882a593Smuzhiyun+ goto err_drm_open; 1334*4882a593Smuzhiyun+ } 1335*4882a593Smuzhiyun+ fcntl(pdev->fd, F_SETFD, FD_CLOEXEC); 1336*4882a593Smuzhiyun+ 1337*4882a593Smuzhiyun+ drmSetClientCap(pdev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); 1338*4882a593Smuzhiyun+ 1339*4882a593Smuzhiyun+ ret = alloc_fb(pdev, NUM_DUMB_BO, bpp); 1340*4882a593Smuzhiyun+ if (ret) { 1341*4882a593Smuzhiyun+ fprintf(stderr, "alloc fb failed\n"); 1342*4882a593Smuzhiyun+ goto err_alloc_fb; 1343*4882a593Smuzhiyun+ } 1344*4882a593Smuzhiyun+ 1345*4882a593Smuzhiyun+ ret = drm_setup(pdev); 1346*4882a593Smuzhiyun+ if (ret) { 1347*4882a593Smuzhiyun+ fprintf(stderr, "drm setup failed\n"); 1348*4882a593Smuzhiyun+ goto err_drm_setup; 1349*4882a593Smuzhiyun+ } 1350*4882a593Smuzhiyun+ 1351*4882a593Smuzhiyun+ pdev->drm_pollfd.fd = pdev->fd; 1352*4882a593Smuzhiyun+ pdev->drm_pollfd.events = POLLIN; 1353*4882a593Smuzhiyun+ 1354*4882a593Smuzhiyun+ pdev->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; 1355*4882a593Smuzhiyun+ pdev->drm_evctx.page_flip_handler = drm_flip_handler; 1356*4882a593Smuzhiyun+ 1357*4882a593Smuzhiyun+ return 0; 1358*4882a593Smuzhiyun+err_alloc_fb: 1359*4882a593Smuzhiyun+ drm_free(pdev); 1360*4882a593Smuzhiyun+err_drm_setup: 1361*4882a593Smuzhiyun+ drmClose(pdev->fd); 1362*4882a593Smuzhiyun+err_drm_open: 1363*4882a593Smuzhiyun+ free(pdev); 1364*4882a593Smuzhiyun+ pdev = NULL; 1365*4882a593Smuzhiyun+ return -1; 1366*4882a593Smuzhiyun } 1367*4882a593Smuzhiyun 1368*4882a593Smuzhiyun-void drm_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) 1369*4882a593Smuzhiyun+int drm_exit(void) 1370*4882a593Smuzhiyun { 1371*4882a593Smuzhiyun- struct drm_buffer *fbuf = drm_dev.cur_bufs[1]; 1372*4882a593Smuzhiyun- lv_coord_t w = (area->x2 - area->x1 + 1); 1373*4882a593Smuzhiyun- lv_coord_t h = (area->y2 - area->y1 + 1); 1374*4882a593Smuzhiyun- int i, y; 1375*4882a593Smuzhiyun+ struct device* dev = pdev; 1376*4882a593Smuzhiyun+ if (!dev) 1377*4882a593Smuzhiyun+ return 0; 1378*4882a593Smuzhiyun 1379*4882a593Smuzhiyun- dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h); 1380*4882a593Smuzhiyun+ free_fb(dev); 1381*4882a593Smuzhiyun+ drm_free(dev); 1382*4882a593Smuzhiyun 1383*4882a593Smuzhiyun- /* Partial update */ 1384*4882a593Smuzhiyun- if ((w != drm_dev.width || h != drm_dev.height) && drm_dev.cur_bufs[0]) 1385*4882a593Smuzhiyun- memcpy(fbuf->map, drm_dev.cur_bufs[0]->map, fbuf->size); 1386*4882a593Smuzhiyun+ if (pdev->fd > 0) 1387*4882a593Smuzhiyun+ drmClose(dev->fd); 1388*4882a593Smuzhiyun 1389*4882a593Smuzhiyun- for (y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) { 1390*4882a593Smuzhiyun- memcpy((uint8_t *)fbuf->map + (area->x1 * (LV_COLOR_SIZE/8)) + (fbuf->pitch * i), 1391*4882a593Smuzhiyun- (uint8_t *)color_p + (w * (LV_COLOR_SIZE/8) * y), 1392*4882a593Smuzhiyun- w * (LV_COLOR_SIZE/8)); 1393*4882a593Smuzhiyun- } 1394*4882a593Smuzhiyun+ free(pdev); 1395*4882a593Smuzhiyun+ pdev = NULL; 1396*4882a593Smuzhiyun 1397*4882a593Smuzhiyun- if (drm_dev.req) 1398*4882a593Smuzhiyun- drm_wait_vsync(disp_drv); 1399*4882a593Smuzhiyun+ return 0; 1400*4882a593Smuzhiyun+} 1401*4882a593Smuzhiyun 1402*4882a593Smuzhiyun- /* show fbuf plane */ 1403*4882a593Smuzhiyun- if (drm_dmabuf_set_plane(fbuf)) { 1404*4882a593Smuzhiyun- err("Flush fail"); 1405*4882a593Smuzhiyun- return; 1406*4882a593Smuzhiyun- } 1407*4882a593Smuzhiyun- else 1408*4882a593Smuzhiyun- dbg("Flush done"); 1409*4882a593Smuzhiyun+int getdrmfd(void) 1410*4882a593Smuzhiyun+{ 1411*4882a593Smuzhiyun+ return pdev->fd; 1412*4882a593Smuzhiyun+} 1413*4882a593Smuzhiyun 1414*4882a593Smuzhiyun- if (!drm_dev.cur_bufs[0]) 1415*4882a593Smuzhiyun- drm_dev.cur_bufs[1] = &drm_dev.drm_bufs[1]; 1416*4882a593Smuzhiyun- else 1417*4882a593Smuzhiyun- drm_dev.cur_bufs[1] = drm_dev.cur_bufs[0]; 1418*4882a593Smuzhiyun+static void drm_wait_flip(struct device* dev, int timeout) 1419*4882a593Smuzhiyun+{ 1420*4882a593Smuzhiyun+ int ret; 1421*4882a593Smuzhiyun 1422*4882a593Smuzhiyun- drm_dev.cur_bufs[0] = fbuf; 1423*4882a593Smuzhiyun+ while (dev->waiting_for_flip) { 1424*4882a593Smuzhiyun+ dev->drm_pollfd.revents = 0; 1425*4882a593Smuzhiyun+ ret = poll(&dev->drm_pollfd, 1, timeout); 1426*4882a593Smuzhiyun+ if (ret <= 0) 1427*4882a593Smuzhiyun+ return; 1428*4882a593Smuzhiyun 1429*4882a593Smuzhiyun- lv_disp_flush_ready(disp_drv); 1430*4882a593Smuzhiyun+ drmHandleEvent(dev->fd, &dev->drm_evctx); 1431*4882a593Smuzhiyun+ } 1432*4882a593Smuzhiyun } 1433*4882a593Smuzhiyun 1434*4882a593Smuzhiyun-#if LV_COLOR_DEPTH == 32 1435*4882a593Smuzhiyun-#define DRM_FOURCC DRM_FORMAT_ARGB8888 1436*4882a593Smuzhiyun-#elif LV_COLOR_DEPTH == 16 1437*4882a593Smuzhiyun-#define DRM_FOURCC DRM_FORMAT_RGB565 1438*4882a593Smuzhiyun-#else 1439*4882a593Smuzhiyun-#error LV_COLOR_DEPTH not supported 1440*4882a593Smuzhiyun-#endif 1441*4882a593Smuzhiyun- 1442*4882a593Smuzhiyun-void drm_get_sizes(lv_coord_t *width, lv_coord_t *height, uint32_t *dpi) 1443*4882a593Smuzhiyun+void setdrmdisp(struct drm_bo *bo) 1444*4882a593Smuzhiyun { 1445*4882a593Smuzhiyun- if (width) 1446*4882a593Smuzhiyun- *width = drm_dev.width; 1447*4882a593Smuzhiyun- 1448*4882a593Smuzhiyun- if (height) 1449*4882a593Smuzhiyun- *height = drm_dev.height; 1450*4882a593Smuzhiyun- 1451*4882a593Smuzhiyun- if (dpi && drm_dev.mmWidth) 1452*4882a593Smuzhiyun- *dpi = DIV_ROUND_UP(drm_dev.width * 25400, drm_dev.mmWidth * 1000); 1453*4882a593Smuzhiyun+ struct device* dev = pdev; 1454*4882a593Smuzhiyun+ int crtc_x, crtc_y, crtc_w, crtc_h; 1455*4882a593Smuzhiyun+ int ret; 1456*4882a593Smuzhiyun+ int fb = bo->fb_id, sw = dev->mode.width, sh = dev->mode.height; 1457*4882a593Smuzhiyun+ 1458*4882a593Smuzhiyun+ if (dev == NULL) 1459*4882a593Smuzhiyun+ return; 1460*4882a593Smuzhiyun+ 1461*4882a593Smuzhiyun+ crtc_w = dev->mode.width; 1462*4882a593Smuzhiyun+ crtc_h = dev->mode.height; 1463*4882a593Smuzhiyun+ crtc_x = 0; 1464*4882a593Smuzhiyun+ crtc_y = 0; 1465*4882a593Smuzhiyun+ 1466*4882a593Smuzhiyun+ DRM_DEBUG("Display bo %d(%dx%d) at (%d,%d) %dx%d\n", fb, sw, sh, 1467*4882a593Smuzhiyun+ crtc_x, crtc_y, crtc_w, crtc_h); 1468*4882a593Smuzhiyun+ ret = drmModeSetPlane(dev->fd, dev->plane_id, dev->crtc_id, fb, 0, 1469*4882a593Smuzhiyun+ crtc_x, crtc_y, crtc_w, crtc_h, 1470*4882a593Smuzhiyun+ 0, 0, sw << 16, sh << 16); 1471*4882a593Smuzhiyun+ if (ret) { 1472*4882a593Smuzhiyun+ fprintf(stderr, "drm set plane failed\n"); 1473*4882a593Smuzhiyun+ return; 1474*4882a593Smuzhiyun+ } 1475*4882a593Smuzhiyun+ if (0) { 1476*4882a593Smuzhiyun+ // Queue page flip 1477*4882a593Smuzhiyun+ dev->waiting_for_flip = 1; 1478*4882a593Smuzhiyun+ ret = drmModePageFlip(dev->fd, dev->crtc_id, fb, 1479*4882a593Smuzhiyun+ DRM_MODE_PAGE_FLIP_EVENT, &dev->waiting_for_flip); 1480*4882a593Smuzhiyun+ if (ret) { 1481*4882a593Smuzhiyun+ fprintf(stderr, "drm page flip failed\n"); 1482*4882a593Smuzhiyun+ return; 1483*4882a593Smuzhiyun+ } 1484*4882a593Smuzhiyun+ // Wait for last page flip 1485*4882a593Smuzhiyun+ drm_wait_flip(dev, -1); 1486*4882a593Smuzhiyun+ } 1487*4882a593Smuzhiyun } 1488*4882a593Smuzhiyun 1489*4882a593Smuzhiyun-void drm_init(void) 1490*4882a593Smuzhiyun+void getdrmresolve(int *w, int *h) 1491*4882a593Smuzhiyun { 1492*4882a593Smuzhiyun- int ret; 1493*4882a593Smuzhiyun+ *w = pdev->mode.width; 1494*4882a593Smuzhiyun+ *h = pdev->mode.height; 1495*4882a593Smuzhiyun+} 1496*4882a593Smuzhiyun 1497*4882a593Smuzhiyun- ret = drm_setup(DRM_FOURCC); 1498*4882a593Smuzhiyun- if (ret) { 1499*4882a593Smuzhiyun- close(drm_dev.fd); 1500*4882a593Smuzhiyun- drm_dev.fd = -1; 1501*4882a593Smuzhiyun- return; 1502*4882a593Smuzhiyun- } 1503*4882a593Smuzhiyun+static void *drm_thread(void *arg) 1504*4882a593Smuzhiyun+{ 1505*4882a593Smuzhiyun+ while (!quit) { 1506*4882a593Smuzhiyun+ pthread_mutex_lock(&draw_mutex); 1507*4882a593Smuzhiyun+ if (draw_update) { 1508*4882a593Smuzhiyun+ setdrmdisp(gbo); 1509*4882a593Smuzhiyun+ draw_update = 0; 1510*4882a593Smuzhiyun+ } 1511*4882a593Smuzhiyun+ pthread_mutex_unlock(&draw_mutex); 1512*4882a593Smuzhiyun+ usleep(10000); 1513*4882a593Smuzhiyun+ } 1514*4882a593Smuzhiyun+ return NULL; 1515*4882a593Smuzhiyun+} 1516*4882a593Smuzhiyun 1517*4882a593Smuzhiyun- ret = drm_setup_buffers(); 1518*4882a593Smuzhiyun- if (ret) { 1519*4882a593Smuzhiyun- err("DRM buffer allocation failed"); 1520*4882a593Smuzhiyun- close(drm_dev.fd); 1521*4882a593Smuzhiyun- drm_dev.fd = -1; 1522*4882a593Smuzhiyun- return; 1523*4882a593Smuzhiyun- } 1524*4882a593Smuzhiyun+void drm_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) 1525*4882a593Smuzhiyun+{ 1526*4882a593Smuzhiyun+ /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/ 1527*4882a593Smuzhiyun+ int32_t x; 1528*4882a593Smuzhiyun+ int32_t y; 1529*4882a593Smuzhiyun+ 1530*4882a593Smuzhiyun+ pthread_mutex_lock(&draw_mutex); 1531*4882a593Smuzhiyun+ for(y = area->y1; y <= area->y2; y++) { 1532*4882a593Smuzhiyun+ int area_w = area->x2 - area->x1 + 1; 1533*4882a593Smuzhiyun+ lv_color_t *disp = (lv_color_t*)(drm_buff + (y * lcd_sw + area->x1) * 4); 1534*4882a593Smuzhiyun+ memcpy(disp, color_p, area_w * 4); 1535*4882a593Smuzhiyun+ color_p += area_w; 1536*4882a593Smuzhiyun+ } 1537*4882a593Smuzhiyun+ draw_update = 1; 1538*4882a593Smuzhiyun+ pthread_mutex_unlock(&draw_mutex); 1539*4882a593Smuzhiyun+ /*IMPORTANT!!! 1540*4882a593Smuzhiyun+ *Inform the graphics library that you are ready with the flushing*/ 1541*4882a593Smuzhiyun+ lv_disp_flush_ready(disp_drv); 1542*4882a593Smuzhiyun+} 1543*4882a593Smuzhiyun 1544*4882a593Smuzhiyun- info("DRM subsystem and buffer mapped successfully"); 1545*4882a593Smuzhiyun+void disp_init(void) 1546*4882a593Smuzhiyun+{ 1547*4882a593Smuzhiyun+ /*You code here*/ 1548*4882a593Smuzhiyun+ drm_init(32); 1549*4882a593Smuzhiyun+ getdrmresolve(&lcd_w, &lcd_h); 1550*4882a593Smuzhiyun+ gbo = malloc_drm_bo(lcd_w, lcd_h, DRM_FORMAT_ARGB8888); 1551*4882a593Smuzhiyun+ drm_buff = gbo->ptr; 1552*4882a593Smuzhiyun+ lcd_sw = gbo->pitch / 4; 1553*4882a593Smuzhiyun+ 1554*4882a593Smuzhiyun+ printf("DRM subsystem and buffer mapped successfully\n"); 1555*4882a593Smuzhiyun } 1556*4882a593Smuzhiyun 1557*4882a593Smuzhiyun-void drm_exit(void) 1558*4882a593Smuzhiyun+void drm_disp_drv_init(int rot) 1559*4882a593Smuzhiyun { 1560*4882a593Smuzhiyun- close(drm_dev.fd); 1561*4882a593Smuzhiyun- drm_dev.fd = -1; 1562*4882a593Smuzhiyun+ /*------------------------- 1563*4882a593Smuzhiyun+ * Initialize your display 1564*4882a593Smuzhiyun+ * -----------------------*/ 1565*4882a593Smuzhiyun+ disp_init(); 1566*4882a593Smuzhiyun+ 1567*4882a593Smuzhiyun+ /*----------------------------- 1568*4882a593Smuzhiyun+ * Create a buffer for drawing 1569*4882a593Smuzhiyun+ *----------------------------*/ 1570*4882a593Smuzhiyun+ 1571*4882a593Smuzhiyun+ /** 1572*4882a593Smuzhiyun+ * LVGL requires a buffer where it internally draws the widgets. 1573*4882a593Smuzhiyun+ * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display. 1574*4882a593Smuzhiyun+ * The buffer has to be greater than 1 display row 1575*4882a593Smuzhiyun+ * 1576*4882a593Smuzhiyun+ * There are 3 buffering configurations: 1577*4882a593Smuzhiyun+ * 1. Create ONE buffer: 1578*4882a593Smuzhiyun+ * LVGL will draw the display's content here and writes it to your display 1579*4882a593Smuzhiyun+ * 1580*4882a593Smuzhiyun+ * 2. Create TWO buffer: 1581*4882a593Smuzhiyun+ * LVGL will draw the display's content to a buffer and writes it your display. 1582*4882a593Smuzhiyun+ * You should use DMA to write the buffer's content to the display. 1583*4882a593Smuzhiyun+ * It will enable LVGL to draw the next part of the screen to the other buffer while 1584*4882a593Smuzhiyun+ * the data is being sent form the first buffer. It makes rendering and flushing parallel. 1585*4882a593Smuzhiyun+ * 1586*4882a593Smuzhiyun+ * 3. Double buffering 1587*4882a593Smuzhiyun+ * Set 2 screens sized buffers and set disp_drv.full_refresh = 1. 1588*4882a593Smuzhiyun+ * This way LVGL will always provide the whole rendered screen in `flush_cb` 1589*4882a593Smuzhiyun+ * and you only need to change the frame buffer's address. 1590*4882a593Smuzhiyun+ */ 1591*4882a593Smuzhiyun+ 1592*4882a593Smuzhiyun+ /* Example for 1) */ 1593*4882a593Smuzhiyun+ static lv_disp_draw_buf_t draw_buf_dsc_1; 1594*4882a593Smuzhiyun+ buf_1 = memalign(64, lcd_w * lcd_h * 4); 1595*4882a593Smuzhiyun+ 1596*4882a593Smuzhiyun+ lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, lcd_w * lcd_h); /*Initialize the display buffer*/ 1597*4882a593Smuzhiyun+ 1598*4882a593Smuzhiyun+ /*----------------------------------- 1599*4882a593Smuzhiyun+ * Register the display in LVGL 1600*4882a593Smuzhiyun+ *----------------------------------*/ 1601*4882a593Smuzhiyun+ 1602*4882a593Smuzhiyun+ static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ 1603*4882a593Smuzhiyun+ lv_disp_drv_init(&disp_drv); /*Basic initialization*/ 1604*4882a593Smuzhiyun+ 1605*4882a593Smuzhiyun+ /*Set up the functions to access to your display*/ 1606*4882a593Smuzhiyun+ 1607*4882a593Smuzhiyun+ /*Set the resolution of the display*/ 1608*4882a593Smuzhiyun+ disp_drv.hor_res = lcd_w; 1609*4882a593Smuzhiyun+ disp_drv.ver_res = lcd_h; 1610*4882a593Smuzhiyun+ 1611*4882a593Smuzhiyun+ disp_drv.sw_rotate = 0; 1612*4882a593Smuzhiyun+ disp_drv.rotated = LV_DISP_ROT_NONE; 1613*4882a593Smuzhiyun+ /*Used to copy the buffer's content to the display*/ 1614*4882a593Smuzhiyun+ disp_drv.flush_cb = drm_flush; 1615*4882a593Smuzhiyun+ 1616*4882a593Smuzhiyun+ /*Set a display buffer*/ 1617*4882a593Smuzhiyun+ disp_drv.draw_buf = &draw_buf_dsc_1; 1618*4882a593Smuzhiyun+ 1619*4882a593Smuzhiyun+ /*Finally register the driver*/ 1620*4882a593Smuzhiyun+ lv_disp_drv_register(&disp_drv); 1621*4882a593Smuzhiyun+ pthread_mutex_init(&draw_mutex, NULL); 1622*4882a593Smuzhiyun+ pthread_create(&drm_thread_pid, NULL, drm_thread, NULL); 1623*4882a593Smuzhiyun } 1624*4882a593Smuzhiyun 1625*4882a593Smuzhiyun #endif 1626*4882a593Smuzhiyundiff --git a/display/drm.h b/display/drm.h 1627*4882a593Smuzhiyunindex ebf2e28..74695a9 100644 1628*4882a593Smuzhiyun--- a/display/drm.h 1629*4882a593Smuzhiyun+++ b/display/drm.h 1630*4882a593Smuzhiyun@@ -40,11 +40,10 @@ extern "C" { 1631*4882a593Smuzhiyun /********************** 1632*4882a593Smuzhiyun * GLOBAL PROTOTYPES 1633*4882a593Smuzhiyun **********************/ 1634*4882a593Smuzhiyun-void drm_init(void); 1635*4882a593Smuzhiyun-void drm_get_sizes(lv_coord_t *width, lv_coord_t *height, uint32_t *dpi); 1636*4882a593Smuzhiyun-void drm_exit(void); 1637*4882a593Smuzhiyun+int drm_init(int bpp); 1638*4882a593Smuzhiyun+void drm_disp_drv_init(int rot); 1639*4882a593Smuzhiyun+int drm_exit(void); 1640*4882a593Smuzhiyun void drm_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p); 1641*4882a593Smuzhiyun-void drm_wait_vsync(lv_disp_drv_t * drv); 1642*4882a593Smuzhiyun 1643*4882a593Smuzhiyun 1644*4882a593Smuzhiyun /********************** 1645*4882a593Smuzhiyun-- 1646*4882a593Smuzhiyun2.25.1 1647*4882a593Smuzhiyun 1648