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