• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.c
3  *
4  * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/errno.h>
21 #include <linux/kfifo.h>
22 #include <linux/interrupt.h>
23 #include <linux/semaphore.h>
24 #include <linux/delay.h>
25 #include <linux/timer.h>
26 #include <linux/kfifo.h>
27 #include <linux/kthread.h>
28 #include <linux/platform_device.h>
29 #include <linux/amlogic/media/canvas/canvas.h>
30 #include <linux/amlogic/media/canvas/canvas_mgr.h>
31 #include <linux/amlogic/media/vfm/vframe.h>
32 #include <linux/amlogic/media/codec_mm/codec_mm.h>
33 #include <linux/dma-mapping.h>
34 #include <linux/dma-map-ops.h>
35 #include <asm-generic/checksum.h>
36 #include <linux/amlogic/media/codec_mm/configs.h>
37 #include <linux/crc32.h>
38 #include <linux/fs.h>
39 #include "vdec.h"
40 #include "frame_check.h"
41 #include "amlogic_fbc_hook.h"
42 #include <linux/highmem.h>
43 #include <linux/page-flags.h>
44 #include "../../../common/chips/decoder_cpu_ver_info.h"
45 #include <asm/cacheflush.h>
46 
47 #define FC_ERROR	0x0
48 
49 #define FC_YUV_DEBUG	0x01
50 #define FC_CRC_DEBUG	0x02
51 #define FC_TST_DEBUG	0x80
52 #define FC_ERR_CRC_BLOCK_MODE	0x10
53 #define FC_CHECK_CRC_LOOP_MODE	0x20
54 
55 #define YUV_MASK	0x01
56 #define CRC_MASK	0x02
57 
58 #define MAX_YUV_SIZE (4096 * 2304)
59 #define YUV_DEF_SIZE (MAX_YUV_SIZE * 3 / 2)
60 #define YUV_DEF_NUM	 1
61 
62 #define MAX_SIZE_AFBC_PLANES 	(4096 * 2048)
63 
64 #define VMAP_STRIDE_SIZE  (1024*1024)
65 
66 static unsigned int fc_debug;
67 static unsigned int size_yuv_buf = (YUV_DEF_SIZE * YUV_DEF_NUM);
68 
69 #define dbg_print(mask, ...) do {					\
70 			if ((fc_debug & mask) ||				\
71 				(mask == FC_ERROR))					\
72 				printk("[FRMAE_CHECK] "__VA_ARGS__);\
73 		} while(0)
74 
75 
76 #define CRC_PATH  "/data/tmp/"
77 #define YUV_PATH  "/data/tmp/"
78 static char comp_crc[128] = "name";
79 
80 static struct vdec_s *single_mode_vdec = NULL;
81 
82 static unsigned int yuv_enable, check_enable;
83 static unsigned int yuv_start[MAX_INSTANCE_MUN];
84 static unsigned int yuv_num[MAX_INSTANCE_MUN];
85 
86 
set_enable(struct pic_check_mgr_t * p,int mask)87 static inline void set_enable(struct pic_check_mgr_t *p, int mask)
88 {
89 	p->enable |= mask;
90 }
91 
set_disable(struct pic_check_mgr_t * p,int mask)92 static inline void set_disable(struct pic_check_mgr_t *p, int mask)
93 {
94 	p->enable &= (~mask);
95 }
96 
check_schedule(struct pic_check_mgr_t * mgr)97 static inline void check_schedule(struct pic_check_mgr_t *mgr)
98 {
99 	if (atomic_read(&mgr->work_inited))
100 		vdec_schedule_work(&mgr->frame_check_work);
101 }
102 
is_oversize(int w,int h)103 static bool is_oversize(int w, int h)
104 {
105 	if (w <= 0 || h <= 0)
106 		return true;
107 
108 	if (h != 0 && (w > (MAX_YUV_SIZE / h)))
109 		return true;
110 
111 	return false;
112 }
113 
114 
get_frame_size(struct pic_check_mgr_t * pic,struct vframe_s * vf)115 static int get_frame_size(struct pic_check_mgr_t *pic,
116 	struct vframe_s *vf)
117 {
118 	if (is_oversize(vf->width, vf->height)) {
119 			dbg_print(FC_ERROR, "vf size err: w=%d, h=%d\n",
120 				vf->width, vf->height);
121 			return -1;
122 	}
123 
124 	pic->size_y = vf->width * vf->height;
125 	pic->size_uv = pic->size_y >> (1 + pic->mjpeg_flag);
126 	pic->size_pic = pic->size_y + (pic->size_y >> 1);
127 
128 	if ((!(vf->type & VIDTYPE_VIU_NV21)) && (!pic->mjpeg_flag))
129 		return 0;
130 
131 	if ((vf->canvas0Addr == vf->canvas1Addr) &&
132 		(vf->canvas0Addr != 0) &&
133 		(vf->canvas0Addr != -1)) {
134 		pic->canvas_w =
135 			canvas_get_width(canvasY(vf->canvas0Addr));
136 		pic->canvas_h =
137 			canvas_get_height(canvasY(vf->canvas0Addr));
138 	} else {
139 		pic->canvas_w = vf->canvas0_config[0].width;
140 		pic->canvas_h = vf->canvas0_config[0].height;
141 	}
142 
143 	if ((pic->canvas_h < 1) || (pic->canvas_w < 1)) {
144 		dbg_print(FC_ERROR, "(canvas,pic) w(%d,%d), h(%d,%d)\n",
145 			pic->canvas_w, vf->width, pic->canvas_h, vf->height);
146 		return -1;
147 	}
148 /*
149 	int blkmod;
150 	blkmod = canvas_get_blkmode(canvasY(vf->canvas0Addr));
151 	if (blkmod != CANVAS_BLKMODE_LINEAR) {
152 		dbg_print(0, "WARN: canvas blkmod %x\n", blkmod);
153 	}
154 */
155 	return 0;
156 }
157 
canvas_get_virt_addr(struct pic_check_mgr_t * pic,struct vframe_s * vf)158 static int canvas_get_virt_addr(struct pic_check_mgr_t *pic,
159 	struct vframe_s *vf)
160 {
161 	int phy_y_addr, phy_uv_addr;
162 	void *vaddr_y, *vaddr_uv;
163 
164 	if ((vf->canvas0Addr == vf->canvas1Addr) &&
165 		(vf->canvas0Addr != 0) &&
166 		(vf->canvas0Addr != -1)) {
167 		phy_y_addr = canvas_get_addr(canvasY(vf->canvas0Addr));
168 		phy_uv_addr = canvas_get_addr(canvasU(vf->canvas0Addr));
169 	} else {
170 		phy_y_addr = vf->canvas0_config[0].phy_addr;
171 		phy_uv_addr = vf->canvas0_config[1].phy_addr;
172 	}
173 	vaddr_y	= codec_mm_phys_to_virt(phy_y_addr);
174 	vaddr_uv = codec_mm_phys_to_virt(phy_uv_addr);
175 
176 	if (((!vaddr_y) || (!vaddr_uv)) && ((!phy_y_addr) || (!phy_uv_addr))) {
177 		dbg_print(FC_ERROR, "%s, y_addr %p(0x%x), uv_addr %p(0x%x)\n",
178 			__func__, vaddr_y, phy_y_addr, vaddr_uv, phy_uv_addr);
179 		return -1;
180 	}
181 	pic->y_vaddr = vaddr_y;
182 	pic->uv_vaddr = vaddr_uv;
183 	pic->y_phyaddr = phy_y_addr;
184 	pic->uv_phyaddr = phy_uv_addr;
185 
186 	if (pic->mjpeg_flag) {
187 		if ((vf->canvas0Addr == vf->canvas1Addr) &&
188 		(vf->canvas0Addr != 0) &&
189 		(vf->canvas0Addr != -1)) {
190 			pic->extra_v_phyaddr = canvas_get_addr(canvasV(vf->canvas0Addr));
191 		} else {
192 			pic->extra_v_phyaddr = vf->canvas0_config[2].phy_addr;
193 		}
194 		pic->extra_v_vaddr = codec_mm_phys_to_virt(phy_uv_addr);
195 
196 		if (!pic->extra_v_vaddr && !pic->extra_v_phyaddr)
197 			return -1;
198 	}
199 
200 	return 0;
201 }
202 
str_strip(char * str)203 static int str_strip(char *str)
204 {
205 	char *s = str;
206 	int i = 0;
207 
208 	while (s[i]) {
209 		if (s[i] == '\n')
210 			s[i] = 0;
211 		else if (s[i] == ' ')
212 			s[i] = '_';
213 		i++;
214 	}
215 
216 	return i;
217 }
218 
fget_crc_str(char * buf,unsigned int size,struct pic_check_t * fc)219 static char *fget_crc_str(char *buf,
220 	unsigned int size, struct pic_check_t *fc)
221 {
222 	unsigned int c = 0, sz, ret, index, crc1, crc2;
223 	mm_segment_t old_fs;
224 	char *cs;
225 
226 	if (!fc->compare_fp)
227 		return NULL;
228 
229 	old_fs = get_fs();
230 	set_fs(KERNEL_DS);
231 
232 	do {
233 		cs = buf;
234 		sz = size;
235 		while (--sz && (c = kernel_read(fc->compare_fp,
236 			cs, 1, &fc->compare_pos) != 0)) {
237 			if (*cs++ == '\n')
238 				break;
239 		}
240 		*cs = '\0';
241 		if ((c == 0) && (cs == buf)) {
242 			set_fs(old_fs);
243 			return NULL;
244 		}
245 		ret = sscanf(buf, "%08u: %8x %8x", &index, &crc1, &crc2);
246 		dbg_print(FC_CRC_DEBUG, "%s, index = %d, cmp = %d\n",
247 			__func__, index, fc->cmp_crc_cnt);
248 	}while(ret != 3 || index != fc->cmp_crc_cnt);
249 
250 	set_fs(old_fs);
251 	fc->cmp_crc_cnt++;
252 
253 	return buf;
254 }
255 
file_open(int mode,const char * str,...)256 static struct file* file_open(int mode, const char *str, ...)
257 {
258 	char file[256] = {0};
259 	struct file* fp = NULL;
260 	va_list args;
261 
262 	va_start(args, str);
263 	vsnprintf(file, sizeof(file), str, args);
264 
265 	fp = filp_open(file, mode, (mode&O_CREAT)?0666:0);
266 	if (IS_ERR(fp)) {
267 		fp = NULL;
268 		dbg_print(FC_ERROR, "open %s failed\n", file);
269 		va_end(args);
270 		return fp;
271 	}
272 	dbg_print(FC_ERROR, "open %s success\n", file);
273 	va_end(args);
274 
275 	return fp;
276 }
277 
write_yuv_work(struct pic_check_mgr_t * mgr)278 static int write_yuv_work(struct pic_check_mgr_t *mgr)
279 {
280 	mm_segment_t old_fs;
281 	unsigned int i, wr_size, pic_num;
282 	struct pic_dump_t *dump = &mgr->pic_dump;
283 
284 	if (dump->dump_cnt > 0) {
285 		if (!dump->yuv_fp) {
286 			dump->yuv_fp = file_open(O_CREAT | O_WRONLY | O_TRUNC,
287 				"%s%s-%d-%d.yuv", YUV_PATH, comp_crc, mgr->id, mgr->file_cnt);
288 			dump->yuv_pos = 0;
289 		}
290 
291 		if ((mgr->enable & YUV_MASK) &&
292 			(dump->yuv_fp != NULL) &&
293 			(dump->dump_cnt >= dump->num)) {
294 
295 			i = 0;
296 			pic_num = dump->dump_cnt;
297 			old_fs = get_fs();
298 			set_fs(KERNEL_DS);
299 			while (pic_num > 0) {
300 				wr_size = kernel_write(dump->yuv_fp,
301 					(dump->buf_addr + i * mgr->size_pic),
302 					mgr->size_pic, &dump->yuv_pos);
303 				if (mgr->size_pic != wr_size) {
304 					dbg_print(FC_ERROR, "buf failed to write yuv file\n");
305 					break;
306 				}
307 				pic_num--;
308 				i++;
309 			}
310 			set_fs(old_fs);
311 			vfs_fsync(dump->yuv_fp, 0);
312 
313 			filp_close(dump->yuv_fp, current->files);
314 			dump->yuv_pos = 0;
315 			dump->yuv_fp = NULL;
316 			set_disable(mgr, YUV_MASK);
317 			dbg_print(FC_YUV_DEBUG,
318 				"closed yuv file, dump yuv exit\n");
319 			dump->num = 0;
320 			dump->dump_cnt = 0;
321 			if (dump->buf_addr != NULL)
322 				vfree(dump->buf_addr);
323 			dump->buf_addr = NULL;
324 			dump->buf_size = 0;
325 		}
326 	}
327 
328 	return 0;
329 }
330 
write_crc_work(struct pic_check_mgr_t * mgr)331 static int write_crc_work(struct pic_check_mgr_t *mgr)
332 {
333 	unsigned int wr_size;
334 	char *crc_buf, crc_tmp[64*30];
335 	mm_segment_t old_fs;
336 	struct pic_check_t *check = &mgr->pic_check;
337 
338 	if (mgr->enable & CRC_MASK) {
339 		wr_size = 0;
340 		while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) {
341 			wr_size += sprintf(&crc_tmp[wr_size], "%s", crc_buf);
342 			if (check->compare_fp != NULL) {
343 				if (!fget_crc_str(crc_buf, SIZE_CRC, check)) {
344 					dbg_print(0, "%s, can't get more compare crc\n", __func__);
345 					filp_close(check->compare_fp, current->files);
346 					check->compare_fp = NULL;
347 				}
348 			}
349 			kfifo_put(&check->new_chk_q, crc_buf);
350 		}
351 		if (check->check_fp && (wr_size != 0)) {
352 			old_fs = get_fs();
353 			set_fs(KERNEL_DS);
354 			if (wr_size != kernel_write(check->check_fp,
355 				crc_tmp, wr_size, &check->check_pos)) {
356 				dbg_print(FC_ERROR, "failed to check_dump_filp\n");
357 			}
358 			set_fs(old_fs);
359 		}
360 	}
361 	return 0;
362 }
363 
do_check_work(struct work_struct * work)364 static void do_check_work(struct work_struct *work)
365 {
366 	struct pic_check_mgr_t *mgr = container_of(work,
367 		struct pic_check_mgr_t, frame_check_work);
368 
369 	write_yuv_work(mgr);
370 
371 	write_crc_work(mgr);
372 }
373 
memcpy_phy_to_virt(char * to_virt,ulong phy_from,unsigned int size)374 static int memcpy_phy_to_virt(char *to_virt,
375 	ulong phy_from, unsigned int size)
376 {
377 	void *vaddr = NULL;
378 	unsigned int tmp_size = 0;
379 
380 	if (single_mode_vdec != NULL) {
381 		unsigned int offset = phy_from & (~PAGE_MASK);
382 		while (size > 0) {
383 			/* flush dcache in isr. */
384 			flush_dcache_page(phys_to_page(phy_from));
385 
386 			if (offset + size >= PAGE_SIZE) {
387 				vaddr = kmap_atomic(phys_to_page(phy_from));
388 				tmp_size = (PAGE_SIZE - offset);
389 				phy_from += tmp_size; //for next loop;
390 				size -= tmp_size;
391 				vaddr += offset;
392 			} else {
393 				vaddr = kmap_atomic(phys_to_page(phy_from));
394 				vaddr += offset;
395 				tmp_size = size;
396 				size = 0;
397 			}
398 			if (vaddr == NULL) {
399 				dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n",
400 					__func__, (unsigned int)phy_from);
401 				return -1;
402 			}
403 
404 			memcpy(to_virt, vaddr, tmp_size);
405 			to_virt += tmp_size;
406 
407 			kunmap_atomic(vaddr - offset);
408 			offset = 0;
409 		}
410 	} else {
411 		while (size > 0) {
412 			if (size >= VMAP_STRIDE_SIZE) {
413 				vaddr = codec_mm_vmap(phy_from, VMAP_STRIDE_SIZE);
414 				tmp_size = VMAP_STRIDE_SIZE;
415 				phy_from += VMAP_STRIDE_SIZE;
416 				size -= VMAP_STRIDE_SIZE;
417 			} else {
418 				vaddr = codec_mm_vmap(phy_from, size);
419 				tmp_size = size;
420 				size = 0;
421 			}
422 			if (vaddr == NULL) {
423 				dbg_print(FC_YUV_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n",
424 					__func__, (unsigned int)phy_from);
425 				return -1;
426 			}
427 			codec_mm_dma_flush(vaddr,
428 				tmp_size, DMA_FROM_DEVICE);
429 			memcpy(to_virt, vaddr, tmp_size);
430 			to_virt += tmp_size;
431 
432 			codec_mm_unmap_phyaddr(vaddr);
433 		}
434 	}
435 	return 0;
436 }
437 
438 
do_yuv_unit_cp(void ** addr,ulong phy,void * virt,int h,int w,int stride)439 static int do_yuv_unit_cp(void **addr, ulong phy, void *virt,
440 	int h, int w, int stride)
441 {
442 	int ret = 0, i;
443 	void *tmp = *addr;
444 
445 	if ((phy != 0) && (virt == NULL)) {
446 		for (i = 0; i < h; i++) {
447 			ret |= memcpy_phy_to_virt(tmp, phy, w);
448 			phy += stride;
449 			tmp += w;
450 		}
451 	} else {
452 		for (i = 0; i < h; i++) {
453 			memcpy(tmp, virt, w);
454 			virt += stride;
455 			tmp += w;
456 		}
457 	}
458 	*addr = tmp;
459 
460 	return ret;
461 }
462 
do_yuv_dump(struct pic_check_mgr_t * mgr,struct vframe_s * vf)463 static int do_yuv_dump(struct pic_check_mgr_t *mgr, struct vframe_s *vf)
464 {
465 	int ret = 0;
466 	void *tmp_addr;
467 	struct pic_dump_t *dump = &mgr->pic_dump;
468 
469 	if (dump->start > 0) {
470 		dump->start--;
471 		return 0;
472 	}
473 
474 	if (dump->dump_cnt >= dump->num)
475 		return 0;
476 
477 	if (single_mode_vdec != NULL) {
478 		if (mgr->size_pic >
479 			(dump->buf_size - dump->dump_cnt * mgr->size_pic)) {
480 			if (dump->buf_size) {
481 				dbg_print(FC_ERROR,
482 					"not enough buf for single mode, force dump less\n");
483 				dump->num = dump->dump_cnt;
484 				check_schedule(mgr);
485 			} else
486 				set_disable(mgr, YUV_MASK);
487 			return -1;
488 		}
489 		tmp_addr = dump->buf_addr +
490 			mgr->size_pic * dump->dump_cnt;
491 	} else {
492 		if (mgr->size_pic > dump->buf_size) {
493 			dbg_print(FC_ERROR,
494 				"not enough size, pic/buf size: 0x%x/0x%x\n",
495 				mgr->size_pic, dump->buf_size);
496 			return -1;
497 		}
498 		tmp_addr = dump->buf_addr;
499 	}
500 
501 	if (vf->width == mgr->canvas_w) {
502 		if ((mgr->uv_vaddr == NULL) || (mgr->y_vaddr == NULL)) {
503 			ret |= memcpy_phy_to_virt(tmp_addr, mgr->y_phyaddr, mgr->size_y);
504 			ret |= memcpy_phy_to_virt(tmp_addr + mgr->size_y,
505 				mgr->uv_phyaddr, mgr->size_uv);
506 			if (mgr->mjpeg_flag) /*mjpeg yuv420 u v is separate */
507 				ret |= memcpy_phy_to_virt(tmp_addr + mgr->size_y + mgr->size_uv,
508 					mgr->extra_v_phyaddr, mgr->size_uv);
509 		} else {
510 			memcpy(tmp_addr, mgr->y_vaddr, mgr->size_y);
511 			memcpy(tmp_addr + mgr->size_y, mgr->uv_vaddr, mgr->size_uv);
512 			if (mgr->mjpeg_flag) /*mjpeg u v is separate */
513 				memcpy(tmp_addr + mgr->size_y + mgr->size_uv,
514 					mgr->extra_v_vaddr, mgr->size_uv);
515 		}
516 	} else {
517 			u32 uv_stride, uv_cpsize;
518 			ret |= do_yuv_unit_cp(&tmp_addr, mgr->y_phyaddr, mgr->y_vaddr,
519 				vf->height, vf->width, mgr->canvas_w);
520 
521 			uv_stride = (mgr->mjpeg_flag) ? (mgr->canvas_w >> 1) : mgr->canvas_w;
522 			uv_cpsize = (mgr->mjpeg_flag) ? (vf->width >> 1) : vf->width;
523 			ret |= do_yuv_unit_cp(&tmp_addr, mgr->uv_phyaddr, mgr->uv_vaddr,
524 					vf->height >> 1, uv_cpsize, uv_stride);
525 
526 			if (mgr->mjpeg_flag) {
527 				ret |= do_yuv_unit_cp(&tmp_addr, mgr->extra_v_phyaddr, mgr->extra_v_vaddr,
528 					vf->height >> 1, uv_cpsize, uv_stride);
529 			}
530 	}
531 
532 	dump->dump_cnt++;
533 	dbg_print(0, "----->dump %dst, size %x (%d x %d), dec total %d\n",
534 		dump->dump_cnt, mgr->size_pic, vf->width, vf->height, mgr->frame_cnt);
535 
536 	if (single_mode_vdec != NULL) {
537 		/* single mode need schedule work to write*/
538 		if (dump->dump_cnt >= dump->num)
539 			check_schedule(mgr);
540 	} else {
541 		int wr_size;
542 		mm_segment_t old_fs;
543 
544 		/* dump for dec pic not in isr */
545 		if (dump->yuv_fp == NULL) {
546 			dump->yuv_fp = file_open(O_CREAT | O_WRONLY | O_TRUNC,
547 				"%s%s-%d-%d.yuv", YUV_PATH, comp_crc, mgr->id, mgr->file_cnt);
548 			if (dump->yuv_fp == NULL)
549 				return -1;
550 		}
551 		old_fs = get_fs();
552 		set_fs(KERNEL_DS);
553 		wr_size = kernel_write(dump->yuv_fp, dump->buf_addr,
554 			mgr->size_pic, &dump->yuv_pos);
555 		if (mgr->size_pic != wr_size) {
556 			dbg_print(FC_ERROR, "buf failed to write yuv file\n");
557 		}
558 		set_fs(old_fs);
559 		vfs_fsync(dump->yuv_fp, 0);
560 	}
561 
562 	return 0;
563 }
564 
crc_store(struct pic_check_mgr_t * mgr,struct vframe_s * vf,int crc_y,int crc_uv)565 static int crc_store(struct pic_check_mgr_t *mgr, struct vframe_s *vf,
566 	int crc_y, int crc_uv)
567 {
568 	int ret = 0;
569 	char *crc_addr = NULL;
570 	int comp_frame = 0, comp_crc_y, comp_crc_uv;
571 	struct pic_check_t *check = &mgr->pic_check;
572 
573 	if (kfifo_get(&check->new_chk_q, &crc_addr) == 0) {
574 		dbg_print(0, "%08d: %08x %08x\n",
575 			mgr->frame_cnt, crc_y, crc_uv);
576 		if (check->check_fp) {
577 			dbg_print(0, "crc32 dropped\n");
578 		} else {
579 			dbg_print(0, "no opened file to write crc32\n");
580 		}
581 		return -1;
582 	}
583 	if (check->cmp_crc_cnt > mgr->frame_cnt) {
584 		sscanf(crc_addr, "%08u: %8x %8x",
585 			&comp_frame, &comp_crc_y, &comp_crc_uv);
586 
587 		dbg_print(0, "%08d: %08x %08x <--> %08d: %08x %08x\n",
588 			mgr->frame_cnt, crc_y, crc_uv,
589 			comp_frame, comp_crc_y, comp_crc_uv);
590 
591 		if (comp_frame == mgr->frame_cnt) {
592 			if ((comp_crc_y != crc_y) || (crc_uv != comp_crc_uv)) {
593 					mgr->pic_dump.start = 0;
594 					if (fc_debug || mgr->pic_dump.num < 3)
595 						mgr->pic_dump.num++;
596 					dbg_print(0, "\n\nError: %08d: %08x %08x != %08x %08x\n\n",
597 						mgr->frame_cnt, crc_y, crc_uv, comp_crc_y, comp_crc_uv);
598 					do_yuv_dump(mgr, vf);
599 					if (fc_debug & FC_ERR_CRC_BLOCK_MODE)
600 						mgr->err_crc_block = 1;
601 					mgr->usr_cmp_result = -mgr->frame_cnt;
602 			}
603 		} else {
604 			mgr->usr_cmp_result = -mgr->frame_cnt;
605 			dbg_print(0, "frame num error: frame_cnt(%d) frame_comp(%d)\n",
606 				mgr->frame_cnt, comp_frame);
607 		}
608 	} else {
609 		dbg_print(0, "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv);
610 	}
611 
612 	if ((check->check_fp) && (crc_addr != NULL)) {
613 		ret = snprintf(crc_addr, SIZE_CRC,
614 			"%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv);
615 
616 		kfifo_put(&check->wr_chk_q, crc_addr);
617 		if ((mgr->frame_cnt & 0xf) == 0)
618 			check_schedule(mgr);
619 	}
620 	return ret;
621 }
622 
623 
crc32_vmap_le(unsigned int * crc32,ulong phyaddr,unsigned int size)624 static int crc32_vmap_le(unsigned int *crc32,
625 	ulong phyaddr, unsigned int size)
626 {
627 	void *vaddr = NULL;
628 	unsigned int crc = *crc32;
629 	unsigned int tmp_size = 0;
630 
631 	/*single mode cannot use codec_mm_vmap*/
632 	if (single_mode_vdec != NULL) {
633 		unsigned int offset = phyaddr & (~PAGE_MASK);
634 		while (size > 0) {
635 			/*flush dcache in isr.*/
636 			flush_dcache_page(phys_to_page(phyaddr));
637 
638 			if (offset + size >= PAGE_SIZE) {
639 				vaddr = kmap_atomic(phys_to_page(phyaddr));
640 				tmp_size = (PAGE_SIZE - offset);
641 				phyaddr += tmp_size;
642 				size -= tmp_size;
643 				vaddr += offset;
644 			} else {
645 				vaddr = kmap_atomic(phys_to_page(phyaddr));
646 				tmp_size = size;
647 				vaddr += offset;
648 				size = 0;
649 			}
650 			if (vaddr == NULL) {
651 				dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n",
652 					__func__, (unsigned int)phyaddr);
653 				return -1;
654 			}
655 
656 			crc = crc32_le(crc, vaddr, tmp_size);
657 
658 			kunmap_atomic(vaddr - offset);
659 			offset = 0;
660 		}
661 	} else {
662 		while (size > 0) {
663 			if (size >= VMAP_STRIDE_SIZE) {
664 				vaddr = codec_mm_vmap(phyaddr, VMAP_STRIDE_SIZE);
665 				tmp_size = VMAP_STRIDE_SIZE;
666 				phyaddr += VMAP_STRIDE_SIZE;
667 				size -= VMAP_STRIDE_SIZE;
668 			} else {
669 				vaddr = codec_mm_vmap(phyaddr, size);
670 				tmp_size = size;
671 				size = 0;
672 			}
673 			if (vaddr == NULL) {
674 				dbg_print(FC_CRC_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n",
675 					__func__, (unsigned int)phyaddr);
676 				return -1;
677 			}
678 			codec_mm_dma_flush(vaddr,
679 				tmp_size, DMA_FROM_DEVICE);
680 
681 			crc = crc32_le(crc, vaddr, tmp_size);
682 
683 			codec_mm_unmap_phyaddr(vaddr);
684 		}
685 	}
686 	*crc32 = crc;
687 
688 	return 0;
689 }
690 
do_check_nv21(struct pic_check_mgr_t * mgr,struct vframe_s * vf)691 static int do_check_nv21(struct pic_check_mgr_t *mgr, struct vframe_s *vf)
692 {
693 	int i;
694 	unsigned int crc_y = 0, crc_uv = 0;
695 	void *p_yaddr, *p_uvaddr;
696 	ulong y_phyaddr, uv_phyaddr;
697 	int ret = 0;
698 
699 	p_yaddr = mgr->y_vaddr;
700 	p_uvaddr = mgr->uv_vaddr;
701 	y_phyaddr = mgr->y_phyaddr;
702 	uv_phyaddr = mgr->uv_phyaddr;
703 	if ((p_yaddr == NULL) || (p_uvaddr == NULL))
704 	{
705 		if (vf->width == mgr->canvas_w) {
706 			ret = crc32_vmap_le(&crc_y, y_phyaddr, mgr->size_y);
707 			ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, mgr->size_uv);
708 		} else {
709 			for (i = 0; i < vf->height; i++) {
710 				ret |= crc32_vmap_le(&crc_y, y_phyaddr, vf->width);
711 				y_phyaddr += mgr->canvas_w;
712 			}
713 			for (i = 0; i < vf->height/2; i++) {
714 				ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, vf->width);
715 				uv_phyaddr += mgr->canvas_w;
716 			}
717 		}
718 		if (ret < 0) {
719 			dbg_print(0, "calc crc failed, may codec_mm_vmap failed\n");
720 			return ret;
721 		}
722 	} else {
723 		if (mgr->frame_cnt == 0) {
724 			unsigned int *p = mgr->y_vaddr;
725 			dbg_print(0, "YUV0000: %08x-%08x-%08x-%08x\n",
726 				p[0], p[1], p[2], p[3]);
727 		}
728 		if (vf->width == mgr->canvas_w) {
729 			crc_y = crc32_le(crc_y, p_yaddr, mgr->size_y);
730 			crc_uv = crc32_le(crc_uv, p_uvaddr, mgr->size_uv);
731 		} else {
732 			for (i = 0; i < vf->height; i++) {
733 				crc_y = crc32_le(crc_y, p_yaddr, vf->width);
734 				p_yaddr += mgr->canvas_w;
735 			}
736 			for (i = 0; i < vf->height/2; i++) {
737 				crc_uv = crc32_le(crc_uv, p_uvaddr, vf->width);
738 				p_uvaddr += mgr->canvas_w;
739 			}
740 		}
741 	}
742 
743 	crc_store(mgr, vf, crc_y, crc_uv);
744 
745 	return 0;
746 }
747 
do_check_yuv16(struct pic_check_mgr_t * mgr,struct vframe_s * vf,char * ybuf,char * uvbuf,char * ubuf,char * vbuf)748 static int do_check_yuv16(struct pic_check_mgr_t *mgr,
749 	struct vframe_s *vf, char *ybuf, char *uvbuf,
750 	char *ubuf, char *vbuf)
751 {
752 	unsigned int crc1, crc2, crc3, crc4;
753 	int w, h;
754 
755 	w = vf->width;
756 	h = vf->height;
757 	crc1 = 0;
758 	crc2 = 0;
759 	crc3 = 0;
760 	crc4 = 0;
761 
762 	crc1 = crc32_le(0, ybuf, w * h *2);
763 	crc2 = crc32_le(0, ubuf, w * h/2);
764 	crc3 = crc32_le(0, vbuf, w * h/2);
765 	crc4 = crc32_le(0, uvbuf, w * h*2/2);
766 	/*
767 	printk("%08d: %08x %08x %08x %08x\n",
768 		mgr->frame_cnt, crc1, crc4, crc2, crc3);
769 	*/
770 	mgr->size_y = w * h * 2;
771 	mgr->size_uv = w * h;
772 	mgr->size_pic = mgr->size_y + mgr->size_uv;
773 	mgr->y_vaddr = ybuf;
774 	mgr->uv_vaddr = uvbuf;
775 	mgr->canvas_w = w;
776 	mgr->canvas_h = h;
777 	crc_store(mgr, vf, crc1, crc4);
778 
779 	return 0;
780 }
781 
fbc_check_prepare(struct pic_check_t * check,int resize,int y_size)782 static int fbc_check_prepare(struct pic_check_t *check,
783 	int resize, int y_size)
784 {
785 	int i = 0;
786 
787 	if  (y_size > MAX_SIZE_AFBC_PLANES)
788 		return -1;
789 
790 	if (((!check->fbc_planes[0]) ||
791 		(!check->fbc_planes[1]) ||
792 		(!check->fbc_planes[2]) ||
793 		(!check->fbc_planes[3])) &&
794 		(!resize))
795 		return -1;
796 
797 	if (resize) {
798 		dbg_print(0, "size changed to 0x%x(y_size)\n", y_size);
799 		for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) {
800 			if (check->fbc_planes[i]) {
801 				vfree(check->fbc_planes[i]);
802 				check->fbc_planes[i] = NULL;
803 			}
804 		}
805 	}
806 	for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) {
807 		if (!check->fbc_planes[i])
808 			check->fbc_planes[i] =
809 				vmalloc(y_size * sizeof(short));
810 	}
811 	if ((!check->fbc_planes[0]) ||
812 		(!check->fbc_planes[1]) ||
813 		(!check->fbc_planes[2]) ||
814 		(!check->fbc_planes[3])) {
815 		dbg_print(0, "vmalloc staicplanes failed %lx %lx %lx %lx\n",
816 			(ulong)check->fbc_planes[0],
817 			(ulong)check->fbc_planes[1],
818 			(ulong)check->fbc_planes[2],
819 			(ulong)check->fbc_planes[3]);
820 		for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) {
821 			if (check->fbc_planes[i]) {
822 				vfree(check->fbc_planes[i]);
823 				check->fbc_planes[i] = NULL;
824 			}
825 		}
826 		return -1;
827 	} else
828 		dbg_print(FC_CRC_DEBUG, "vmalloc staicplanes sucessed\n");
829 
830 	return 0;
831 }
832 
load_user_cmp_crc(struct pic_check_mgr_t * mgr)833 int load_user_cmp_crc(struct pic_check_mgr_t *mgr)
834 {
835 	int i;
836 	struct pic_check_t *chk;
837 	void *qaddr;
838 
839 	if (mgr == NULL ||
840 		(mgr->cmp_pool == NULL)||
841 		(mgr->usr_cmp_num == 0))
842 		return 0;
843 
844 	chk = &mgr->pic_check;
845 
846 	if (chk->cmp_crc_cnt > 0) {
847 		pr_info("cmp crc32 data is ready\n");
848 		return -1;
849 	}
850 
851 	if (chk->check_addr == NULL) {
852 		pr_info("no cmp crc buf\n"); /* vmalloc again or return */
853 		return -1;
854 	}
855 
856 	if (mgr->usr_cmp_num >= USER_CMP_POOL_MAX_SIZE)
857 		mgr->usr_cmp_num = USER_CMP_POOL_MAX_SIZE - 1;
858 
859 	for (i = 0; i < mgr->usr_cmp_num; i++) {
860 		qaddr = chk->check_addr + i * SIZE_CRC;
861 		dbg_print(FC_CRC_DEBUG, "%s, %8d: %08x %08x\n", __func__,
862 			mgr->cmp_pool[i].pic_num,
863 			mgr->cmp_pool[i].y_crc,
864 			mgr->cmp_pool[i].uv_crc);
865 		sprintf(qaddr, "%8d: %08x %08x\n",
866 			mgr->cmp_pool[i].pic_num,
867 			mgr->cmp_pool[i].y_crc,
868 			mgr->cmp_pool[i].uv_crc);
869 
870 		kfifo_put(&chk->new_chk_q, qaddr);
871 		chk->cmp_crc_cnt++;
872 	}
873 
874 	mgr->usr_cmp_result = 0;
875 
876 	vfree(mgr->cmp_pool);
877 	mgr->cmp_pool = NULL;
878 
879 	return 0;
880 }
881 
882 
decoder_do_frame_check(struct vdec_s * vdec,struct vframe_s * vf)883 int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf)
884 {
885 	int resize = 0;
886 	void *planes[4];
887 	struct pic_check_t *check = NULL;
888 	struct pic_check_mgr_t *mgr = NULL;
889 	int ret = 0;
890 
891 	if (vdec == NULL) {
892 		if (single_mode_vdec == NULL)
893 			return 0;
894 		mgr = &single_mode_vdec->vfc;
895 	} else {
896 		mgr = &vdec->vfc;
897 		single_mode_vdec = NULL;
898 	}
899 
900 	if ((mgr == NULL) || (vf == NULL) ||
901 		(mgr->enable == 0))
902 		return 0;
903 
904 	mgr->mjpeg_flag = ((vdec) &&
905 		(vdec->format == VFORMAT_MJPEG)) ? 1 : 0;
906 
907 	if (get_frame_size(mgr, vf) < 0)
908 		return -1;
909 
910 	if (mgr->last_size_pic != mgr->size_pic) {
911 		resize = 1;
912 		dbg_print(0, "size changed, %x-->%x [%d x %d]\n",
913 			mgr->last_size_pic, mgr->size_pic,
914 			vf->width, vf->height);
915 		/* for slt, if no compare crc file, use the
916 		 * cmp crc from amstream ioctl write */
917 		load_user_cmp_crc(mgr);
918 	} else
919 		resize = 0;
920 	mgr->last_size_pic = mgr->size_pic;
921 
922 	if ((vf->type & VIDTYPE_VIU_NV21) || (mgr->mjpeg_flag)) {
923 		int flush_size;
924 
925 		if (canvas_get_virt_addr(mgr, vf) < 0)
926 			return -2;
927 
928 		/* flush */
929 		flush_size = mgr->mjpeg_flag ?
930 				((mgr->canvas_w * mgr->canvas_h) >> 2) :
931 				((mgr->canvas_w * mgr->canvas_h) >> 1);
932 		if (mgr->y_vaddr)
933 			codec_mm_dma_flush(mgr->y_vaddr,
934 				mgr->canvas_w * mgr->canvas_h, DMA_FROM_DEVICE);
935 		if (mgr->uv_vaddr)
936 			codec_mm_dma_flush(mgr->uv_vaddr,
937 				flush_size, DMA_FROM_DEVICE);
938 		if ((mgr->mjpeg_flag) && (mgr->extra_v_vaddr))
939 			codec_mm_dma_flush(mgr->extra_v_vaddr,
940 				flush_size, DMA_FROM_DEVICE);
941 
942 		if (mgr->enable & CRC_MASK)
943 			ret = do_check_nv21(mgr, vf);
944 
945 		if (mgr->enable & YUV_MASK)
946 			do_yuv_dump(mgr, vf);
947 
948 	} else if  (vf->type & VIDTYPE_SCATTER) {
949 		check = &mgr->pic_check;
950 
951 		if (mgr->pic_dump.buf_addr != NULL) {
952 			dbg_print(0, "scatter free yuv buf\n");
953 			vfree(mgr->pic_dump.buf_addr);
954 			mgr->pic_dump.buf_addr = NULL;
955 		}
956 		if (fbc_check_prepare(check,
957 				resize, mgr->size_y) < 0)
958 			return -3;
959 		planes[0] = check->fbc_planes[0];
960 		planes[1] = check->fbc_planes[1];
961 		planes[2] = check->fbc_planes[2];
962 		planes[3] = check->fbc_planes[3];
963 		ret = AMLOGIC_FBC_vframe_decoder(planes, vf, 0, 0);
964 		if (ret < 0) {
965 			dbg_print(0, "amlogic_fbc_lib.ko error %d\n", ret);
966 		} else {
967 			do_check_yuv16(mgr, vf,
968 				(void *)planes[0], (void *)planes[3],//uv
969 				(void *)planes[1], (void *)planes[2]);
970 		}
971 	}
972 	mgr->frame_cnt++;
973 
974 	if (mgr->usr_cmp_num > 0) {
975 		mgr->usr_cmp_num -= 1;
976 	}
977 
978 	return ret;
979 }
980 EXPORT_SYMBOL(decoder_do_frame_check);
981 
dump_buf_alloc(struct pic_dump_t * dump)982 static int dump_buf_alloc(struct pic_dump_t *dump)
983 {
984 	if ((dump->buf_addr != NULL) &&
985 		(dump->buf_size != 0))
986 		return 0;
987 
988 	dump->buf_addr =
989 		(char *)vmalloc(size_yuv_buf);
990 	if (!dump->buf_addr) {
991 		dump->buf_size = 0;
992 		dbg_print(0, "vmalloc yuv buf failed\n");
993 		return -ENOMEM;
994 	}
995 	dump->buf_size = size_yuv_buf;
996 
997 	dbg_print(0, "%s: buf for yuv is alloced\n", __func__);
998 
999 	return 0;
1000 }
1001 
dump_yuv_trig(struct pic_check_mgr_t * mgr,int id,int start,int num)1002 int dump_yuv_trig(struct pic_check_mgr_t *mgr,
1003 	int id, int start, int num)
1004 {
1005 	struct pic_dump_t *dump = &mgr->pic_dump;
1006 
1007 	if (!dump->num) {
1008 		mgr->id = id;
1009 		dump->start = start;
1010 		dump->num = num;
1011 		dump->end = start + num;
1012 		dump->dump_cnt = 0;
1013 		dump->yuv_fp = NULL;
1014 		if (!atomic_read(&mgr->work_inited)) {
1015 			INIT_WORK(&mgr->frame_check_work, do_check_work);
1016 			atomic_set(&mgr->work_inited, 1);
1017 		}
1018 		dump_buf_alloc(dump);
1019 		str_strip(comp_crc);
1020 		set_enable(mgr, YUV_MASK);
1021 	} else {
1022 		dbg_print(FC_ERROR, "yuv dump now, trig later\n");
1023 		return -EBUSY;
1024 	}
1025 	dbg_print(0, "dump yuv trigger, from %d to %d frame\n",
1026 		dump->start, dump->end);
1027 	return 0;
1028 }
1029 
frame_check_init(struct pic_check_mgr_t * mgr,int id)1030 int frame_check_init(struct pic_check_mgr_t *mgr, int id)
1031 {
1032 	int i;
1033 	struct pic_dump_t *dump = &mgr->pic_dump;
1034 	struct pic_check_t *check = &mgr->pic_check;
1035 
1036 	mgr->frame_cnt = 0;
1037 	mgr->size_pic = 0;
1038 	mgr->last_size_pic = 0;
1039 	mgr->id = id;
1040 
1041 	dump->num = 0;
1042 	dump->dump_cnt = 0;
1043 	dump->yuv_fp = NULL;
1044 	check->check_pos = 0;
1045 	check->compare_pos = 0;
1046 
1047 	if (!atomic_read(&mgr->work_inited)) {
1048 		INIT_WORK(&mgr->frame_check_work, do_check_work);
1049 		atomic_set(&mgr->work_inited, 1);
1050 	}
1051 	/* for dump error yuv prepare. */
1052 	dump_buf_alloc(dump);
1053 
1054 	/* try to open compare crc32 file */
1055 	str_strip(comp_crc);
1056 	check->compare_fp = file_open(O_RDONLY,
1057 		"%s%s", CRC_PATH, comp_crc);
1058 
1059 	/* create crc32 log file */
1060 	check->check_fp = file_open(O_CREAT| O_WRONLY | O_TRUNC,
1061 		"%s%s-%d-%d.crc", CRC_PATH, comp_crc, id, mgr->file_cnt);
1062 
1063 	INIT_KFIFO(check->new_chk_q);
1064 	INIT_KFIFO(check->wr_chk_q);
1065 	check->check_addr = vmalloc(SIZE_CRC * SIZE_CHECK_Q);
1066 	if (check->check_addr == NULL) {
1067 		dbg_print(FC_ERROR, "vmalloc qbuf fail\n");
1068 	} else {
1069 		void *qaddr = NULL, *rdret = NULL;
1070 		check->cmp_crc_cnt = 0;
1071 		for (i = 0; i < SIZE_CHECK_Q; i++) {
1072 			qaddr = check->check_addr + i * SIZE_CRC;
1073 			rdret = fget_crc_str(qaddr,
1074 				SIZE_CRC, check);
1075 			if (rdret == NULL) {
1076 				if (i < 3)
1077 					dbg_print(0, "can't get compare crc string\n");
1078 				if (check->compare_fp) {
1079 					filp_close(check->compare_fp, current->files);
1080 					check->compare_fp = NULL;
1081 				}
1082 			}
1083 
1084 			kfifo_put(&check->new_chk_q, qaddr);
1085 		}
1086 	}
1087 	set_enable(mgr, CRC_MASK);
1088 	dbg_print(0, "%s end\n", __func__);
1089 
1090 	return 0;
1091 }
1092 
frame_check_exit(struct pic_check_mgr_t * mgr)1093 void frame_check_exit(struct pic_check_mgr_t *mgr)
1094 {
1095 	int i;
1096 	struct pic_dump_t *dump = &mgr->pic_dump;
1097 	struct pic_check_t *check = &mgr->pic_check;
1098 
1099 	if (mgr->enable != 0) {
1100 		if (dump->dump_cnt != 0) {
1101 			dbg_print(0, "%s, cnt = %d, num = %d\n",
1102 				__func__, dump->dump_cnt, dump->num);
1103 			set_enable(mgr, YUV_MASK);
1104 		}
1105 		if (atomic_read(&mgr->work_inited)) {
1106 			cancel_work_sync(&mgr->frame_check_work);
1107 			atomic_set(&mgr->work_inited, 0);
1108 		}
1109 		if (single_mode_vdec != NULL)
1110 			write_yuv_work(mgr);
1111 		write_crc_work(mgr);
1112 
1113 		for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) {
1114 			if (check->fbc_planes[i]) {
1115 				vfree(check->fbc_planes[i]);
1116 				check->fbc_planes[i] = NULL;
1117 			}
1118 		}
1119 		if (check->check_addr) {
1120 			vfree(check->check_addr);
1121 			check->check_addr = NULL;
1122 		}
1123 
1124 		if (mgr->cmp_pool) {
1125 			vfree(mgr->cmp_pool);
1126 			mgr->cmp_pool = NULL;
1127 		}
1128 
1129 		if (check->check_fp) {
1130 			filp_close(check->check_fp, current->files);
1131 			check->check_fp = NULL;
1132 		}
1133 		if (check->compare_fp) {
1134 			filp_close(check->compare_fp, current->files);
1135 			check->compare_fp = NULL;
1136 		}
1137 		if (dump->yuv_fp) {
1138 			filp_close(dump->yuv_fp, current->files);
1139 			dump->yuv_fp = NULL;
1140 		}
1141 		if (dump->buf_addr) {
1142 			vfree(dump->buf_addr);
1143 			dump->buf_addr = NULL;
1144 		}
1145 		mgr->file_cnt++;
1146 		set_disable(mgr, YUV_MASK | CRC_MASK);
1147 		dbg_print(0, "%s end\n", __func__);
1148 	}
1149 }
1150 
1151 
vdec_frame_check_init(struct vdec_s * vdec)1152 int vdec_frame_check_init(struct vdec_s *vdec)
1153 {
1154 	int ret = 0, id = 0;
1155 
1156 	if (vdec == NULL)
1157 		return 0;
1158 
1159 	if ((vdec->is_reset) &&
1160 		(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXL))
1161 		return 0;
1162 
1163 	vdec->vfc.err_crc_block = 0;
1164 	single_mode_vdec = (vdec_single(vdec))? vdec : NULL;
1165 
1166 	if (!check_enable && !yuv_enable)
1167 		return 0;
1168 
1169 	vdec->canvas_mode = CANVAS_BLKMODE_LINEAR;
1170 	id = vdec->id;
1171 
1172 	if (check_enable & (0x01 << id)) {
1173 		frame_check_init(&vdec->vfc, id);
1174 		/*repeat check one video crc32, not clear enable*/
1175 		if ((fc_debug & FC_CHECK_CRC_LOOP_MODE) == 0)
1176 			check_enable &= ~(0x01 << id);
1177 	}
1178 
1179 	if (yuv_enable & (0x01 << id)) {
1180 		ret = dump_yuv_trig(&vdec->vfc,
1181 			id, yuv_start[id], yuv_num[id]);
1182 		if (ret < 0)
1183 			pr_info("dump yuv init failed\n");
1184 		else {
1185 			pr_info("dump yuv init ok, total %d\n",
1186 				yuv_num[id]);
1187 			vdec->canvas_mode = CANVAS_BLKMODE_LINEAR;
1188 		}
1189 		yuv_num[id] = 0;
1190 		yuv_start[id] = 0;
1191 		yuv_enable &= ~(0x01 << id);
1192 	}
1193 
1194 	return ret;
1195 }
1196 
vdec_frame_check_exit(struct vdec_s * vdec)1197 void vdec_frame_check_exit(struct vdec_s *vdec)
1198 {
1199 	if (vdec == NULL)
1200 		return;
1201 	frame_check_exit(&vdec->vfc);
1202 
1203 	single_mode_vdec = NULL;
1204 }
1205 
dump_yuv_store(struct class * class,struct class_attribute * attr,const char * buf,size_t size)1206 ssize_t dump_yuv_store(struct class *class,
1207 		struct class_attribute *attr,
1208 		const char *buf, size_t size)
1209 {
1210 	struct vdec_s *vdec = NULL;
1211 	unsigned int id = 0, num = 0, start = 0;
1212 	int ret = -1;
1213 
1214 	ret = sscanf(buf, "%d %d %d", &id, &start, &num);
1215 	if (ret < 0) {
1216 		pr_info("%s, parse failed\n", buf);
1217 		return size;
1218 	}
1219 	if ((num == 0) || (num > YUV_MAX_DUMP_NUM)) {
1220 		pr_info("requred yuv num %d, max %d\n",
1221 			num, YUV_MAX_DUMP_NUM);
1222 		return size;
1223 	}
1224 	vdec = vdec_get_vdec_by_id(id);
1225 	if (vdec == NULL) {
1226 		yuv_start[id] = start;
1227 		yuv_num[id] = num;
1228 		yuv_enable |= (1 << id);
1229 		pr_info("no connected vdec.%d now, set dump ok\n", id);
1230 		return size;
1231 	}
1232 
1233 	ret = dump_yuv_trig(&vdec->vfc, id, start, num);
1234 	if (ret < 0)
1235 		pr_info("trigger dump yuv failed\n");
1236 	else
1237 		pr_info("trigger dump yuv init ok, total %d frames\n", num);
1238 
1239 	return size;
1240 }
1241 
dump_yuv_show(struct class * class,struct class_attribute * attr,char * buf)1242 ssize_t dump_yuv_show(struct class *class,
1243 		struct class_attribute *attr, char *buf)
1244 {
1245 	int i;
1246 	char *pbuf = buf;
1247 
1248 	for (i = 0; i < MAX_INSTANCE_MUN; i++) {
1249 		pbuf += pr_info("vdec.%d, start: %d, total: %d frames\n",
1250 			i, yuv_start[i], yuv_num[i]);
1251 	}
1252 	pbuf += sprintf(pbuf,
1253 		"\nUsage: echo [id] [start] [num] > dump_yuv\n\n");
1254 	return pbuf - buf;
1255 }
1256 
1257 
frame_check_store(struct class * class,struct class_attribute * attr,const char * buf,size_t size)1258 ssize_t frame_check_store(struct class *class,
1259 		struct class_attribute *attr,
1260 		const char *buf, size_t size)
1261 {
1262 	int ret = -1;
1263 	int on_off, id;
1264 
1265 	ret = sscanf(buf, "%d %d", &id, &on_off);
1266 	if (ret < 0) {
1267 		pr_info("%s, parse failed\n", buf);
1268 		return size;
1269 	}
1270 	if (id >= MAX_INSTANCE_MUN) {
1271 		pr_info("%d out of max vdec id\n", id);
1272 		return size;
1273 	}
1274 	if (on_off)
1275 		check_enable |= (1 << id);
1276 	else
1277 		check_enable &= ~(1 << id);
1278 
1279 	return size;
1280 }
1281 
frame_check_show(struct class * class,struct class_attribute * attr,char * buf)1282 ssize_t frame_check_show(struct class *class,
1283 		struct class_attribute *attr, char *buf)
1284 {
1285 	int i;
1286 	char *pbuf = buf;
1287 
1288 	for (i = 0; i < MAX_INSTANCE_MUN; i++) {
1289 		pbuf += sprintf(pbuf,
1290 			"vdec.%d\tcrc: %s\n", i,
1291 			(check_enable & (0x01 << i))?"enabled":"--");
1292 	}
1293 	pbuf += sprintf(pbuf,
1294 		"\nUsage:\techo [id]  [1:on/0:off] > frame_check\n\n");
1295 
1296 	if (fc_debug & FC_ERR_CRC_BLOCK_MODE) {
1297 		/* cat frame_check to next frame when block */
1298 		struct vdec_s *vdec = NULL;
1299 		vdec = vdec_get_vdec_by_id(__ffs(check_enable));
1300 		if (vdec)
1301 			vdec->vfc.err_crc_block = 0;
1302 	}
1303 
1304 	return pbuf - buf;
1305 }
1306 
1307 
1308 module_param_string(comp_crc, comp_crc, 128, 0664);
1309 MODULE_PARM_DESC(comp_crc, "\n crc_filename\n");
1310 
1311 module_param(fc_debug, uint, 0664);
1312 MODULE_PARM_DESC(fc_debug, "\n frame check debug\n");
1313 
1314 module_param(size_yuv_buf, uint, 0664);
1315 MODULE_PARM_DESC(size_yuv_buf, "\n size_yuv_buf\n");
1316 
1317