upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / mfc5x / mfc_buf.c
1 /*
2  * linux/drivers/media/video/samsung/mfc5x/mfc_buf.c
3  *
4  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5  *              http://www.samsung.com/
6  *
7  * Buffer manager for Samsung MFC (Multi Function Codec - FIMV) driver
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include <linux/slab.h>
15 #include <linux/spinlock.h>
16 #include <linux/mm.h>
17 #include <linux/err.h>
18
19 #include "mfc.h"
20 #include "mfc_mem.h"
21 #include "mfc_buf.h"
22 #include "mfc_log.h"
23 #include "mfc_errno.h"
24
25 #ifdef CONFIG_VIDEO_MFC_VCM_UMP
26 #include <plat/s5p-vcm.h>
27
28 #include "ump_kernel_interface.h"
29 #include "ump_kernel_interface_ref_drv.h"
30 #include "ump_kernel_interface_vcm.h"
31 #endif
32
33 #define PRINT_BUF
34 #undef DEBUG_ALLOC_FREE
35
36 static struct list_head mfc_alloc_head[MFC_MAX_MEM_PORT_NUM];
37 /* The free node list sorted by real address */
38 static struct list_head mfc_free_head[MFC_MAX_MEM_PORT_NUM];
39
40 /* FIXME: test locking, add locking mechanisim */
41 /*
42 static spinlock_t lock;
43 */
44
45 void mfc_print_buf(void)
46 {
47 #ifdef PRINT_BUF
48         struct list_head *pos;
49         struct mfc_alloc_buffer *alloc = NULL;
50         struct mfc_free_buffer *free = NULL;
51         int port, i;
52
53         for (port = 0; port < mfc_mem_count(); port++) {
54                 mfc_dbg("---- port %d buffer list ----", port);
55
56                 i = 0;
57                 list_for_each(pos, &mfc_alloc_head[port]) {
58                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
59                         mfc_dbg("[A #%04d] addr: 0x%08x, size: %d",
60                                 i, (unsigned int)alloc->addr, alloc->size);
61                         mfc_dbg("\t  real: 0x%08lx", alloc->real);
62                         mfc_dbg("\t  type: 0x%08x, owner: %d",
63                                 alloc->type, alloc->owner);
64 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
65                         mfc_dbg("\t* vcm sysmmu");
66                         if (alloc->vcm_s) {
67                                 mfc_dbg("\t  start: 0x%08x, res_size  : 0x%08x\n",
68                                         (unsigned int)alloc->vcm_s->res.start,
69                                         (unsigned int)alloc->vcm_s->res.res_size);
70                                 mfc_dbg("\t  bound_size: 0x%08x\n",
71                                         (unsigned int)alloc->vcm_s->res.bound_size);
72                         }
73
74                         mfc_dbg("\t* vcm kernel");
75                         if (alloc->vcm_k) {
76                                 mfc_dbg("\t  start: 0x%08x, res_size  : 0x%08x\n",
77                                         (unsigned int)alloc->vcm_k->start,
78                                         (unsigned int)alloc->vcm_k->res_size);
79                                 mfc_dbg("\t  bound_size: 0x%08x\n",
80                                         (unsigned int)alloc->vcm_k->bound_size);
81                         }
82
83                         mfc_dbg("\t* ump");
84                         if (alloc->ump_handle) {
85                                 mfc_dbg("\t  secure id: 0x%08x",
86                                         mfc_ump_get_id(alloc->ump_handle));
87                         }
88 #elif defined(CONFIG_S5P_VMEM)
89                         mfc_dbg("\t  vmem cookie: 0x%08x addr: 0x%08lx, size: %d",
90                                 alloc->vmem_cookie, alloc->vmem_addr,
91                                 alloc->vmem_size);
92 #else
93                         mfc_dbg("\t  offset: 0x%08x", alloc->ofs);
94 #endif
95                         i++;
96                 }
97
98                 i = 0;
99                 list_for_each(pos, &mfc_free_head[port]) {
100                         free = list_entry(pos, struct mfc_free_buffer, list);
101                         mfc_dbg("[F #%04d] addr: 0x%08lx, size: %d",
102                                 i, free->real, free->size);
103                         i++;
104                 }
105         }
106 #endif
107 }
108
109 static int mfc_put_free_buf(unsigned int addr, int size, int port)
110 {
111         struct list_head *pos, *nxt;
112         struct mfc_free_buffer *free;
113         struct mfc_free_buffer *next = NULL;
114         struct mfc_free_buffer *prev;
115         /* 0x00: not merged, 0x01: prev merged, 0x02: next merged */
116         int merged = 0x00;
117
118         mfc_dbg("addr: 0x%08x, size: %d, port: %d\n", addr, size, port);
119
120         list_for_each_safe(pos, nxt, &mfc_free_head[port]) {
121                 next = list_entry(pos, struct mfc_free_buffer, list);
122
123                 /*
124                  * When the allocated address must be align without VMEM,
125                  * the free buffer can be overlap
126                  * previous free buffer temporaily
127                  * Target buffer will be shrink after this operation
128                  */
129                 if (addr <= next->real) {
130                         prev = list_entry(pos->prev, struct mfc_free_buffer, list);
131
132                         mfc_dbg("prev->addr: 0x%08lx, size: %d", prev->real, prev->size);
133                         /* merge previous free buffer */
134                         if (prev && ((prev->real + prev->size) == addr)) {
135                                 addr  = prev->real;
136                                 size += prev->size;
137
138                                 prev->size = size;
139
140                                 merged |= 0x01;
141                                 mfc_dbg("auto merge free buffer[p]: addr: 0x%08lx, size: %d",
142                                         prev->real, prev->size);
143                         }
144
145                         mfc_dbg("next->addr: 0x%08lx, size: %d", next->real, next->size);
146                         /* merge next free buffer */
147                         if ((addr + size) == next->real) {
148                                 next->real  = addr;
149                                 next->size += size;
150
151                                 if (merged)
152                                         prev->size = next->size;
153
154                                 merged |= 0x02;
155                                 mfc_dbg("auto merge free buffer[n]: addr: 0x%08lx, size: %d",
156                                         next->real, next->size);
157                         }
158
159                         break;
160                 }
161         }
162
163         if (!merged) {
164                 free = (struct mfc_free_buffer *)
165                         kzalloc(sizeof(struct mfc_free_buffer), GFP_KERNEL);
166
167                 if (unlikely(free == NULL))
168                         return -ENOMEM;
169
170                 free->real = addr;
171                 free->size = size;
172
173                 list_add_tail(&free->list, pos);
174         }
175
176         /* bi-directional merged */
177         else if ((merged & 0x03) == 0x03) {
178                 list_del(&next->list);
179                 kfree(next);
180         }
181
182         return 0;
183 }
184
185 static unsigned int mfc_get_free_buf(int size, int align, int port)
186 {
187         struct list_head *pos, *nxt;
188         struct mfc_free_buffer *free;
189         struct mfc_free_buffer *match = NULL;
190         int align_size = 0;
191         unsigned int addr = 0;
192
193         mfc_dbg("size: %d, align: %d, port: %d\n",
194                         size, align, port);
195
196         if (list_empty(&mfc_free_head[port])) {
197                 mfc_err("no free node in mfc buffer\n");
198
199                 return 0;
200         }
201
202         /* find best fit area */
203         list_for_each_safe(pos, nxt, &mfc_free_head[port]) {
204                 free = list_entry(pos, struct mfc_free_buffer, list);
205
206 #if (defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM))
207                 /*
208                  * Align the start address.
209                  * We assume the start address of free buffer aligned with 4KB
210                  */
211                 align_size = ALIGN(align_size + size, PAGE_SIZE) - size;
212
213                 if (align > PAGE_SIZE) {
214                         align_size  = ALIGN(free->real, align) - free->real;
215                         align_size += ALIGN(align_size + size, PAGE_SIZE) - size;
216                 } else {
217                         align_size = ALIGN(align_size + size, PAGE_SIZE) - size;
218                 }
219 #else
220                 align_size = ALIGN(free->real, align) - free->real;
221 #endif
222                 if (free->size >= (size + align_size)) {
223                         if (match != NULL) {
224                                 if (free->size < match->size)
225                                         match = free;
226                         } else {
227                                 match = free;
228                         }
229                 }
230         }
231
232         if (match != NULL) {
233                 addr = match->real;
234                 align_size = ALIGN(addr, align) - addr;
235
236 #if !(defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM))
237                 if (align_size > 0) {
238                         /*
239                          * When the allocated address must be align without VMEM,
240                          * the free buffer can be overlap
241                          * previous free buffer temporaily
242                          */
243                         if (mfc_put_free_buf(match->real, align_size, port) < 0)
244                                 return 0;
245                 }
246 #endif
247                 /* change allocated buffer address & size */
248                 match->real += (size + align_size);
249                 match->size -= (size + align_size);
250
251                 if (match->size == 0) {
252                         list_del(&match->list);
253                         kfree(match);
254                 }
255         } else {
256                 mfc_err("no suitable free node in mfc buffer\n");
257
258                 return 0;
259         }
260
261         return addr;
262 }
263
264 int mfc_init_buf(void)
265 {
266         int port;
267         int ret = 0;
268
269         for (port = 0; port < mfc_mem_count(); port++) {
270                 INIT_LIST_HEAD(&mfc_alloc_head[port]);
271                 INIT_LIST_HEAD(&mfc_free_head[port]);
272
273                 ret = mfc_put_free_buf(mfc_mem_data_base(port),
274                         mfc_mem_data_size(port), port);
275         }
276
277         /*
278         spin_lock_init(&lock);
279         */
280
281         mfc_print_buf();
282
283         return ret;
284 }
285
286 void mfc_final_buf(void)
287 {
288         struct list_head *pos, *nxt;
289         struct mfc_alloc_buffer *alloc;
290         struct mfc_free_buffer *free;
291         int port;
292         /*
293         unsigned long flags;
294         */
295
296         /*
297         spin_lock_irqsave(&lock, flags);
298         */
299
300         for (port = 0; port < mfc_mem_count(); port++) {
301                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
302                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
303 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
304                         if (alloc->ump_handle)
305                                 mfc_ump_unmap(alloc->ump_handle);
306
307                         if (alloc->vcm_k)
308                                 mfc_vcm_unmap(alloc->vcm_k);
309
310                         if (alloc->vcm_s)
311                                 mfc_vcm_unbind(alloc->vcm_s,
312                                                 alloc->type & MBT_OTHER);
313
314                         if (mfc_put_free_buf(alloc->vcm_addr,
315                                 alloc->vcm_size, port) < 0) {
316
317                                 mfc_err("failed to add free buffer\n");
318                         } else {
319                                 list_del(&alloc->list);
320                                 kfree(alloc);
321                         }
322 #elif defined(CONFIG_S5P_VMEM)
323                         if (alloc->vmem_cookie)
324                                 s5p_vfree(alloc->vmem_cookie);
325
326                         if (mfc_put_free_buf(alloc->vmem_addr,
327                                 alloc->vmem_size, port) < 0) {
328
329                                 mfc_err("failed to add free buffer\n");
330                         } else {
331                                 list_del(&alloc->list);
332                                 kfree(alloc);
333                         }
334 #else
335                         if (mfc_put_free_buf(alloc->real,
336                                 alloc->size, port) < 0) {
337
338                                 mfc_err("failed to add free buffer\n");
339                         } else {
340                                 list_del(&alloc->list);
341                                 kfree(alloc);
342                         }
343 #endif
344                 }
345         }
346
347         /*
348         spin_unlock_irqrestore(&lock, flags);
349         */
350
351         mfc_print_buf();
352
353         /*
354         spin_lock_irqsave(&lock, flags);
355         */
356
357         for (port = 0; port < mfc_mem_count(); port++) {
358                 list_for_each_safe(pos, nxt, &mfc_free_head[port]) {
359                         free = list_entry(pos, struct mfc_free_buffer, list);
360                         list_del(&free->list);
361                         kfree(free);
362                 }
363         }
364
365         /*
366         spin_unlock_irqrestore(&lock, flags);
367         */
368
369         mfc_print_buf();
370 }
371
372 void mfc_merge_buf(void)
373 {
374         struct list_head *pos, *nxt;
375         struct mfc_free_buffer *n1;
376         struct mfc_free_buffer *n2;
377         int port;
378
379         for (port = 0; port < mfc_mem_count(); port++) {
380                 list_for_each_safe(pos, nxt, &mfc_free_head[port]) {
381                         n1 = list_entry(pos, struct mfc_free_buffer, list);
382                         n2 = list_entry(nxt, struct mfc_free_buffer, list);
383
384                         mfc_dbg("merge pre: n1: 0x%08lx, n2: 0x%08lx",
385                                 n1->real, n2->real);
386
387                         if (!list_is_last(pos, &mfc_free_head[port])) {
388                                 if ((n1->real + n1->size) == n2->real) {
389                                         n2->real  = n1->real;
390                                         n2->size += n1->size;
391                                         list_del(&n1->list);
392                                         kfree(n1);
393                                 }
394                         }
395
396                         mfc_dbg("merge aft: n1: 0x%08lx, n2: 0x%08lx, last: %d",
397                                 n1->real, n2->real,
398                                 list_is_last(pos, &mfc_free_head[port]));
399                 }
400         }
401
402 #ifdef DEBUG_ALLOC_FREE
403         mfc_print_buf();
404 #endif
405 }
406
407 /* FIXME: port auto select, return values */
408 struct mfc_alloc_buffer *_mfc_alloc_buf(
409         struct mfc_inst_ctx *ctx, int size, int align, int flag)
410 {
411         unsigned int addr;
412         struct mfc_alloc_buffer *alloc;
413         int port = flag & 0xFFFF;
414 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
415         int align_size = 0;
416         struct ump_vcm ump_vcm;
417 #elif defined(CONFIG_S5P_VMEM)
418         int align_size = 0;
419 #endif
420         /*
421         unsigned long flags;
422         */
423
424         if (size <= 0)
425                 return NULL;
426
427         alloc = (struct mfc_alloc_buffer *)
428                 kzalloc(sizeof(struct mfc_alloc_buffer), GFP_KERNEL);
429
430         if (unlikely(alloc == NULL))
431                 return NULL;
432
433         /* FIXME: right position? */
434         if (port > (mfc_mem_count() - 1))
435                 port = mfc_mem_count() - 1;
436
437         /*
438         spin_lock_irqsave(&lock, flags);
439         */
440
441         addr = mfc_get_free_buf(size, align, port);
442
443         mfc_dbg("mfc_get_free_buf: 0x%08x\n", addr);
444
445         if (!addr) {
446                 mfc_dbg("cannot get suitable free buffer\n");
447                 /* FIXME: is it need?
448                 mfc_put_free_buf(addr, size, port);
449                 */
450                 kfree(alloc);
451                 /*
452                 spin_unlock_irqrestore(&lock, flags);
453                 */
454
455                 return NULL;
456         }
457
458 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
459         if (align > PAGE_SIZE) {
460                 align_size = ALIGN(addr, align) - addr;
461                 align_size += ALIGN(align_size + size, PAGE_SIZE) - size;
462         } else {
463                 align_size = ALIGN(align_size + size, PAGE_SIZE) - size;
464         }
465
466         alloc->vcm_s = mfc_vcm_bind(addr, size + align_size);
467         if (IS_ERR(alloc->vcm_s)) {
468                 mfc_put_free_buf(addr, size, port);
469                 kfree(alloc);
470
471                 return NULL;
472                 /*
473                 return PTR_ERR(alloc->vcm_s);
474                 */
475         }
476
477         if (flag & MBT_KERNEL) {
478                 alloc->vcm_k = mfc_vcm_map(alloc->vcm_s->res.phys);
479                 if (IS_ERR(alloc->vcm_k)) {
480                         mfc_vcm_unbind(alloc->vcm_s,
481                                         alloc->type & MBT_OTHER);
482                         mfc_put_free_buf(addr, size, port);
483                         kfree(alloc);
484
485                         return NULL;
486                         /*
487                         return PTR_ERR(alloc->vcm_k);
488                         */
489                 }
490         }
491
492         if (flag & MBT_USER) {
493                 ump_vcm.vcm = alloc->vcm_s->res.vcm;
494                 ump_vcm.vcm_res = &(alloc->vcm_s->res);
495                 ump_vcm.dev_id = VCM_DEV_MFC;
496
497                 alloc->ump_handle = mfc_ump_map(alloc->vcm_s->res.phys, (unsigned long)&ump_vcm);
498                 if (IS_ERR(alloc->ump_handle)) {
499                         mfc_vcm_unmap(alloc->vcm_k);
500                         mfc_vcm_unbind(alloc->vcm_s,
501                                         alloc->type & MBT_OTHER);
502                         mfc_put_free_buf(addr, size, port);
503                         kfree(alloc);
504
505                 return NULL;
506                         /*
507                         return PTR_ERR(alloc->vcm_k);
508                         */
509                 }
510         }
511
512         alloc->vcm_addr = addr;
513         alloc->vcm_size = size + align_size;
514 #elif defined(CONFIG_S5P_VMEM)
515         if (align > PAGE_SIZE) {
516                 align_size = ALIGN(addr, align) - addr;
517                 align_size += ALIGN(align_size + size, PAGE_SIZE) - size;
518         } else {
519                 align_size = ALIGN(align_size + size, PAGE_SIZE) - size;
520         }
521
522         alloc->vmem_cookie = s5p_vmem_vmemmap(size + align_size,
523                         addr, addr + (size + align_size));
524
525         if (!alloc->vmem_cookie) {
526                 mfc_dbg("cannot map free buffer to memory\n");
527                 mfc_put_free_buf(addr, size, port);
528                 kfree(alloc);
529
530                 return NULL;
531         }
532
533         alloc->vmem_addr = addr;
534         alloc->vmem_size = size + align_size;
535 #endif
536         alloc->real = ALIGN(addr, align);
537         alloc->size = size;
538
539 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
540         if (alloc->vcm_k)
541                 alloc->addr = (unsigned char *)alloc->vcm_k->start;
542         else
543                 alloc->addr = NULL;
544 #elif defined(CONFIG_S5P_VMEM)
545         alloc->addr = (unsigned char *)(mfc_mem_addr(port) +
546                 mfc_mem_base_ofs(alloc->real));
547 #else
548         alloc->addr = (unsigned char *)(mfc_mem_addr(port) +
549                 mfc_mem_base_ofs(alloc->real));
550         /*
551         alloc->user = (unsigned char *)(ctx->userbase +
552                 mfc_mem_data_ofs(alloc->real, 1));
553         */
554         alloc->ofs = mfc_mem_data_ofs(alloc->real, 1);
555 #endif
556         alloc->type = flag & 0xFFFF0000;
557         alloc->owner = ctx->id;
558
559         list_add(&alloc->list, &mfc_alloc_head[port]);
560
561         /*
562         spin_unlock_irqrestore(&lock, flags);
563         */
564
565 #ifdef DEBUG_ALLOC_FREE
566         mfc_print_buf();
567 #endif
568
569         return alloc;
570 }
571
572 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
573 unsigned int mfc_vcm_bind_from_others(struct mfc_inst_ctx *ctx,
574                                 struct mfc_buf_alloc_arg *args, int flag)
575 {
576         int ret;
577         unsigned int addr, size;
578         unsigned int secure_id = args->secure_id;
579         int port = flag & 0xFFFF;
580
581         struct vcm_res *vcm_res;
582         struct vcm_mmu_res *s_res;
583         struct mfc_alloc_buffer *alloc;
584
585         ump_dd_handle ump_mem;
586
587         /* FIXME: right position? */
588         if (port > (mfc_mem_count() - 1))
589                 port = mfc_mem_count() - 1;
590
591         ump_mem = ump_dd_handle_create_from_secure_id(secure_id);
592         ump_dd_reference_add(ump_mem);
593
594         vcm_res = (struct vcm_res *)
595                 ump_dd_meminfo_get(secure_id, (void*)VCM_DEV_MFC);
596         if (!vcm_res) {
597                 mfc_dbg("%s: Failed to get vcm_res\n", __func__);
598                 goto err_ret;
599         }
600
601         size = vcm_res->bound_size;
602
603         alloc = (struct mfc_alloc_buffer *)
604                 kzalloc(sizeof(struct mfc_alloc_buffer), GFP_KERNEL);
605         if(!alloc) {
606                 mfc_dbg("%s: Failed to get mfc_alloc_buffer\n", __func__);
607                 goto err_ret;
608         }
609
610         addr = mfc_get_free_buf(size, ALIGN_2KB, port);
611         if (!addr) {
612                 mfc_dbg("cannot get suitable free buffer\n");
613                 goto err_ret_alloc;
614         }
615         mfc_dbg("mfc_get_free_buf: 0x%08x\n", addr);
616
617         s_res = kzalloc(sizeof(struct vcm_mmu_res), GFP_KERNEL);
618         if (!s_res) {
619                 mfc_dbg("%s: Failed to get vcm_mmu_res\n", __func__);
620                 goto err_ret_alloc;
621         }
622
623         s_res->res.start = addr;
624         s_res->res.res_size = size;
625         s_res->res.vcm = ctx->dev->vcm_info.sysmmu_vcm;
626         INIT_LIST_HEAD(&s_res->bound);
627
628         ret = vcm_bind(&s_res->res, vcm_res->phys);
629         if (ret < 0) {
630                 mfc_dbg("%s: Failed to vcm_bind\n", __func__);
631                 goto err_ret_s_res;
632         }
633
634         alloc->vcm_s = s_res;
635         alloc->vcm_addr = addr;
636         alloc->ump_handle = ump_mem;
637         alloc->vcm_size = size;
638         alloc->real = addr;
639         alloc->size = size;
640         alloc->type = flag & 0xFFFF0000;
641         alloc->owner = ctx->id;
642
643         list_add(&alloc->list, &mfc_alloc_head[port]);
644
645         mfc_print_buf();
646
647         return 0;
648
649 err_ret_s_res:
650         kfree(s_res);
651 err_ret_alloc:
652         kfree(alloc);
653 err_ret:
654         return -1;
655 }
656 #endif
657
658 int
659 mfc_alloc_buf(struct mfc_inst_ctx *ctx, struct mfc_buf_alloc_arg *args, int flag)
660 {
661         struct mfc_alloc_buffer *alloc;
662
663         alloc = _mfc_alloc_buf(ctx, args->size, args->align, flag);
664
665         if (unlikely(alloc == NULL))
666                 return MFC_MEM_ALLOC_FAIL;
667         /*
668         args->phys = (unsigned int)alloc->real;
669         */
670         args->addr = (unsigned int)alloc->addr;
671 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
672         if (alloc->ump_handle)
673                 args->secure_id = mfc_ump_get_id(alloc->ump_handle);
674 #elif defined(CONFIG_S5P_VMEM)
675         args->cookie = (unsigned int)alloc->vmem_cookie;
676 #else
677         args->offset = alloc->ofs;
678 #endif
679         return MFC_OK;
680 }
681
682 int _mfc_free_buf(unsigned long real)
683 {
684         struct list_head *pos, *nxt;
685         struct mfc_alloc_buffer *alloc;
686         int port;
687         int found = 0;
688         /*
689         unsigned long flags;
690         */
691
692         mfc_dbg("addr: 0x%08lx\n", real);
693
694         /*
695         spin_lock_irqsave(&lock, flags);
696         */
697
698         for (port = 0; port < mfc_mem_count(); port++) {
699                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
700                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
701
702                         if (alloc->real == real) {
703                                 found = 1;
704 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
705                                 if (alloc->ump_handle)
706                                         mfc_ump_unmap(alloc->ump_handle);
707
708                                 if (alloc->vcm_k)
709                                         mfc_vcm_unmap(alloc->vcm_k);
710
711                                 if (alloc->vcm_s)
712                                         mfc_vcm_unbind(alloc->vcm_s,
713                                                         alloc->type & MBT_OTHER);
714
715                                 if (mfc_put_free_buf(alloc->vcm_addr,
716                                         alloc->vcm_size, port) < 0) {
717
718                                         mfc_err("failed to add free buffer\n");
719                                 } else {
720                                         list_del(&alloc->list);
721                                         kfree(alloc);
722                                 }
723 #elif defined(CONFIG_S5P_VMEM)
724                                 if (alloc->vmem_cookie)
725                                         s5p_vfree(alloc->vmem_cookie);
726
727                                 if (mfc_put_free_buf(alloc->vmem_addr,
728                                         alloc->vmem_size, port) < 0) {
729
730                                         mfc_err("failed to add free buffer\n");
731                                 } else {
732                                         list_del(&alloc->list);
733                                         kfree(alloc);
734                                 }
735 #else
736                                 if (mfc_put_free_buf(alloc->real,
737                                         alloc->size, port) < 0) {
738
739                                         mfc_err("failed to add free buffer\n");
740                                 } else {
741                                         list_del(&alloc->list);
742                                         kfree(alloc);
743                                 }
744 #endif
745                                 break;
746                         }
747                 }
748
749                 if (found)
750                         break;
751         }
752
753         /*
754         spin_unlock_irqrestore(&lock, flags);
755         */
756
757 #ifdef DEBUG_ALLOC_FREE
758         mfc_print_buf();
759 #endif
760
761         if (found)
762                 return 0;
763
764         return -1;
765 }
766
767 int mfc_free_buf(struct mfc_inst_ctx *ctx, unsigned int key)
768 {
769         unsigned long real;
770
771         real = mfc_get_buf_real(ctx->id, key);
772         if (unlikely(real == 0))
773                 return MFC_MEM_INVALID_ADDR_FAIL;
774
775         if (_mfc_free_buf(real) < 0)
776                 return MFC_MEM_INVALID_ADDR_FAIL;
777
778         return MFC_OK;
779 }
780
781 void mfc_free_buf_type(int owner, int type)
782 {
783         int port;
784         struct list_head *pos, *nxt;
785         struct mfc_alloc_buffer *alloc;
786
787         for (port = 0; port < mfc_mem_count(); port++) {
788                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
789                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
790
791                         if ((alloc->owner == owner) && (alloc->type == type)) {
792                                 if (mfc_put_free_buf(alloc->real,
793                                         alloc->size, port) < 0) {
794
795                                         mfc_err("failed to add free buffer\n");
796                                 } else {
797                                         list_del(&alloc->list);
798                                         kfree(alloc);
799                                 }
800                         }
801                 }
802         }
803 }
804
805 /* FIXME: add MFC Buffer Type */
806 void mfc_free_buf_inst(int owner)
807 {
808         struct list_head *pos, *nxt;
809         int port;
810         struct mfc_alloc_buffer *alloc;
811         /*
812         unsigned long flags;
813         */
814
815         mfc_dbg("owner: %d\n", owner);
816
817         /*
818         spin_lock_irqsave(&lock, flags);
819         */
820
821         for (port = 0; port < mfc_mem_count(); port++) {
822                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
823                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
824
825                         if (alloc->owner == owner) {
826 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
827                                 if (alloc->ump_handle)
828                                         mfc_ump_unmap(alloc->ump_handle);
829
830                                 if (alloc->vcm_k)
831                                         mfc_vcm_unmap(alloc->vcm_k);
832
833                                 if (alloc->vcm_s)
834                                         mfc_vcm_unbind(alloc->vcm_s,
835                                                         alloc->type & MBT_OTHER);
836
837                                 if (mfc_put_free_buf(alloc->vcm_addr,
838                                         alloc->vcm_size, port) < 0) {
839
840                                         mfc_err("failed to add free buffer\n");
841                                 } else {
842                                         list_del(&alloc->list);
843                                         kfree(alloc);
844                                 }
845 #elif defined(CONFIG_S5P_VMEM)
846                                 if (alloc->vmem_cookie)
847                                         s5p_vfree(alloc->vmem_cookie);
848
849                                 if (mfc_put_free_buf(alloc->vmem_addr,
850                                         alloc->vmem_size, port) < 0) {
851
852                                         mfc_err("failed to add free buffer\n");
853                                 } else {
854                                         list_del(&alloc->list);
855                                         kfree(alloc);
856                                 }
857 #else
858                                 if (mfc_put_free_buf(alloc->real,
859                                         alloc->size, port) < 0) {
860
861                                         mfc_err("failed to add free buffer\n");
862                                 } else {
863                                         list_del(&alloc->list);
864                                         kfree(alloc);
865                                 }
866 #endif
867                         }
868                 }
869         }
870
871         /*
872         spin_unlock_irqrestore(&lock, flags);
873         */
874
875 #ifdef DEBUG_ALLOC_FREE
876         mfc_print_buf();
877 #endif
878 }
879
880 unsigned long mfc_get_buf_real(int owner, unsigned int key)
881 {
882         struct list_head *pos, *nxt;
883         int port;
884         struct mfc_alloc_buffer *alloc;
885
886 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
887                 mfc_dbg("owner: %d, secure id: 0x%08x\n", owner, key);
888 #elif defined(CONFIG_S5P_VMEM)
889                 mfc_dbg("owner: %d, cookie: 0x%08x\n", owner, key);
890 #else
891                 mfc_dbg("owner: %d, offset: 0x%08x\n", owner, key);
892 #endif
893
894         for (port = 0; port < mfc_mem_count(); port++) {
895                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
896                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
897
898                         if (alloc->owner == owner) {
899 #if defined(CONFIG_VIDEO_MFC_VCM_UMP)
900                                 if (alloc->ump_handle) {
901                                         if (mfc_ump_get_id(alloc->ump_handle) == key)
902                                                 return alloc->real;
903                                 }
904 #elif defined(CONFIG_S5P_VMEM)
905                                 if (alloc->vmem_cookie == key)
906                                         return alloc->real;
907 #else
908                                 if (alloc->ofs == key)
909                                         return alloc->real;
910 #endif
911                         }
912                 }
913         }
914
915         return 0;
916 }
917
918 #if 0
919 unsigned char *mfc_get_buf_addr(int owner, unsigned char *user)
920 {
921         struct list_head *pos, *nxt;
922         int port;
923         struct mfc_alloc_buffer *alloc;
924
925         mfc_dbg("owner: %d, user: 0x%08x\n", owner, (unsigned int)user);
926
927         for (port = 0; port < mfc_mem_count(); port++) {
928                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
929                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
930
931                         if ((alloc->owner == owner)
932                                 && (alloc->user == user)){
933
934                                 return alloc->addr;
935                         }
936                 }
937         }
938
939         return NULL;
940 }
941
942 unsigned char *_mfc_get_buf_addr(int owner, unsigned char *user)
943 {
944         struct list_head *pos, *nxt;
945         int port;
946         struct mfc_alloc_buffer *alloc;
947
948         mfc_dbg("owner: %d, user: 0x%08x\n", owner, (unsigned int)user);
949
950         for (port = 0; port < mfc_mem_count(); port++) {
951                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
952                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
953
954                         if ((alloc->owner == owner)
955                                 && ((alloc->user <= user) || ((alloc->user + alloc->size) > user))){
956
957                                 return alloc->addr;
958                         }
959                 }
960         }
961
962         return NULL;
963 }
964 #endif
965
966 #ifdef CONFIG_VIDEO_MFC_VCM_UMP
967 void *mfc_get_buf_ump_handle(unsigned long real)
968 {
969         struct list_head *pos, *nxt;
970         int port;
971         struct mfc_alloc_buffer *alloc;
972
973         mfc_dbg("real: 0x%08lx\n", real);
974
975         for (port = 0; port < mfc_mem_count(); port++) {
976                 list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) {
977                         alloc = list_entry(pos, struct mfc_alloc_buffer, list);
978
979                         if (alloc->real == real)
980                                 return alloc->ump_handle;
981                 }
982         }
983
984         return NULL;
985 }
986 #endif
987