xref: /OK3568_Linux_fs/external/mpp/mpp/vproc/rga/rga.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/ioctl.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdint.h>
24 
25 #include "mpp_mem.h"
26 #include "mpp_debug.h"
27 #include "mpp_common.h"
28 
29 #include "rga.h"
30 #include "rga_api.h"
31 
32 static RK_U32 rga_debug = 0;
33 
34 #define RGB_DBG_FUNCTION    (0x00000001)
35 #define RGB_DBG_COPY        (0x00000002)
36 #define RGB_DBG_DUP_FIELD   (0x00000004)
37 
38 #define rga_dbg(flag, fmt, ...) _mpp_dbg(rga_debug, flag, fmt, ## __VA_ARGS__)
39 #define rga_dbg_func(fmt, ...)  _mpp_dbg_f(rga_debug, RGB_DBG_FUNCTION, fmt, ## __VA_ARGS__)
40 #define rga_dbg_copy(fmt, ...)  _mpp_dbg(rga_debug, RGB_DBG_COPY, fmt, ## __VA_ARGS__)
41 #define rga_dbg_dup(fmt, ...)   _mpp_dbg(rga_debug, RGB_DBG_COPY, fmt, ## __VA_ARGS__)
42 
43 #define DEFAULT_RGA_DEV     "/dev/rga"
44 
45 typedef struct RgaCtxImpl_t {
46     RK_S32 rga_fd;
47 
48     // context holds only one request structure and serial process all input
49     RgaReq request;
50 } RgaCtxImpl;
51 
is_yuv_format(int fmt)52 static int is_yuv_format(int fmt)
53 {
54     if (fmt >= RGA_FMT_YCbCr_422_SP && fmt <= RGA_FMT_YCrCb_420_P) {
55         return 1;
56     }
57 
58     return 0;
59 }
60 
is_rgb_format(int fmt)61 static int is_rgb_format(int fmt)
62 {
63     if (fmt >= RGA_FMT_RGBA_8888 && fmt <= RGA_FMT_BGR_888) {
64         return 1;
65     }
66 
67     return 0;
68 }
69 
rga_fmt_map(MppFrameFormat fmt)70 static RgaFormat rga_fmt_map(MppFrameFormat fmt)
71 {
72     RgaFormat ret;
73 
74     switch (fmt) {
75     case MPP_FMT_YUV420P:
76         ret = RGA_FMT_YCbCr_420_P;
77         break;
78     case MPP_FMT_YUV420SP:
79         ret = RGA_FMT_YCbCr_420_SP;
80         break;
81     case MPP_FMT_YUV422P:
82         ret = RGA_FMT_YCbCr_422_P;
83         break;
84     case MPP_FMT_YUV422SP:
85         ret = RGA_FMT_YCrCb_422_SP;
86         break;
87     case MPP_FMT_RGB565:
88         ret = RGA_FMT_RGB_565;
89         break;
90     case MPP_FMT_RGB888:
91         ret = RGA_FMT_RGB_888;
92         break;
93     case MPP_FMT_ARGB8888:
94         ret = RGA_FMT_RGBA_8888;
95         break;
96     default:
97         ret = RGA_FMT_BUTT;
98         mpp_err("unsupport mpp fmt %d found\n", fmt);
99         break;
100     }
101 
102     return ret;
103 }
104 
rga_init(RgaCtx * ctx)105 MPP_RET rga_init(RgaCtx *ctx)
106 {
107     MPP_RET ret = MPP_OK;
108     RgaCtxImpl *impl = NULL;
109 
110     rga_dbg_func("in\n");
111 
112     *ctx = NULL;
113 
114     impl = mpp_malloc(RgaCtxImpl, 1);
115     if (!impl) {
116         mpp_err_f("malloc context failed\n");
117         ret = MPP_ERR_NULL_PTR;
118         goto END;
119     }
120 
121     impl->rga_fd = open(DEFAULT_RGA_DEV, O_RDWR | O_CLOEXEC, 0);
122     if (impl->rga_fd < 0) {
123         mpp_err_f("open device failed\n");
124         mpp_free(impl);
125         impl = NULL;
126         ret = MPP_ERR_OPEN_FILE;
127         goto END;
128     }
129 
130 END:
131     *ctx = impl;
132     rga_dbg_func("out\n");
133     return ret;
134 }
135 
rga_deinit(RgaCtx ctx)136 MPP_RET rga_deinit(RgaCtx ctx)
137 {
138     MPP_RET ret = MPP_OK;
139     RgaCtxImpl *impl = NULL;
140 
141     rga_dbg_func("in\n");
142 
143     impl = (RgaCtxImpl *)ctx;
144     if (!impl) {
145         mpp_err_f("invalid input");
146         ret = MPP_ERR_NULL_PTR;
147         goto END;
148     }
149 
150     if (impl->rga_fd >= 0) {
151         close(impl->rga_fd);
152         impl->rga_fd = -1;
153     }
154 
155     mpp_free(impl);
156 END:
157     rga_dbg_func("out\n");
158     return ret;
159 }
160 
rga_ioctl(RgaCtxImpl * impl)161 static MPP_RET rga_ioctl(RgaCtxImpl *impl)
162 {
163     int io_ret = ioctl(impl->rga_fd, RGA_BLIT_SYNC, &impl->request);
164     if (io_ret) {
165         mpp_err("rga ioctl failed errno:%d %s", errno, strerror(errno));
166         return MPP_NOK;
167     }
168 
169     return MPP_OK;
170 }
171 
config_rga_image(RgaImg * img,MppFrame frame)172 static MPP_RET config_rga_image(RgaImg *img, MppFrame frame)
173 {
174     RgaFormat fmt = rga_fmt_map(mpp_frame_get_fmt(frame));
175     MppBuffer buf = mpp_frame_get_buffer(frame);
176     RK_U32 width  = mpp_frame_get_width(frame);
177     RK_U32 height = mpp_frame_get_height(frame);
178     RK_U32 h_str  = mpp_frame_get_hor_stride(frame);
179     RK_U32 v_str  = mpp_frame_get_ver_stride(frame);
180     RK_S32 fd = mpp_buffer_get_fd(buf);
181 
182     if (fmt >= RGA_FMT_BUTT) {
183         mpp_err("invalid input format for rga process %d\n", fmt);
184         return MPP_NOK;
185     }
186 
187     memset(img, 0, sizeof(RgaImg));
188     img->yrgb_addr = fd;
189     img->format = (RK_U32)fmt;
190     img->act_w = width;
191     img->act_h = height;
192     img->vir_w = h_str;
193     img->vir_h = v_str;
194 
195     return MPP_OK;
196 }
197 
config_rga_yuv2rgb_mode(RgaCtx ctx)198 static MPP_RET config_rga_yuv2rgb_mode(RgaCtx ctx)
199 {
200     RgaCtxImpl *impl = (RgaCtxImpl *)ctx;
201     RgaReq *request = &impl->request;
202 
203     /*
204      * yuv2rgb_mode only set when translate yuv to rgb, or rga to yuv.
205      * If format of input and output are both yuv or rga, set yuv2rgb_mode to 0.
206      */
207     int src_format = request->src.format;
208     int dst_format = request->dst.format;
209 
210     request->yuv2rgb_mode = 0;
211     if (is_yuv_format(src_format) && is_rgb_format(dst_format)) {
212         /* Special config for yuv to rgb */
213         request->yuv2rgb_mode |= 0x1 << 0;
214     } else if (is_rgb_format(src_format) && is_yuv_format(dst_format)) {
215         /* Special config for rgb to yuv */
216         request->yuv2rgb_mode = (2 << 4);
217     }
218 
219     return MPP_OK;
220 }
221 
rga_control(RgaCtx ctx,RgaCmd cmd,void * param)222 MPP_RET rga_control(RgaCtx ctx, RgaCmd cmd, void *param)
223 {
224     if (NULL == ctx) {
225         mpp_err_f("invalid NULL input\n");
226         return MPP_ERR_NULL_PTR;
227     }
228 
229     rga_dbg_func("in\n");
230 
231     MPP_RET ret = MPP_OK;
232     RgaCtxImpl *impl = (RgaCtxImpl *)ctx;
233     RgaReq *request = &impl->request;
234 
235     switch (cmd) {
236     case RGA_CMD_INIT : {
237         memset(request, 0, sizeof(*request));
238         request->mmu_info.mmu_en = 1;
239         request->mmu_info.mmu_flag = 1;
240         request->mmu_info.mmu_flag = ((2 & 0x3) << 4) | 1;
241         request->mmu_info.mmu_flag |= (1 << 31) | (1 << 10) | (1 << 8);
242     } break;
243     case RGA_CMD_SET_SRC : {
244         if (NULL == param) {
245             mpp_err("invalid NULL param for setup source\n");
246             ret = MPP_NOK;
247             break;
248         }
249 
250         MppFrame *src = (MppFrame *)param;
251         ret = config_rga_image(&request->src, src);
252     } break;
253     case RGA_CMD_SET_DST : {
254         if (NULL == param) {
255             mpp_err("invalid NULL param for setup destination\n");
256             ret = MPP_NOK;
257             break;
258         }
259 
260         MppFrame *dst = (MppFrame *)param;
261         ret = config_rga_image(&request->dst, dst);
262         // When config dst setup default clip
263         RK_U32 width  = mpp_frame_get_width(dst);
264         RK_U32 height = mpp_frame_get_height(dst);
265         request->clip.xmin = 0;
266         request->clip.xmax = width - 1;
267         request->clip.ymin = 0;
268         request->clip.ymax = height - 1;
269     } break;
270     case RGA_CMD_RUN_SYNC : {
271         config_rga_yuv2rgb_mode(ctx);
272         ret = rga_ioctl(impl);
273     } break;
274     default : {
275         mpp_err("invalid command %d\n", cmd);
276         ret = MPP_NOK;
277     } break;
278     }
279 
280     rga_dbg_func("out\n");
281     return ret;
282 }
283 
284 // sample for copy function
rga_copy(RgaCtx ctx,MppFrame src,MppFrame dst)285 MPP_RET rga_copy(RgaCtx ctx, MppFrame src, MppFrame dst)
286 {
287     MPP_RET ret = MPP_OK;
288     RgaCtxImpl *impl = (RgaCtxImpl *)ctx;
289     MppBuffer src_buf = mpp_frame_get_buffer(src);
290     MppBuffer dst_buf = mpp_frame_get_buffer(dst);
291     RK_U32 src_w = mpp_frame_get_width(src);
292     RK_U32 src_h = mpp_frame_get_height(src);
293     RK_U32 dst_w = mpp_frame_get_width(dst);
294     RK_U32 dst_h = mpp_frame_get_height(dst);
295     RK_S32 src_fd = mpp_buffer_get_fd(src_buf);
296     RK_S32 dst_fd = mpp_buffer_get_fd(dst_buf);
297     RgaReq *request = &impl->request;
298 
299     RgaFormat src_fmt = rga_fmt_map(mpp_frame_get_fmt(src));
300     RgaFormat dst_fmt = rga_fmt_map(mpp_frame_get_fmt(dst));
301 
302     rga_dbg_func("in\n");
303 
304     if (src_fmt >= RGA_FMT_BUTT || dst_fmt >= RGA_FMT_BUTT) {
305         mpp_err("invalid input format for rga process src %d dst %d\n",
306                 src_fmt, dst_fmt);
307         ret = MPP_NOK;
308         goto END;
309     }
310 
311     mpp_assert(src_w > 0 && src_h > 0);
312 
313     if (dst_w == 0 || dst_h == 0) {
314         dst_w = src_w;
315         dst_h = src_h;
316     }
317 
318     rga_dbg_copy("[fd:w:h:fmt] src - %d:%d:%d:%d dst - %d:%d:%d:%d\n",
319                  src_fd, src_w, src_h, src_fmt,
320                  dst_fd, dst_w, dst_h, dst_fmt);
321 
322     memset(request, 0, sizeof(*request));
323     request->src.yrgb_addr = src_fd;
324     request->src.format = (RK_U32)src_fmt;
325     request->src.vir_w = mpp_frame_get_hor_stride(src);
326     request->src.vir_h = mpp_frame_get_ver_stride(src);
327     request->src.act_w = src_w;
328     request->src.act_h = src_h;
329 
330     request->dst.yrgb_addr = dst_fd;
331     request->dst.vir_w = dst_w;
332     request->dst.vir_h = dst_h;
333     request->dst.format = (RK_U32)dst_fmt;
334     request->clip.xmin = 0;
335     request->clip.xmax = dst_w - 1;
336     request->clip.ymin = 0;
337     request->clip.ymax = dst_h - 1;
338     request->dst.act_w = dst_w;
339     request->dst.act_h = dst_h;
340 
341     config_rga_yuv2rgb_mode(ctx);
342 
343     request->mmu_info.mmu_en = 1;
344     request->mmu_info.mmu_flag = 1;
345     request->mmu_info.mmu_flag = ((2 & 0x3) << 4) | 1;
346     request->mmu_info.mmu_flag |= (1 << 31) | (1 << 10) | (1 << 8);
347 
348     ret = rga_ioctl(impl);
349 END:
350     rga_dbg_func("out\n");
351     return ret;
352 }
353 
354 // sample for duplicate field to frame function
rga_dup_field(RgaCtx ctx,MppFrame frame)355 MPP_RET rga_dup_field(RgaCtx ctx, MppFrame frame)
356 {
357     MPP_RET ret = MPP_OK;
358     RgaCtxImpl *impl = (RgaCtxImpl *)ctx;
359     MppBuffer buf = mpp_frame_get_buffer(frame);
360     RK_U32 width  = mpp_frame_get_width(frame);
361     RK_U32 height = mpp_frame_get_height(frame);
362     RK_U32 h_str  = mpp_frame_get_hor_stride(frame);
363     RK_U32 v_str  = mpp_frame_get_ver_stride(frame);
364     RK_S32 fd = mpp_buffer_get_fd(buf);
365     void *ptr = mpp_buffer_get_ptr(buf);
366     RgaFormat fmt = rga_fmt_map(mpp_frame_get_fmt(frame));
367     RgaReq *request = &impl->request;
368 
369     rga_dbg_func("in\n");
370 
371     mpp_assert(fmt == RGA_FMT_YCbCr_420_SP);
372     mpp_assert(width > 0 && height > 0);
373     if (fmt != RGA_FMT_YCbCr_420_SP || width == 0 || height == 0) {
374         ret = MPP_NOK;
375         goto END;
376     }
377 
378     rga_dbg_dup("[fd:w:h:h_str:v_str:fmt] %d:%d:%d:%d:%d:%d\n",
379                 fd, width, height, h_str, v_str, fmt);
380 
381     memset(request, 0, sizeof(*request));
382     request->src.yrgb_addr = fd;
383     request->src.format = (RK_U32)fmt;
384     request->src.vir_w = h_str * 2;
385     request->src.vir_h = v_str / 2;
386     request->src.act_w = width;
387     request->src.act_h = height / 2;
388 
389     request->dst.yrgb_addr = 0;
390     request->dst.uv_addr = (RK_U32)((uintptr_t)ptr) + h_str; // special process here
391     request->dst.vir_w = h_str * 2;
392     request->dst.vir_h = v_str / 2;
393     request->dst.format = (RK_U32)fmt;
394     request->dst.act_w = width;
395     request->dst.act_h = height / 2;
396 
397     request->clip.xmin = 0;
398     request->clip.xmax = h_str * 2 - 1;
399     request->clip.ymin = 0;
400     request->clip.ymax = v_str / 2 - 1;
401 
402     request->mmu_info.mmu_en = 1;
403     request->mmu_info.mmu_flag = ((2 & 0x3) << 4) | 1;
404     request->mmu_info.mmu_flag |= (1 << 31) | (1 << 10) | (1 << 8);
405 
406     ret = rga_ioctl(impl);
407 END:
408     rga_dbg_func("out\n");
409     return ret;
410 }
411