• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/frame_provider/decoder/utils/vdec_input.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 
18 #include <linux/uaccess.h>
19 #include <linux/list.h>
20 #include <linux/slab.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/amlogic/media/codec_mm/codec_mm.h>
23 
24 #include "../../../stream_input/amports/amports_priv.h"
25 #include "vdec.h"
26 #include "vdec_input.h"
27 
28 #include <asm/cacheflush.h>
29 #include <linux/crc32.h>
30 
31 
32 #define VFRAME_BLOCK_SIZE (512 * SZ_1K)/*512 for 1080p default init.*/
33 #define VFRAME_BLOCK_SIZE_4K (2 * SZ_1M) /*2M for 4K default.*/
34 #define VFRAME_BLOCK_SIZE_MAX (4 * SZ_1M)
35 
36 #define VFRAME_BLOCK_PAGEALIGN 4
37 #define VFRAME_BLOCK_MIN_LEVEL (2 * SZ_1M)
38 #define VFRAME_BLOCK_MAX_LEVEL (8 * SZ_1M)
39 #define VFRAME_BLOCK_MAX_TOTAL_SIZE (16 * SZ_1M)
40 
41 /*
42 2s for OMX
43 */
44 #define MAX_FRAME_DURATION_S 2
45 
46 
47 #define VFRAME_BLOCK_HOLE (SZ_64K)
48 
49 #define MIN_FRAME_PADDING_SIZE ((u32)(L1_CACHE_BYTES))
50 
51 #define EXTRA_PADDING_SIZE  (16 * SZ_1K) /*HEVC_PADDING_SIZE*/
52 
53 #define MEM_NAME "VFRAME_INPUT"
54 
55 //static int vdec_input_get_duration_u64(struct vdec_input_s *input);
56 static struct vframe_block_list_s *
57 	vdec_input_alloc_new_block(struct vdec_input_s *input,
58 	ulong phy_addr,
59 	int size);
60 
aml_copy_from_user(void * to,const void * from,ulong n)61 static int aml_copy_from_user(void *to, const void *from, ulong n)
62 {
63 	int ret =0;
64 
65 	if (likely(access_ok(from, n)))
66 		ret = copy_from_user(to, from, n);
67 	else
68 		memcpy(to, from, n);
69 
70 	return ret;
71 }
72 
copy_from_user_to_phyaddr(void * virts,const char __user * buf,u32 size,ulong phys,u32 pading,bool is_mapped)73 static int copy_from_user_to_phyaddr(void *virts, const char __user *buf,
74 		u32 size, ulong phys, u32 pading, bool is_mapped)
75 {
76 	u32 i, span = SZ_1M;
77 	u32 count = size / PAGE_ALIGN(span);
78 	u32 remain = size % PAGE_ALIGN(span);
79 	ulong addr = phys;
80 	u8 *p = virts;
81 
82 	if (is_mapped) {
83 		if (aml_copy_from_user(p, buf, size))
84 			return -EFAULT;
85 
86 		if (pading)
87 			memset(p + size, 0, pading);
88 
89 		codec_mm_dma_flush(p, size + pading, DMA_TO_DEVICE);
90 
91 		return 0;
92 	}
93 
94 	for (i = 0; i < count; i++) {
95 		addr = phys + i * span;
96 		p = codec_mm_vmap(addr, span);
97 		if (!p)
98 			return -1;
99 
100 		if (aml_copy_from_user(p, buf + i * span, span)) {
101 			codec_mm_unmap_phyaddr(p);
102 			return -EFAULT;
103 		}
104 
105 		codec_mm_dma_flush(p, span, DMA_TO_DEVICE);
106 		codec_mm_unmap_phyaddr(p);
107 	}
108 
109 	if (!remain)
110 		return 0;
111 
112 	span = size - remain;
113 	addr = phys + span;
114 	p = codec_mm_vmap(addr, remain + pading);
115 	if (!p)
116 		return -1;
117 
118 	if (aml_copy_from_user(p, buf + span, remain)) {
119 		codec_mm_unmap_phyaddr(p);
120 		return -EFAULT;
121 	}
122 
123 	if (pading)
124 		memset(p + remain, 0, pading);
125 
126 	codec_mm_dma_flush(p, remain + pading, DMA_TO_DEVICE);
127 	codec_mm_unmap_phyaddr(p);
128 
129 	return 0;
130 }
131 
vframe_chunk_fill(struct vdec_input_s * input,struct vframe_chunk_s * chunk,const char * buf,size_t count,struct vframe_block_list_s * block)132 static int vframe_chunk_fill(struct vdec_input_s *input,
133 			struct vframe_chunk_s *chunk, const char *buf,
134 			size_t count, struct vframe_block_list_s *block)
135 {
136 	u8 *p = (u8 *)block->start_virt + block->wp;
137 	if (block->type == VDEC_TYPE_FRAME_BLOCK) {
138 		copy_from_user_to_phyaddr(p, buf, count,
139 			block->start + block->wp,
140 			chunk->pading_size,
141 			block->is_mapped);
142 	} else if (block->type == VDEC_TYPE_FRAME_CIRCULAR) {
143 		size_t len = min((size_t)(block->size - block->wp), count);
144 		u32 wp;
145 
146 		copy_from_user_to_phyaddr(p, buf, len,
147 				block->start + block->wp, 0,
148 				block->is_mapped);
149 		p += len;
150 
151 		if (count > len) {
152 			copy_from_user_to_phyaddr(p, buf + len,
153 				count - len,
154 				block->start, 0,
155 				block->is_mapped);
156 
157 			p += count - len;
158 		}
159 
160 		wp = block->wp + count;
161 		if (wp >= block->size)
162 			wp -= block->size;
163 
164 		len = min(block->size - wp, chunk->pading_size);
165 
166 		if (!block->is_mapped) {
167 			p = codec_mm_vmap(block->start + wp, len);
168 			memset(p, 0, len);
169 			codec_mm_dma_flush(p, len, DMA_TO_DEVICE);
170 			codec_mm_unmap_phyaddr(p);
171 		} else {
172 			memset(p, 0, len);
173 			codec_mm_dma_flush(p, len, DMA_TO_DEVICE);
174 		}
175 
176 		if (chunk->pading_size > len) {
177 			p = (u8 *)block->start_virt;
178 
179 			if (!block->is_mapped) {
180 				p = codec_mm_vmap(block->start,
181 					chunk->pading_size - len);
182 				memset(p, 0, chunk->pading_size - len);
183 				codec_mm_dma_flush(p,
184 					chunk->pading_size - len,
185 					DMA_TO_DEVICE);
186 				codec_mm_unmap_phyaddr(p);
187 			} else {
188 				memset(p, 0, chunk->pading_size - len);
189 				codec_mm_dma_flush(p,
190 					chunk->pading_size - len,
191 					DMA_TO_DEVICE);
192 			}
193 		}
194 	}
195 
196 	return 0;
197 }
198 
vframe_block_space(struct vframe_block_list_s * block)199 static inline u32 vframe_block_space(struct vframe_block_list_s *block)
200 {
201 	if (block->type == VDEC_TYPE_FRAME_BLOCK) {
202 		return block->size - block->wp;
203 	} else {
204 		return (block->rp >= block->wp) ?
205 			   (block->rp - block->wp) :
206 			   (block->rp - block->wp + block->size);
207 	}
208 }
209 
vframe_block_add_chunk(struct vframe_block_list_s * block,struct vframe_chunk_s * chunk)210 static void vframe_block_add_chunk(struct vframe_block_list_s *block,
211 				struct vframe_chunk_s *chunk)
212 {
213 	block->wp += chunk->size + chunk->pading_size;
214 	if (block->wp >= block->size)
215 		block->wp -= block->size;
216 	block->data_size += chunk->size;
217 	block->chunk_count++;
218 	chunk->block = block;
219 	block->input->wr_block = block;
220 	chunk->sequence = block->input->sequence;
221 	block->input->sequence++;
222 }
223 
vframe_block_free_block(struct vframe_block_list_s * block)224 static void vframe_block_free_block(struct vframe_block_list_s *block)
225 {
226 	if (block->addr) {
227 		codec_mm_free_for_dma(MEM_NAME,	block->addr);
228 	}
229 	/*
230 	*pr_err("free block %d, size=%d\n", block->id, block->size);
231 	*/
232 	kfree(block);
233 }
234 
vframe_block_init_alloc_storage(struct vdec_input_s * input,struct vframe_block_list_s * block,ulong phy_addr,int size)235 static int vframe_block_init_alloc_storage(struct vdec_input_s *input,
236 			struct vframe_block_list_s *block,
237 			ulong phy_addr,
238 			int size)
239 {
240 	int alloc_size = input->default_block_size;
241 	block->magic = 0x4b434c42;
242 	block->input = input;
243 	block->type = input->type;
244 
245 	/*
246 	 * todo: for different type use different size
247 	 */
248 	if (phy_addr) {
249 		block->is_out_buf = 1;
250 		block->start_virt = NULL;
251 		block->start = phy_addr;
252 		block->size = size;
253 	} else {
254 		alloc_size = PAGE_ALIGN(alloc_size);
255 		block->addr = codec_mm_alloc_for_dma_ex(
256 			MEM_NAME,
257 			alloc_size/PAGE_SIZE,
258 			VFRAME_BLOCK_PAGEALIGN,
259 			CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER,
260 			input->id,
261 			block->id);
262 
263 		if (!block->addr) {
264 			pr_err("Input block allocation failed\n");
265 			return -ENOMEM;
266 		}
267 
268 		block->start_virt = (void *)codec_mm_phys_to_virt(block->addr);
269 		if (block->start_virt)
270 			block->is_mapped = true;
271 		block->start = block->addr;
272 		block->size = alloc_size;
273 		block->is_out_buf = 0;
274 	}
275 
276 	return 0;
277 }
278 
vdec_input_init(struct vdec_input_s * input,struct vdec_s * vdec)279 void vdec_input_init(struct vdec_input_s *input, struct vdec_s *vdec)
280 {
281 	INIT_LIST_HEAD(&input->vframe_block_list);
282 	INIT_LIST_HEAD(&input->vframe_block_free_list);
283 	INIT_LIST_HEAD(&input->vframe_chunk_list);
284 	spin_lock_init(&input->lock);
285 	input->id = vdec->id;
286 	input->block_nums = 0;
287 	input->vdec = vdec;
288 	input->block_id_seq = 0;
289 	input->size = 0;
290 	input->default_block_size = VFRAME_BLOCK_SIZE;
291 }
vdec_input_prepare_bufs(struct vdec_input_s * input,int frame_width,int frame_height)292 int vdec_input_prepare_bufs(struct vdec_input_s *input,
293 	int frame_width, int frame_height)
294 {
295 	struct vframe_block_list_s *block;
296 	int i;
297 	unsigned long flags;
298 
299 	if (vdec_secure(input->vdec))
300 		return 0;
301 	if (input->size > 0)
302 		return 0;
303 	if (frame_width * frame_height >= 1920 * 1088) {
304 		/*have add data before. ignore prepare buffers.*/
305 		input->default_block_size = VFRAME_BLOCK_SIZE_4K;
306 	}
307 	/*prepared 3 buffers for smooth start.*/
308 	for (i = 0; i < 3; i++) {
309 		block = vdec_input_alloc_new_block(input, 0, 0);
310 		if (!block)
311 			break;
312 		flags = vdec_input_lock(input);
313 		list_move_tail(&block->list,
314 				&input->vframe_block_free_list);
315 		input->wr_block = NULL;
316 		vdec_input_unlock(input, flags);
317 	}
318 	return 0;
319 }
320 
vdec_input_dump_block_locked(struct vframe_block_list_s * block,char * buf,int size)321 static int vdec_input_dump_block_locked(
322 	struct vframe_block_list_s *block,
323 	char *buf, int size)
324 {
325 	char *pbuf = buf;
326 	char sbuf[512];
327 	int tsize = 0;
328 	int s;
329 	if (!pbuf) {
330 		pbuf = sbuf;
331 		size = 512;
332 	}
333 	#define BUFPRINT(args...) \
334 	do {\
335 		s = snprintf(pbuf, size - tsize, args);\
336 		tsize += s;\
337 		pbuf += s; \
338 	} while (0)
339 
340 	BUFPRINT("\tblock:[%d:%p]-addr=%p,vstart=%p,type=%d\n",
341 		block->id,
342 		block,
343 		(void *)block->addr,
344 		(void *)block->start_virt,
345 		block->type);
346 	BUFPRINT("\t-blocksize=%d,data=%d,wp=%d,rp=%d,chunk_count=%d\n",
347 		block->size,
348 		block->data_size,
349 		block->wp,
350 		block->rp,
351 		block->chunk_count);
352 	/*
353 	BUFPRINT("\tlist=%p,next=%p,prev=%p\n",
354 		&block->list,
355 		block->list.next,
356 		block->list.prev);
357 	*/
358 	#undef BUFPRINT
359 	if (!buf)
360 		pr_info("%s", sbuf);
361 	return tsize;
362 }
363 
vdec_input_dump_blocks(struct vdec_input_s * input,char * bufs,int size)364 int vdec_input_dump_blocks(struct vdec_input_s *input,
365 	char *bufs, int size)
366 {
367 	struct list_head *p, *tmp;
368 	unsigned long flags;
369 	char *lbuf = bufs;
370 	char sbuf[256];
371 	int s = 0;
372 
373 	if (size <= 0)
374 		return 0;
375 	if (!bufs)
376 		lbuf = sbuf;
377 	s += snprintf(lbuf + s, size - s,
378 		"blocks:vdec-%d id:%d,bufsize=%d,dsize=%d,frames:%d,dur:%dms\n",
379 		input->id,
380 		input->block_nums,
381 		input->size,
382 		input->data_size,
383 		input->have_frame_num,
384 		vdec_input_get_duration_u64(input)/1000);
385 	if (bufs)
386 		lbuf += s;
387 	else {
388 		pr_info("%s", sbuf);
389 		lbuf = NULL;
390 	}
391 
392 	flags = vdec_input_lock(input);
393 	/* dump input blocks */
394 	list_for_each_safe(p, tmp, &input->vframe_block_list) {
395 		struct vframe_block_list_s *block = list_entry(
396 			p, struct vframe_block_list_s, list);
397 		if (bufs != NULL) {
398 			lbuf = bufs + s;
399 			if (size - s < 128)
400 				break;
401 		}
402 		s += vdec_input_dump_block_locked(block, lbuf, size - s);
403 	}
404 	list_for_each_safe(p, tmp, &input->vframe_block_free_list) {
405 		struct vframe_block_list_s *block = list_entry(
406 			p, struct vframe_block_list_s, list);
407 		if (bufs != NULL) {
408 			lbuf = bufs + s;
409 			if (size - s < 128)
410 				break;
411 		}
412 		s += vdec_input_dump_block_locked(block, lbuf, size - s);
413 	}
414 	vdec_input_unlock(input, flags);
415 	return s;
416 }
417 
vdec_input_dump_chunk_locked(int id,struct vframe_chunk_s * chunk,char * buf,int size)418 static int vdec_input_dump_chunk_locked(
419 	int id,
420 	struct vframe_chunk_s *chunk,
421 	char *buf, int size)
422 {
423 	char *pbuf = buf;
424 	char sbuf[512];
425 	int tsize = 0;
426 	int s;
427 	if (!pbuf) {
428 		pbuf = sbuf;
429 		size = 512;
430 	}
431 	#define BUFPRINT(args...) \
432 	do {\
433 		s = snprintf(pbuf, size - tsize, args);\
434 		tsize += s;\
435 		pbuf += s; \
436 	} while (0)
437 
438 	BUFPRINT(
439 		"\t[%d][%lld:%p]-off=%d,size:%d,p:%d,\tpts64=%lld,addr=%p\n",
440 		id,
441 		chunk->sequence,
442 		chunk->block,
443 		chunk->offset,
444 		chunk->size,
445 		chunk->pading_size,
446 		chunk->pts64,
447 		(void *)(chunk->block->addr + chunk->offset));
448 	/*
449 	BUFPRINT("\tlist=%p,next=%p,prev=%p\n",
450 		&chunk->list,
451 		chunk->list.next,
452 		chunk->list.prev);
453 	*/
454 	#undef BUFPRINT
455 	if (!buf)
456 		pr_info("%s", sbuf);
457 	return tsize;
458 }
459 
vdec_input_dump_chunks(int id,struct vdec_input_s * input,char * bufs,int size)460 int vdec_input_dump_chunks(int id, struct vdec_input_s *input,
461 	char *bufs, int size)
462 {
463 
464 	struct list_head *p, *tmp;
465 	unsigned long flags;
466 	char *lbuf = bufs;
467 	char sbuf[256];
468 	int s = 0;
469 	int i = 0;
470 
471 	if (size <= 0)
472 		return 0;
473 	if (!bufs)
474 		lbuf = sbuf;
475 	s = snprintf(lbuf + s, size - s,
476 		"[%d]blocks:vdec-%d id:%d,bufsize=%d,dsize=%d,frames:%d,maxframe:%d\n",
477 		id,
478 		input->id,
479 		input->block_nums,
480 		input->size,
481 		input->data_size,
482 		input->have_frame_num,
483 		input->frame_max_size);
484 	if (bufs)
485 		lbuf += s;
486 	if (!bufs) {
487 		pr_info("%s", sbuf);
488 		lbuf = NULL;
489 	}
490 	flags = vdec_input_lock(input);
491 	/*dump chunks list infos.*/
492 	list_for_each_safe(p, tmp, &input->vframe_chunk_list) {
493 		struct vframe_chunk_s *chunk = list_entry(
494 				p, struct vframe_chunk_s, list);
495 		if (bufs != NULL)
496 			lbuf = bufs + s;
497 		s += vdec_input_dump_chunk_locked(id, chunk, lbuf, size - s);
498 		i++;
499 		if (i >= 10)
500 			break;
501 	}
502 	vdec_input_unlock(input, flags);
503 	return s;
504 }
505 
506 
507 
vdec_input_set_buffer(struct vdec_input_s * input,u32 start,u32 size)508 int vdec_input_set_buffer(struct vdec_input_s *input, u32 start, u32 size)
509 {
510 	if (input_frame_based(input))
511 		return -EINVAL;
512 
513 	input->start = start;
514 	input->size = size;
515 	input->swap_rp = start;
516 
517 	if (vdec_secure(input->vdec))
518 		input->swap_page_phys = codec_mm_alloc_for_dma("SWAP",
519 			1, 0, CODEC_MM_FLAGS_TVP);
520 	else {
521 		input->swap_page = dma_alloc_coherent(v4l_get_dev_from_codec_mm(),
522 				PAGE_SIZE,
523 				&input->swap_page_phys, GFP_KERNEL);
524 
525 		if (input->swap_page == NULL)
526 			return -ENOMEM;
527 	}
528 
529 	if (input->swap_page_phys == 0)
530 		return -ENOMEM;
531 	return 0;
532 }
533 EXPORT_SYMBOL(vdec_input_set_buffer);
534 
vdec_input_set_type(struct vdec_input_s * input,int type,int target)535 void vdec_input_set_type(struct vdec_input_s *input, int type, int target)
536 {
537 	input->type = type;
538 	input->target = target;
539 	if (type == VDEC_TYPE_FRAME_CIRCULAR) {
540 		/*alway used max block.*/
541 		input->default_block_size = VFRAME_BLOCK_SIZE_MAX;
542 	}
543 }
544 EXPORT_SYMBOL(vdec_input_set_type);
545 
vdec_input_get_status(struct vdec_input_s * input,struct vdec_input_status_s * status)546 int vdec_input_get_status(struct vdec_input_s *input,
547 			struct vdec_input_status_s *status)
548 {
549 	unsigned long flags;
550 
551 	if (input->vdec == NULL)
552 		return -EINVAL;
553 
554 	flags = vdec_input_lock(input);
555 
556 	if (list_empty(&input->vframe_block_list)) {
557 		status->size = VFRAME_BLOCK_SIZE;
558 		status->data_len = 0;
559 		status->free_len = VFRAME_BLOCK_SIZE;
560 		status->read_pointer = 0;
561 	} else {
562 		int r = VFRAME_BLOCK_MAX_LEVEL - vdec_input_level(input)
563 			- VFRAME_BLOCK_HOLE;
564 		status->size = input->size;
565 		status->data_len = vdec_input_level(input);
566 		status->free_len = (r > 0) ? r : 0;
567 		status->read_pointer = input->total_rd_count;
568 	}
569 
570 	vdec_input_unlock(input, flags);
571 
572 	return 0;
573 }
574 EXPORT_SYMBOL(vdec_input_get_status);
575 
vdec_input_add_block(struct vdec_input_s * input,struct vframe_block_list_s * block)576 static void vdec_input_add_block(struct vdec_input_s *input,
577 				struct vframe_block_list_s *block)
578 {
579 	unsigned long flags;
580 
581 	flags = vdec_input_lock(input);
582 	block->wp = 0;
583 	block->id = input->block_id_seq++;
584 	list_add_tail(&block->list, &input->vframe_block_list);
585 	input->size += block->size;
586 	input->block_nums++;
587 	input->wr_block = block;
588 	vdec_input_unlock(input, flags);
589 }
590 
vdec_input_del_block_locked(struct vdec_input_s * input,struct vframe_block_list_s * block)591 static inline void vdec_input_del_block_locked(struct vdec_input_s *input,
592 				struct vframe_block_list_s *block)
593 {
594 	list_del(&block->list);
595 	input->size -= block->size;
596 	input->block_nums--;
597 }
598 
vdec_input_level(struct vdec_input_s * input)599 int vdec_input_level(struct vdec_input_s *input)
600 {
601 	return input->total_wr_count - input->total_rd_count;
602 }
603 EXPORT_SYMBOL(vdec_input_level);
604 
605 static struct vframe_block_list_s *
vdec_input_alloc_new_block(struct vdec_input_s * input,ulong phy_addr,int size)606 	vdec_input_alloc_new_block(struct vdec_input_s *input,
607 	ulong phy_addr,
608 	int size)
609 {
610 	struct vframe_block_list_s *block;
611 	block = kzalloc(sizeof(struct vframe_block_list_s),
612 			GFP_KERNEL);
613 	if (block == NULL) {
614 		input->no_mem_err_cnt++;
615 		pr_err("vframe_block structure allocation failed\n");
616 		return NULL;
617 	}
618 
619 	if (vframe_block_init_alloc_storage(input,
620 		block, phy_addr, size) != 0) {
621 		kfree(block);
622 		pr_err("vframe_block storage allocation failed\n");
623 		return NULL;
624 	}
625 
626 	INIT_LIST_HEAD(&block->list);
627 
628 	vdec_input_add_block(input, block);
629 
630 	/*
631 	 *pr_info("vdec-%d:new block id=%d, total_blocks:%d, size=%d\n",
632 	 *	input->id,
633 	 *	block->id,
634 	 *	input->block_nums,
635 	 *	block->size);
636 	 */
637 	if (0 && input->size > VFRAME_BLOCK_MAX_LEVEL * 2) {
638 		/*
639 		used
640 		*/
641 		pr_info(
642 		"input[%d] reach max: size:%d, blocks:%d",
643 			input->id,
644 			input->size,
645 			input->block_nums);
646 		pr_info("level:%d, wr:%lld,rd:%lld\n",
647 			vdec_input_level(input),
648 			input->total_wr_count,
649 			input->total_rd_count);
650 		vdec_input_dump_blocks(input, NULL, 0);
651 	}
652 	return block;
653 }
vdec_input_get_duration_u64(struct vdec_input_s * input)654 int vdec_input_get_duration_u64(struct vdec_input_s *input)
655 {
656 	int duration = (input->last_inpts_u64 - input->last_comsumed_pts_u64);
657 	if (input->last_in_nopts_cnt > 0 &&
658 		input->last_comsumed_pts_u64 > 0 &&
659 		input->last_duration > 0) {
660 		duration += (input->last_in_nopts_cnt -
661 			input->last_comsumed_no_pts_cnt) *
662 			input->last_duration;
663 	}
664 	if (duration > 1000 * 1000000)/*> 1000S,I think jumped.*/
665 		duration = 0;
666 	if (duration <= 0 && input->last_duration > 0) {
667 		/*..*/
668 		duration = input->last_duration * input->have_frame_num;
669 	}
670 	if (duration < 0)
671 		duration = 0;
672 	return duration;
673 }
674 EXPORT_SYMBOL(vdec_input_get_duration_u64);
675 
676 /*
677 	ret >= 13: have enough buffer, blocked add more buffers
678 */
vdec_input_have_blocks_enough(struct vdec_input_s * input)679 static int vdec_input_have_blocks_enough(struct vdec_input_s *input)
680 {
681 	int ret = 0;
682 	if (vdec_input_level(input) > VFRAME_BLOCK_MIN_LEVEL)
683 		ret += 1;
684 	if (vdec_input_level(input) >= VFRAME_BLOCK_MAX_LEVEL)
685 		ret += 2;
686 	if (vdec_input_get_duration_u64(input) > MAX_FRAME_DURATION_S)
687 		ret += 4;
688 	if (input->have_frame_num > 30)
689 		ret += 8;
690 	else
691 		ret -= 8;/*not enough frames.*/
692 	if (input->size >= VFRAME_BLOCK_MAX_TOTAL_SIZE)
693 		ret += 100;/*always bloced add more buffers.*/
694 
695 	return ret;
696 }
vdec_input_get_free_block(struct vdec_input_s * input,int size,struct vframe_block_list_s ** block_ret)697 static int	vdec_input_get_free_block(
698 	struct vdec_input_s *input,
699 	int size,/*frame size + pading*/
700 	struct vframe_block_list_s **block_ret)
701 {
702 	struct vframe_block_list_s *to_freeblock = NULL;
703 	struct vframe_block_list_s *block = NULL;
704 	unsigned long flags;
705 	flags = vdec_input_lock(input);
706 	/*get from free list.*/
707 	if (!list_empty(&input->vframe_block_free_list)) {
708 		block = list_entry(input->vframe_block_free_list.next,
709 		struct vframe_block_list_s, list);
710 		if (block->size < (size)) {
711 			vdec_input_del_block_locked(input, block);
712 			to_freeblock = block;
713 			block = NULL;
714 		} else {
715 			list_move_tail(&block->list,
716 				&input->vframe_block_list);
717 			input->wr_block = block;/*swith to new block*/
718 		}
719 	}
720 	vdec_input_unlock(input, flags);
721 	if (to_freeblock) {
722 		/*free the small block.*/
723 		vframe_block_free_block(to_freeblock);
724 	}
725 	if (block) {
726 		*block_ret = block;
727 		return 0;
728 	}
729 
730 	if (vdec_input_have_blocks_enough(input) > 13) {
731 		/*buf fulled */
732 		return -EAGAIN;
733 	}
734 	if (input->no_mem_err_cnt > 3) {
735 		/*alloced failed more times.
736 		*/
737 		return -EAGAIN;
738 	}
739 	if (input->default_block_size <=
740 		size * 2) {
741 		int def_size = input->default_block_size;
742 		do {
743 			def_size *= 2;
744 		} while ((def_size <= 2 * size) &&
745 			(def_size <= VFRAME_BLOCK_SIZE_MAX));
746 		if (def_size < size)
747 			def_size = ALIGN(size + 64, (1 << 17));
748 		/*128k aligned,same as codec_mm*/
749 		input->default_block_size = def_size;
750 	}
751 	block = vdec_input_alloc_new_block(input, 0, 0);
752 	if (!block) {
753 		input->no_mem_err_cnt++;
754 		return -EAGAIN;
755 	}
756 	input->no_mem_err_cnt = 0;
757 	*block_ret = block;
758 	return 0;
759 }
760 
vdec_input_add_chunk(struct vdec_input_s * input,const char * buf,size_t count,u32 handle)761 int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf,
762 		size_t count, u32 handle)
763 {
764 	unsigned long flags;
765 	struct vframe_chunk_s *chunk;
766 	struct vdec_s *vdec = input->vdec;
767 	struct vframe_block_list_s *block;
768 	int need_pading_size = MIN_FRAME_PADDING_SIZE;
769 
770 	if (vdec_secure(vdec)) {
771 		block = vdec_input_alloc_new_block(input, (ulong)buf,
772 			PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */
773 		if (!block)
774 			return -ENOMEM;
775 		block->handle = handle;
776 	} else {
777 #if 0
778 		if (add_count == 0) {
779 			add_count++;
780 			memcpy(sps, buf, 30);
781 			return 30;
782 		} else if (add_count == 1) {
783 			add_count++;
784 			memcpy(pps, buf, 8);
785 			return 8;
786 		}
787 		add_count++;
788 #endif
789 
790 #if 0
791 		pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count);
792 
793 		if (count >= 8) {
794 			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
795 			buf[0], buf[1], buf[2], buf[3],
796 			buf[4], buf[5], buf[6], buf[7]);
797 		}
798 		if (count >= 16) {
799 			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
800 			buf[8], buf[9], buf[10], buf[11],
801 			buf[12], buf[13], buf[14], buf[15]);
802 		}
803 		if (count >= 24) {
804 			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
805 			buf[16], buf[17], buf[18], buf[19],
806 			buf[20], buf[21], buf[22], buf[23]);
807 		}
808 		if (count >= 32) {
809 			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
810 			buf[24], buf[25], buf[26], buf[27],
811 			buf[28], buf[29], buf[30], buf[31]);
812 	}
813 #endif
814 		if (input_stream_based(input))
815 			return -EINVAL;
816 
817 		if (count < PAGE_SIZE) {
818 			need_pading_size = PAGE_ALIGN(count + need_pading_size) -
819 				count;
820 		} else {
821 			/*to 64 bytes aligned;*/
822 			if (count & 0x3f)
823 				need_pading_size += 64 - (count & 0x3f);
824 		}
825 		block = input->wr_block;
826 		if (block &&
827 			(vframe_block_space(block) > (count + need_pading_size))) {
828 			/*this block have enough buffers.
829 			do nothings.
830 			*/
831 		} else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) {
832 			/*in circular module.
833 			only one block,.*/
834 			return -EAGAIN;
835 		} else if (block != NULL) {
836 			/*have block but not enough space.
837 			recycle the no enough blocks.*/
838 			flags = vdec_input_lock(input);
839 			if (input->wr_block == block &&
840 				block->chunk_count == 0) {
841 				block->rp = 0;
842 				block->wp = 0;
843 				/*block no data move to freelist*/
844 				list_move_tail(&block->list,
845 					&input->vframe_block_free_list);
846 				input->wr_block = NULL;
847 			}
848 			vdec_input_unlock(input, flags);
849 			block = NULL;
850 		}
851 		if (!block) {/*try new block.*/
852 			int ret = vdec_input_get_free_block(input,
853 				count + need_pading_size + EXTRA_PADDING_SIZE,
854 				&block);
855 			if (ret < 0)/*no enough block now.*/
856 				return ret;
857 		}
858 	}
859 
860 	chunk = kzalloc(sizeof(struct vframe_chunk_s), GFP_KERNEL);
861 
862 	if (!chunk) {
863 		pr_err("vframe_chunk structure allocation failed\n");
864 		return -ENOMEM;
865 	}
866 
867 	chunk->magic = 0x4b554843;
868 	if (vdec->pts_valid) {
869 		chunk->pts = vdec->pts;
870 		chunk->pts64 = vdec->pts64;
871 	}
872 
873 	if (vdec->timestamp_valid)
874 		chunk->timestamp = vdec->timestamp;
875 
876 	if (vdec->pts_valid &&
877 		input->last_inpts_u64 > 0 &&
878 		input->last_in_nopts_cnt == 0) {
879 		int d = (int)(chunk->pts64 - input->last_inpts_u64);
880 		if (d > 0 && (d < input->last_duration))
881 			input->last_duration = d;
882 		/*	alwasy: used the smallest duration;
883 			if 60fps->30 fps.
884 			maybe have warning value.
885 		*/
886 	}
887 	chunk->pts_valid = vdec->pts_valid;
888 	vdec->pts_valid = false;
889 	INIT_LIST_HEAD(&chunk->list);
890 
891 	if (vdec_secure(vdec)) {
892 		chunk->offset = 0;
893 		chunk->size = count;
894 		chunk->pading_size = PAGE_ALIGN(chunk->size + need_pading_size) -
895 			chunk->size;
896 	} else {
897 		chunk->offset = block->wp;
898 		chunk->size = count;
899 		chunk->pading_size = need_pading_size;
900 		if (vframe_chunk_fill(input, chunk, buf, count, block)) {
901 			pr_err("vframe_chunk_fill failed\n");
902 			kfree(chunk);
903 			return -EFAULT;
904 		}
905 
906 	}
907 
908 
909 	flags = vdec_input_lock(input);
910 
911 	vframe_block_add_chunk(block, chunk);
912 
913 	list_add_tail(&chunk->list, &input->vframe_chunk_list);
914 	input->data_size += chunk->size;
915 	input->have_frame_num++;
916 
917 	if (input->have_frame_num == 1)
918 		input->vdec_up(vdec);
919 	ATRACE_COUNTER(MEM_NAME, input->have_frame_num);
920 	if (chunk->pts_valid) {
921 		input->last_inpts_u64 = chunk->pts64;
922 		input->last_in_nopts_cnt = 0;
923 	} else {
924 		/*nopts*/
925 		input->last_in_nopts_cnt++;
926 	}
927 	if (chunk->size > input->frame_max_size)
928 		input->frame_max_size = chunk->size;
929 	input->total_wr_count += count;
930 	vdec_input_unlock(input, flags);
931 #if 0
932 	if (add_count == 2)
933 		input->total_wr_count += 38;
934 #endif
935 
936 	return count;
937 }
938 
vdec_input_add_frame(struct vdec_input_s * input,const char * buf,size_t count)939 int vdec_input_add_frame(struct vdec_input_s *input, const char *buf,
940 			size_t count)
941 {
942 	int ret = 0;
943 	struct drm_info drm;
944 	struct vdec_s *vdec = input->vdec;
945 	unsigned long phy_buf;
946 
947 	if (vdec_secure(vdec)) {
948 		while (count > 0) {
949 			if (count < sizeof(struct drm_info))
950 				return -EIO;
951 			if (copy_from_user((void*)&drm, buf + ret, sizeof(struct drm_info)))
952 				return -EAGAIN;
953 			if (!(drm.drm_flag & TYPE_DRMINFO_V2))
954 				return -EIO; /*must drm info v2 version*/
955 			phy_buf = (unsigned long) drm.drm_phy;
956 			vdec_input_add_chunk(input, (char *)phy_buf,
957 				(size_t)drm.drm_pktsize, drm.handle);
958 			count -= sizeof(struct drm_info);
959 			ret += sizeof(struct drm_info);
960 
961 			/* the drm frame data might include head infos and raw */
962 			/* data thus the next drm unit still need a valid pts.*/
963 			if (count >= sizeof(struct drm_info))
964 				vdec->pts_valid = true;
965 		}
966 	} else {
967 		ret = vdec_input_add_chunk(input, buf, count, 0);
968 	}
969 
970 	return ret;
971 }
972 EXPORT_SYMBOL(vdec_input_add_frame);
973 
vdec_input_add_frame_with_dma(struct vdec_input_s * input,ulong addr,size_t count,u32 handle)974 int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr,
975 			size_t count, u32 handle)
976 {
977 	struct vdec_s *vdec = input->vdec;
978 
979 	return vdec_secure(vdec) ?
980 		vdec_input_add_chunk(input, (char *)addr, count, handle) : -1;
981 }
982 EXPORT_SYMBOL(vdec_input_add_frame_with_dma);
983 
vdec_input_next_chunk(struct vdec_input_s * input)984 struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input)
985 {
986 	struct vframe_chunk_s *chunk = NULL;
987 	unsigned long flags;
988 	flags = vdec_input_lock(input);
989 	if (!list_empty(&input->vframe_chunk_list)) {
990 		chunk = list_first_entry(&input->vframe_chunk_list,
991 				struct vframe_chunk_s, list);
992 	}
993 	vdec_input_unlock(input, flags);
994 	return chunk;
995 }
996 EXPORT_SYMBOL(vdec_input_next_chunk);
997 
vdec_input_next_input_chunk(struct vdec_input_s * input)998 struct vframe_chunk_s *vdec_input_next_input_chunk(
999 			struct vdec_input_s *input)
1000 {
1001 	struct vframe_chunk_s *chunk = NULL;
1002 	struct list_head *p;
1003 	unsigned long flags;
1004 	flags = vdec_input_lock(input);
1005 
1006 	list_for_each(p, &input->vframe_chunk_list) {
1007 		struct vframe_chunk_s *c = list_entry(
1008 			p, struct vframe_chunk_s, list);
1009 		if ((c->flag & VFRAME_CHUNK_FLAG_CONSUMED) == 0) {
1010 			chunk = c;
1011 			break;
1012 		}
1013 	}
1014 	vdec_input_unlock(input, flags);
1015 	return chunk;
1016 }
1017 EXPORT_SYMBOL(vdec_input_next_input_chunk);
1018 
vdec_input_release_chunk(struct vdec_input_s * input,struct vframe_chunk_s * chunk)1019 void vdec_input_release_chunk(struct vdec_input_s *input,
1020 			struct vframe_chunk_s *chunk)
1021 {
1022 	struct vframe_chunk_s *p;
1023 	u32 chunk_valid = 0;
1024 	unsigned long flags;
1025 	struct vframe_block_list_s *block = chunk->block;
1026 	struct vframe_block_list_s *tofreeblock = NULL;
1027 	flags = vdec_input_lock(input);
1028 
1029 	list_for_each_entry(p, &input->vframe_chunk_list, list) {
1030 		if (p == chunk) {
1031 			chunk_valid = 1;
1032 			break;
1033 		}
1034 	}
1035 	/* 2 threads go here, the other done the deletion,so return*/
1036 	if (chunk_valid == 0) {
1037 		vdec_input_unlock(input, flags);
1038 		pr_err("%s chunk is deleted,so return.\n", __func__);
1039 		return;
1040 	}
1041 
1042 	list_del(&chunk->list);
1043 	input->have_frame_num--;
1044 	ATRACE_COUNTER(MEM_NAME, input->have_frame_num);
1045 	if (chunk->pts_valid) {
1046 		input->last_comsumed_no_pts_cnt = 0;
1047 		input->last_comsumed_pts_u64 = chunk->pts64;
1048 	} else
1049 		input->last_comsumed_no_pts_cnt++;
1050 	block->rp += chunk->size;
1051 	if (block->rp >= block->size)
1052 		block->rp -= block->size;
1053 	block->data_size -= chunk->size;
1054 	block->chunk_count--;
1055 	input->data_size -= chunk->size;
1056 	input->total_rd_count += chunk->size;
1057 	if (block->is_out_buf) {
1058 		list_move_tail(&block->list,
1059 			&input->vframe_block_free_list);
1060 	} else if (block->chunk_count == 0 &&
1061 		input->wr_block != block ) {/*don't free used block*/
1062 		if (block->size < input->default_block_size) {
1063 			vdec_input_del_block_locked(input, block);
1064 			tofreeblock = block;
1065 		} else {
1066 			block->rp = 0;
1067 			block->wp = 0;
1068 			list_move_tail(&block->list,
1069 				&input->vframe_block_free_list);
1070 		}
1071 	}
1072 
1073 	vdec_input_unlock(input, flags);
1074 	if (tofreeblock)
1075 		vframe_block_free_block(tofreeblock);
1076 	kfree(chunk);
1077 }
1078 EXPORT_SYMBOL(vdec_input_release_chunk);
1079 
vdec_input_lock(struct vdec_input_s * input)1080 unsigned long vdec_input_lock(struct vdec_input_s *input)
1081 {
1082 	unsigned long flags;
1083 
1084 	spin_lock_irqsave(&input->lock, flags);
1085 
1086 	return flags;
1087 }
1088 EXPORT_SYMBOL(vdec_input_lock);
1089 
vdec_input_unlock(struct vdec_input_s * input,unsigned long flags)1090 void vdec_input_unlock(struct vdec_input_s *input, unsigned long flags)
1091 {
1092 	spin_unlock_irqrestore(&input->lock, flags);
1093 }
1094 EXPORT_SYMBOL(vdec_input_unlock);
1095 
vdec_input_release(struct vdec_input_s * input)1096 void vdec_input_release(struct vdec_input_s *input)
1097 {
1098 	struct list_head *p, *tmp;
1099 
1100 	/* release chunk data */
1101 	list_for_each_safe(p, tmp, &input->vframe_chunk_list) {
1102 		struct vframe_chunk_s *chunk = list_entry(
1103 				p, struct vframe_chunk_s, list);
1104 		vdec_input_release_chunk(input, chunk);
1105 	}
1106 	list_for_each_safe(p, tmp, &input->vframe_block_list) {
1107 		/*should never here.*/
1108 		list_move_tail(p, &input->vframe_block_free_list);
1109 	}
1110 	/* release input blocks */
1111 	list_for_each_safe(p, tmp, &input->vframe_block_free_list) {
1112 		struct vframe_block_list_s *block = list_entry(
1113 			p, struct vframe_block_list_s, list);
1114 		vdec_input_del_block_locked(input, block);
1115 		vframe_block_free_block(block);
1116 	}
1117 
1118 	/* release swap pages */
1119 	if (vdec_secure(input->vdec)) {
1120 		if (input->swap_page_phys)
1121 			codec_mm_free_for_dma("SWAP", input->swap_page_phys);
1122 	} else {
1123 		if (input->swap_page) {
1124 			dma_free_coherent(v4l_get_dev_from_codec_mm(),
1125 				PAGE_SIZE, input->swap_page,
1126 				input->swap_page_phys);
1127 		}
1128 	}
1129 	input->swap_page = NULL;
1130 	input->swap_page_phys = 0;
1131 	input->swap_valid = false;
1132 }
1133 EXPORT_SYMBOL(vdec_input_release);
1134 
vdec_input_get_freed_handle(struct vdec_s * vdec)1135 u32 vdec_input_get_freed_handle(struct vdec_s *vdec)
1136 {
1137 	struct vframe_block_list_s *block;
1138 	struct vdec_input_s *input = &vdec->input;
1139 	unsigned long flags;
1140 	u32 handle = 0;
1141 
1142 	if (!vdec_secure(vdec))
1143 		return 0;
1144 
1145 	flags = vdec_input_lock(input);
1146 	do {
1147 		block = list_first_entry_or_null(&input->vframe_block_free_list,
1148 		struct vframe_block_list_s, list);
1149 		if (!block) {
1150 			break;
1151 		}
1152 
1153 		handle = block->handle;
1154 		vdec_input_del_block_locked(input, block);
1155 		kfree(block);
1156 
1157 	} while(!handle);
1158 
1159 	vdec_input_unlock(input, flags);
1160 	return handle;
1161 }
1162 EXPORT_SYMBOL(vdec_input_get_freed_handle);
1163 
1164 
1165