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