blob: 40f676d3c6040a11b689d3d5cabfa4ebb291b659 [file] [log] [blame]
Googler9398cc32022-12-02 17:21:52 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
Googler9726be62022-12-14 05:53:31 +00002/*
Googler9398cc32022-12-02 17:21:52 +08003 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
Googler9726be62022-12-14 05:53:31 +00004 */
5
6#include "ionvideo.h"
7
Googler9398cc32022-12-02 17:21:52 +08008#define IONVIDEO_CANVAS_COUNT 5
9int ionvideo_canvas_id[IONVIDEO_CANVAS_COUNT] = {-1, -1, -1, -1, -1};
10
11void ionvideo_alloc_canvas(void)
12{
13 const char *owner = "ionvideo";
14 int i;
15
16 if (ionvideo_canvas_id[0] != -1 &&
17 ionvideo_canvas_id[1] != -1 &&
18 ionvideo_canvas_id[2] != -1 &&
19 ionvideo_canvas_id[3] != -1 &&
20 ionvideo_canvas_id[4] != -1)
21 return;
22
23 for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) {
24 if (ionvideo_canvas_id[i] == -1)
25 ionvideo_canvas_id[i] =
26 canvas_pool_map_alloc_canvas(owner);
27 }
28
29 for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) {
30 if (ionvideo_canvas_id[i] == -1) {
31 pr_err("%s: %x, %x, %x, %x, %x\n",
32 __func__,
33 ionvideo_canvas_id[0],
34 ionvideo_canvas_id[1],
35 ionvideo_canvas_id[2],
36 ionvideo_canvas_id[3],
37 ionvideo_canvas_id[4]);
38 break;
39 }
40 }
41}
42
43void ionvideo_free_canvas(void)
44{
45 int i;
46
47 for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) {
48 if (ionvideo_canvas_id[i] != -1) {
49 canvas_pool_map_free_canvas(ionvideo_canvas_id[i]);
50 ionvideo_canvas_id[i] = -1;
51 }
52 }
53}
54
Googler9726be62022-12-14 05:53:31 +000055static inline void paint_mode_convert(int paint_mode, int *src_position,
56 int *dst_paint_position,
57 int *dst_plane_position)
58{
Googler9726be62022-12-14 05:53:31 +000059 if (paint_mode == 0) { /* stretch full */
60 dst_paint_position[0] = dst_plane_position[0];
61 dst_paint_position[1] = dst_plane_position[1];
62 dst_paint_position[2] = dst_plane_position[2];
63 dst_paint_position[3] = dst_plane_position[3];
64 } else if (paint_mode == 1) { /* keep size */
65 dst_paint_position[0] =
66 (dst_plane_position[2] - src_position[2]) >> 1;
67 dst_paint_position[1] =
68 (dst_plane_position[3] - src_position[3]) >> 1;
69 dst_paint_position[2] = src_position[2];
70 dst_paint_position[3] = src_position[3];
71 } else if (paint_mode == 2) {
72 int dw = 0, dh = 0;
73
74 if (src_position[2] * dst_plane_position[3] >=
75 dst_plane_position[2]
76 * src_position[3]) { /* crop full */
77 dh = dst_plane_position[3];
78 dw = dh * src_position[2] / src_position[3];
79 } else {
80 dw = dst_plane_position[2];
81 dh = dw * src_position[3] / src_position[2];
82 }
83 dst_paint_position[0] = (dst_plane_position[2] - dw) >> 1;
84 dst_paint_position[1] = (dst_plane_position[3] - dh) >> 1;
85 dst_paint_position[2] = dw;
86 dst_paint_position[3] = dh;
87 } else if (paint_mode == 3) { /* keep ration black */
88 int dw = 0, dh = 0;
89
90 if (src_position[2] * dst_plane_position[3] >=
91 dst_plane_position[2] * src_position[3]) {
92 dw = dst_plane_position[2];
93 dh = dw * src_position[3] / src_position[2];
94 } else {
95 dh = dst_plane_position[3];
96 dw = dh * src_position[2] / src_position[3];
97 }
98 dst_paint_position[0] = (dst_plane_position[2] - dw) >> 1;
99 dst_paint_position[1] = (dst_plane_position[3] - dh) >> 1;
100 dst_paint_position[2] = dw;
101 dst_paint_position[3] = dh;
102 } else if (paint_mode == 4) {
103 ;
104 }
105}
106
107static int get_input_format(struct vframe_s *vf)
108{
109 int format = GE2D_FORMAT_M24_NV21;
110
111 if (vf->type & VIDTYPE_VIU_422) {
112 if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) {
Googler9398cc32022-12-02 17:21:52 +0800113 format = GE2D_FORMAT_S16_YUV422 |
114 (GE2D_FORMAT_S16_YUV422B & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000115 } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) {
Googler9398cc32022-12-02 17:21:52 +0800116 format = GE2D_FORMAT_S16_YUV422 |
117 (GE2D_FORMAT_S16_YUV422T & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000118 } else {
119 format = GE2D_FORMAT_S16_YUV422;
120 }
121
122 if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) {
123 if ((vf->bitdepth & BITDEPTH_Y10) &&
Googler9398cc32022-12-02 17:21:52 +0800124 (vf->bitdepth & FULL_PACK_422_MODE))
Googler9726be62022-12-14 05:53:31 +0000125 format = GE2D_FORMAT_S16_10BIT_YUV422;
126 }
127 } else if (vf->type & VIDTYPE_VIU_NV21) {
128 if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) {
Googler9398cc32022-12-02 17:21:52 +0800129 format = GE2D_FORMAT_M24_NV21 |
130 (GE2D_FORMAT_M24_NV21B & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000131 } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) {
Googler9398cc32022-12-02 17:21:52 +0800132 format = GE2D_FORMAT_M24_NV21 |
133 (GE2D_FORMAT_M24_NV21T & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000134 } else {
135 format = GE2D_FORMAT_M24_NV21;
136 }
137 } else {
138 if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) {
Googler9398cc32022-12-02 17:21:52 +0800139 format = GE2D_FORMAT_M24_YUV420 |
140 (GE2D_FMT_M24_YUV420B & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000141 } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) {
Googler9398cc32022-12-02 17:21:52 +0800142 format = GE2D_FORMAT_M24_YUV420 |
143 (GE2D_FORMAT_M24_YUV420T & (3 << 3));
Googler9726be62022-12-14 05:53:31 +0000144 } else {
145 format = GE2D_FORMAT_M24_YUV420;
146 }
147 }
148 return format;
149}
150
151static inline void ge2d_src_config(struct vframe_s *vf,
152 struct config_para_ex_s *ge2d_config)
153{
Googler9398cc32022-12-02 17:21:52 +0800154 int canvas_id = -1;
Googler9726be62022-12-14 05:53:31 +0000155 struct canvas_s src_cs0, src_cs1, src_cs2;
156
157 if (vf->canvas0Addr == (u32)-1) {
Googler9398cc32022-12-02 17:21:52 +0800158 canvas_config_config(ionvideo_canvas_id[2],
159 &vf->canvas0_config[0]);
Googler9726be62022-12-14 05:53:31 +0000160
161 if (vf->plane_num > 1)
Googler9398cc32022-12-02 17:21:52 +0800162 canvas_config_config(ionvideo_canvas_id[3],
163 &vf->canvas0_config[1]);
Googler9726be62022-12-14 05:53:31 +0000164
165 if (vf->plane_num > 2)
Googler9398cc32022-12-02 17:21:52 +0800166 canvas_config_config(ionvideo_canvas_id[4],
167 &vf->canvas0_config[2]);
Googler9726be62022-12-14 05:53:31 +0000168
Googler9398cc32022-12-02 17:21:52 +0800169 canvas_id =
170 ionvideo_canvas_id[2]
171 | (ionvideo_canvas_id[3] << 8)
172 | (ionvideo_canvas_id[4] << 16);
Googler9726be62022-12-14 05:53:31 +0000173
174 ge2d_config->src_planes[0].addr =
175 vf->canvas0_config[0].phy_addr;
176 ge2d_config->src_planes[0].w =
177 vf->canvas0_config[0].width;
178 ge2d_config->src_planes[0].h =
179 vf->canvas0_config[0].height;
180 ge2d_config->src_planes[1].addr =
181 vf->canvas0_config[1].phy_addr;
182 ge2d_config->src_planes[1].w =
183 vf->canvas0_config[1].width;
184 ge2d_config->src_planes[1].h =
185 vf->canvas0_config[1].height << 1;
186
187 if (vf->plane_num == 3) {
188 ge2d_config->src_planes[2].addr =
189 vf->canvas0_config[2].phy_addr;
190 ge2d_config->src_planes[2].w =
191 vf->canvas0_config[2].width;
192 ge2d_config->src_planes[2].h =
193 vf->canvas0_config[2].height << 1;
194 }
Googler9398cc32022-12-02 17:21:52 +0800195 ge2d_config->src_para.canvas_index = canvas_id;
Googler9726be62022-12-14 05:53:31 +0000196 } else {
197 canvas_read(vf->canvas0Addr & 0xff, &src_cs0);
198 canvas_read(vf->canvas0Addr >> 8 & 0xff, &src_cs1);
199 canvas_read(vf->canvas0Addr >> 16 & 0xff, &src_cs2);
200 ge2d_config->src_planes[0].addr = src_cs0.addr;
201 ge2d_config->src_planes[0].w = src_cs0.width;
202 ge2d_config->src_planes[0].h = src_cs0.height;
203 ge2d_config->src_planes[1].addr = src_cs1.addr;
204 ge2d_config->src_planes[1].w = src_cs1.width;
205 ge2d_config->src_planes[1].h = src_cs1.height;
206 ge2d_config->src_planes[2].addr = src_cs2.addr;
207 ge2d_config->src_planes[2].w = src_cs2.width;
208 ge2d_config->src_planes[2].h = src_cs2.height;
Googler9398cc32022-12-02 17:21:52 +0800209 ge2d_config->src_para.canvas_index = vf->canvas0Addr;
Googler9726be62022-12-14 05:53:31 +0000210 }
211 /* data operating. */
212 ge2d_config->alu_const_color = 0; /* 0x000000ff; */
213 ge2d_config->bitmask_en = 0;
214 ge2d_config->src1_gb_alpha = 0; /* 0xff; */
215
216 ge2d_config->src_key.key_enable = 0;
217 ge2d_config->src_key.key_mask = 0;
218 ge2d_config->src_key.key_mode = 0;
Googler9726be62022-12-14 05:53:31 +0000219 ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
220 ge2d_config->src_para.format = get_input_format(vf);
221 ge2d_config->src_para.fill_color_en = 0;
222 ge2d_config->src_para.fill_mode = 0;
223 ge2d_config->src_para.x_rev = 0;
224 ge2d_config->src_para.y_rev = 0;
225 ge2d_config->src_para.color = 0xffffffff;
226 ge2d_config->src_para.top = 0;
227 ge2d_config->src_para.left = 0;
228 ge2d_config->src_para.width = vf->width;
229
230 if (vf->type & VIDTYPE_INTERLACE)
231 ge2d_config->src_para.height = vf->height >> 1;
232 else
233 ge2d_config->src_para.height = vf->height;
234
235 ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
236/* ppmgr2_printk(2, "vf_width is %d , vf_height is %d type:%p\n",
237 * vf->width, vf->height, (void *)vf->type);
238 */
239}
240
241static int ge2d_paint_dst(struct ge2d_context_s *context,
Googler9398cc32022-12-02 17:21:52 +0800242 struct config_para_ex_s *ge2d_config,
243 int dst_canvas_id, int dst_pixel_format,
244 int *src_position, int *dst_paint_position,
245 int *dst_plane_position)
Googler9726be62022-12-14 05:53:31 +0000246{
247 struct canvas_s dst_cd;
248
249 ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
250 ge2d_config->dst_para.fill_color_en = 0;
251 ge2d_config->dst_para.fill_mode = 0;
252 ge2d_config->dst_para.color = 0;
253 ge2d_config->dst_para.top = dst_plane_position[0];
254 ge2d_config->dst_para.left = dst_plane_position[1];
255 ge2d_config->dst_para.width = dst_plane_position[2];
256 ge2d_config->dst_para.height = dst_plane_position[3];
257
258 if (dst_pixel_format == GE2D_FORMAT_S8_Y) {
259 canvas_read(dst_canvas_id & 0xff, &dst_cd);
260 ge2d_config->dst_planes[0].addr = dst_cd.addr;
261 ge2d_config->dst_planes[0].w = dst_cd.width;
262 ge2d_config->dst_planes[0].h = dst_cd.height;
263 ge2d_config->dst_para.canvas_index = dst_canvas_id & 0xff;
264 ge2d_config->dst_para.format = dst_pixel_format
265 | GE2D_LITTLE_ENDIAN;
266
267 if (ge2d_context_config_ex(context, ge2d_config) < 0) {
268 ppmgr2_printk(1, "Ge2d configing error.\n");
269 return -1;
270 }
271 stretchblt_noalpha(context, src_position[0], src_position[1],
Googler9398cc32022-12-02 17:21:52 +0800272 src_position[2], src_position[3],
273 dst_paint_position[0],
274 dst_paint_position[1],
275 dst_paint_position[2],
276 dst_paint_position[3]);
Googler9726be62022-12-14 05:53:31 +0000277 canvas_read(dst_canvas_id >> 8 & 0xff, &dst_cd);
278 ge2d_config->dst_planes[0].addr = dst_cd.addr;
279 ge2d_config->dst_planes[0].w = dst_cd.width;
280 ge2d_config->dst_planes[0].h = dst_cd.height;
281 ge2d_config->dst_para.canvas_index = dst_canvas_id >> 8 & 0xff;
282 ge2d_config->dst_para.format = GE2D_FORMAT_S8_CB
283 | GE2D_LITTLE_ENDIAN;
284 ge2d_config->dst_para.width = dst_paint_position[2] >> 1;
285 ge2d_config->dst_para.height = dst_paint_position[3] >> 1;
286
287 if (ge2d_context_config_ex(context, ge2d_config) < 0) {
288 ppmgr2_printk(1, "Ge2d configing error.\n");
289 return -1;
290 }
291 stretchblt_noalpha(context, src_position[0], src_position[1],
Googler9398cc32022-12-02 17:21:52 +0800292 src_position[2], src_position[3],
293 dst_paint_position[0],
294 dst_paint_position[1],
295 dst_paint_position[2],
296 dst_paint_position[3]);
Googler9726be62022-12-14 05:53:31 +0000297
298 canvas_read(dst_canvas_id >> 16 & 0xff, &dst_cd);
299 ge2d_config->dst_planes[0].addr = dst_cd.addr;
300 ge2d_config->dst_planes[0].w = dst_cd.width;
301 ge2d_config->dst_planes[0].h = dst_cd.height;
302 ge2d_config->dst_para.canvas_index = dst_canvas_id >> 16 & 0xff;
303 ge2d_config->dst_para.format = GE2D_FORMAT_S8_CR
304 | GE2D_LITTLE_ENDIAN;
305
306 if (ge2d_context_config_ex(context, ge2d_config) < 0) {
307 ppmgr2_printk(1, "Ge2d configing error.\n");
308 return -1;
309 }
310 stretchblt_noalpha(context, src_position[0], src_position[1],
Googler9398cc32022-12-02 17:21:52 +0800311 src_position[2], src_position[3],
312 dst_paint_position[0],
313 dst_paint_position[1],
314 dst_paint_position[2],
315 dst_paint_position[3]);
Googler9726be62022-12-14 05:53:31 +0000316 } else {
317 canvas_read(dst_canvas_id & 0xff, &dst_cd);
318 ge2d_config->dst_planes[0].addr = dst_cd.addr;
319 ge2d_config->dst_planes[0].w = dst_cd.width;
320 ge2d_config->dst_planes[0].h = dst_cd.height;
321 ge2d_config->dst_para.format = dst_pixel_format
322 | GE2D_LITTLE_ENDIAN;
323 ge2d_config->dst_para.canvas_index = dst_canvas_id;
324
Googler9398cc32022-12-02 17:21:52 +0800325 if (dst_paint_position[2] > dst_cd.width ||
326 dst_paint_position[3] > dst_cd.height) {
Googler9726be62022-12-14 05:53:31 +0000327 pr_info("ppmgr2-dev: error: id %d,width %d,height %d, ",
328 dst_canvas_id, dst_cd.width, dst_cd.height);
329 pr_info("ppmgr2-dev: dst_width %d,dst_height %d\n",
330 dst_paint_position[2], dst_paint_position[3]);
331 ppmgr2_printk(1, "error case : dst addr:%p\n",
Googler9398cc32022-12-02 17:21:52 +0800332 (void *)dst_cd.addr);
Googler9726be62022-12-14 05:53:31 +0000333 return -1;
334 }
335 if (ge2d_context_config_ex(context, ge2d_config) < 0) {
336 ppmgr2_printk(1, "Ge2d configing error.\n");
337 return -1;
338 }
339 stretchblt_noalpha(context, src_position[0], src_position[1],
Googler9398cc32022-12-02 17:21:52 +0800340 src_position[2], src_position[3],
341 dst_paint_position[0],
342 dst_paint_position[1],
343 dst_paint_position[2],
344 dst_paint_position[3]);
Googler9726be62022-12-14 05:53:31 +0000345 }
346/* ppmgr2_printk(2, "dst addr:%p w:%d h:%d canvas_id:%p format:%p\n",
347 * (void *)dst_cd.addr, dst_cd.width, dst_cd.height,
348 * (void *)dst_canvas_id,
349 * (void *)ge2d_config->dst_para.format);
350 */
351 ppmgr2_printk(2, "dst plane w:%d h:%d paint w:%d h:%d\n",
Googler9398cc32022-12-02 17:21:52 +0800352 dst_plane_position[2], dst_plane_position[3],
353 dst_paint_position[2], dst_paint_position[3]);
Googler9726be62022-12-14 05:53:31 +0000354
355 return 0;
356}
357
358static inline void ge2d_mirror_config(int dst_mirror,
Googler9398cc32022-12-02 17:21:52 +0800359 struct config_para_ex_s *ge2d_config)
Googler9726be62022-12-14 05:53:31 +0000360{
361 if (dst_mirror == 1) {
362 ge2d_config->dst_para.x_rev = 1;
363 ge2d_config->dst_para.y_rev = 0;
364 } else if (dst_mirror == 2) {
365 ge2d_config->dst_para.x_rev = 0;
366 ge2d_config->dst_para.y_rev = 1;
367 } else {
368 ge2d_config->dst_para.x_rev = 0;
369 ge2d_config->dst_para.y_rev = 0;
370 }
371}
372
373static inline void ge2d_angle_config(int dst_angle,
Googler9398cc32022-12-02 17:21:52 +0800374 struct config_para_ex_s *ge2d_config)
Googler9726be62022-12-14 05:53:31 +0000375{
376 if (dst_angle == 1) {
377 ge2d_config->dst_xy_swap = 1;
378 ge2d_config->dst_para.x_rev ^= 1;
379 } else if (dst_angle == 2) {
380 ge2d_config->dst_para.x_rev ^= 1;
381 ge2d_config->dst_para.y_rev ^= 1;
382 } else if (dst_angle == 3) {
383 ge2d_config->dst_xy_swap = 1;
384 ge2d_config->dst_para.y_rev ^= 1;
385 } else {
386 ge2d_config->dst_xy_swap = 0;
387 }
388}
389
390/*
391 * use ppmgr2 need to init struct ge2d_context_s,
392 * pixel_format, canvas_width, canvas_height,
393 * phy_addr, buffer_size, canvas_number.
394 */
395int ppmgr2_init(struct ppmgr2_device *ppd)
396{
397 int i = 0;
398 /* switch_mod_gate_by_name("ge2d", 1); */
399 ppd->context = create_ge2d_work_queue();
400 if (!ppd->context) {
401 ppmgr2_printk(1, "create ge2d work queue error!\n");
402 return -1;
403 }
Googler9398cc32022-12-02 17:21:52 +0800404 ppmgr2_printk(2, "%s!\n", __func__);
Googler9726be62022-12-14 05:53:31 +0000405 ppd->paint_mode = 0;
406 ppd->angle = 0;
407 ppd->mirror = 0;
408 ppd->ge2d_fmt = 0;
409 ppd->dst_width = 0;
410 ppd->dst_height = 0;
411 for (i = 0; i < IONVIDEO_POOL_SIZE; i++) {
412 ppd->phy_addr[i] = NULL;
413 ppd->canvas_id[i] = -1;
414 }
415 return 0;
416}
417
418int ppmgr2_canvas_config(struct ppmgr2_device *ppd, int index)
419{
420 int canvas_width;
421 int canvas_height;
Googler9398cc32022-12-02 17:21:52 +0800422 void *phy_addr;
Googler9726be62022-12-14 05:53:31 +0000423
Googler9398cc32022-12-02 17:21:52 +0800424 if (!ppd) {
425 ppmgr2_printk(1, "NULL physical address!\n");
Googler9726be62022-12-14 05:53:31 +0000426 return -1;
427 }
428
429 canvas_width = ppd->dst_buffer_width;
430 canvas_height = ppd->dst_buffer_height;
431
432 if (index >= IONVIDEO_POOL_SIZE) {
Googler9398cc32022-12-02 17:21:52 +0800433 ppmgr2_printk(0, "canvas index too large! %d>=%d\n", index,
434 IONVIDEO_POOL_SIZE);
Googler9726be62022-12-14 05:53:31 +0000435 return -1;
436 }
437
438 phy_addr = ppd->phy_addr[index];
439
440 if (IS_ERR_OR_NULL(phy_addr)) {
441 ppmgr2_printk(1, "NULL physical address!\n");
442 return -1;
443 }
444
Googler9398cc32022-12-02 17:21:52 +0800445 if (ppd->ge2d_fmt == GE2D_FORMAT_M24_NV21 || ppd->ge2d_fmt ==
446 GE2D_FORMAT_M24_NV12) {
447 canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr,
448 canvas_width, canvas_height, CANVAS_ADDR_NOWRAP,
449 CANVAS_BLKMODE_LINEAR);
450 canvas_config(ionvideo_canvas_id[1],
451 (ulong)
452 (phy_addr + (canvas_width * canvas_height)),
453 canvas_width, canvas_height >> 1,
454 CANVAS_ADDR_NOWRAP,
455 CANVAS_BLKMODE_LINEAR);
456 ppd->canvas_id[index] = ionvideo_canvas_id[0] |
457 (ionvideo_canvas_id[1] << 8);
Googler9726be62022-12-14 05:53:31 +0000458 } else if (ppd->ge2d_fmt == GE2D_FORMAT_S8_Y) {
Googler9398cc32022-12-02 17:21:52 +0800459 canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr,
460 canvas_width, canvas_height, CANVAS_ADDR_NOWRAP,
461 CANVAS_BLKMODE_LINEAR);
462 canvas_config(ionvideo_canvas_id[1],
463 (ulong)(phy_addr + canvas_width * canvas_height),
464 canvas_width >> 1, canvas_height >> 1,
465 CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
466 canvas_config(ionvideo_canvas_id[2],
467 (ulong)
468 (phy_addr + (canvas_width * canvas_height * 5 >>
469 2)),
Googler9726be62022-12-14 05:53:31 +0000470 canvas_width >> 1, canvas_height >> 1,
471 CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
Googler9398cc32022-12-02 17:21:52 +0800472 ppd->canvas_id[index] = ionvideo_canvas_id[0]
473 | (ionvideo_canvas_id[1] << 8)
474 | (ionvideo_canvas_id[2] << 16);
Googler9726be62022-12-14 05:53:31 +0000475 } else {
476 int bpp = 0;
477
478 if (ppd->ge2d_fmt == GE2D_FORMAT_S32_ABGR) {
479 bpp = 4;
Googler9398cc32022-12-02 17:21:52 +0800480 } else if (ppd->ge2d_fmt == GE2D_FORMAT_S24_BGR ||
481 ppd->ge2d_fmt == GE2D_FORMAT_S24_RGB) {
Googler9726be62022-12-14 05:53:31 +0000482 bpp = 3;
483 } else if (ppd->ge2d_fmt == GE2D_FORMAT_S16_RGB_565) {
484 bpp = 2;
485 } else {
486 ppmgr2_printk(1, "Not support format!\n");
487 return -1;
488 }
Googler9398cc32022-12-02 17:21:52 +0800489 canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr,
490 canvas_width * bpp, canvas_height,
491 CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
492 ppd->canvas_id[index] = ionvideo_canvas_id[0];
Googler9726be62022-12-14 05:53:31 +0000493 }
494 ppmgr2_printk(2, "canvas[%d] phy_addr:%p width:%d height:%d\n", index,
Googler9398cc32022-12-02 17:21:52 +0800495 phy_addr, canvas_width, canvas_height);
Googler9726be62022-12-14 05:53:31 +0000496
497 return 0;
498}
499
500void ppmgr2_set_angle(struct ppmgr2_device *ppd, int angle)
501{
502 ppd->angle = angle;
503}
504
505void ppmgr2_set_mirror(struct ppmgr2_device *ppd, int mirror)
506{
507 ppd->mirror = mirror;
508}
509
510void ppmgr2_set_paint_mode(struct ppmgr2_device *ppd, int paint_mode)
511{
512 ppd->paint_mode = paint_mode;
513}
514
515int ppmgr2_process(struct vframe_s *vf, struct ppmgr2_device *ppd, int index)
516{
517 int ret = 0;
518 struct vframe_s *src_vf = vf;
519 int src_position[4] = {0};
520 int dst_paint_position[4] = {0}, dst_plane_position[4] = {0};
521 int dst_pixel_format = ppd->ge2d_fmt;
522 struct ge2d_context_s *context = ppd->context;
Googler9398cc32022-12-02 17:21:52 +0800523 struct config_para_ex_s *ge2d_config = &ppd->ge2d_config;
Googler9726be62022-12-14 05:53:31 +0000524 int angle = (ppd->angle + src_vf->orientation) % 4;
525 int dst_canvas_id = 0;
526
Googler9398cc32022-12-02 17:21:52 +0800527 if (!ppd->phy_addr[index]) {
528 pr_err("ionvideo:NULL physical address!\n");
Googler9726be62022-12-14 05:53:31 +0000529 return -1;
530 }
531
Googler9398cc32022-12-02 17:21:52 +0800532 if (src_vf->type & VIDTYPE_INTERLACE) {
533 if ((ppd->bottom_first && src_vf->type & 0x2) ||
534 (ppd->bottom_first == 0 &&
535 (src_vf->type & 0x2) == 0)) {
536 return -EAGAIN;
Googler9726be62022-12-14 05:53:31 +0000537 }
538 }
539
540 mutex_lock(ppd->ge2d_canvas_mutex);
Googler9398cc32022-12-02 17:21:52 +0800541 ionvideo_alloc_canvas();
Googler9726be62022-12-14 05:53:31 +0000542 ppmgr2_canvas_config(ppd, index);
543 dst_canvas_id = ppd->canvas_id[index];
544 src_position[0] = 0;
545 src_position[1] = 0;
546 src_position[2] = src_vf->width;
547 src_position[3] = src_vf->height;
548 if (src_position[2] == 0 || src_position[3] == 0) {
549 ppmgr2_printk(1, "Source frame error!\n");
550 mutex_unlock(ppd->ge2d_canvas_mutex);
551 return -1;
552 }
553 dst_plane_position[0] = 0;
554 dst_plane_position[1] = 0;
555 dst_plane_position[2] = ppd->dst_width;
556 dst_plane_position[3] = ppd->dst_height;
557
558 ge2d_src_config(src_vf, ge2d_config);
559
560 ge2d_mirror_config(ppd->mirror, ge2d_config);
561 ge2d_angle_config(angle, ge2d_config);
562 paint_mode_convert(ppd->paint_mode, src_position, dst_paint_position,
Googler9398cc32022-12-02 17:21:52 +0800563 dst_plane_position);
Googler9726be62022-12-14 05:53:31 +0000564
565 if (src_vf->type & VIDTYPE_INTERLACE)
566 src_position[3] = src_vf->height >> 1;
567
568 ret = ge2d_paint_dst(context, ge2d_config, dst_canvas_id,
Googler9398cc32022-12-02 17:21:52 +0800569 dst_pixel_format, src_position,
570 dst_paint_position, dst_plane_position);
Googler9726be62022-12-14 05:53:31 +0000571
572 mutex_unlock(ppd->ge2d_canvas_mutex);
573
574 return ret;
575}
576
577void ppmgr2_release(struct ppmgr2_device *ppd)
578{
579 if (ppd->context)
580 destroy_ge2d_work_queue(ppd->context);
581
582 /* switch_mod_gate_by_name("ge2d", 0); */
Googler9398cc32022-12-02 17:21:52 +0800583 ppmgr2_printk(2, "%s!\n", __func__);
Googler9726be62022-12-14 05:53:31 +0000584}
585
586int v4l_to_ge2d_format(int v4l2_format)
587{
588 int format = GE2D_FORMAT_M24_NV21;
589
590 switch (v4l2_format) {
591 case V4L2_PIX_FMT_RGB32:
592 format = GE2D_FORMAT_S32_ABGR;
593 break;
594 case V4L2_PIX_FMT_RGB565:
595 format = GE2D_FORMAT_S16_RGB_565;
596 break;
597 case V4L2_PIX_FMT_BGR24:
598 format = GE2D_FORMAT_S24_RGB;
599 break;
600 case V4L2_PIX_FMT_RGB24:
601 format = GE2D_FORMAT_S24_BGR;
602 break;
603 case V4L2_PIX_FMT_NV12:
604 format = GE2D_FORMAT_M24_NV12;
605 break;
606 case V4L2_PIX_FMT_NV21:
607 format = GE2D_FORMAT_M24_NV21;
608 break;
609 case V4L2_PIX_FMT_YUV420:
610 case V4L2_PIX_FMT_YVU420:
611 format = GE2D_FORMAT_S8_Y;
612 break;
613 default:
614 break;
615 }
616 return format;
617}