1 /*
2 * drivers/amlogic/media/frame_provider/decoder/utils/decoder_mmu_box.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/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 struct decoder_mmu_box {
33 int max_sc_num;
34 const char *name;
35 int channel_id;
36 int tvp_mode;
37 int box_ref_cnt;
38 struct mutex mutex;
39 struct list_head list;
40 struct codec_mm_scatter *sc_list[1];
41 };
42 #define MAX_KEEP_FRAME 4
43 #define START_KEEP_ID 0x9
44 #define MAX_KEEP_ID (INT_MAX - 1)
45 struct decoder_mmu_box_mgr {
46 int num;
47 struct mutex mutex;
48 struct codec_mm_scatter *keep_sc[MAX_KEEP_FRAME];
49 int keep_id[MAX_KEEP_FRAME];
50 int next_id;/*id for keep & free.*/
51 struct list_head box_list;
52 };
53 static struct decoder_mmu_box_mgr global_mgr;
get_decoder_mmu_box_mgr(void)54 static struct decoder_mmu_box_mgr *get_decoder_mmu_box_mgr(void)
55 {
56 return &global_mgr;
57 }
58
decoder_mmu_box_mgr_add_box(struct decoder_mmu_box * box)59 static int decoder_mmu_box_mgr_add_box(struct decoder_mmu_box *box)
60 {
61 struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
62
63 mutex_lock(&mgr->mutex);
64 list_add_tail(&box->list, &mgr->box_list);
65 mutex_unlock(&mgr->mutex);
66 return 0;
67 }
68
decoder_mmu_box_mgr_del_box(struct decoder_mmu_box * box)69 static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box)
70 {
71 struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
72
73 mutex_lock(&mgr->mutex);
74 list_del(&box->list);
75 mutex_unlock(&mgr->mutex);
76 return 0;
77 }
78
decoder_mmu_box_valide_check(void * box)79 bool decoder_mmu_box_valide_check(void *box)
80 {
81 struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
82 struct decoder_mmu_box *mmu_box = NULL;
83 bool is_valide = false;
84
85 mutex_lock(&mgr->mutex);
86 list_for_each_entry(mmu_box, &mgr->box_list, list) {
87 if (mmu_box && mmu_box == box) {
88 is_valide = true;
89 break;
90 }
91 }
92 mutex_unlock(&mgr->mutex);
93
94 return is_valide;
95 }
96 EXPORT_SYMBOL(decoder_mmu_box_valide_check);
97
decoder_mmu_try_to_release_box(void * handle)98 void decoder_mmu_try_to_release_box(void *handle)
99 {
100 struct decoder_mmu_box *box = handle;
101 bool is_keep = false;
102 int i;
103
104 if (!box || box->box_ref_cnt)
105 return;
106
107 mutex_lock(&box->mutex);
108 for (i = 0; i < box->max_sc_num; i++) {
109 if (box->sc_list[i]) {
110 is_keep = true;
111 break;
112 }
113 }
114 mutex_unlock(&box->mutex);
115
116 if (!is_keep) {
117 decoder_mmu_box_mgr_del_box(box);
118 codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
119 kfree(box);
120 }
121 }
122 EXPORT_SYMBOL(decoder_mmu_try_to_release_box);
123
decoder_mmu_box_sc_check(void * handle,int is_tvp)124 int decoder_mmu_box_sc_check(void *handle, int is_tvp)
125 {
126 struct decoder_mmu_box *box = handle;
127 if (!box) {
128 pr_err("mmu box NULL !!!\n");
129 return 0;
130 }
131 return codec_mm_scatter_size(is_tvp);
132 }
133 EXPORT_SYMBOL(decoder_mmu_box_sc_check);
134
135
decoder_mmu_box_alloc_box(const char * name,int channel_id,int max_num,int min_size_M,int mem_flags)136 void *decoder_mmu_box_alloc_box(const char *name,
137 int channel_id,
138 int max_num,
139 int min_size_M,
140 int mem_flags)
141 /*min_size_M:wait alloc this size*/
142 {
143 struct decoder_mmu_box *box;
144 int size;
145
146 pr_debug("decoder_mmu_box_alloc_box, mem_flags = 0x%x\n", mem_flags);
147
148 size = sizeof(struct decoder_mmu_box) +
149 sizeof(struct codec_mm_scatter *) *
150 max_num;
151 box = kmalloc(size, GFP_KERNEL);
152 if (!box) {
153 pr_err("can't alloc decoder buffers box!!!\n");
154 return NULL;
155 }
156 memset(box, 0, size);
157 box->max_sc_num = max_num;
158 box->name = name;
159 box->channel_id = channel_id;
160 box->tvp_mode = mem_flags;
161
162 mutex_init(&box->mutex);
163 INIT_LIST_HEAD(&box->list);
164 decoder_mmu_box_mgr_add_box(box);
165 codec_mm_scatter_mgt_delay_free_swith(1, 2000,
166 min_size_M, box->tvp_mode);
167 return (void *)box;
168 }
169 EXPORT_SYMBOL(decoder_mmu_box_alloc_box);
170
decoder_mmu_box_alloc_idx(void * handle,int idx,int num_pages,unsigned int * mmu_index_adr)171 int decoder_mmu_box_alloc_idx(
172 void *handle, int idx, int num_pages,
173 unsigned int *mmu_index_adr)
174 {
175 struct decoder_mmu_box *box = handle;
176 struct codec_mm_scatter *sc;
177 int ret;
178 int i;
179
180 if (!box || idx < 0 || idx >= box->max_sc_num) {
181 pr_err("can't alloc mmu box(%p),idx:%d\n",
182 box, idx);
183 return -1;
184 }
185 mutex_lock(&box->mutex);
186 sc = box->sc_list[idx];
187 if (sc) {
188 if (sc->page_max_cnt >= num_pages)
189 ret = codec_mm_scatter_alloc_want_pages(sc,
190 num_pages);
191 else {
192 codec_mm_scatter_dec_owner_user(sc, 0);
193 box->sc_list[idx] = NULL;
194 sc = NULL;
195 }
196
197 }
198 if (!sc) {
199 sc = codec_mm_scatter_alloc(num_pages + 64, num_pages,
200 box->tvp_mode);
201 if (!sc) {
202 mutex_unlock(&box->mutex);
203 pr_err("alloc mmu failed, need pages=%d\n",
204 num_pages);
205 return -1;
206 }
207 box->sc_list[idx] = sc;
208 box->box_ref_cnt++;
209 }
210
211 for (i = 0; i < num_pages; i++)
212 mmu_index_adr[i] = PAGE_INDEX(sc->pages_list[i]);
213
214 mutex_unlock(&box->mutex);
215
216 return 0;
217 }
218 EXPORT_SYMBOL(decoder_mmu_box_alloc_idx);
219
decoder_mmu_box_free_idx_tail(void * handle,int idx,int start_release_index)220 int decoder_mmu_box_free_idx_tail(
221 void *handle, int idx,
222 int start_release_index)
223 {
224 struct decoder_mmu_box *box = handle;
225 struct codec_mm_scatter *sc;
226
227 if (!box || idx < 0 || idx >= box->max_sc_num) {
228 pr_err("can't free tail mmu box(%p),idx:%d in (%d-%d)\n",
229 box, idx, 0,
230 box ? (box->max_sc_num - 1) : 0);
231 return -1;
232 }
233 mutex_lock(&box->mutex);
234 sc = box->sc_list[idx];
235 if (sc && start_release_index < sc->page_cnt)
236 codec_mm_scatter_free_tail_pages_fast(sc,
237 start_release_index);
238 mutex_unlock(&box->mutex);
239 return 0;
240 }
241 EXPORT_SYMBOL(decoder_mmu_box_free_idx_tail);
242
decoder_mmu_box_free_idx(void * handle,int idx)243 int decoder_mmu_box_free_idx(void *handle, int idx)
244 {
245 struct decoder_mmu_box *box = handle;
246 struct codec_mm_scatter *sc;
247
248 if (!box || idx < 0 || idx >= box->max_sc_num) {
249 pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n",
250 box, idx, 0,
251 box ? (box->max_sc_num - 1) : 0);
252 return -1;
253 }
254 mutex_lock(&box->mutex);
255 sc = box->sc_list[idx];
256 if (sc && sc->page_cnt > 0) {
257 codec_mm_scatter_dec_owner_user(sc, 0);
258 box->sc_list[idx] = NULL;
259 box->box_ref_cnt--;
260 }
261 mutex_unlock(&box->mutex);
262
263 if (sc && box->box_ref_cnt == 0)
264 codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
265
266 return 0;
267 }
268 EXPORT_SYMBOL(decoder_mmu_box_free_idx);
269
decoder_mmu_box_free(void * handle)270 int decoder_mmu_box_free(void *handle)
271 {
272 struct decoder_mmu_box *box = handle;
273 struct codec_mm_scatter *sc;
274 int i;
275
276 if (!box) {
277 pr_err("can't free box of NULL box!\n");
278 return -1;
279 }
280 mutex_lock(&box->mutex);
281 for (i = 0; i < box->max_sc_num; i++) {
282 sc = box->sc_list[i];
283 if (sc) {
284 codec_mm_scatter_dec_owner_user(sc, 0);
285 box->sc_list[i] = NULL;
286 }
287 }
288 mutex_unlock(&box->mutex);
289 decoder_mmu_box_mgr_del_box(box);
290 codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
291 kfree(box);
292 return 0;
293 }
294 EXPORT_SYMBOL(decoder_mmu_box_free);
295
decoder_mmu_box_get_mem_handle(void * box_handle,int idx)296 void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx)
297 {
298 struct decoder_mmu_box *box = box_handle;
299
300 if (!box || idx < 0 || idx >= box->max_sc_num)
301 return NULL;
302 return box->sc_list[idx];
303 }
304 EXPORT_SYMBOL(decoder_mmu_box_get_mem_handle);
305
decoder_mmu_box_dump(struct decoder_mmu_box * box,void * buf,int size)306 static int decoder_mmu_box_dump(struct decoder_mmu_box *box,
307 void *buf, int size)
308 {
309 char *pbuf = buf;
310 char sbuf[512];
311 int tsize = 0;
312 int s;
313 int i;
314
315 if (!buf) {
316 pbuf = sbuf;
317 size = 512;
318 }
319 #define BUFPRINT(args...) \
320 do {\
321 s = snprintf(pbuf, size - tsize, args);\
322 tsize += s;\
323 pbuf += s; \
324 } while (0)
325
326 for (i = 0; i < box->max_sc_num; i++) {
327 struct codec_mm_scatter *sc = box->sc_list[i];
328
329 if (sc) {
330 BUFPRINT("sc mem[%d]:%p, size=%d\n",
331 i, sc,
332 sc->page_cnt << PAGE_SHIFT);
333 }
334 }
335 #undef BUFPRINT
336 if (!buf)
337 pr_info("%s", sbuf);
338
339 return tsize;
340 }
341
decoder_mmu_box_dump_all(void * buf,int size)342 static int decoder_mmu_box_dump_all(void *buf, int size)
343 {
344 struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
345 char *pbuf = buf;
346 char sbuf[512];
347 int tsize = 0;
348 int s;
349 int i;
350 struct list_head *head, *list;
351
352 if (!pbuf) {
353 pbuf = sbuf;
354 size = 512;
355 }
356
357 #define BUFPRINT(args...) \
358 do {\
359 s = snprintf(pbuf, size - tsize, args);\
360 tsize += s;\
361 pbuf += s; \
362 } while (0)
363
364 mutex_lock(&mgr->mutex);
365 head = &mgr->box_list;
366 list = head->next;
367 i = 0;
368 while (list != head) {
369 struct decoder_mmu_box *box;
370 box = list_entry(list, struct decoder_mmu_box,
371 list);
372 BUFPRINT("box[%d]: %s, %splayer_id:%d, max_num:%d\n",
373 i,
374 box->name,
375 box->tvp_mode ? "TVP mode " : "",
376 box->channel_id,
377 box->max_sc_num);
378 if (buf) {
379 s += decoder_mmu_box_dump(box, pbuf, size - tsize);
380 if (s > 0) {
381 tsize += s;
382 pbuf += s;
383 }
384 } else {
385 pr_info("%s", sbuf);
386 pbuf = sbuf;
387 tsize += decoder_mmu_box_dump(box, NULL, 0);
388 }
389 list = list->next;
390 i++;
391 }
392 mutex_unlock(&mgr->mutex);
393
394
395 #undef BUFPRINT
396 if (!buf)
397 pr_info("%s", sbuf);
398 return tsize;
399 }
400
401
402
403 static ssize_t
box_dump_show(struct class * class,struct class_attribute * attr,char * buf)404 box_dump_show(struct class *class,
405 struct class_attribute *attr, char *buf)
406 {
407 ssize_t ret = 0;
408
409 ret = decoder_mmu_box_dump_all(buf, PAGE_SIZE);
410 return ret;
411 }
412
413
414 static CLASS_ATTR_RO(box_dump);
415
416 static struct attribute *decoder_mmu_box_class_attrs[] = {
417 &class_attr_box_dump.attr,
418 NULL
419 };
420
421 ATTRIBUTE_GROUPS(decoder_mmu_box_class);
422
423 static struct class decoder_mmu_box_class = {
424 .name = "decoder_mmu_box",
425 .class_groups = decoder_mmu_box_class_groups,
426 };
427
decoder_mmu_box_init(void)428 int decoder_mmu_box_init(void)
429 {
430 int r;
431
432 memset(&global_mgr, 0, sizeof(global_mgr));
433 INIT_LIST_HEAD(&global_mgr.box_list);
434 mutex_init(&global_mgr.mutex);
435 global_mgr.next_id = START_KEEP_ID;
436 r = class_register(&decoder_mmu_box_class);
437 return r;
438 }
439 EXPORT_SYMBOL(decoder_mmu_box_init);
440
decoder_mmu_box_exit(void)441 void decoder_mmu_box_exit(void)
442 {
443 class_unregister(&decoder_mmu_box_class);
444 pr_info("dec mmu box exit.\n");
445 }
446
447 #if 0
448 static int __init decoder_mmu_box_init(void)
449 {
450 int r;
451
452 memset(&global_mgr, 0, sizeof(global_mgr));
453 INIT_LIST_HEAD(&global_mgr.box_list);
454 mutex_init(&global_mgr.mutex);
455 global_mgr.next_id = START_KEEP_ID;
456 r = class_register(&decoder_mmu_box_class);
457 return r;
458 }
459
460 module_init(decoder_mmu_box_init);
461 #endif
462