• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/amports/decoder/decoder_bmmu_box.c
3  *
4  * Copyright (C) 2015 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 #define DEBUG
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/errno.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/slab.h>
29 #include <linux/amlogic/media/codec_mm/codec_mm_scatter.h>
30 #include <linux/platform_device.h>
31 
32 #include <linux/amlogic/media/video_sink/video_keeper.h>
33 #include "decoder_bmmu_box.h"
34 #include <linux/amlogic/media/codec_mm/codec_mm.h>
35 #include <linux/amlogic/media/codec_mm/codec_mm_keeper.h>
36 
37 #if 1 // FIXME
try_free_keep_video(int flags)38 void try_free_keep_video(int flags)
39 {
40 	pr_err("Error: %s() is not supported.\n", __func__);
41 }
42 
43 #endif
44 
45 struct decoder_bmmu_box {
46 	int max_mm_num;
47 	const char *name;
48 	int channel_id;
49 	struct mutex mutex;
50 	struct list_head list;
51 	int total_size;
52 	int box_ref_cnt;
53 	int change_size_on_need_smaller;
54 	int align2n;		/*can overwite on idx alloc */
55 	int mem_flags;		/*can overwite on idx alloc */
56 	struct codec_mm_s *mm_list[1];
57 };
58 
59 struct decoder_bmmu_box_mgr {
60 	int num;
61 	struct mutex mutex;
62 	struct list_head box_list;
63 };
64 static struct decoder_bmmu_box_mgr global_blk_mgr;
get_decoder_bmmu_box_mgr(void)65 static struct decoder_bmmu_box_mgr *get_decoder_bmmu_box_mgr(void)
66 {
67 	return &global_blk_mgr;
68 }
69 
decoder_bmmu_box_mgr_add_box(struct decoder_bmmu_box * box)70 static int decoder_bmmu_box_mgr_add_box(struct decoder_bmmu_box *box)
71 {
72 	struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
73 
74 	mutex_lock(&mgr->mutex);
75 	list_add_tail(&box->list, &mgr->box_list);
76 	mutex_unlock(&mgr->mutex);
77 	return 0;
78 }
79 
decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box * box)80 static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box)
81 {
82 	struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
83 
84 	mutex_lock(&mgr->mutex);
85 	list_del(&box->list);
86 	mutex_unlock(&mgr->mutex);
87 	return 0;
88 }
89 
decoder_bmmu_box_valide_check(void * box)90 bool decoder_bmmu_box_valide_check(void *box)
91 {
92 	struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
93 	struct decoder_bmmu_box *bmmu_box = NULL;
94 	bool is_valide = false;
95 
96 	mutex_lock(&mgr->mutex);
97 	list_for_each_entry(bmmu_box, &mgr->box_list, list) {
98 		if (bmmu_box && bmmu_box == box) {
99 			is_valide = true;
100 			break;
101 		}
102 	}
103 	mutex_unlock(&mgr->mutex);
104 
105 	return is_valide;
106 }
107 EXPORT_SYMBOL(decoder_bmmu_box_valide_check);
108 
decoder_bmmu_box_alloc_box(const char * name,int channel_id,int max_num,int aligned,int mem_flags)109 void *decoder_bmmu_box_alloc_box(const char *name,
110 		int channel_id, int max_num,
111 		int aligned, int mem_flags)
112 /*min_size_M:wait alloc this size*/
113 {
114 	struct decoder_bmmu_box *box;
115 	int size;
116 	int tvp_flags;
117 	tvp_flags = (mem_flags & CODEC_MM_FLAGS_TVP) ?
118 		CODEC_MM_FLAGS_TVP : 0;
119 
120 	pr_debug("decoder_bmmu_box_alloc_box, tvp_flags = %x\n", tvp_flags);
121 
122 	size = sizeof(struct decoder_bmmu_box) + sizeof(struct codec_mm_s *) *
123 		   max_num;
124 	box = kmalloc(size, GFP_KERNEL);
125 	if (!box) {
126 		pr_err("can't alloc decoder buffers box!!!\n");
127 		return NULL;
128 	}
129 	memset(box, 0, size);
130 	box->max_mm_num = max_num;
131 	box->name = name;
132 	box->channel_id = channel_id;
133 	box->align2n = aligned;
134 	box->mem_flags = mem_flags | tvp_flags;
135 	mutex_init(&box->mutex);
136 	INIT_LIST_HEAD(&box->list);
137 	decoder_bmmu_box_mgr_add_box(box);
138 	return (void *)box;
139 }
140 EXPORT_SYMBOL(decoder_bmmu_box_alloc_box);
141 
decoder_bmmu_box_alloc_idx(void * handle,int idx,int size,int aligned_2n,int mem_flags)142 int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n,
143 							   int mem_flags)
144 /*align& flags if -1 user box default.*/
145 {
146 	struct decoder_bmmu_box *box = handle;
147 	struct codec_mm_s *mm;
148 	int align = aligned_2n;
149 	int memflags = mem_flags;
150 
151 	if (!box || idx < 0 || idx >= box->max_mm_num) {
152 		pr_err("can't alloc mmu box(%p),idx:%d\n",
153 				box, idx);
154 		return -1;
155 	}
156 	if (align == -1)
157 		align = box->align2n;
158 	if (memflags == -1)
159 		memflags = box->mem_flags;
160 
161 	mutex_lock(&box->mutex);
162 	mm = box->mm_list[idx];
163 	if (mm) {
164 		int invalid = 0;
165 		int keeped = 0;
166 
167 		keeped = is_codec_mm_keeped(mm);
168 		if (!keeped) {
169 			if (mm->page_count * PAGE_SIZE < size) {
170 				/*size is small. */
171 				invalid = 1;
172 			} else if (box->change_size_on_need_smaller &&
173 					   (mm->buffer_size > (size << 1))) {
174 				/*size is too large. */
175 				invalid = 2;
176 			} else if (mm->phy_addr & ((1 << align) - 1)) {
177 				/*addr is not align */
178 				invalid = 4;
179 			}
180 			if (invalid) {
181 				box->total_size -= mm->buffer_size;
182 				codec_mm_release(mm, box->name);
183 				box->mm_list[idx] = NULL;
184 				mm = NULL;
185 			}
186 		} else {
187 			box->total_size -= mm->buffer_size;
188 			codec_mm_release(mm, box->name);
189 			box->mm_list[idx] = NULL;
190 			mm = NULL;
191 		}
192 	}
193 	if (!mm) {
194 		mm = codec_mm_alloc(box->name, size, align, memflags);
195 		if (mm) {
196 			box->mm_list[idx] = mm;
197 			box->total_size += mm->buffer_size;
198 			mm->ins_id = box->channel_id;
199 			mm->ins_buffer_id = idx;
200 			box->box_ref_cnt++;
201 		}
202 	}
203 	mutex_unlock(&box->mutex);
204 	return mm ? 0 : -ENOMEM;
205 }
206 
decoder_bmmu_box_free_idx(void * handle,int idx)207 int decoder_bmmu_box_free_idx(void *handle, int idx)
208 {
209 	struct decoder_bmmu_box *box = handle;
210 	struct codec_mm_s *mm;
211 
212 	if (!box || idx < 0 || idx >= box->max_mm_num) {
213 		pr_err("can't free idx of box(%p),idx:%d  in (%d-%d)\n",
214 				box, idx, 0,
215 			   box ? (box->max_mm_num - 1) : 0);
216 		return -1;
217 	}
218 	mutex_lock(&box->mutex);
219 	mm = box->mm_list[idx];
220 	if (mm) {
221 		box->total_size -= mm->buffer_size;
222 		codec_mm_release(mm, box->name);
223 		box->mm_list[idx] = NULL;
224 		mm = NULL;
225 		box->box_ref_cnt--;
226 	}
227 	mutex_unlock(&box->mutex);
228 	return 0;
229 }
230 EXPORT_SYMBOL(decoder_bmmu_box_free_idx);
231 
decoder_bmmu_box_free(void * handle)232 int decoder_bmmu_box_free(void *handle)
233 {
234 	struct decoder_bmmu_box *box = handle;
235 	struct codec_mm_s *mm;
236 	int i;
237 
238 	if (!box) {
239 		pr_err("can't free box of NULL box!\n");
240 		return -1;
241 	}
242 	mutex_lock(&box->mutex);
243 	for (i = 0; i < box->max_mm_num; i++) {
244 		mm = box->mm_list[i];
245 		if (mm) {
246 			codec_mm_release(mm, box->name);
247 			box->mm_list[i] = NULL;
248 		}
249 	}
250 	mutex_unlock(&box->mutex);
251 	decoder_bmmu_box_mgr_del_box(box);
252 	kfree(box);
253 	return 0;
254 }
255 EXPORT_SYMBOL(decoder_bmmu_box_free);
256 
decoder_bmmu_try_to_release_box(void * handle)257 void decoder_bmmu_try_to_release_box(void *handle)
258 {
259 	struct decoder_bmmu_box *box = handle;
260 	bool is_keep = false;
261 	int i;
262 
263 	if (!box || box->box_ref_cnt)
264 		return;
265 
266 	mutex_lock(&box->mutex);
267 	for (i = 0; i < box->max_mm_num; i++) {
268 		if (box->mm_list[i]) {
269 			is_keep = true;
270 			break;
271 		}
272 	}
273 	mutex_unlock(&box->mutex);
274 
275 	if (!is_keep) {
276 		decoder_bmmu_box_mgr_del_box(box);
277 		kfree(box);
278 	}
279 }
280 EXPORT_SYMBOL(decoder_bmmu_try_to_release_box);
281 
decoder_bmmu_box_get_mem_handle(void * box_handle,int idx)282 void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx)
283 {
284 	struct decoder_bmmu_box *box = box_handle;
285 
286 	if (!box || idx < 0 || idx >= box->max_mm_num)
287 		return NULL;
288 	return box->mm_list[idx];
289 }
290 EXPORT_SYMBOL(decoder_bmmu_box_get_mem_handle);
291 
decoder_bmmu_box_get_mem_size(void * box_handle,int idx)292 int decoder_bmmu_box_get_mem_size(void *box_handle, int idx)
293 {
294 	struct decoder_bmmu_box *box = box_handle;
295 	int size = 0;
296 
297 	if (!box || idx < 0 || idx >= box->max_mm_num)
298 		return 0;
299 	mutex_lock(&box->mutex);
300 	if (box->mm_list[idx] != NULL)
301 		size = box->mm_list[idx]->buffer_size;
302 	mutex_unlock(&box->mutex);
303 	return size;
304 }
305 
306 
decoder_bmmu_box_get_phy_addr(void * box_handle,int idx)307 unsigned long decoder_bmmu_box_get_phy_addr(void *box_handle, int idx)
308 {
309 	struct decoder_bmmu_box *box = box_handle;
310 	struct codec_mm_s *mm;
311 
312 	if (!box || idx < 0 || idx >= box->max_mm_num)
313 		return 0;
314 	mm = box->mm_list[idx];
315 	if (!mm)
316 		return 0;
317 	return mm->phy_addr;
318 }
319 EXPORT_SYMBOL(decoder_bmmu_box_get_phy_addr);
320 
decoder_bmmu_box_get_virt_addr(void * box_handle,int idx)321 void *decoder_bmmu_box_get_virt_addr(void *box_handle, int idx)
322 {
323 	struct decoder_bmmu_box *box = box_handle;
324 	struct codec_mm_s *mm;
325 
326 	if (!box || idx < 0 || idx >= box->max_mm_num)
327 		return NULL;
328 	mm = box->mm_list[idx];
329 	if (!mm)
330 		return 0;
331 	return codec_mm_phys_to_virt(mm->phy_addr);
332 }
333 
334 /*flags: &0x1 for wait,*/
decoder_bmmu_box_check_and_wait_size(int size,int flags)335 int decoder_bmmu_box_check_and_wait_size(int size, int flags)
336 {
337 	if ((flags & BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) &&
338 		codec_mm_get_free_size() < size) {
339 		pr_err("CMA force free keep,for size = %d\n", size);
340 		/*need free others?
341 		 */
342 		try_free_keep_video(1);
343 	}
344 
345 	return codec_mm_enough_for_size(size,
346 			flags & BMMU_ALLOC_FLAGS_WAIT);
347 }
348 
decoder_bmmu_box_alloc_idx_wait(void * handle,int idx,int size,int aligned_2n,int mem_flags,int wait_flags)349 int decoder_bmmu_box_alloc_idx_wait(
350 	void *handle, int idx,
351 	int size, int aligned_2n,
352 	int mem_flags,
353 	int wait_flags)
354 {
355 	int have_space;
356 	int ret = -1;
357 	int keeped = 0;
358 
359 	if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) {
360 		struct decoder_bmmu_box *box = handle;
361 		struct codec_mm_s *mm;
362 		mutex_lock(&box->mutex);
363 		mm = box->mm_list[idx];
364 		keeped = is_codec_mm_keeped(mm);
365 		mutex_unlock(&box->mutex);
366 
367 		if (!keeped)
368 			return 0;/*have alloced memery before.*/
369 	}
370 	have_space = decoder_bmmu_box_check_and_wait_size(
371 					size,
372 					wait_flags);
373 	if (have_space) {
374 		ret = decoder_bmmu_box_alloc_idx(handle,
375 				idx, size, aligned_2n, mem_flags);
376 		if (ret == -ENOMEM) {
377 			pr_info("bmmu alloc idx fail, try free keep video.\n");
378 			try_free_keep_video(1);
379 		}
380 	} else {
381 		try_free_keep_video(1);
382 		ret = -ENOMEM;
383 	}
384 	return ret;
385 }
386 EXPORT_SYMBOL(decoder_bmmu_box_alloc_idx_wait);
387 
decoder_bmmu_box_alloc_buf_phy(void * handle,int idx,int size,unsigned char * driver_name,unsigned long * buf_phy_addr)388 int decoder_bmmu_box_alloc_buf_phy(
389 	void *handle, int idx,
390 	int size, unsigned char *driver_name,
391 	unsigned long *buf_phy_addr)
392 {
393 	if (!decoder_bmmu_box_check_and_wait_size(
394 			size,
395 			1)) {
396 		pr_info("%s not enough buf for buf_idx = %d\n",
397 					driver_name, idx);
398 		return	-ENOMEM;
399 	}
400 	if (!decoder_bmmu_box_alloc_idx_wait(
401 			handle,
402 			idx,
403 			size,
404 			-1,
405 			-1,
406 			BMMU_ALLOC_FLAGS_WAITCLEAR
407 			)) {
408 		*buf_phy_addr =
409 			decoder_bmmu_box_get_phy_addr(
410 			handle,
411 			idx);
412 		/*
413 		 *pr_info("%s malloc buf_idx = %d addr = %ld size = %d\n",
414 		 *	driver_name, idx, *buf_phy_addr, size);
415 		 */
416 		} else {
417 			pr_info("%s malloc failed  %d\n", driver_name, idx);
418 			return -ENOMEM;
419 	}
420 
421 	return 0;
422 }
423 EXPORT_SYMBOL(decoder_bmmu_box_alloc_buf_phy);
424 
decoder_bmmu_box_dump(struct decoder_bmmu_box * box,void * buf,int size)425 static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf,
426 								 int size)
427 {
428 	char *pbuf = buf;
429 	char sbuf[512];
430 	int tsize = 0;
431 	int s;
432 	int i;
433 	if (!buf) {
434 		pbuf = sbuf;
435 		size = 512;
436 	}
437 #define BUFPRINT(args...) \
438 	do {\
439 		s = snprintf(pbuf, size - tsize, args);\
440 		tsize += s;\
441 		pbuf += s; \
442 	} while (0)
443 
444 	for (i = 0; i < box->max_mm_num; i++) {
445 		struct codec_mm_s *mm = box->mm_list[i];
446 		if (buf && (size - tsize) < 256) {
447 			BUFPRINT("\n\t**NOT END**\n");
448 			break;
449 		}
450 		if (mm) {
451 			BUFPRINT("code mem[%d]:%p, addr=%p, size=%d,from=%d\n",
452 					 i,
453 					 (void *)mm,
454 					 (void *)mm->phy_addr,
455 					 mm->buffer_size,
456 					 mm->from_flags);
457 			if (!buf) {
458 				pr_info("%s", sbuf);
459 				pbuf = sbuf;
460 			}
461 		}
462 	}
463 #undef BUFPRINT
464 
465 	return tsize;
466 }
467 
decoder_bmmu_box_dump_all(void * buf,int size)468 static int decoder_bmmu_box_dump_all(void *buf, int size)
469 {
470 	struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
471 	char *pbuf = buf;
472 	char sbuf[512];
473 	int tsize = 0;
474 	int s;
475 	int i;
476 	struct list_head *head, *list;
477 	if (!buf) {
478 		pbuf = sbuf;
479 		size = 512;
480 	}
481 #define BUFPRINT(args...) \
482 	do {\
483 		s = snprintf(pbuf, size - tsize, args);\
484 		tsize += s;\
485 		pbuf += s; \
486 	} while (0)
487 
488 	mutex_lock(&mgr->mutex);
489 	head = &mgr->box_list;
490 	list = head->next;
491 	i = 0;
492 	while (list != head) {
493 		struct decoder_bmmu_box *box;
494 
495 		box = list_entry(list, struct decoder_bmmu_box, list);
496 		BUFPRINT("box[%d]: %s, %splayer_id:%d, max_num:%d, size:%d\n",
497 				 i, box->name,
498 				 (box->mem_flags & CODEC_MM_FLAGS_TVP) ?
499 				 "TVP mode " : "",
500 				 box->channel_id,
501 				 box->max_mm_num,
502 				 box->total_size);
503 		if (buf) {
504 			s = decoder_bmmu_box_dump(box, pbuf, size - tsize);
505 			if (s > 0) {
506 				tsize += s;
507 				pbuf += s;
508 			}
509 		} else {
510 			pr_info("%s", sbuf);
511 			pbuf = sbuf;
512 			tsize += decoder_bmmu_box_dump(box, NULL, 0);
513 		}
514 		list = list->next;
515 		i++;
516 	}
517 	mutex_unlock(&mgr->mutex);
518 
519 #undef BUFPRINT
520 	if (!buf)
521 		pr_info("%s", sbuf);
522 	return tsize;
523 }
524 
box_dump_show(struct class * class,struct class_attribute * attr,char * buf)525 static ssize_t box_dump_show(struct class *class, struct class_attribute *attr,
526 							 char *buf)
527 {
528 	ssize_t ret = 0;
529 
530 	ret = decoder_bmmu_box_dump_all(buf, PAGE_SIZE);
531 	return ret;
532 }
533 
box_debug_show(struct class * class,struct class_attribute * attr,char * buf)534 static ssize_t box_debug_show(struct class *class,
535 		struct class_attribute *attr,
536 		char *buf)
537 {
538 	ssize_t size = 0;
539 	size += sprintf(buf, "box debug help:\n");
540 	size += sprintf(buf + size, "echo n > debug\n");
541 	size += sprintf(buf + size, "n==0: clear all debugs)\n");
542 	size += sprintf(buf + size,
543 	"n=1: dump all box\n");
544 
545 	return size;
546 }
547 
548 
box_debug_store(struct class * class,struct class_attribute * attr,const char * buf,size_t size)549 static ssize_t box_debug_store(struct class *class,
550 		struct class_attribute *attr,
551 		const char *buf, size_t size)
552 {
553 	unsigned val;
554 	ssize_t ret;
555 	val = -1;
556 	ret = sscanf(buf, "%d", &val);
557 	if (ret != 1)
558 		return -EINVAL;
559 	switch (val) {
560 	case 1:
561 		decoder_bmmu_box_dump_all(NULL , 0);
562 		break;
563 	default:
564 		pr_err("unknow cmd! %d\n", val);
565 	}
566 	return size;
567 
568 }
569 
570 
571 static CLASS_ATTR_RO(box_dump);
572 static CLASS_ATTR_RW(box_debug);
573 
574 static struct attribute *decoder_bmmu_box_class_attrs[] = {
575 	&class_attr_box_dump.attr,
576 	&class_attr_box_debug.attr,
577 	NULL
578 };
579 
580 ATTRIBUTE_GROUPS(decoder_bmmu_box_class);
581 
582 static struct class decoder_bmmu_box_class = {
583 		.name = "decoder_bmmu_box",
584 		.class_groups = decoder_bmmu_box_class_groups,
585 	};
586 
decoder_bmmu_box_init(void)587 int decoder_bmmu_box_init(void)
588 {
589 	int r;
590 
591 	memset(&global_blk_mgr, 0, sizeof(global_blk_mgr));
592 	INIT_LIST_HEAD(&global_blk_mgr.box_list);
593 	mutex_init(&global_blk_mgr.mutex);
594 	r = class_register(&decoder_bmmu_box_class);
595 	return r;
596 }
597 EXPORT_SYMBOL(decoder_bmmu_box_init);
598 
decoder_bmmu_box_exit(void)599 void decoder_bmmu_box_exit(void)
600 {
601 	class_unregister(&decoder_bmmu_box_class);
602 	pr_info("dec bmmu box exit.\n");
603 }
604 
605 #if 0
606 static int __init decoder_bmmu_box_init(void)
607 {
608 	int r;
609 
610 	memset(&global_blk_mgr, 0, sizeof(global_blk_mgr));
611 	INIT_LIST_HEAD(&global_blk_mgr.box_list);
612 	mutex_init(&global_blk_mgr.mutex);
613 	r = class_register(&decoder_bmmu_box_class);
614 	return r;
615 }
616 
617 module_init(decoder_bmmu_box_init);
618 #endif
619