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