1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
3*4882a593Smuzhiyun * author: Zhihua Wang, hogan.wang@rock-chips.com
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun * General Public License (GPL), available from the file
8*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the
9*4882a593Smuzhiyun * OpenIB.org BSD license below:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or
12*4882a593Smuzhiyun * without modification, are permitted provided that the following
13*4882a593Smuzhiyun * conditions are met:
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * - Redistributions of source code must retain the above
16*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
17*4882a593Smuzhiyun * disclaimer.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above
20*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
21*4882a593Smuzhiyun * disclaimer in the documentation and/or other materials
22*4882a593Smuzhiyun * provided with the distribution.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31*4882a593Smuzhiyun * SOFTWARE.
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun #include <stdio.h>
34*4882a593Smuzhiyun #include <unistd.h>
35*4882a593Smuzhiyun #include <string.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #include <rga/RgaApi.h>
38*4882a593Smuzhiyun #include "display.h"
39*4882a593Smuzhiyun #include "rkdrm_display.h"
40*4882a593Smuzhiyun //#include "rkfacial.h"
41*4882a593Smuzhiyun #include "rga_control.h"
42*4882a593Smuzhiyun #include <pthread.h>
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define BUF_COUNT 3
45*4882a593Smuzhiyun #define USE_NV12
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct display {
48*4882a593Smuzhiyun int fmt;
49*4882a593Smuzhiyun int width;
50*4882a593Smuzhiyun int height;
51*4882a593Smuzhiyun int plane_type;
52*4882a593Smuzhiyun struct drm_dev dev;
53*4882a593Smuzhiyun struct drm_buf buf[BUF_COUNT];
54*4882a593Smuzhiyun int buf_cnt;
55*4882a593Smuzhiyun int rga_fmt;
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun struct display g_disp;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct window {
61*4882a593Smuzhiyun bo_t bo;
62*4882a593Smuzhiyun int fd;
63*4882a593Smuzhiyun int width;
64*4882a593Smuzhiyun int height;
65*4882a593Smuzhiyun int x;
66*4882a593Smuzhiyun int y;
67*4882a593Smuzhiyun int fmt;
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct window win0, win1, win2;
71*4882a593Smuzhiyun static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
72*4882a593Smuzhiyun static pthread_t g_th;
73*4882a593Smuzhiyun
drm_display_init(struct display * disp)74*4882a593Smuzhiyun static int drm_display_init(struct display *disp)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun int ret;
77*4882a593Smuzhiyun if (drmInit(&disp->dev)) {
78*4882a593Smuzhiyun fprintf(stderr, "drmInit: Failed\n");
79*4882a593Smuzhiyun return -1;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun for (int i = 0; i < disp->buf_cnt; i++) {
83*4882a593Smuzhiyun ret = drmGetBuffer(disp->dev.drm_fd, disp->width, disp->height, disp->fmt, &disp->buf[i]);
84*4882a593Smuzhiyun if (ret) {
85*4882a593Smuzhiyun fprintf(stderr, "Alloc drm buffer failed, %d\n", i);
86*4882a593Smuzhiyun return -1;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun return 0;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
display_compose(void * srcp,int srcw,int srch,int fmt,int x,int y)93*4882a593Smuzhiyun static void display_compose(void *srcp, int srcw, int srch, int fmt, int x, int y)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun rga_info_t src, dst;
96*4882a593Smuzhiyun memset(&src, 0, sizeof(rga_info_t));
97*4882a593Smuzhiyun src.fd = -1;
98*4882a593Smuzhiyun src.virAddr = srcp;
99*4882a593Smuzhiyun src.mmuFlag = 1;
100*4882a593Smuzhiyun rga_set_rect(&src.rect, 0, 0, srcw, srch, srcw, srch, fmt);
101*4882a593Smuzhiyun memset(&dst, 0, sizeof(rga_info_t));
102*4882a593Smuzhiyun dst.fd = -1;
103*4882a593Smuzhiyun dst.virAddr = win0.bo.ptr;
104*4882a593Smuzhiyun dst.mmuFlag = 1;
105*4882a593Smuzhiyun rga_set_rect(&dst.rect, x, y, srcw, srch, win0.width, win0.height, fmt);
106*4882a593Smuzhiyun if (c_RkRgaBlit(&src, &dst, NULL))
107*4882a593Smuzhiyun printf("%s: rga fail\n", __func__);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
display_win_thread(void * arg)110*4882a593Smuzhiyun static void *display_win_thread(void *arg)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun while (1) {
113*4882a593Smuzhiyun pthread_mutex_lock(&lock);
114*4882a593Smuzhiyun display_compose(win1.bo.ptr, win1.width, win1.height, win1.fmt, win1.x, win1.y);
115*4882a593Smuzhiyun display_compose(win2.bo.ptr, win2.width, win2.height, win2.fmt, win2.x, win2.y);
116*4882a593Smuzhiyun pthread_mutex_unlock(&lock);
117*4882a593Smuzhiyun display_commit(win0.bo.ptr, win0.fd, win0.fmt, win0.width, win0.height, 0);
118*4882a593Smuzhiyun usleep(10000);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun pthread_exit(NULL);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
display_init(int width,int height)123*4882a593Smuzhiyun int display_init(int width, int height)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun int ret;
126*4882a593Smuzhiyun #ifdef USE_NV12
127*4882a593Smuzhiyun g_disp.fmt = DRM_FORMAT_NV12;
128*4882a593Smuzhiyun g_disp.rga_fmt = RK_FORMAT_YCbCr_420_SP;
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun #ifdef USE_RGB888
131*4882a593Smuzhiyun g_disp.fmt = DRM_FORMAT_BGR888;
132*4882a593Smuzhiyun g_disp.rga_fmt = RK_FORMAT_RGB_888;
133*4882a593Smuzhiyun #endif
134*4882a593Smuzhiyun g_disp.width = width;
135*4882a593Smuzhiyun g_disp.height = height;
136*4882a593Smuzhiyun g_disp.plane_type = DRM_PLANE_TYPE_OVERLAY;
137*4882a593Smuzhiyun g_disp.buf_cnt = BUF_COUNT;
138*4882a593Smuzhiyun ret = drm_display_init(&g_disp);
139*4882a593Smuzhiyun if (ret)
140*4882a593Smuzhiyun return ret;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun win0.width = 720;
143*4882a593Smuzhiyun win0.height = 1280;
144*4882a593Smuzhiyun rga_control_buffer_init(&win0.bo, &win0.fd, win0.width, win0.height, 12);
145*4882a593Smuzhiyun win1.width = 720;
146*4882a593Smuzhiyun win1.height = 640;
147*4882a593Smuzhiyun rga_control_buffer_init(&win1.bo, &win1.fd, win1.width, win1.height, 12);
148*4882a593Smuzhiyun win2.width = 720;
149*4882a593Smuzhiyun win2.height = 640;
150*4882a593Smuzhiyun win2.x = 0;
151*4882a593Smuzhiyun win2.y = 640;
152*4882a593Smuzhiyun rga_control_buffer_init(&win2.bo, &win2.fd, win2.width, win2.height, 12);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun if (pthread_create(&g_th, NULL, display_win_thread, NULL)) {
155*4882a593Smuzhiyun printf("%s create fail!\n", __func__);
156*4882a593Smuzhiyun return -1;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun
drm_display_exit(struct display * disp)163*4882a593Smuzhiyun static void drm_display_exit(struct display *disp)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun drmDeinit(&disp->dev);
166*4882a593Smuzhiyun for (int i = 0; i < disp->buf_cnt; i++)
167*4882a593Smuzhiyun drmPutBuffer(disp->dev.drm_fd, &disp->buf[i]);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun rga_control_buffer_deinit(&win0.bo, win0.fd);
170*4882a593Smuzhiyun rga_control_buffer_deinit(&win1.bo, win1.fd);
171*4882a593Smuzhiyun rga_control_buffer_deinit(&win2.bo, win2.fd);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
display_exit(void)174*4882a593Smuzhiyun void display_exit(void)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun drm_display_exit(&g_disp);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
drm_commit(struct display * disp,int num,void * ptr,int fd,int fmt,int w,int h,int rotation)179*4882a593Smuzhiyun void drm_commit(struct display *disp, int num, void *ptr, int fd, int fmt, int w, int h, int rotation)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun int ret;
182*4882a593Smuzhiyun rga_info_t src, dst;
183*4882a593Smuzhiyun char *map = disp->buf[num].map;
184*4882a593Smuzhiyun int dst_w = disp->width;
185*4882a593Smuzhiyun int dst_h = disp->height;
186*4882a593Smuzhiyun int dst_fmt = disp->rga_fmt;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun memset(&src, 0, sizeof(rga_info_t));
189*4882a593Smuzhiyun src.fd = -1;
190*4882a593Smuzhiyun src.virAddr = ptr;
191*4882a593Smuzhiyun src.mmuFlag = 1;
192*4882a593Smuzhiyun src.rotation = rotation;
193*4882a593Smuzhiyun rga_set_rect(&src.rect, 0, 0, w, h, w, h, fmt);
194*4882a593Smuzhiyun memset(&dst, 0, sizeof(rga_info_t));
195*4882a593Smuzhiyun dst.fd = -1;
196*4882a593Smuzhiyun dst.virAddr = map;
197*4882a593Smuzhiyun dst.mmuFlag = 1;
198*4882a593Smuzhiyun rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, dst_fmt);
199*4882a593Smuzhiyun if (c_RkRgaBlit(&src, &dst, NULL)) {
200*4882a593Smuzhiyun printf("%s: rga fail\n", __func__);
201*4882a593Smuzhiyun return;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun ret = drmCommit(&disp->buf[num], disp->width, disp->height, 0, 0, &disp->dev, disp->plane_type);
205*4882a593Smuzhiyun if (ret) {
206*4882a593Smuzhiyun fprintf(stderr, "display commit error, ret = %d\n", ret);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
display_commit(void * ptr,int fd,int fmt,int w,int h,int rotation)210*4882a593Smuzhiyun void display_commit(void *ptr, int fd, int fmt, int w, int h, int rotation)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun static int num = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun drm_commit(&g_disp, num, ptr, fd, fmt, w, h, rotation);
215*4882a593Smuzhiyun num = (num + 1) % BUF_COUNT;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
display_switch(enum display_video_type type)218*4882a593Smuzhiyun void display_switch(enum display_video_type type)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun #if 0
221*4882a593Smuzhiyun set_rgb_display(NULL);
222*4882a593Smuzhiyun set_ir_display(NULL);
223*4882a593Smuzhiyun set_usb_display(NULL);
224*4882a593Smuzhiyun if (type == DISPLAY_VIDEO_RGB)
225*4882a593Smuzhiyun set_rgb_display(display_commit);
226*4882a593Smuzhiyun else if (type == DISPLAY_VIDEO_IR)
227*4882a593Smuzhiyun set_ir_display(display_commit);
228*4882a593Smuzhiyun else if (type == DISPLAY_VIDEO_USB)
229*4882a593Smuzhiyun set_usb_display(display_commit);
230*4882a593Smuzhiyun #endif
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
display_win(void * srcp,int fmt,int srcw,int srch,int rotation,void * dstp,int dstw,int dsth)233*4882a593Smuzhiyun void display_win(void *srcp, int fmt, int srcw, int srch, int rotation, void *dstp, int dstw, int dsth)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun rga_info_t src, dst;
236*4882a593Smuzhiyun memset(&src, 0, sizeof(rga_info_t));
237*4882a593Smuzhiyun src.fd = -1;
238*4882a593Smuzhiyun src.virAddr = srcp;
239*4882a593Smuzhiyun src.mmuFlag = 1;
240*4882a593Smuzhiyun src.rotation = rotation;
241*4882a593Smuzhiyun rga_set_rect(&src.rect, 0, 0, srcw, srch, srcw, srch, fmt);
242*4882a593Smuzhiyun memset(&dst, 0, sizeof(rga_info_t));
243*4882a593Smuzhiyun dst.fd = -1;
244*4882a593Smuzhiyun dst.virAddr = dstp;
245*4882a593Smuzhiyun dst.mmuFlag = 1;
246*4882a593Smuzhiyun rga_set_rect(&dst.rect, 0, 0, dstw, dsth, dstw, dsth, fmt);
247*4882a593Smuzhiyun if (c_RkRgaBlit(&src, &dst, NULL))
248*4882a593Smuzhiyun printf("%s: rga fail\n", __func__);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
display_win1(void * ptr,int fd,int fmt,int w,int h,int rotation)251*4882a593Smuzhiyun void display_win1(void *ptr, int fd, int fmt, int w, int h, int rotation)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun pthread_mutex_lock(&lock);
254*4882a593Smuzhiyun win0.fmt = fmt;
255*4882a593Smuzhiyun win1.fmt = fmt;
256*4882a593Smuzhiyun display_win(ptr, fmt, w, h, rotation, win1.bo.ptr, win1.width, win1.height);
257*4882a593Smuzhiyun pthread_mutex_unlock(&lock);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
display_win2(void * ptr,int fd,int fmt,int w,int h,int rotation)260*4882a593Smuzhiyun void display_win2(void *ptr, int fd, int fmt, int w, int h, int rotation)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun pthread_mutex_lock(&lock);
263*4882a593Smuzhiyun win0.fmt = fmt;
264*4882a593Smuzhiyun win2.fmt = fmt;
265*4882a593Smuzhiyun display_win(ptr, fmt, w, h, rotation, win2.bo.ptr, win2.width, win2.height);
266*4882a593Smuzhiyun pthread_mutex_unlock(&lock);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
display_get_resolution(int * width,int * height)269*4882a593Smuzhiyun void display_get_resolution(int *width, int *height)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun *width = g_disp.width;
272*4882a593Smuzhiyun *height = g_disp.height;
273*4882a593Smuzhiyun }
274