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