1 /*
2 * g2d_mixer/g2d_mixer.c
3 *
4 * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5 * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17 #include <hal_cache.h>
18 #include <stdio.h>
19 #include "g2d_mixer.h"
20 #include <stdlib.h>
21 #include <string.h>
22 #include "simple_idr.h"
23
24 /**
25 * when image includes the alpha of pixel equal 0, using AVOID_PREMUL
26 */
27 #define AVOID_PREMUL 1
28 #define NOT_AVOID_PREMUL 0
29
30 static struct g2d_mixer_task *g2d_task_list = NULL;
31
32 static struct id_dir* idr;
33
g2d_mixer_idr_init(void)34 int g2d_mixer_idr_init(void)
35 {
36 idr = id_creat();
37 if (idr == NULL){
38 hal_log_err("err alloc idr\n");
39 return -1;
40 }
41 return 0;
42 }
43
g2d_mixer_idr_remove(void)44 int g2d_mixer_idr_remove(void)
45 {
46 if(idr != NULL)
47 id_destroyed(idr);
48 return 0;
49 }
50
g2d_list_add_tail(struct g2d_mixer_task * node,struct g2d_mixer_task * head)51 static void g2d_list_add_tail(struct g2d_mixer_task *node, struct g2d_mixer_task *head)
52 {
53 struct g2d_mixer_task *temp = g2d_task_list;
54 if(g2d_task_list == NULL)
55 g2d_task_list = node;
56 else {
57 while(temp != NULL){
58 temp = temp->next;
59 }
60 temp = node;
61 }
62 node->next = NULL;
63
64 }
g2d_list_del(struct g2d_mixer_task * node)65 static void g2d_list_del(struct g2d_mixer_task *node)
66 {
67 struct g2d_mixer_task *temp = g2d_task_list;
68 struct g2d_mixer_task *pre_temp = NULL;
69 while(temp != node){
70 pre_temp = temp;
71 temp = temp->next;
72 }
73 if(pre_temp != NULL)
74 pre_temp->next = node->next;
75 node->next = NULL;
76 if(temp == g2d_task_list)
77 g2d_task_list = NULL;
78 }
79
g2d_bsp_maskblt(struct g2d_mixer_frame * p_frame,g2d_image_enh * src,g2d_image_enh * ptn,g2d_image_enh * mask,g2d_image_enh * dst,__u32 back_flag,__u32 fore_flag)80 static __s32 g2d_bsp_maskblt(struct g2d_mixer_frame *p_frame,
81 g2d_image_enh *src, g2d_image_enh *ptn,
82 g2d_image_enh *mask, g2d_image_enh *dst,
83 __u32 back_flag, __u32 fore_flag)
84 {
85 g2d_rect rect0;
86 __s32 ret = -1;
87
88 if (!dst) {
89 G2D_ERR_MSG("Null pointer!\n");
90 goto OUT;
91 }
92
93 if (dst->format > G2D_FORMAT_BGRA1010102) {
94 G2D_ERR_MSG("Un support out format:%d\n", dst->format);
95 goto OUT;
96 }
97 g2d_vlayer_set(p_frame->ovl_v, 0, dst, NOT_AVOID_PREMUL);
98
99 if (src) {
100 src->clip_rect.w = dst->clip_rect.w;
101 src->clip_rect.h = dst->clip_rect.h;
102 g2d_uilayer_set(p_frame->ovl_u, 0, src);
103 }
104 if (ptn) {
105 ptn->clip_rect.w = dst->clip_rect.w;
106 ptn->clip_rect.h = dst->clip_rect.h;
107 g2d_uilayer_set(p_frame->ovl_u, 1, ptn);
108 }
109
110 if (mask != NULL) {
111 mask->clip_rect.w = dst->clip_rect.w;
112 mask->clip_rect.h = dst->clip_rect.h;
113 g2d_uilayer_set(p_frame->ovl_u, 2, mask);
114
115 /* set the ROP4 */
116 bld_set_rop_ctrl(p_frame->bld, 0x1);
117 bld_rop3_set(p_frame->bld, 0, back_flag & 0xff);
118 bld_rop3_set(p_frame->bld, 1, fore_flag & 0xff);
119 } else {
120 bld_set_rop_ctrl(p_frame->bld, 0x0);
121 bld_rop3_set(p_frame->bld, 0, back_flag);
122 }
123
124 rect0.x = 0;
125 rect0.y = 0;
126 rect0.w = dst->clip_rect.w;
127 rect0.h = dst->clip_rect.h;
128 bld_in_set(p_frame->bld, 0, rect0, dst->bpremul);
129 bld_out_setting(p_frame->bld, dst);
130 g2d_wb_set(p_frame->wb, dst);
131 ret = 0;
132 OUT:
133 return ret;
134
135 }
136
g2d_fillrectangle(struct g2d_mixer_frame * p_frame,g2d_image_enh * dst,__u32 color_value)137 static __s32 g2d_fillrectangle(struct g2d_mixer_frame *p_frame,
138 g2d_image_enh *dst, __u32 color_value)
139 {
140 g2d_rect rect0;
141 __s32 ret = -1;
142
143 if (!dst || !p_frame) {
144 G2D_ERR_MSG("Null pointer!\n");
145 goto OUT;
146 }
147
148 /* set the input layer */
149 g2d_vlayer_set(p_frame->ovl_v, 0, dst, NOT_AVOID_PREMUL);
150 /* set the fill color value */
151 g2d_ovl_v_fc_set(p_frame->ovl_v, color_value);
152
153 if (dst->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0) {
154 g2d_vsu_para_set(p_frame->scal, dst->format, dst->clip_rect.w,
155 dst->clip_rect.h, dst->clip_rect.w,
156 dst->clip_rect.h, 0xff);
157 bld_csc_reg_set(p_frame->bld, 1, G2D_RGB2YUV_709);
158 }
159
160 /* for interleaved test */
161 if ((dst->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0)
162 && (dst->format <= G2D_FORMAT_IYUV422_Y1U0Y0V0)) {
163 bld_csc_reg_set(p_frame->bld, 0, G2D_RGB2YUV_709);
164 bld_csc_reg_set(p_frame->bld, 1, G2D_RGB2YUV_709);
165 bld_csc_reg_set(p_frame->bld, 2, G2D_RGB2YUV_709);
166
167 bld_bk_set(p_frame->bld, 0xff123456);
168 bld_porter_duff(p_frame->bld, G2D_BLD_SRCOVER);
169
170 g2d_ovl_u_fc_set(p_frame->ovl_u, 0, 0xffffffff);
171 g2d_ovl_u_fc_set(p_frame->ovl_u, 1, 0xffffffff);
172 }
173
174 rect0.x = 0;
175 rect0.y = 0;
176 rect0.w = dst->clip_rect.w;
177 rect0.h = dst->clip_rect.h;
178 bld_in_set(p_frame->bld, 0, rect0, dst->bpremul);
179 bld_cs_set(p_frame->bld, dst->format);
180
181 /* ROP sel ch0 pass */
182 bld_set_rop_ctrl(p_frame->bld, 0xf0);
183 bld_out_setting(p_frame->bld, dst);
184 g2d_wb_set(p_frame->wb, dst);
185
186 ret = 0;
187 OUT:
188 return ret;
189 }
190
191 /* fix add */
g2d_bld_check_coor(g2d_image_enh * src,g2d_image_enh * src2,g2d_image_enh * dst)192 static bool g2d_bld_check_coor(g2d_image_enh *src,
193 g2d_image_enh *src2, g2d_image_enh *dst)
194 {
195 if (dst->width < src->clip_rect.w || dst->width < src2->clip_rect.w
196 || dst->height < src->clip_rect.h ||
197 dst->height < src2->clip_rect.h)
198 return false;
199
200 return true;
201 }
202
g2d_bsp_bld(struct g2d_mixer_frame * p_frame,g2d_image_enh * src,g2d_image_enh * src2,g2d_image_enh * dst,__u32 flag,g2d_ck * ck_para)203 static __s32 g2d_bsp_bld(struct g2d_mixer_frame *p_frame, g2d_image_enh *src,
204 g2d_image_enh *src2, g2d_image_enh *dst,
205 __u32 flag, g2d_ck *ck_para)
206 {
207 g2d_rect rect0, rect1;
208 __s32 ret = -1;
209 __u32 midw, midh;
210
211 if (!dst || !src || !p_frame || !ck_para) {
212 G2D_ERR_MSG("Null pointer!\n");
213 goto OUT;
214 }
215
216 if (g2d_bld_check_coor(src, src2, dst) == false){
217 pr_err("[BLD] size is not suitable!");
218 goto OUT;
219 }
220
221 g2d_vlayer_set(p_frame->ovl_v, 0, src, NOT_AVOID_PREMUL);
222 g2d_vlayer_overlay_set(p_frame->ovl_v, 0, &src->coor,
223 dst->clip_rect.w, dst->clip_rect.h);
224
225 g2d_uilayer_set(p_frame->ovl_u, 2, src2);
226 g2d_uilayer_overlay_set(p_frame->ovl_u, 2, &src2->coor,
227 dst->clip_rect.w, dst->clip_rect.h);
228
229 if (src->format > G2D_FORMAT_BGRA1010102) {
230 if (src2->format > G2D_FORMAT_BGRA1010102) {
231 pr_err("[BLD] not support two yuv layer!\n");
232 goto OUT;
233 } else {
234 /* YUV_XXX->YUV444->RGB overlay size */
235 g2d_ovl_v_calc_coarse(p_frame->ovl_v, src->format, dst->clip_rect.w,
236 dst->clip_rect.h, dst->clip_rect.w,
237 dst->clip_rect.h, &midw, &midh);
238 g2d_vsu_para_set(p_frame->scal, src->format, midw, midh,
239 dst->clip_rect.w, dst->clip_rect.h, dst->alpha);
240
241 if (src->clip_rect.w <= 1280 && src->clip_rect.h <= 720) {
242 bld_csc_reg_set(p_frame->bld, 0, G2D_YUV2RGB_601);
243 } else
244 bld_csc_reg_set(p_frame->bld, 0, G2D_YUV2RGB_709);
245
246 }
247 } else {
248 if (src2->format > G2D_FORMAT_BGRA1010102) {
249 pr_err("[BLD] please use ch0(src0) to set YUV layer!\n");
250 goto OUT;
251 }
252 }
253
254 if (dst->format > G2D_FORMAT_BGRA1010102) {
255 if (dst->clip_rect.w <= 1280 && dst->clip_rect.h <= 720) {
256 bld_csc_reg_set(p_frame->bld, 2, G2D_RGB2YUV_601);
257 } else
258 bld_csc_reg_set(p_frame->bld, 2, G2D_RGB2YUV_709);
259 }
260
261 bld_set_rop_ctrl(p_frame->bld, 0xf0);
262
263 rect0.x = 0;
264 rect0.y = 0;
265 rect0.w = dst->clip_rect.w;/* overlay size */
266 rect0.h = dst->clip_rect.h;
267
268 rect1.x = 0;
269 rect1.y = 0;
270 rect1.w = dst->clip_rect.w;
271 rect1.h = dst->clip_rect.h;
272
273 bld_in_set(p_frame->bld, 0, rect0, src->bpremul);
274 bld_in_set(p_frame->bld, 1, rect1, src2->bpremul);
275
276 if (flag == 0) {
277 /* flag not set use default */
278 flag = G2D_BLD_SRCOVER;
279 }
280
281 bld_porter_duff(p_frame->bld, flag & 0xFFF);
282
283 bld_ck_para_set(p_frame->bld, ck_para, flag);
284
285 bld_cs_set(p_frame->bld, dst->format);
286 bld_out_setting(p_frame->bld, dst);
287 g2d_wb_set(p_frame->wb, dst);
288
289 ret = 0;
290 OUT:
291 return ret;
292 }
293
g2d_bsp_bitblt(struct g2d_mixer_frame * p_frame,g2d_image_enh * src,g2d_image_enh * dst,__u32 flag)294 static __s32 g2d_bsp_bitblt(struct g2d_mixer_frame *p_frame, g2d_image_enh *src,
295 g2d_image_enh *dst, __u32 flag)
296 {
297 g2d_rect rect0, rect1;
298 bool bpre;
299 __u32 midw, midh;
300 __s32 ret = -1;
301
302 if (!p_frame || !src || !dst)
303 goto OUT;
304
305 if ((flag & 0x0fffffff) == G2D_BLT_NONE) {
306 g2d_vlayer_set(p_frame->ovl_v, 0, src, AVOID_PREMUL);
307 /* need abp process */
308 if (src->mode)
309 g2d_uilayer_set(p_frame->ovl_u, 2,
310 dst);
311 if ((src->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0) ||
312 (src->clip_rect.w != dst->clip_rect.w) ||
313 (src->clip_rect.h != dst->clip_rect.h)) {
314 g2d_ovl_v_calc_coarse(
315 p_frame->ovl_v, src->format, src->clip_rect.w,
316 src->clip_rect.h, dst->clip_rect.w,
317 dst->clip_rect.h, &midw, &midh);
318 g2d_vsu_para_set(p_frame->scal, src->format, midw, midh,
319 dst->clip_rect.w, dst->clip_rect.h,
320 0xff);
321 }
322 bld_porter_duff(p_frame->bld, G2D_BLD_SRCOVER);
323 /*Default value*/
324 bld_set_rop_ctrl(p_frame->bld, 0xf0);
325 rect0.x = 0;
326 rect0.y = 0;
327 rect0.w = dst->clip_rect.w;
328 rect0.h = dst->clip_rect.h;
329 bld_in_set(p_frame->bld, 0, rect0, dst->bpremul);
330 bld_cs_set(p_frame->bld, src->format);
331 if (src->mode) {
332 /* need abp process */
333 rect1.x = 0;
334 rect1.y = 0;
335 rect1.w = dst->clip_rect.w;
336 rect1.h = dst->clip_rect.h;
337 bld_in_set(p_frame->bld, 1, rect1, dst->bpremul);
338 }
339 if ((src->format <= G2D_FORMAT_BGRA1010102) &&
340 (dst->format > G2D_FORMAT_BGRA1010102)) {
341 bld_csc_reg_set(p_frame->bld, 2, G2D_RGB2YUV_709);
342 }
343 if ((src->format > G2D_FORMAT_BGRA1010102) &&
344 (dst->format <= G2D_FORMAT_BGRA1010102)) {
345 bld_csc_reg_set(p_frame->bld, 2, G2D_YUV2RGB_709);
346 }
347 bld_out_setting(p_frame->bld, dst);
348 g2d_wb_set(p_frame->wb, dst);
349 } else if (flag & 0xff) {
350 if ((src->format > G2D_FORMAT_BGRA1010102) |
351 (dst->format > G2D_FORMAT_BGRA1010102)) {
352 G2D_ERR_MSG("Only support rgb format!\n");
353 goto OUT;
354 }
355 g2d_uilayer_set(p_frame->ovl_u, 0, dst);
356 g2d_vlayer_set(p_frame->ovl_v, 0, src, AVOID_PREMUL);
357 bpre = false;
358 if (src->bpremul || dst->bpremul)
359 bpre = true;
360 if ((src->clip_rect.w != dst->clip_rect.w)
361 || (src->clip_rect.h != dst->clip_rect.h)) {
362 g2d_ovl_v_calc_coarse(
363 p_frame->ovl_v, src->format, src->clip_rect.w,
364 src->clip_rect.h, dst->clip_rect.w,
365 dst->clip_rect.h, &midw, &midh);
366 g2d_vsu_para_set(p_frame->scal, src->format, midw, midh,
367 dst->clip_rect.w, dst->clip_rect.h,
368 0xff);
369 }
370 /*Default value*/
371 bld_porter_duff(p_frame->bld, G2D_BLD_SRCOVER);
372 bld_set_rop_ctrl(p_frame->bld, 0x00);
373 bld_rop2_set(p_frame->bld, flag & 0xff);
374
375 /*set bld para */
376 rect0.x = 0;
377 rect0.y = 0;
378 rect0.w = dst->clip_rect.w;
379 rect0.h = dst->clip_rect.h;
380 bld_in_set(p_frame->bld, 0, rect0, bpre);
381 bld_out_setting(p_frame->bld, dst);
382 g2d_wb_set(p_frame->wb, dst);
383 }
384
385 ret = 0;
386 OUT:
387 return ret;
388
389 }
390
391 /**
392 * @name :g2d_split_mem
393 * @brief :split memory from a big memory, only support y8
394 * @param[IN] :
395 * @param[IN] :
396 * @return :0 if success, -1 else
397 */
g2d_split_mem(struct g2d_mixer_task * p_task,struct mixer_para * p_para)398 static __s32 g2d_split_mem(struct g2d_mixer_task *p_task,
399 struct mixer_para *p_para)
400 {
401
402 __s32 ret = 0, i = 0;
403 __u32 src_addr = 0, dst_addr = 0;
404
405 if (p_para[0].op_flag & OP_SPLIT_MEM) {
406 p_task->en_split_mem = 1;
407 /*ret = g2d_set_image_addr(&p_task->frame[0].dst_item, &p_para[0].dst_image_h);
408 if (ret)
409 goto OUT;*/
410 dst_addr = p_para[0].dst_image_h.laddr[0];
411
412 /*ret = g2d_set_image_addr(&p_task->frame[0].src_item,
413 &p_para[0].src_image_h);*/
414 if (ret)
415 goto OUT;
416 src_addr = p_para[0].src_image_h.laddr[0];
417
418 for (i = 0; i < p_task->frame_cnt; ++i) {
419 p_para[i].src_image_h.laddr[0] = src_addr;
420 p_para[i].dst_image_h.laddr[0] = dst_addr;
421 src_addr += p_para[i].src_image_h.width * p_para[i].src_image_h.height;
422 dst_addr += p_para[i].dst_image_h.width * p_para[i].dst_image_h.height;
423 }
424 }
425
426 OUT:
427 return ret;
428 }
429
g2d_mixer_mem_setup(struct g2d_mixer_task * p_task,struct mixer_para * p_para)430 static __s32 g2d_mixer_mem_setup(struct g2d_mixer_task *p_task,
431 struct mixer_para *p_para)
432 {
433 __u32 i = 0, frame_index = 0;
434 __u32 rcq_reg_mem_size = 0;
435 __s32 ret = -1;
436 struct g2d_reg_block **p_reg_blks;
437 struct g2d_rcq_head *rcq_hd = NULL;
438
439 if (!p_task->p_rcq_info)
440 goto OUT;
441
442 p_task->p_rcq_info->block_num_per_frame =
443 p_task->frame[0].frame_get_reg_block_num(&p_task->frame[0]);
444
445 p_task->p_rcq_info->alloc_num_per_frame =
446 G2D_RCQ_HEADER_ALIGN(p_task->p_rcq_info->block_num_per_frame);
447 /*header length after 32 BYTE algin*/
448
449 p_task->p_rcq_info->rcq_header_len =
450 p_task->p_rcq_info->alloc_num_per_frame *
451 sizeof(*(p_task->p_rcq_info->vir_addr));
452
453 /*real block num*/
454 p_task->p_rcq_info->cur_num =
455 p_task->p_rcq_info->block_num_per_frame * p_task->frame_cnt;
456
457 /*block num that need to be alloced*/
458 p_task->p_rcq_info->alloc_num =
459 p_task->p_rcq_info->alloc_num_per_frame * p_task->frame_cnt;
460
461 /*regblocks + rcq header*/
462 rcq_reg_mem_size =
463 p_task->frame[0].frame_get_rcq_mem_size(&p_task->frame[0]) *
464 p_task->frame_cnt;
465
466 rcq_reg_mem_size += sizeof(*(p_task->p_rcq_info->vir_addr)) *
467 p_task->p_rcq_info->alloc_num;
468
469 p_task->p_rcq_info->rcq_reg_mem_size = rcq_reg_mem_size;
470 if (g2d_top_mem_pool_alloc(p_task->p_rcq_info)) {
471 G2D_ERR_MSG("g2d_top_mem_pool_alloc fail!\n");
472 goto OUT;
473 }
474
475 /*malloc memory for rcq queue*/
476
477 if (!p_task->p_rcq_info->vir_addr) {
478 G2D_ERR_MSG("Malloc rcq queue memory fail!\n");
479 goto OUT;
480 }
481
482 p_task->p_rcq_info->reg_blk =
483 hal_malloc(sizeof(*(p_task->p_rcq_info->reg_blk)) *
484 p_task->p_rcq_info->cur_num);
485
486 if (p_task->p_rcq_info->reg_blk == NULL) {
487 G2D_ERR_MSG("kalloc for g2d_reg_block failed\n");
488 goto OUT;
489 }
490 memset(p_task->p_rcq_info->reg_blk, 0, sizeof(*(p_task->p_rcq_info->reg_blk)) *
491 p_task->p_rcq_info->cur_num);
492 p_reg_blks = p_task->p_rcq_info->reg_blk;
493
494 g2d_split_mem(p_task, p_para);
495
496 for (i = 0; i < p_task->frame_cnt; ++i) {
497
498 if (p_task->frame[i].frame_mem_setup(
499 &p_task->frame[i], &p_para[i], p_task)) {
500 G2D_ERR_MSG("Frame:%ld setupt fail!\n", i);
501 goto OUT;
502 }
503 /*overlay video*/
504 p_task->frame[i].ovl_v->get_reg_block(p_task->frame[i].ovl_v,
505 p_reg_blks);
506 p_reg_blks += p_task->frame[i].ovl_v->get_reg_block_num(
507 p_task->frame[i].ovl_v);
508
509 /*overlay ui*/
510 p_task->frame[i].ovl_u->get_reg_block(p_task->frame[i].ovl_u,
511 p_reg_blks);
512
513 p_reg_blks += p_task->frame[i].ovl_u->get_reg_block_num(
514 p_task->frame[i].ovl_u);
515
516 /*scaler*/
517 p_task->frame[i].scal->get_reg_block(p_task->frame[i].scal,
518 p_reg_blks);
519 p_reg_blks += p_task->frame[i].scal->get_reg_block_num(
520 p_task->frame[i].scal);
521
522 /*blender*/
523 p_task->frame[i].bld->get_reg_block(p_task->frame[i].bld,
524 p_reg_blks);
525 p_reg_blks += p_task->frame[i].bld->get_reg_block_num(
526 p_task->frame[i].bld);
527
528 /*write back*/
529 p_task->frame[i].wb->get_reg_block(p_task->frame[i].wb,
530 p_reg_blks);
531 p_reg_blks +=
532 p_task->frame[i].wb->get_reg_block_num(p_task->frame[i].wb);
533 }
534
535 p_reg_blks = p_task->p_rcq_info->reg_blk;
536 rcq_hd = p_task->p_rcq_info->vir_addr;
537
538 for (frame_index = 0; frame_index < p_task->frame_cnt; ++frame_index) {
539 for (i = 0; i < p_task->p_rcq_info->alloc_num_per_frame; ++i) {
540 struct g2d_reg_block *reg_blk = *p_reg_blks;
541
542 if (p_task->p_rcq_info->alloc_num_per_frame >
543 p_task->p_rcq_info->block_num_per_frame &&
544 i == p_task->p_rcq_info->block_num_per_frame) {
545 if (frame_index == p_task->frame_cnt - 1)
546 rcq_hd->dirty.bits.n_header_len = 0;
547 else
548 rcq_hd->dirty.bits.n_header_len =
549 p_task->p_rcq_info->rcq_header_len;
550 ++rcq_hd;
551 } else {
552 rcq_hd->low_addr =
553 (__u32)((unsigned long)(reg_blk->phy_addr));
554 #if defined(CONFIG_ARM64)
555 rcq_hd->dw0.bits.high_addr =
556 (u8)((__u64)(reg_blk->phy_addr) >> 32);
557 #else
558 rcq_hd->dw0.bits.high_addr =
559 (u8)((__u64)(unsigned long)(reg_blk->phy_addr) >> 32);
560 #endif
561 rcq_hd->dw0.bits.len = reg_blk->size;
562 rcq_hd->dirty.bits.dirty = reg_blk->dirty;
563 rcq_hd->reg_offset = (__u32)(__u64)(
564 reg_blk->reg_addr -
565 (u8 *)(unsigned long)p_task->p_g2d_info->io);
566 reg_blk->rcq_hd = rcq_hd;
567
568 /*last frame's next frame len should be zero*/
569 if (frame_index == p_task->frame_cnt - 1)
570 rcq_hd->dirty.bits.n_header_len = 0;
571 else
572 rcq_hd->dirty.bits.n_header_len =
573 p_task->p_rcq_info->rcq_header_len;
574
575 ++rcq_hd;
576 ++p_reg_blks;
577 }
578 }
579 }
580
581 ret = 0;
582 OUT:
583 return ret;
584 }
585
frame_get_rcq_mem_size(struct g2d_mixer_frame * p_frame)586 static __u32 frame_get_rcq_mem_size(struct g2d_mixer_frame *p_frame)
587 {
588 int rcq_mem_size = 0;
589
590 rcq_mem_size += p_frame->wb->get_rcq_mem_size(p_frame->wb);
591 rcq_mem_size += p_frame->ovl_v->get_rcq_mem_size(p_frame->ovl_v);
592 rcq_mem_size += p_frame->ovl_u->get_rcq_mem_size(p_frame->ovl_u);
593 rcq_mem_size += p_frame->scal->get_rcq_mem_size(p_frame->scal);
594 rcq_mem_size += p_frame->bld->get_rcq_mem_size(p_frame->bld);
595
596 return rcq_mem_size;
597 }
598
599
frame_mem_setup(struct g2d_mixer_frame * p_frame,struct mixer_para * p_para,struct g2d_mixer_task * p_task)600 static __s32 frame_mem_setup(struct g2d_mixer_frame *p_frame,
601 struct mixer_para *p_para,
602 struct g2d_mixer_task *p_task)
603 {
604 __s32 ret = -1;
605
606 ret = p_frame->wb->rcq_setup(p_frame->wb, p_frame->g2d_base,
607 p_task->p_rcq_info);
608 if (ret)
609 goto OUT;
610 ret = p_frame->ovl_v->rcq_setup(p_frame->ovl_v, p_frame->g2d_base,
611 p_task->p_rcq_info);
612 if (ret)
613 goto OUT;
614 ret = p_frame->ovl_u->rcq_setup(p_frame->ovl_u, p_frame->g2d_base,
615 p_task->p_rcq_info);
616 if (ret)
617 goto OUT;
618 ret = p_frame->bld->rcq_setup(p_frame->bld, p_frame->g2d_base,
619 p_task->p_rcq_info);
620 if (ret)
621 goto OUT;
622 ret = p_frame->scal->rcq_setup(p_frame->scal, p_frame->g2d_base,
623 p_task->p_rcq_info);
624 if (ret)
625 goto OUT;
626
627 if (p_task->en_split_mem)
628 goto OUT;
629
630 OUT:
631 return ret;
632 }
633
634 /**
635 * @rong This function is to use black spot avoidance scheme
636 * @para g2d_image_enh *p_dst_image, g2d_image_enh *p_src_image
637 */
modify_premul(g2d_image_enh * p_dst_image,g2d_image_enh * p_src_image)638 static void modify_premul(g2d_image_enh *p_dst_image, g2d_image_enh *p_src_image)
639 {
640 p_dst_image->bpremul = 1;
641 p_src_image->bpremul = 1;
642 }
643
g2d_mixer_frame_apply(struct g2d_mixer_frame * p_frame,struct mixer_para * p_para)644 __s32 g2d_mixer_frame_apply(struct g2d_mixer_frame *p_frame,
645 struct mixer_para *p_para)
646 {
647 __s32 ret = -1;
648
649 if (g2d_image_check(&p_para->dst_image_h))
650 goto OUT;
651 if ((p_para->op_flag & OP_BITBLT) || (p_para->op_flag & OP_BLEND)) {
652 if (g2d_image_check(&p_para->src_image_h))
653 goto OUT;
654 if (p_para->op_flag & OP_BLEND) {
655 /* actually is use as src2 */
656 if (g2d_image_check(&p_para->ptn_image_h))
657 goto OUT;
658 }
659 } else if ((p_para->op_flag & OP_MASK)) {
660 p_para->dst_image_h.bbuff = 1;
661 p_para->dst_image_h.gamut = G2D_BT709;
662 p_para->src_image_h.bbuff = 1;
663 p_para->src_image_h.gamut = G2D_BT709;
664 p_para->ptn_image_h.bbuff = 1;
665 p_para->ptn_image_h.gamut = G2D_BT709;
666 p_para->mask_image_h.bbuff = 1;
667 p_para->mask_image_h.gamut = G2D_BT709;
668 }
669
670
671 ret = 0;
672 if (p_para->op_flag & OP_BITBLT) {
673 modify_premul(&p_para->dst_image_h, &p_para->src_image_h);
674 ret = g2d_bsp_bitblt(p_frame, &p_para->src_image_h,
675 &p_para->dst_image_h, p_para->flag_h);
676 } else if (p_para->op_flag & OP_BLEND) {
677 ret = g2d_bsp_bld(p_frame, &p_para->src_image_h, &p_para->ptn_image_h,
678 &p_para->dst_image_h, p_para->bld_cmd,
679 &p_para->ck_para);
680 } else if (p_para->op_flag & OP_FILLRECT) {
681 ret = g2d_fillrectangle(p_frame, &p_para->dst_image_h,
682 p_para->dst_image_h.color);
683 } else if (p_para->op_flag & OP_MASK) {
684 ret = g2d_bsp_maskblt(
685 p_frame, &p_para->src_image_h, &p_para->ptn_image_h,
686 &p_para->mask_image_h, &p_para->dst_image_h,
687 p_para->back_flag, p_para->fore_flag);
688 }
689
690 OUT:
691 return ret;
692 }
693
g2d_mixer_frame_destory(struct g2d_mixer_frame * p_frame)694 static __s32 g2d_mixer_frame_destory(struct g2d_mixer_frame *p_frame)
695 {
696 __s32 ret = 0;
697 ret += p_frame->wb->destory(p_frame->wb);
698 ret += p_frame->ovl_v->destory(p_frame->ovl_v);
699 ret += p_frame->ovl_u->destory(p_frame->ovl_u);
700 ret += p_frame->bld->destory(p_frame->bld);
701 ret += p_frame->scal->destory(p_frame->scal);
702
703 return ret;
704 }
705
frame_get_reg_block_num(struct g2d_mixer_frame * p_frame)706 static __u32 frame_get_reg_block_num(struct g2d_mixer_frame *p_frame)
707 {
708 __u32 block_num = 0;
709
710 block_num += p_frame->ovl_u->get_reg_block_num(p_frame->ovl_u);
711 block_num += p_frame->ovl_v->get_reg_block_num(p_frame->ovl_v);
712 block_num += p_frame->scal->get_reg_block_num(p_frame->scal);
713 block_num += p_frame->bld->get_reg_block_num(p_frame->bld);
714 block_num += p_frame->wb->get_reg_block_num(p_frame->wb);
715 return block_num;
716 }
717
g2d_mixer_frame_setup(struct g2d_mixer_frame * p_frame,unsigned int index)718 static int g2d_mixer_frame_setup(struct g2d_mixer_frame *p_frame, unsigned int index)
719 {
720 int ret = -1;
721
722 if (!p_frame) {
723 G2D_ERR_MSG("Null pointer!\n");
724 goto OUT;
725 }
726
727 p_frame->apply = g2d_mixer_frame_apply;
728 p_frame->frame_id = index;
729 p_frame->destory = g2d_mixer_frame_destory;
730 p_frame->frame_get_reg_block_num = frame_get_reg_block_num;
731 p_frame->frame_mem_setup = frame_mem_setup;
732 p_frame->frame_get_rcq_mem_size = frame_get_rcq_mem_size;
733
734 p_frame->wb = g2d_wb_submodule_setup(p_frame);
735 if (!p_frame->wb) {
736 G2D_ERR_MSG("Write back submodule setup fail!\n");
737 goto FREE;
738 }
739
740 p_frame->ovl_v = g2d_ovl_v_submodule_setup(p_frame);
741 if (!p_frame->ovl_v) {
742 G2D_ERR_MSG("ovl v submodule setup fail!\n");
743 goto FREE;
744 }
745
746 p_frame->ovl_u = g2d_ovl_u_submodule_setup(p_frame);
747 if (!p_frame->ovl_u) {
748 G2D_ERR_MSG("ovl u submodule setup fail!\n");
749 goto FREE;
750 }
751
752 p_frame->bld = g2d_bld_submodule_setup(p_frame);
753 if (!p_frame->bld) {
754 G2D_ERR_MSG("bld submodule setup fail!\n");
755 goto FREE;
756 }
757
758 p_frame->scal = g2d_scaler_submodule_setup(p_frame);
759 if (!p_frame->scal) {
760 G2D_ERR_MSG("scaler submodule setup fail!\n");
761 goto FREE;
762 }
763
764 ret = 0;
765 goto OUT;
766
767 FREE:
768 free(p_frame->wb);
769 free(p_frame->ovl_v);
770 free(p_frame->ovl_u);
771 free(p_frame->bld);
772 free(p_frame->scal);
773 OUT:
774 return ret;
775 }
776
g2d_mixer_apply(struct g2d_mixer_task * p_task,struct mixer_para * p_para)777 static __s32 g2d_mixer_apply(struct g2d_mixer_task *p_task,
778 struct mixer_para *p_para)
779 {
780 __u32 i = 0, ret = -1;
781
782 #if G2D_MIXER_RCQ_USED == 1
783 g2d_top_rcq_update_en(0);
784 g2d_top_rcq_irq_en(0);
785 #if defined(CONFIG_ARM64)
786 g2d_top_set_rcq_head((__u64)p_task->p_rcq_info->phy_addr,
787 p_task->p_rcq_info->rcq_header_len);
788 #else
789 g2d_top_set_rcq_head((__u64)(unsigned long)p_task->p_rcq_info->phy_addr,
790 p_task->p_rcq_info->rcq_header_len);
791 #endif
792 #else
793 g2d_mixer_irq_en(0);
794 g2d_mixer_start(0);
795 #endif
796
797 isb();
798
799 for (i = 0; i < p_task->frame_cnt; ++i) {
800 ret = p_task->frame[i].apply(&p_task->frame[i],
801 &p_para[i]);
802 if (ret)
803 G2D_ERR_MSG("Frame%ld apply fail!\n", i);
804 }
805 hal_dcache_clean((unsigned long)p_task->p_rcq_info->vir_addr,p_task->p_rcq_info->rcq_reg_mem_size);
806 isb();
807
808 #if G2D_MIXER_RCQ_USED == 1
809 g2d_top_rcq_irq_en(1);
810 g2d_top_rcq_update_en(1);
811 #else
812 g2d_mixer_irq_en(1);
813 g2d_mixer_start(1);
814 #endif
815 isb();
816
817 ret = g2d_wait_cmd_finish(WAIT_CMD_TIME_MS*p_task->frame_cnt);
818 memcpy(p_task->p_para, p_para,
819 sizeof(struct mixer_para) * p_task->frame_cnt);
820
821 return ret;
822 }
823
g2d_mixer_task_destory(struct g2d_mixer_task * p_task)824 static __s32 g2d_mixer_task_destory(struct g2d_mixer_task *p_task)
825 {
826 __u32 i = 0;
827
828 for (i = 0; i < p_task->frame_cnt; ++i) {
829 if (p_task->frame[i].destory(&p_task->frame[i]))
830 G2D_ERR_MSG("Frame:%ld destory fail!\n", i);
831 }
832 g2d_top_mem_pool_free(p_task->p_rcq_info);
833
834 if (p_task->p_rcq_info) {
835 free(p_task->p_rcq_info->reg_blk);
836 free(p_task->p_rcq_info);
837 }
838
839 if (p_task->p_para)
840 free(p_task->p_para);
841
842 g2d_list_del(p_task);
843
844 id_free(idr, p_task->task_id);
845 free(p_task->frame);
846 free(p_task);
847
848 return 0;
849 }
850
851 /**
852 * @name :create_mixer_task
853 * @brief :create mixer task instance include memory allocate
854 * @param[IN] :p_g2d_info:pointer of hardware resource
855 * @param[IN] :p_para:mixer task parameter
856 * @param[IN] :frame_len:number of frame
857 * @return :task_id >= 1, else fail
858 */
create_mixer_task(__g2d_info_t * p_g2d_info,struct mixer_para * p_para,unsigned int frame_len)859 int create_mixer_task(__g2d_info_t *p_g2d_info, struct mixer_para *p_para,
860 unsigned int frame_len)
861 {
862 __u32 i = 0;
863 struct g2d_mixer_task *task = NULL;
864
865 if (!p_g2d_info || !frame_len) {
866 G2D_ERR_MSG("Null pointer!\n");
867 goto OUT;
868 }
869
870 task = hal_malloc(sizeof(struct g2d_mixer_task));
871 if (!task) {
872 G2D_ERR_MSG("kmalloc g2d_mixer_task fail!\n");
873 goto OUT;
874 }
875 memset(task, 0, sizeof(struct g2d_mixer_task));
876 task->frame_cnt = frame_len;
877 task->frame = hal_malloc(frame_len*sizeof(struct g2d_mixer_frame));
878
879 task->p_rcq_info =
880 hal_malloc(sizeof(struct g2d_rcq_mem_info));
881
882 if (!task->frame || !task->p_rcq_info) {
883 G2D_ERR_MSG("Kmalloc fail!\n");
884 goto FREE;
885 }
886 memset(task->frame, 0, frame_len*sizeof(struct g2d_mixer_frame));
887 memset(task->p_rcq_info, 0, sizeof(struct g2d_rcq_mem_info));
888
889 task->destory = g2d_mixer_task_destory;
890 task->apply = g2d_mixer_apply;
891 task->mixer_mem_setup = g2d_mixer_mem_setup;
892 task->p_g2d_info = p_g2d_info;
893 task->task_id = id_alloc(idr, NULL);
894 if (task->task_id == NO_ID) {
895 goto FREE;
896 }
897
898 for (i = 0; i < frame_len; ++i) {
899 if (g2d_mixer_frame_setup(&task->frame[i], i)) {
900 G2D_ERR_MSG("frame %ld g2d_mixer_frame_setup fail\n", i);
901 goto FREE;
902 }
903 task->frame[i].g2d_base = (u8 *)(unsigned long)p_g2d_info->io;
904 }
905
906 if (task->mixer_mem_setup(task, p_para)) {
907 task->destory(task);
908 goto OUT;
909 }
910 task->p_para = hal_malloc(sizeof(struct mixer_para) * task->frame_cnt);
911 if (!task->p_para) {
912 task->destory(task);
913 goto OUT;
914 }
915 memcpy(task->p_para, p_para, sizeof(struct mixer_para) * task->frame_cnt);
916
917
918 g2d_list_add_tail(task, g2d_task_list);
919
920 return task->task_id;
921 IDA_REMOVE:
922
923 id_free(idr, task->task_id);
924 FREE:
925 free(task->frame);
926 free(task->p_rcq_info);
927 free(task);
928 OUT:
929 return 0;
930 }
931
932 /**
933 * @name :g2d_mixer_get_inst
934 * @brief :get task instance of specified task id
935 * @param[IN] :id: task id
936 * @return :pointer of mixer task or NULL if fail
937 */
g2d_mixer_get_inst(int id)938 struct g2d_mixer_task *g2d_mixer_get_inst(int id)
939 {
940
941 struct g2d_mixer_task *find = g2d_task_list;
942
943
944 while(find->task_id != id &&find !=NULL)
945 find = find->next;
946 return find;
947 }
948
mixer_task_process(__g2d_info_t * p_g2d_info,struct mixer_para * p_para,unsigned int frame_len)949 __s32 mixer_task_process(__g2d_info_t *p_g2d_info, struct mixer_para *p_para,
950 unsigned int frame_len)
951 {
952 __s32 ret = -1;
953 struct g2d_mixer_task *p_task = NULL;
954 int id = 0;
955
956 id = create_mixer_task(p_g2d_info, p_para, frame_len);
957 p_task = g2d_mixer_get_inst(id);
958 if (!p_task)
959 goto OUT;
960
961 ret = p_task->apply(p_task, p_para);
962
963 p_task->destory(p_task);
964
965 OUT:
966 return ret;
967 }
968