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