• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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