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