3c4cc242d4e1434b83db9487b0013a96d2f138ee
[platform/adaptation/ap_samsung/libexynos-common.git] / libgscaler / libgscaler.cpp
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  * Copyright@ Samsung Electronics Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /*!
19  * \file      libgscaler.cpp
20  * \brief     source file for Gscaler HAL
21  * \author    Sungchun Kang (sungchun.kang@samsung.com)
22  * \date      2013/06/01
23  *
24  * <b>Revision History: </b>
25  * - 2013.06.01 : Sungchun Kang (sungchun.kang@samsung.com) \n
26  *   Create
27  */
28
29 #include "libgscaler_obj.h"
30
31 void *exynos_gsc_create(void)
32 {
33     CGscaler *gsc = new CGscaler(GSC_M2M_MODE);
34     if (!gsc) {
35         ALOGE("%s:: failed to allocate Gscaler handle", __func__);
36         return NULL;
37     }
38     if (gsc->m_gsc_find_and_create(gsc) == false) {
39         ALOGE("%s::m_exynos_gsc_find_and_create() fail", __func__);
40         delete gsc;
41         return NULL;
42     }
43
44     return reinterpret_cast<void *>(gsc);
45 }
46
47 void *exynos_gsc_create_exclusive(
48     int dev_num,
49     int mode,
50     int out_mode,
51     int allow_drm)
52 {
53     int i     = 0;
54     int op_id = 0;
55     unsigned int total_sleep_time  = 0;
56     int ret = 0;
57
58     Exynos_gsc_In();
59
60     if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
61         ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
62         return NULL;
63     }
64
65     if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
66         CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
67         if (!gsc) {
68             ALOGE("%s:: failed to allocate Gscaler handle", __func__);
69             return NULL;
70         }
71
72         gsc->scaler = exynos_sc_create_exclusive(dev_num - HW_SCAL0,
73             allow_drm);
74         if (!gsc->scaler) {
75             delete(gsc);
76             ALOGE("%s::exynos_sc_create fail", __func__);
77             return NULL;
78         }
79         Exynos_gsc_Out();
80         return reinterpret_cast<void *>(gsc);
81     }
82
83     if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
84         ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
85         return NULL;
86     }
87
88     CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
89     if (!gsc) {
90         ALOGE("%s:: failed to allocate Gscaler handle", __func__);
91         return NULL;
92     }
93
94     if (mode == GSC_M2M_MODE) {
95         gsc->gsc_fd = gsc->m_gsc_m2m_create(dev_num);
96         if (gsc->gsc_fd < 0) {
97             ALOGE("%s::m_gsc_m2m_create(%i) fail", __func__, dev_num);
98             goto err;
99         }
100     } else if (mode == GSC_OUTPUT_MODE) {
101         ret = gsc->m_gsc_output_create(gsc, dev_num, out_mode);
102         if (ret < 0) {
103             ALOGE("%s::m_gsc_output_create(%i) fail", __func__, dev_num);
104             goto err;
105         }
106     } else if (mode == GSC_CAPTURE_MODE) {
107         ret = gsc->m_gsc_capture_create(gsc, dev_num, out_mode);
108         if (ret < 0) {
109             ALOGE("%s::m_gsc_capture_create(%i) fail", __func__, dev_num);
110             goto err;
111         }
112     } else {
113             ALOGE("%s::Unsupported Mode(%i) fail", __func__, dev_num);
114             goto err;
115     }
116
117     Exynos_gsc_Out();
118
119     return reinterpret_cast<void *>(gsc);
120 err:
121     switch (mode) {
122     case GSC_M2M_MODE:
123         gsc->m_gsc_m2m_destroy(gsc);
124         break;
125     case GSC_OUTPUT_MODE:
126         gsc->m_gsc_out_destroy(gsc);
127         break;
128     case GSC_CAPTURE_MODE:
129         gsc->m_gsc_cap_destroy(gsc);
130         break;
131     }
132
133     delete(gsc);
134
135     Exynos_gsc_Out();
136
137     return NULL;
138 }
139
140 void exynos_gsc_destroy(void *handle)
141 {
142     Exynos_gsc_In();
143
144     int i = 0;
145     CGscaler* gsc = GetGscaler(handle);
146     if (gsc == NULL) {
147         ALOGE("%s::handle == NULL() fail", __func__);
148         return;
149     }
150
151     if (gsc->mode == GSC_OUTPUT_MODE)
152         gsc->m_gsc_out_destroy(gsc);
153     else if (gsc->mode ==GSC_CAPTURE_MODE)
154         gsc->m_gsc_cap_destroy(gsc);
155     else
156         gsc->m_gsc_m2m_destroy(gsc);
157
158     delete(gsc);
159
160     Exynos_gsc_Out();
161 }
162
163 int exynos_gsc_set_csc_property(
164     void        *handle,
165     unsigned int eq_auto,
166     unsigned int range_full,
167     unsigned int v4l2_colorspace)
168 {
169     Exynos_gsc_In();
170
171     CGscaler *gsc = GetGscaler(handle);
172     if (gsc == NULL) {
173         ALOGE("%s::handle == NULL() fail", __func__);
174         return -1;
175     }
176
177     if (gsc->gsc_id >= HW_SCAL0) {
178         int ret;
179         ret = exynos_sc_csc_exclusive(gsc->scaler,
180                             range_full, v4l2_colorspace);
181         Exynos_gsc_Out();
182         return ret;
183     }
184     gsc->eq_auto = eq_auto;
185     gsc->range_full = range_full;
186     gsc->v4l2_colorspace = v4l2_colorspace;
187
188     Exynos_gsc_Out();
189
190     return 0;
191 }
192
193 int exynos_gsc_set_src_format(
194     void        *handle,
195     unsigned int width,
196     unsigned int height,
197     unsigned int crop_left,
198     unsigned int crop_top,
199     unsigned int crop_width,
200     unsigned int crop_height,
201     unsigned int v4l2_colorformat,
202     unsigned int cacheable,
203     unsigned int mode_drm)
204 {
205     Exynos_gsc_In();
206
207     CGscaler *gsc = GetGscaler(handle);
208     if (gsc == NULL) {
209         ALOGE("%s::handle == NULL() fail", __func__);
210         return -1;
211     }
212     gsc->src_info.width            = width;
213     gsc->src_info.height           = height;
214     gsc->src_info.crop_left        = crop_left;
215     gsc->src_info.crop_top         = crop_top;
216     gsc->src_info.crop_width       = crop_width;
217     gsc->src_info.crop_height      = crop_height;
218     gsc->src_info.v4l2_colorformat = v4l2_colorformat;
219     gsc->src_info.cacheable        = cacheable;
220     gsc->src_info.mode_drm         = mode_drm;
221     gsc->src_info.dirty            = true;
222
223     Exynos_gsc_Out();
224
225     return 0;
226 }
227
228 int exynos_gsc_set_dst_format(
229     void        *handle,
230     unsigned int width,
231     unsigned int height,
232     unsigned int crop_left,
233     unsigned int crop_top,
234     unsigned int crop_width,
235     unsigned int crop_height,
236     unsigned int v4l2_colorformat,
237     unsigned int cacheable,
238     unsigned int mode_drm)
239 {
240     Exynos_gsc_In();
241
242     CGscaler *gsc = GetGscaler(handle);
243     if (gsc == NULL) {
244         ALOGE("%s::handle == NULL() fail", __func__);
245         return -1;
246     }
247
248     gsc->dst_info.width            = width;
249     gsc->dst_info.height           = height;
250     gsc->dst_info.crop_left        = crop_left;
251     gsc->dst_info.crop_top         = crop_top;
252     gsc->dst_info.crop_width       = crop_width;
253     gsc->dst_info.crop_height      = crop_height;
254     gsc->dst_info.v4l2_colorformat = v4l2_colorformat;
255     gsc->dst_info.dirty            = true;
256     gsc->dst_info.cacheable        = cacheable;
257     gsc->dst_info.mode_drm         = mode_drm;
258
259     Exynos_gsc_Out();
260
261     return 0;
262 }
263
264 int exynos_gsc_set_rotation(
265     void *handle,
266     int   rotation,
267     int   flip_horizontal,
268     int   flip_vertical)
269 {
270     CGscaler *gsc = GetGscaler(handle);
271     if (gsc == NULL) {
272         ALOGE("%s::handle == NULL() fail", __func__);
273         return -1;
274     }
275
276     int new_rotation = rotation % 360;
277
278     if (new_rotation % 90 != 0) {
279         ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__,
280             rotation);
281         return -1;
282     }
283
284     if(new_rotation < 0)
285         new_rotation = -new_rotation;
286
287     gsc->dst_info.rotation        = new_rotation;
288     gsc->dst_info.flip_horizontal = flip_horizontal;
289     gsc->dst_info.flip_vertical   = flip_vertical;
290
291     return 0;
292 }
293
294 int exynos_gsc_set_src_addr(
295     void *handle,
296     void *addr[3],
297     int mem_type,
298     int acquireFenceFd)
299 {
300     Exynos_gsc_In();
301
302     CGscaler* gsc = GetGscaler(handle);
303     if (gsc == NULL) {
304         ALOGE("%s::handle == NULL() fail", __func__);
305         return -1;
306     }
307
308     gsc->src_info.buf.addr[0] = addr[0];
309     gsc->src_info.buf.addr[1] = addr[1];
310     gsc->src_info.buf.addr[2] = addr[2];
311     gsc->src_info.acquireFenceFd = acquireFenceFd;
312     gsc->src_info.buf.mem_type = (enum v4l2_memory)mem_type;
313
314     Exynos_gsc_Out();
315
316     return 0;
317 }
318
319 int exynos_gsc_set_dst_addr(
320     void *handle,
321     void *addr[3],
322     int mem_type,
323     int acquireFenceFd)
324 {
325     Exynos_gsc_In();
326
327     CGscaler* gsc = GetGscaler(handle);
328     if (gsc == NULL) {
329         ALOGE("%s::handle == NULL() fail", __func__);
330         return -1;
331     }
332
333     gsc->dst_info.buf.addr[0] = addr[0];
334     gsc->dst_info.buf.addr[1] = addr[1];
335     gsc->dst_info.buf.addr[2] = addr[2];
336     gsc->dst_info.acquireFenceFd = acquireFenceFd;
337     gsc->dst_info.buf.mem_type = (enum v4l2_memory)mem_type;
338
339     Exynos_gsc_Out();
340
341     return 0;
342 }
343
344 int exynos_gsc_convert(void *handle)
345 {
346     Exynos_gsc_In();
347
348     int ret    = -1;
349     CGscaler* gsc = GetGscaler(handle);
350     if (gsc == NULL) {
351         ALOGE("%s::handle == NULL() fail", __func__);
352         return ret;
353     }
354
355     if (gsc->m_gsc_m2m_run_core(handle) < 0) {
356         ALOGE("%s::exynos_gsc_run_core fail", __func__);
357         goto done;
358     }
359
360     if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
361         ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
362         goto done;
363     }
364
365     if (gsc->src_info.releaseFenceFd >= 0) {
366         close(gsc->src_info.releaseFenceFd);
367         gsc->src_info.releaseFenceFd = -1;
368     }
369
370     if (gsc->dst_info.releaseFenceFd >= 0) {
371         close(gsc->dst_info.releaseFenceFd);
372         gsc->dst_info.releaseFenceFd = -1;
373     }
374
375     if (gsc->m_gsc_m2m_stop(handle) < 0) {
376         ALOGE("%s::m_gsc_m2m_stop", __func__);
377         goto done;
378     }
379
380     ret = 0;
381
382 done:
383     Exynos_gsc_Out();
384
385     return ret;
386 }
387
388 int exynos_gsc_subdev_s_crop(void *handle,
389         exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
390 {
391     struct v4l2_subdev_crop sd_crop;
392     CGscaler *gsc = GetGscaler(handle);
393     if (gsc == NULL) {
394         ALOGE("%s::handle == NULL() fail", __func__);
395         return -1;
396     }
397
398     sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
399     sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
400     sd_crop.rect.left = dst_img->x;
401     sd_crop.rect.top = dst_img->y;
402     sd_crop.rect.width = dst_img->w;
403     sd_crop.rect.height = dst_img->h;
404
405     return exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop);
406 }
407
408 int exynos_gsc_config_exclusive(void *handle,
409     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
410 {
411     Exynos_gsc_In();
412
413     int ret = 0;
414     CGscaler* gsc = GetGscaler(handle);
415     if (gsc == NULL) {
416         ALOGE("%s::handle == NULL() fail", __func__);
417         return -1;
418     }
419     if (gsc->gsc_id >= HW_SCAL0) {
420         ret = exynos_sc_config_exclusive(gsc->scaler,
421             (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
422         Exynos_gsc_Out();
423         return ret;
424     }
425
426     switch (gsc->mode) {
427     case GSC_M2M_MODE:
428         ret = gsc->m_gsc_m2m_config(handle, src_img, dst_img);
429         break;
430     case GSC_OUTPUT_MODE:
431         ret = gsc->m_gsc_out_config(handle, src_img, dst_img);
432         break;
433     case GSC_CAPTURE_MODE:
434         ret = gsc->m_gsc_cap_config(handle, src_img, dst_img);
435         break;
436     default:
437         break;
438     }
439
440     Exynos_gsc_Out();
441
442     return ret;
443 }
444
445 int exynos_gsc_run_exclusive(void *handle,
446     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
447 {
448     Exynos_gsc_In();
449
450     int ret = 0;
451     CGscaler* gsc = GetGscaler(handle);
452     if (gsc == NULL) {
453         ALOGE("%s::handle == NULL() fail", __func__);
454         return -1;
455     }
456
457     if (gsc->gsc_id >= HW_SCAL0) {
458         ret = exynos_sc_run_exclusive(gsc->scaler,
459             (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
460         Exynos_gsc_Out();
461         return ret;
462     }
463
464     switch (gsc->mode) {
465     case GSC_M2M_MODE:
466         ret = gsc->m_gsc_m2m_run(handle, src_img, dst_img);
467         break;
468     case GSC_OUTPUT_MODE:
469         ret = gsc->m_gsc_out_run(handle, src_img);
470         break;
471     case GSC_CAPTURE_MODE:
472         ret = gsc->m_gsc_cap_run(handle, dst_img);
473         break;
474     default:
475         break;
476     }
477
478     Exynos_gsc_Out();
479
480     return ret;
481 }
482
483 void *exynos_gsc_create_blend_exclusive(int dev_num, int mode, int out_mode,
484                                                                 int allow_drm)
485 {
486     int i     = 0;
487     int op_id = 0;
488     unsigned int total_sleep_time  = 0;
489     int ret = 0;
490
491     Exynos_gsc_In();
492
493     if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
494         ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
495         return NULL;
496     }
497
498     if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
499         CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
500         if (!gsc) {
501             ALOGE("%s:: failed to allocate Gscaler handle", __func__);
502             return NULL;
503         }
504
505         gsc->scaler = exynos_sc_create_blend_exclusive(dev_num - HW_SCAL0, allow_drm);
506         if (!gsc->scaler) {
507             Exynos_gsc_Out();
508             delete(gsc);
509             ALOGE("%s::exynos_sc_create_blend_exclusive failed", __func__);
510             return NULL;
511         }
512         Exynos_gsc_Out();
513
514         return reinterpret_cast<void *>(gsc);
515     }
516
517     Exynos_gsc_Out();
518
519     return NULL;
520 }
521
522 int exynos_gsc_config_blend_exclusive(void *handle,
523     exynos_mpp_img *src_img, exynos_mpp_img *dst_img,
524     struct SrcBlendInfo  *srcblendinfo)
525 {
526     Exynos_gsc_In();
527
528     int ret = 0;
529     CGscaler* gsc = GetGscaler(handle);
530     if (gsc == NULL) {
531         ALOGE("%s::handle == NULL() fail", __func__);
532         return -1;
533     }
534     if (gsc->gsc_id >= HW_SCAL0) {
535         ret = exynos_sc_config_blend_exclusive(gsc->scaler,
536                                                (exynos_sc_img *)src_img,
537                                                (exynos_sc_img *)dst_img,
538                                                srcblendinfo);
539         Exynos_gsc_Out();
540         return ret;
541     }
542         Exynos_gsc_Out();
543         return ret;
544 }
545
546 int exynos_gsc_wait_frame_done_exclusive(void *handle)
547 {
548     Exynos_gsc_In();
549
550     int ret = 0;
551     CGscaler* gsc = GetGscaler(handle);
552     if (gsc == NULL) {
553         ALOGE("%s::handle == NULL() fail", __func__);
554         return -1;
555     }
556
557     if (gsc->gsc_id >= HW_SCAL0) {
558         ret = exynos_sc_wait_frame_done_exclusive(gsc->scaler);
559         Exynos_gsc_Out();
560         return ret;
561     }
562
563     if (gsc->mode == GSC_M2M_MODE)
564         ret = gsc->m_gsc_m2m_wait_frame_done(handle);
565
566     Exynos_gsc_Out();
567
568     return ret;
569 }
570
571 int exynos_gsc_stop_exclusive(void *handle)
572 {
573     Exynos_gsc_In();
574
575     int ret = 0;
576     CGscaler* gsc = GetGscaler(handle);
577     if (gsc == NULL) {
578         ALOGE("%s::handle == NULL() fail", __func__);
579         return -1;
580     }
581
582     if (gsc->gsc_id >= HW_SCAL0) {
583         ret = exynos_sc_stop_exclusive(gsc->scaler);
584         Exynos_gsc_Out();
585         return ret;
586     }
587
588     switch (gsc->mode) {
589     case GSC_M2M_MODE:
590         ret = gsc->m_gsc_m2m_stop(handle);
591         break;
592     case GSC_OUTPUT_MODE:
593         ret = gsc->m_gsc_out_stop(handle);
594         break;
595     case  GSC_CAPTURE_MODE:
596         ret = gsc->m_gsc_cap_stop(handle);
597         break;
598     default:
599         break;
600     }
601
602     Exynos_gsc_Out();
603
604     return ret;
605 }
606
607 int exynos_gsc_free_and_close(void *handle)
608 {
609     Exynos_gsc_In();
610
611     struct v4l2_requestbuffers reqbuf;
612     struct v4l2_buffer buf;
613     struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
614     int ret = 0;
615     CGscaler* gsc = GetGscaler(handle);
616     if (gsc == NULL) {
617         ALOGE("%s::handle == NULL() fail", __func__);
618         return -1;
619     }
620
621
622     if (gsc->gsc_id >= HW_SCAL0) {
623         ret = exynos_sc_free_and_close(gsc->scaler);
624         Exynos_gsc_Out();
625         return ret;
626     }
627
628     memset(&reqbuf, 0, sizeof(struct v4l2_requestbuffers));
629     if (gsc->mode == GSC_OUTPUT_MODE)
630             reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
631     else
632             reqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
633
634     reqbuf.memory = V4L2_MEMORY_DMABUF;
635     reqbuf.count  = 0;
636
637     if (exynos_v4l2_reqbufs(gsc->mdev.gsc_vd_entity->fd, &reqbuf) < 0) {
638         ALOGE("%s::request buffers failed", __func__);
639         return -1;
640     }
641
642     exynos_gsc_destroy(gsc);
643     Exynos_gsc_Out();
644
645     return 0;
646 }