f4aa92a5e4b64297ab6a37d48ad9f12ee1ebd393
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / ipp / sec_converter.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #include <sys/ioctl.h>
32
33 #include "sec.h"
34 #include "sec_util.h"
35 #include "sec_video_types.h"
36 #include "sec_video_fourcc.h"
37 #include "sec_drm_ipp.h"
38 #include "sec_converter.h"
39
40 #include <drm_fourcc.h>
41
42 //#define INCREASE_NUM 1
43 #define DEQUEUE_FORCE 1
44
45 #if INCREASE_NUM
46 #define CVT_BUF_MAX    6
47 #endif
48
49 typedef struct _SECCvtFuncData
50 {
51     CvtFunc  func;
52     void    *data;
53     struct xorg_list   link;
54 } SECCvtFuncData;
55
56 typedef struct _SECCvtBuf
57 {
58     SECCvtType    type;
59     int           index;
60     unsigned int  handles[EXYNOS_DRM_PLANAR_MAX];
61     CARD32        begin;
62
63     SECVideoBuf  *vbuf;
64
65     struct xorg_list   link;
66 } SECCvtBuf;
67
68 struct _SECCvt
69 {
70     CARD32        stamp;
71
72     int  prop_id;
73
74     ScrnInfoPtr   pScrn;
75     SECCvtOp      op;
76     SECCvtProp    props[CVT_TYPE_MAX];
77
78     struct xorg_list   func_datas;
79     struct xorg_list   src_bufs;
80     struct xorg_list   dst_bufs;
81
82 #if INCREASE_NUM
83     int           src_index;
84     int           dst_index;
85 #endif
86
87     Bool          started;
88     Bool          first_event;
89
90     struct xorg_list   link;
91 };
92
93 static unsigned int formats[] =
94 {
95     FOURCC_RGB565,
96     FOURCC_SR16,
97     FOURCC_RGB32,
98     FOURCC_SR32,
99     FOURCC_YV12,
100     FOURCC_I420,
101     FOURCC_S420,
102     FOURCC_ST12,
103     FOURCC_SN12,
104     FOURCC_NV12,
105     FOURCC_SN21,
106     FOURCC_NV21,
107     FOURCC_YUY2,
108     FOURCC_SUYV,
109     FOURCC_UYVY,
110     FOURCC_SYVY,
111     FOURCC_ITLV,
112 };
113
114 static struct xorg_list cvt_list;
115
116 static void
117 _initList (void)
118 {
119     static Bool inited = FALSE;
120
121     if (inited)
122         return;
123
124     xorg_list_init (&cvt_list);
125
126     inited = TRUE;
127 }
128
129 static SECCvt*
130 _findCvt (CARD32 stamp)
131 {
132     SECCvt *cur = NULL, *next = NULL;
133
134     _initList ();
135
136     if (cvt_list.next != NULL)
137     {
138         xorg_list_for_each_entry_safe (cur, next, &cvt_list, link)
139         {
140             if (cur->stamp == stamp)
141                 return cur;
142         }
143     }
144
145     return NULL;
146 }
147
148 static enum drm_exynos_ipp_cmd
149 _drmCommand (SECCvtOp op)
150 {
151     switch (op)
152     {
153     case CVT_OP_OUTPUT:
154         return IPP_CMD_OUTPUT;
155     default:
156         return IPP_CMD_M2M;
157     }
158 }
159
160 static enum drm_exynos_degree
161 _drmDegree (int degree)
162 {
163     switch (degree % 360)
164     {
165     case 90:
166         return EXYNOS_DRM_DEGREE_90;
167     case 180:
168         return EXYNOS_DRM_DEGREE_180;
169     case 270:
170         return EXYNOS_DRM_DEGREE_270;
171     default:
172         return EXYNOS_DRM_DEGREE_0;
173     }
174 }
175
176 static void
177 _FillConfig (SECCvtType type, SECCvtProp *prop, struct drm_exynos_ipp_config *config)
178 {
179     config->ops_id = (type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
180
181     if (prop->hflip)
182         config->flip |= EXYNOS_DRM_FLIP_HORIZONTAL;
183     if (prop->vflip)
184         config->flip |= EXYNOS_DRM_FLIP_VERTICAL;
185
186     config->degree = _drmDegree (prop->degree);
187     config->fmt = secUtilGetDrmFormat (prop->id);
188     config->sz.hsize = (__u32)prop->width;
189     config->sz.vsize = (__u32)prop->height;
190     config->pos.x = (__u32)prop->crop.x;
191     config->pos.y = (__u32)prop->crop.y;
192     config->pos.w = (__u32)prop->crop.width;
193     config->pos.h = (__u32)prop->crop.height;
194 }
195
196 static void
197 _fillProperty (SECCvt *cvt, SECCvtType type, SECVideoBuf *vbuf, SECCvtProp *prop)
198 {
199     prop->id = vbuf->id;
200     prop->width = vbuf->width;
201     prop->height = vbuf->height;
202     prop->crop = vbuf->crop;
203
204     prop->degree = cvt->props[type].degree;
205     prop->vflip = cvt->props[type].vflip;
206     prop->hflip = cvt->props[type].hflip;
207     prop->secure = cvt->props[type].secure;
208     prop->csc_range = cvt->props[type].csc_range;
209 }
210
211 static Bool
212 _SetVbufConverting (SECVideoBuf *vbuf, SECCvt *cvt, Bool converting)
213 {
214     if (!converting)
215     {
216         ConvertInfo *cur = NULL, *next = NULL;
217
218         xorg_list_for_each_entry_safe (cur, next, &vbuf->convert_info, link)
219         {
220             if (cur->cvt == (void*)cvt)
221             {
222                 xorg_list_del (&cur->link);
223                 free (cur);
224                 return TRUE;
225             }
226         }
227
228         XDBG_ERROR (MCVT, "failed: %ld not found in %ld.\n", cvt->stamp, vbuf->stamp);
229         return FALSE;
230     }
231     else
232     {
233         ConvertInfo *info = NULL, *next = NULL;
234
235         xorg_list_for_each_entry_safe (info, next, &vbuf->convert_info, link)
236         {
237             if (info->cvt == (void*)cvt)
238             {
239                 XDBG_ERROR (MCVT, "failed: %ld already converting %ld.\n", cvt->stamp, vbuf->stamp);
240                 return FALSE;
241             }
242         }
243
244         info = calloc (1, sizeof (ConvertInfo));
245         XDBG_RETURN_VAL_IF_FAIL (info != NULL, FALSE);
246
247         info->cvt = (void*)cvt;
248
249         xorg_list_add (&info->link, &vbuf->convert_info);
250
251         return TRUE;
252     }
253 }
254
255 #if 0
256 static void
257 _printBufIndices (SECCvt *cvt, SECCvtType type, char *str)
258 {
259     struct xorg_list *bufs;
260     SECCvtBuf *cur, *next;
261     char nums[128];
262
263     bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
264
265     snprintf (nums, 128, "bufs:");
266
267     list_rev_for_each_entry_safe (cur, next, bufs, link)
268     {
269         snprintf (nums, 128, "%s %d", nums, cur->index);
270     }
271
272     ErrorF ("%s: cvt(%p) %s(%s). \n", str, cvt,
273                (type == CVT_TYPE_SRC)?"SRC":"DST", nums);
274 }
275 #endif
276
277 static int
278 _secCvtGetEmptyIndex (SECCvt *cvt, SECCvtType type)
279 {
280 #if INCREASE_NUM
281     int ret;
282
283     if(type == CVT_TYPE_SRC)
284     {
285         ret = cvt->src_index++;
286         if (cvt->src_index >= CVT_BUF_MAX)
287             cvt->src_index = 0;
288     }
289     else
290     {
291         ret = cvt->dst_index++;
292         if (cvt->dst_index >= CVT_BUF_MAX)
293             cvt->dst_index = 0;
294     }
295
296     return ret;
297 #else
298     struct xorg_list *bufs;
299     SECCvtBuf *cur = NULL, *next = NULL;
300     int ret = 0;
301
302     bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
303
304     while (1)
305     {
306         Bool found = FALSE;
307
308         xorg_list_for_each_entry_safe (cur, next, bufs, link)
309         {
310             if (ret == cur->index)
311             {
312                 found = TRUE;
313                 break;
314             }
315         }
316
317         if (!found)
318             break;
319
320         ret++;
321     }
322
323     return ret;
324 #endif
325 }
326
327 static SECCvtBuf*
328 _secCvtFindBuf (SECCvt *cvt, SECCvtType type, int index)
329 {
330     struct xorg_list *bufs;
331     SECCvtBuf *cur = NULL, *next = NULL;
332
333     bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
334
335     xorg_list_for_each_entry_safe (cur, next, bufs, link)
336     {
337         if (index == cur->index)
338             return cur;
339     }
340
341     XDBG_ERROR (MCVT, "cvt(%p), type(%d), index(%d) not found.\n", cvt, type, index);
342
343     return NULL;
344 }
345
346 static Bool
347 _secCvtQueue (SECCvt *cvt, SECCvtBuf *cbuf)
348 {
349     struct drm_exynos_ipp_queue_buf buf = {0,};
350     struct xorg_list *bufs;
351     int i;
352     int index = _secCvtGetEmptyIndex (cvt, cbuf->type);
353
354     buf.prop_id = cvt->prop_id;
355     buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
356     buf.buf_type = IPP_BUF_ENQUEUE;
357     buf.buf_id = cbuf->index = index;
358     buf.user_data = (__u64)cvt->stamp;
359
360     for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
361         buf.handle[i] = (__u32)cbuf->handles[i];
362
363     if (!secDrmIppQueueBuf (cvt->pScrn, &buf))
364         return FALSE;
365
366     bufs = (cbuf->type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
367     xorg_list_add (&cbuf->link, bufs);
368
369     _SetVbufConverting (cbuf->vbuf, cvt, TRUE);
370
371 #if 0
372     if (cbuf->type == CVT_TYPE_SRC)
373         _printBufIndices (cvt, CVT_TYPE_SRC, "in");
374 #endif
375
376     XDBG_DEBUG (MCVT, "cvt(%p), cbuf(%p), type(%d), index(%d) vbuf(%p) converting(%d)\n",
377                 cvt, cbuf, cbuf->type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf));
378
379     return TRUE;
380 }
381
382 static void
383 _secCvtDequeue (SECCvt *cvt, SECCvtBuf *cbuf)
384 {
385     struct drm_exynos_ipp_queue_buf buf = {0,};
386     int i;
387
388     if (!_secCvtFindBuf (cvt, cbuf->type, cbuf->index))
389     {
390         XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n",
391                       cvt, cbuf->type, cbuf->index);
392         return;
393     }
394
395     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf));
396
397     buf.prop_id = cvt->prop_id;
398     buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
399     buf.buf_type = IPP_BUF_DEQUEUE;
400     buf.buf_id = cbuf->index;
401     buf.user_data = (__u64)cvt->stamp;
402
403     for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
404         buf.handle[i] = (__u32)cbuf->handles[i];
405
406     if (!secDrmIppQueueBuf (cvt->pScrn, &buf))
407         return;
408 }
409
410 static void
411 _secCvtDequeued (SECCvt *cvt, SECCvtType type, int index)
412 {
413     SECCvtBuf *cbuf = _secCvtFindBuf (cvt, type, index);
414
415     if (!cbuf)
416     {
417         XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n",
418                       cvt, type, index);
419         return;
420     }
421
422     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf));
423
424     _SetVbufConverting (cbuf->vbuf, cvt, FALSE);
425
426     XDBG_DEBUG (MCVT, "cvt(%p) type(%d) index(%d) vbuf(%p) converting(%d)\n",
427                 cvt, type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf));
428
429     xorg_list_del (&cbuf->link);
430
431 #if 0
432     if (cbuf->type == CVT_TYPE_SRC)
433         _printBufIndices (cvt, CVT_TYPE_SRC, "out");
434 #endif
435
436     secUtilVideoBufferUnref (cbuf->vbuf);
437     free (cbuf);
438 }
439
440 static void
441 _secCvtDequeueAll (SECCvt *cvt)
442 {
443     SECCvtBuf *cur = NULL, *next = NULL;
444
445     xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link)
446     {
447         _secCvtDequeue (cvt, cur);
448     }
449
450     xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link)
451     {
452         _secCvtDequeue (cvt, cur);
453     }
454 }
455
456 static void
457 _secCvtDequeuedAll (SECCvt *cvt)
458 {
459     SECCvtBuf *cur = NULL, *next = NULL;
460
461     xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link)
462     {
463         _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, cur->index);
464     }
465
466     xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link)
467     {
468         _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, cur->index);
469     }
470 }
471
472 static void
473 _secCvtStop (SECCvt *cvt)
474 {
475     struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
476
477     XDBG_RETURN_IF_FAIL (cvt != NULL);
478
479     if (!cvt->started)
480         return;
481
482     _secCvtDequeueAll (cvt);
483
484     ctrl.prop_id = cvt->prop_id;
485     ctrl.ctrl = IPP_CTRL_STOP;
486
487     secDrmIppCmdCtrl (cvt->pScrn, &ctrl);
488
489     _secCvtDequeuedAll (cvt);
490
491     XDBG_TRACE (MCVT, "cvt(%p)\n", cvt);
492
493     cvt->prop_id = -1;
494
495     memset (cvt->props, 0, sizeof (SECCvtProp) * CVT_TYPE_MAX);
496
497 #if INCREASE_NUM
498     cvt->src_index = 0;
499     cvt->dst_index = 0;
500 #endif
501     cvt->started = FALSE;
502
503     return;
504 }
505
506 Bool
507 secCvtSupportFormat (SECCvtOp op, int id)
508 {
509     unsigned int *drmfmts;
510     int i, size, num = 0;
511     unsigned int drmfmt = secUtilGetDrmFormat (id);
512
513     XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, FALSE);
514     XDBG_RETURN_VAL_IF_FAIL (id > 0, FALSE);
515
516     size = sizeof (formats) / sizeof (unsigned int);
517
518     for (i = 0; i < size; i++)
519         if (formats[i] == id)
520             break;
521
522     if (i == size)
523     {
524         XDBG_ERROR (MCVT, "converter(op:%d) not support : '%c%c%c%c'.\n",
525                     op, FOURCC_STR (id));
526         return FALSE;
527     }
528
529     drmfmts = secDrmIppGetFormatList (&num);
530     if (!drmfmts)
531     {
532         XDBG_ERROR (MCVT, "no drm format list.\n");
533         return FALSE;
534     }
535
536     for (i = 0; i < num; i++)
537         if (drmfmts[i] == drmfmt)
538         {
539             free (drmfmts);
540             return TRUE;
541         }
542
543     XDBG_ERROR (MCVT, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR (id));
544
545     free (drmfmts);
546
547     return FALSE;
548 }
549
550 Bool
551 secCvtEnsureSize (SECCvtProp *src, SECCvtProp *dst)
552 {
553     if (src)
554     {
555         int type = secUtilGetColorType (src->id);
556
557         XDBG_RETURN_VAL_IF_FAIL (src->width >= 16, FALSE);
558         XDBG_RETURN_VAL_IF_FAIL (src->height >= 8, FALSE);
559         XDBG_RETURN_VAL_IF_FAIL (src->crop.width >= 16, FALSE);
560         XDBG_RETURN_VAL_IF_FAIL (src->crop.height >= 8, FALSE);
561
562         if (src->width % 16)
563         {
564             if (!IS_ZEROCOPY (src->id))
565             {
566                 int new_width = (src->width + 16) & (~0xF);
567                 XDBG_DEBUG (MCVT, "src's width : %d to %d.\n", src->width, new_width);
568                 src->width = new_width;
569             }
570         }
571
572         if (type == TYPE_YUV420 && src->height % 2)
573             XDBG_WARNING (MCVT, "src's height(%d) is not multiple of 2!!!\n", src->height);
574
575         if (type == TYPE_YUV420 || type == TYPE_YUV422)
576         {
577             src->crop.x = src->crop.x & (~0x1);
578             src->crop.width = src->crop.width & (~0x1);
579         }
580
581         if (type == TYPE_YUV420)
582             src->crop.height = src->crop.height & (~0x1);
583
584         if (src->crop.x + src->crop.width > src->width)
585             src->crop.width = src->width - src->crop.x;
586         if (src->crop.y + src->crop.height > src->height)
587             src->crop.height = src->height - src->crop.y;
588     }
589
590     if (dst)
591     {
592         int type = secUtilGetColorType (dst->id);
593
594         XDBG_RETURN_VAL_IF_FAIL (dst->width >= 16, FALSE);
595         XDBG_RETURN_VAL_IF_FAIL (dst->height >= 8, FALSE);
596         XDBG_RETURN_VAL_IF_FAIL (dst->crop.width >= 16, FALSE);
597         XDBG_RETURN_VAL_IF_FAIL (dst->crop.height >= 4, FALSE);
598
599         if (dst->width % 16)
600         {
601             int new_width = (dst->width + 16) & (~0xF);
602             XDBG_DEBUG (MCVT, "dst's width : %d to %d.\n", dst->width, new_width);
603             dst->width = new_width;
604         }
605
606         dst->height = dst->height & (~0x1);
607
608         if (type == TYPE_YUV420 && dst->height % 2)
609             XDBG_WARNING (MCVT, "dst's height(%d) is not multiple of 2!!!\n", dst->height);
610
611         if (type == TYPE_YUV420 || type == TYPE_YUV422)
612         {
613             dst->crop.x = dst->crop.x & (~0x1);
614             dst->crop.width = dst->crop.width & (~0x1);
615         }
616
617         if (type == TYPE_YUV420)
618             dst->crop.height = dst->crop.height & (~0x1);
619
620         if (dst->crop.x + dst->crop.width > dst->width)
621             dst->crop.width = dst->width - dst->crop.x;
622         if (dst->crop.y + dst->crop.height > dst->height)
623             dst->crop.height = dst->height - dst->crop.y;
624     }
625
626     return TRUE;
627 }
628
629 SECCvt*
630 secCvtCreate (ScrnInfoPtr pScrn, SECCvtOp op)
631 {
632     SECCvt *cvt;
633     CARD32 stamp = GetTimeInMillis ();
634
635     _initList ();
636
637     XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
638     XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, NULL);
639
640     while (_findCvt (stamp))
641         stamp++;
642
643     cvt = calloc (1, sizeof (SECCvt));
644     XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, NULL);
645
646     cvt->stamp = stamp;
647
648     cvt->pScrn = pScrn;
649     cvt->op = op;
650     cvt->prop_id = -1;
651
652     xorg_list_init (&cvt->func_datas);
653     xorg_list_init (&cvt->src_bufs);
654     xorg_list_init (&cvt->dst_bufs);
655
656     XDBG_TRACE (MCVT, "op(%d), cvt(%p) stamp(%ld)\n", op, cvt, stamp);
657
658     xorg_list_add (&cvt->link, &cvt_list);
659
660     return cvt;
661 }
662
663 void
664 secCvtDestroy (SECCvt *cvt)
665 {
666     SECCvtFuncData *cur = NULL, *next = NULL;
667
668     if (!cvt)
669         return;
670
671     _secCvtStop (cvt);
672
673     xorg_list_del (&cvt->link);
674
675     xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link)
676     {
677         xorg_list_del (&cur->link);
678         free (cur);
679     }
680
681     XDBG_TRACE (MCVT, "cvt(%p)\n", cvt);
682
683     free (cvt);
684 }
685
686 SECCvtOp
687 secCvtGetOp (SECCvt *cvt)
688 {
689     XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, CVT_OP_M2M);
690
691     return cvt->op;
692 }
693
694 Bool
695 secCvtSetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst)
696 {
697     if (cvt->started)
698         return TRUE;
699
700     struct drm_exynos_ipp_property property;
701
702     XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
703     XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
704     XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
705
706     if (!secCvtEnsureSize (src, dst))
707         return FALSE;
708
709     if (dst->crop.x + dst->crop.width > dst->width)
710     {
711         XDBG_ERROR (MCVT, "dst(%d+%d > %d). !\n", dst->crop.x, dst->crop.width, dst->width);
712     }
713
714     if (!secCvtSupportFormat (cvt->op, src->id))
715     {
716         XDBG_ERROR (MCVT, "cvt(%p) src '%c%c%c%c' not supported.\n",
717                     cvt, FOURCC_STR (src->id));
718         return FALSE;
719     }
720
721     if (!secCvtSupportFormat (cvt->op, dst->id))
722     {
723         XDBG_ERROR (MCVT, "cvt(%p) dst '%c%c%c%c' not supported.\n",
724                     cvt, FOURCC_STR (dst->id));
725         return FALSE;
726     }
727
728     memcpy (&cvt->props[CVT_TYPE_SRC], src, sizeof (SECCvtProp));
729     memcpy (&cvt->props[CVT_TYPE_DST], dst, sizeof (SECCvtProp));
730
731     CLEAR (property);
732     _FillConfig (CVT_TYPE_SRC, &cvt->props[CVT_TYPE_SRC], &property.config[0]);
733     _FillConfig (CVT_TYPE_DST, &cvt->props[CVT_TYPE_DST], &property.config[1]);
734     property.cmd = _drmCommand (cvt->op);
735 #ifdef _F_WEARABLE_FEATURE_
736     property.type = IPP_EVENT_DRIVEN;
737 #endif
738     property.prop_id = cvt->prop_id;
739     property.protect = dst->secure;
740     property.range = dst->csc_range;
741
742     XDBG_TRACE (MCVT, "cvt(%p) src('%c%c%c%c', '%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
743                 cvt, FOURCC_STR(src->id), FOURCC_STR(secUtilGetDrmFormat(src->id)),
744                 src->width, src->height,
745                 src->crop.x, src->crop.y, src->crop.width, src->crop.height,
746                 src->degree, src->hflip, src->vflip,
747                 src->secure, src->csc_range);
748
749     XDBG_TRACE (MCVT, "cvt(%p) dst('%c%c%c%c', '%c%c%c%c',%dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
750                 cvt, FOURCC_STR(dst->id), FOURCC_STR(secUtilGetDrmFormat(dst->id)),
751                 dst->width, dst->height,
752                 dst->crop.x, dst->crop.y, dst->crop.width, dst->crop.height,
753                 dst->degree, dst->hflip, dst->vflip,
754                 dst->secure, dst->csc_range);
755
756     cvt->prop_id = secDrmIppSetProperty (cvt->pScrn, &property);
757     XDBG_RETURN_VAL_IF_FAIL (cvt->prop_id >= 0, FALSE);
758
759     return TRUE;
760 }
761
762 void
763 secCvtGetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst)
764 {
765     XDBG_RETURN_IF_FAIL (cvt != NULL);
766
767     if (src)
768         *src = cvt->props[CVT_TYPE_SRC];
769
770     if (dst)
771         *dst = cvt->props[CVT_TYPE_DST];
772 }
773
774 Bool
775 secCvtConvert (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst)
776 {
777     SECCvtBuf *src_cbuf = NULL, *dst_cbuf = NULL;
778     SECCvtProp src_prop, dst_prop;
779
780     XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
781     XDBG_RETURN_VAL_IF_FAIL (cvt->op == CVT_OP_M2M, FALSE);
782     XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
783     XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
784     XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (src), FALSE);
785     XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (dst), FALSE);
786
787     _fillProperty (cvt, CVT_TYPE_SRC, src, &src_prop);
788     _fillProperty (cvt, CVT_TYPE_DST, dst, &dst_prop);
789
790     if (memcmp (&cvt->props[CVT_TYPE_SRC], &src_prop, sizeof (SECCvtProp)) ||
791         memcmp (&cvt->props[CVT_TYPE_DST], &dst_prop, sizeof (SECCvtProp)))
792     {
793         XDBG_ERROR (MCVT, "cvt(%p) prop changed!\n", cvt);
794         XDBG_TRACE (MCVT, "cvt(%p) src_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
795                     cvt, FOURCC_STR(cvt->props[CVT_TYPE_SRC].id),
796                     cvt->props[CVT_TYPE_SRC].width, cvt->props[CVT_TYPE_SRC].height,
797                     cvt->props[CVT_TYPE_SRC].crop.x, cvt->props[CVT_TYPE_SRC].crop.y,
798                     cvt->props[CVT_TYPE_SRC].crop.width, cvt->props[CVT_TYPE_SRC].crop.height,
799                     cvt->props[CVT_TYPE_SRC].degree,
800                     cvt->props[CVT_TYPE_SRC].hflip, cvt->props[CVT_TYPE_SRC].vflip,
801                     cvt->props[CVT_TYPE_SRC].secure, cvt->props[CVT_TYPE_SRC].csc_range);
802         XDBG_TRACE (MCVT, "cvt(%p) src_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
803                     cvt, FOURCC_STR(src_prop.id), src_prop.width, src_prop.height,
804                     src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
805                     src_prop.degree, src_prop.hflip, src_prop.vflip,
806                     src_prop.secure, src_prop.csc_range);
807         XDBG_TRACE (MCVT, "cvt(%p) dst_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
808                     cvt, FOURCC_STR(cvt->props[CVT_TYPE_DST].id),
809                     cvt->props[CVT_TYPE_DST].width, cvt->props[CVT_TYPE_DST].height,
810                     cvt->props[CVT_TYPE_DST].crop.x, cvt->props[CVT_TYPE_DST].crop.y,
811                     cvt->props[CVT_TYPE_DST].crop.width, cvt->props[CVT_TYPE_DST].crop.height,
812                     cvt->props[CVT_TYPE_DST].degree,
813                     cvt->props[CVT_TYPE_DST].hflip, cvt->props[CVT_TYPE_DST].vflip,
814                     cvt->props[CVT_TYPE_DST].secure, cvt->props[CVT_TYPE_DST].csc_range);
815         XDBG_TRACE (MCVT, "cvt(%p) dst_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
816                     cvt, FOURCC_STR(dst_prop.id), dst_prop.width, dst_prop.height,
817                     dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height,
818                     dst_prop.degree, dst_prop.hflip, dst_prop.vflip,
819                     dst_prop.secure, dst_prop.csc_range);
820         return FALSE;
821     }
822
823     XDBG_GOTO_IF_FAIL (cvt->prop_id >= 0, fail_to_convert);
824     XDBG_GOTO_IF_FAIL (src->handles[0] > 0, fail_to_convert);
825     XDBG_GOTO_IF_FAIL (dst->handles[0] > 0, fail_to_convert);
826
827     src_cbuf = calloc (1, sizeof (SECCvtBuf));
828     XDBG_GOTO_IF_FAIL (src_cbuf != NULL, fail_to_convert);
829     dst_cbuf = calloc (1, sizeof (SECCvtBuf));
830     XDBG_GOTO_IF_FAIL (dst_cbuf != NULL, fail_to_convert);
831
832     src_cbuf->type = CVT_TYPE_SRC;
833     src_cbuf->vbuf = secUtilVideoBufferRef (src);
834     memcpy (src_cbuf->handles, src->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX);
835
836     if (!_secCvtQueue (cvt, src_cbuf))
837     {
838         secUtilVideoBufferUnref (src_cbuf->vbuf);
839         goto fail_to_convert;
840     }
841
842     XDBG_DEBUG (MCVT, "cvt(%p) srcbuf(%p) converting(%d)\n",
843                 cvt, src, VBUF_IS_CONVERTING (src));
844
845     dst_cbuf->type = CVT_TYPE_DST;
846     dst_cbuf->vbuf = secUtilVideoBufferRef (dst);
847     memcpy (dst_cbuf->handles, dst->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX);
848
849     if (!_secCvtQueue (cvt, dst_cbuf))
850     {
851         secUtilVideoBufferUnref (dst_cbuf->vbuf);
852         goto fail_to_convert;
853     }
854
855     XDBG_DEBUG (MCVT, "cvt(%p) dstbuf(%p) converting(%d)\n",
856                 cvt, dst, VBUF_IS_CONVERTING (dst));
857
858     XDBG_DEBUG (MVBUF, "==> ipp (%ld,%d,%d : %ld,%d,%d) \n",
859                 src->stamp, VBUF_IS_CONVERTING (src), src->showing,
860                 dst->stamp, VBUF_IS_CONVERTING (dst), dst->showing);
861
862     if (!cvt->started)
863     {
864         struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
865
866         ctrl.prop_id = cvt->prop_id;
867         ctrl.ctrl = IPP_CTRL_PLAY;
868
869         if (!secDrmIppCmdCtrl (cvt->pScrn, &ctrl))
870             goto fail_to_convert;
871
872         XDBG_TRACE (MCVT, "cvt(%p) start.\n", cvt);
873
874         cvt->started = TRUE;
875     }
876
877     dst->dirty = TRUE;
878
879     SECPtr pSec = SECPTR (cvt->pScrn);
880     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT)
881         src_cbuf->begin = GetTimeInMillis ();
882
883     return TRUE;
884
885 fail_to_convert:
886
887     if (src_cbuf)
888         free (src_cbuf);
889     if (dst_cbuf)
890         free (dst_cbuf);
891
892     _secCvtStop (cvt);
893
894     return FALSE;
895 }
896
897 Bool
898 secCvtAddCallback (SECCvt *cvt, CvtFunc func, void *data)
899 {
900     SECCvtFuncData *func_data;
901
902     XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
903     XDBG_RETURN_VAL_IF_FAIL (func != NULL, FALSE);
904
905     func_data = calloc (1, sizeof (SECCvtFuncData));
906     XDBG_RETURN_VAL_IF_FAIL (func_data != NULL, FALSE);
907
908     xorg_list_add (&func_data->link, &cvt->func_datas);
909
910     func_data->func = func;
911     func_data->data = data;
912
913     return TRUE;
914 }
915
916 void
917 secCvtRemoveCallback (SECCvt *cvt, CvtFunc func, void *data)
918 {
919     SECCvtFuncData *cur = NULL, *next = NULL;
920
921     XDBG_RETURN_IF_FAIL (cvt != NULL);
922     XDBG_RETURN_IF_FAIL (func != NULL);
923
924     xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link)
925     {
926         if (cur->func == func && cur->data == data)
927         {
928             xorg_list_del (&cur->link);
929             free (cur);
930         }
931     }
932 }
933
934 void
935 secCvtHandleIppEvent (int fd, unsigned int *buf_idx, void *data, Bool error)
936 {
937     CARD32 stamp = (CARD32)data;
938     SECCvt *cvt;
939     SECCvtBuf *src_cbuf, *dst_cbuf;
940     SECVideoBuf *src_vbuf, *dst_vbuf;
941     SECCvtFuncData *curr = NULL, *next = NULL;
942
943     XDBG_RETURN_IF_FAIL (buf_idx != NULL);
944
945     cvt = _findCvt (stamp);
946     if (!cvt)
947     {
948         XDBG_DEBUG (MCVT, "invalid cvt's stamp (%ld).\n", stamp);
949         return;
950     }
951
952     XDBG_DEBUG (MCVT, "cvt(%p) index(%d, %d)\n",
953                 cvt, buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]);
954
955 #if 0
956     char temp[64];
957     snprintf (temp, 64, "%d,%d", buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]);
958     _printBufIndices (cvt, CVT_TYPE_SRC, temp);
959 #endif
960
961 #if DEQUEUE_FORCE
962     SECCvtBuf *cur = NULL, *prev = NULL;
963
964     list_rev_for_each_entry_safe (cur, prev, &cvt->src_bufs, link)
965     {
966         if (buf_idx[EXYNOS_DRM_OPS_SRC] != cur->index)
967         {
968             unsigned int indice[EXYNOS_DRM_OPS_MAX] = {cur->index, cur->index};
969
970             XDBG_WARNING (MCVT, "cvt(%p) event(%d,%d) has been skipped!! \n",
971                           cvt, cur->index, cur->index);
972
973             /* To make sure all events are received, _secCvtDequeued should be called
974              * for every event. If a event has been skipped, to call _secCvtDequeued
975              * forcely, we call secCvtHandleIppEvent recursivly.
976              */
977             secCvtHandleIppEvent (0, indice, (void*)cvt->stamp, TRUE);
978         }
979         else
980             break;
981     }
982 #endif
983
984     src_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]);
985     XDBG_RETURN_IF_FAIL (src_cbuf != NULL);
986
987     dst_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]);
988     XDBG_RETURN_IF_FAIL (dst_cbuf != NULL);
989
990     SECPtr pSec = SECPTR (cvt->pScrn);
991     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT)
992     {
993         CARD32 cur, sub;
994         cur = GetTimeInMillis ();
995         sub = cur - src_cbuf->begin;
996         ErrorF ("cvt(%p)   ipp interval  : %6ld ms\n", cvt, sub);
997     }
998
999     src_vbuf = src_cbuf->vbuf;
1000     dst_vbuf = dst_cbuf->vbuf;
1001
1002     XDBG_DEBUG (MVBUF, "<== ipp (%ld,%d,%d : %ld,%d,%d) \n",
1003                 src_vbuf->stamp, VBUF_IS_CONVERTING (src_vbuf), src_vbuf->showing,
1004                 dst_vbuf->stamp, VBUF_IS_CONVERTING (dst_vbuf), dst_vbuf->showing);
1005
1006     if (!cvt->first_event)
1007     {
1008         XDBG_DEBUG (MCVT, "cvt(%p) got a IPP event. \n", cvt);
1009         cvt->first_event = TRUE;
1010     }
1011
1012     xorg_list_for_each_entry_safe (curr, next, &cvt->func_datas, link)
1013     {
1014         if (curr->func)
1015             curr->func (cvt, src_vbuf, dst_vbuf, curr->data, error);
1016     }
1017
1018     _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]);
1019     _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]);
1020 }