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 <linux/v4l2-subdev.h>
30 
31 #include "libgscaler_obj.h"
32 #include "libgscaler_media.h"
33 
exynos_gsc_create(void)34 void *exynos_gsc_create(void)
35 {
36     CGscaler *gsc = new CGscaler(GSC_M2M_MODE);
37     if (!gsc) {
38         ALOGE("%s:: failed to allocate Gscaler handle", __func__);
39         return NULL;
40     }
41     if (gsc->m_gsc_find_and_create(gsc) == false) {
42         ALOGE("%s::m_exynos_gsc_find_and_create() fail", __func__);
43         delete gsc;
44         return NULL;
45     }
46 
47     return reinterpret_cast<void *>(gsc);
48 }
49 
exynos_gsc_create_exclusive(int dev_num,int mode,int out_mode,int allow_drm)50 void *exynos_gsc_create_exclusive(
51     int dev_num,
52     int mode,
53     int out_mode,
54     int allow_drm)
55 {
56     Exynos_gsc_In();
57 
58     if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
59         ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
60         return NULL;
61     }
62 
63     if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
64         CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
65         if (!gsc) {
66             ALOGE("%s:: failed to allocate Gscaler handle", __func__);
67             return NULL;
68         }
69 
70         gsc->scaler = exynos_sc_create_exclusive(dev_num - HW_SCAL0,
71             allow_drm);
72         if (!gsc->scaler) {
73             delete(gsc);
74             ALOGE("%s::exynos_sc_create fail", __func__);
75             return NULL;
76         }
77         Exynos_gsc_Out();
78         return reinterpret_cast<void *>(gsc);
79     }
80 
81     if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
82         ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
83         return NULL;
84     }
85 
86     CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
87     if (!gsc) {
88         ALOGE("%s:: failed to allocate Gscaler handle", __func__);
89         return NULL;
90     }
91 
92     if (mode == GSC_M2M_MODE) {
93         gsc->gsc_fd = gsc->m_gsc_m2m_create(dev_num);
94         if (gsc->gsc_fd < 0) {
95             ALOGE("%s::m_gsc_m2m_create(%i) fail", __func__, dev_num);
96             goto err;
97         }
98     } else {
99             ALOGE("%s::Unsupported Mode(%i) fail", __func__, dev_num);
100 	    goto err;
101     }
102 
103     Exynos_gsc_Out();
104 
105     return reinterpret_cast<void *>(gsc);
106 err:
107     switch (mode) {
108     case GSC_M2M_MODE:
109         gsc->m_gsc_m2m_destroy(gsc);
110         break;
111     }
112 
113     delete(gsc);
114 
115     Exynos_gsc_Out();
116 
117     return NULL;
118 }
119 
exynos_gsc_destroy(void * handle)120 void exynos_gsc_destroy(void *handle)
121 {
122     Exynos_gsc_In();
123 
124     CGscaler* gsc = GetGscaler(handle);
125     if (gsc == NULL) {
126         ALOGE("%s::handle == NULL() fail", __func__);
127         return;
128     }
129 
130     if (gsc->mode == GSC_M2M_MODE)
131         gsc->m_gsc_m2m_destroy(gsc);
132 
133     delete(gsc);
134 
135     Exynos_gsc_Out();
136 }
137 
exynos_gsc_set_csc_property(void * handle,unsigned int eq_auto,unsigned int range_full,unsigned int v4l2_colorspace)138 int exynos_gsc_set_csc_property(
139     void        *handle,
140     unsigned int eq_auto,
141     unsigned int range_full,
142     unsigned int v4l2_colorspace)
143 {
144     Exynos_gsc_In();
145 
146     CGscaler *gsc = GetGscaler(handle);
147     if (gsc == NULL) {
148         ALOGE("%s::handle == NULL() fail", __func__);
149         return -1;
150     }
151 
152     if (gsc->gsc_id >= HW_SCAL0) {
153         int ret;
154         ret = exynos_sc_csc_exclusive(gsc->scaler,
155                             range_full, v4l2_colorspace);
156         Exynos_gsc_Out();
157         return ret;
158     }
159     gsc->eq_auto = eq_auto;
160     gsc->range_full = range_full;
161     gsc->v4l2_colorspace = v4l2_colorspace;
162 
163     Exynos_gsc_Out();
164 
165     return 0;
166 }
167 
exynos_gsc_set_src_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm)168 int exynos_gsc_set_src_format(
169     void        *handle,
170     unsigned int width,
171     unsigned int height,
172     unsigned int crop_left,
173     unsigned int crop_top,
174     unsigned int crop_width,
175     unsigned int crop_height,
176     unsigned int v4l2_colorformat,
177     unsigned int cacheable,
178     unsigned int mode_drm)
179 {
180     Exynos_gsc_In();
181 
182     CGscaler *gsc = GetGscaler(handle);
183     if (gsc == NULL) {
184         ALOGE("%s::handle == NULL() fail", __func__);
185         return -1;
186     }
187     gsc->src_info.width            = width;
188     gsc->src_info.height           = height;
189     gsc->src_info.crop_left        = crop_left;
190     gsc->src_info.crop_top         = crop_top;
191     gsc->src_info.crop_width       = crop_width;
192     gsc->src_info.crop_height      = crop_height;
193     gsc->src_info.v4l2_colorformat = v4l2_colorformat;
194     gsc->src_info.cacheable        = cacheable;
195     gsc->src_info.mode_drm         = mode_drm;
196     gsc->src_info.dirty            = true;
197 
198     Exynos_gsc_Out();
199 
200     return 0;
201 }
202 
exynos_gsc_set_dst_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm)203 int exynos_gsc_set_dst_format(
204     void        *handle,
205     unsigned int width,
206     unsigned int height,
207     unsigned int crop_left,
208     unsigned int crop_top,
209     unsigned int crop_width,
210     unsigned int crop_height,
211     unsigned int v4l2_colorformat,
212     unsigned int cacheable,
213     unsigned int mode_drm)
214 {
215     Exynos_gsc_In();
216 
217     CGscaler *gsc = GetGscaler(handle);
218     if (gsc == NULL) {
219         ALOGE("%s::handle == NULL() fail", __func__);
220         return -1;
221     }
222 
223     gsc->dst_info.width            = width;
224     gsc->dst_info.height           = height;
225     gsc->dst_info.crop_left        = crop_left;
226     gsc->dst_info.crop_top         = crop_top;
227     gsc->dst_info.crop_width       = crop_width;
228     gsc->dst_info.crop_height      = crop_height;
229     gsc->dst_info.v4l2_colorformat = v4l2_colorformat;
230     gsc->dst_info.dirty            = true;
231     gsc->dst_info.cacheable        = cacheable;
232     gsc->dst_info.mode_drm         = mode_drm;
233 
234     Exynos_gsc_Out();
235 
236     return 0;
237 }
238 
exynos_gsc_set_rotation(void * handle,int rotation,int flip_horizontal,int flip_vertical)239 int exynos_gsc_set_rotation(
240     void *handle,
241     int   rotation,
242     int   flip_horizontal,
243     int   flip_vertical)
244 {
245     CGscaler *gsc = GetGscaler(handle);
246     if (gsc == NULL) {
247         ALOGE("%s::handle == NULL() fail", __func__);
248         return -1;
249     }
250 
251     int new_rotation = rotation % 360;
252 
253     if (new_rotation % 90 != 0) {
254         ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__,
255             rotation);
256         return -1;
257     }
258 
259     if(new_rotation < 0)
260         new_rotation = -new_rotation;
261 
262     gsc->dst_info.rotation        = new_rotation;
263     gsc->dst_info.flip_horizontal = flip_horizontal;
264     gsc->dst_info.flip_vertical   = flip_vertical;
265 
266     return 0;
267 }
268 
exynos_gsc_set_src_addr(void * handle,void * addr[3],int mem_type,int acquireFenceFd)269 int exynos_gsc_set_src_addr(
270     void *handle,
271     void *addr[3],
272     int mem_type,
273     int acquireFenceFd)
274 {
275     Exynos_gsc_In();
276 
277     CGscaler* gsc = GetGscaler(handle);
278     if (gsc == NULL) {
279         ALOGE("%s::handle == NULL() fail", __func__);
280         return -1;
281     }
282 
283     gsc->src_info.buf.addr[0] = addr[0];
284     gsc->src_info.buf.addr[1] = addr[1];
285     gsc->src_info.buf.addr[2] = addr[2];
286     gsc->src_info.acquireFenceFd = acquireFenceFd;
287     gsc->src_info.buf.mem_type = (enum v4l2_memory)mem_type;
288 
289     Exynos_gsc_Out();
290 
291     return 0;
292 }
293 
exynos_gsc_set_dst_addr(void * handle,void * addr[3],int mem_type,int acquireFenceFd)294 int exynos_gsc_set_dst_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->dst_info.buf.addr[0] = addr[0];
309     gsc->dst_info.buf.addr[1] = addr[1];
310     gsc->dst_info.buf.addr[2] = addr[2];
311     gsc->dst_info.acquireFenceFd = acquireFenceFd;
312     gsc->dst_info.buf.mem_type = (enum v4l2_memory)mem_type;
313 
314     Exynos_gsc_Out();
315 
316     return 0;
317 }
318 
exynos_gsc_convert(void * handle)319 int exynos_gsc_convert(void *handle)
320 {
321     Exynos_gsc_In();
322 
323     int ret    = -1;
324     CGscaler* gsc = GetGscaler(handle);
325     if (gsc == NULL) {
326         ALOGE("%s::handle == NULL() fail", __func__);
327         return ret;
328     }
329 
330     if (gsc->m_gsc_m2m_run_core(handle) < 0) {
331         ALOGE("%s::exynos_gsc_run_core fail", __func__);
332         goto done;
333     }
334 
335     if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
336         ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
337         goto done;
338     }
339 
340     if (gsc->src_info.releaseFenceFd >= 0) {
341         close(gsc->src_info.releaseFenceFd);
342         gsc->src_info.releaseFenceFd = -1;
343     }
344 
345     if (gsc->dst_info.releaseFenceFd >= 0) {
346         close(gsc->dst_info.releaseFenceFd);
347         gsc->dst_info.releaseFenceFd = -1;
348     }
349 
350     if (gsc->m_gsc_m2m_stop(handle) < 0) {
351         ALOGE("%s::m_gsc_m2m_stop", __func__);
352         goto done;
353     }
354 
355     ret = 0;
356 
357 done:
358     Exynos_gsc_Out();
359 
360     return ret;
361 }
362 
exynos_gsc_subdev_s_crop(void * handle,exynos_mpp_img __UNUSED__ * src_img,exynos_mpp_img * dst_img)363 int exynos_gsc_subdev_s_crop(void *handle,
364         exynos_mpp_img __UNUSED__ *src_img, exynos_mpp_img *dst_img)
365 {
366     struct v4l2_subdev_crop sd_crop;
367     CGscaler *gsc = GetGscaler(handle);
368     if (gsc == NULL) {
369         ALOGE("%s::handle == NULL() fail", __func__);
370         return -1;
371     }
372 
373     sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
374     sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
375     sd_crop.rect.left = dst_img->x;
376     sd_crop.rect.top = dst_img->y;
377     sd_crop.rect.width = dst_img->w;
378     sd_crop.rect.height = dst_img->h;
379 
380     return exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop);
381 }
382 
exynos_gsc_config_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)383 int exynos_gsc_config_exclusive(void *handle,
384     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
385 {
386     Exynos_gsc_In();
387 
388     int ret = 0;
389     CGscaler* gsc = GetGscaler(handle);
390     if (gsc == NULL) {
391         ALOGE("%s::handle == NULL() fail", __func__);
392         return -1;
393     }
394     if (gsc->gsc_id >= HW_SCAL0) {
395         ret = exynos_sc_config_exclusive(gsc->scaler,
396             (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
397         Exynos_gsc_Out();
398         return ret;
399     }
400 
401     switch (gsc->mode) {
402     case GSC_M2M_MODE:
403         ret = gsc->m_gsc_m2m_config(handle, src_img, dst_img);
404         break;
405     case GSC_OUTPUT_MODE:
406         ret = gsc->m_gsc_out_config(handle, src_img, dst_img);
407         break;
408     case GSC_CAPTURE_MODE:
409         ret = gsc->m_gsc_cap_config(handle, src_img, dst_img);
410         break;
411     default:
412         break;
413     }
414 
415     Exynos_gsc_Out();
416 
417     return ret;
418 }
419 
exynos_gsc_run_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)420 int exynos_gsc_run_exclusive(void *handle,
421     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
422 {
423     Exynos_gsc_In();
424 
425     int ret = 0;
426     CGscaler* gsc = GetGscaler(handle);
427     if (handle == NULL) {
428         ALOGE("%s::handle == NULL() fail", __func__);
429         return -1;
430     }
431 
432     if (gsc->gsc_id >= HW_SCAL0) {
433         ret = exynos_sc_run_exclusive(gsc->scaler,
434             (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
435         Exynos_gsc_Out();
436         return ret;
437     }
438 
439     switch (gsc->mode) {
440     case GSC_M2M_MODE:
441         ret = gsc->m_gsc_m2m_run(handle, src_img, dst_img);
442         break;
443     case GSC_OUTPUT_MODE:
444         ret = gsc->m_gsc_out_run(handle, src_img);
445         break;
446     case GSC_CAPTURE_MODE:
447         ret = gsc->m_gsc_cap_run(handle, dst_img);
448         break;
449     default:
450         break;
451     }
452 
453     Exynos_gsc_Out();
454 
455     return ret;
456 }
457 
exynos_gsc_create_blend_exclusive(int dev_num,int mode,int out_mode,int allow_drm)458 void *exynos_gsc_create_blend_exclusive(int dev_num, int mode, int out_mode,
459                                                                 int allow_drm)
460 {
461     Exynos_gsc_In();
462 
463     if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
464         ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
465         return NULL;
466     }
467 
468     if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
469         CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
470         if (!gsc) {
471             ALOGE("%s:: failed to allocate Gscaler handle", __func__);
472             return NULL;
473         }
474 
475         gsc->scaler = exynos_sc_create_blend_exclusive(dev_num - HW_SCAL0, allow_drm);
476         if (!gsc->scaler) {
477             Exynos_gsc_Out();
478             delete(gsc);
479             ALOGE("%s::exynos_sc_create_blend_exclusive failed", __func__);
480             return NULL;
481         }
482         Exynos_gsc_Out();
483 
484         return reinterpret_cast<void *>(gsc);
485     }
486 
487     Exynos_gsc_Out();
488 
489     return NULL;
490 }
491 
exynos_gsc_config_blend_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img,struct SrcBlendInfo * srcblendinfo)492 int exynos_gsc_config_blend_exclusive(void *handle,
493     exynos_mpp_img *src_img, exynos_mpp_img *dst_img,
494     struct SrcBlendInfo  *srcblendinfo)
495 {
496     Exynos_gsc_In();
497 
498     int ret = 0;
499     CGscaler* gsc = GetGscaler(handle);
500     if (gsc == NULL) {
501         ALOGE("%s::handle == NULL() fail", __func__);
502         return -1;
503     }
504     if (gsc->gsc_id >= HW_SCAL0) {
505         ret = exynos_sc_config_blend_exclusive(gsc->scaler,
506                                                (exynos_sc_img *)src_img,
507                                                (exynos_sc_img *)dst_img,
508                                                srcblendinfo);
509         Exynos_gsc_Out();
510         return ret;
511     }
512         Exynos_gsc_Out();
513         return ret;
514 }
515 
exynos_gsc_wait_frame_done_exclusive(void * handle)516 int exynos_gsc_wait_frame_done_exclusive(void *handle)
517 {
518     Exynos_gsc_In();
519 
520     int ret = 0;
521     CGscaler* gsc = GetGscaler(handle);
522     if (handle == NULL) {
523         ALOGE("%s::handle == NULL() fail", __func__);
524         return -1;
525     }
526 
527     if (gsc->gsc_id >= HW_SCAL0) {
528         ret = exynos_sc_wait_frame_done_exclusive(gsc->scaler);
529         Exynos_gsc_Out();
530         return ret;
531     }
532 
533     if (gsc->mode == GSC_M2M_MODE)
534         ret = gsc->m_gsc_m2m_wait_frame_done(handle);
535 
536     Exynos_gsc_Out();
537 
538     return ret;
539 }
540 
exynos_gsc_stop_exclusive(void * handle)541 int exynos_gsc_stop_exclusive(void *handle)
542 {
543     Exynos_gsc_In();
544 
545     int ret = 0;
546     CGscaler* gsc = GetGscaler(handle);
547     if (handle == NULL) {
548         ALOGE("%s::handle == NULL() fail", __func__);
549         return -1;
550     }
551 
552     if (gsc->gsc_id >= HW_SCAL0) {
553         ret = exynos_sc_stop_exclusive(gsc->scaler);
554         Exynos_gsc_Out();
555         return ret;
556     }
557 
558     switch (gsc->mode) {
559     case GSC_M2M_MODE:
560         ret = gsc->m_gsc_m2m_stop(handle);
561         break;
562     default:
563         break;
564     }
565 
566     Exynos_gsc_Out();
567 
568     return ret;
569 }
570 
exynos_gsc_free_and_close(void * handle)571 int exynos_gsc_free_and_close(void *handle)
572 {
573     Exynos_gsc_In();
574 
575     struct v4l2_requestbuffers reqbuf;
576     int ret = 0;
577     CGscaler* gsc = GetGscaler(handle);
578     if (gsc == NULL) {
579         ALOGE("%s::handle == NULL() fail", __func__);
580         return -1;
581     }
582 
583 
584     if (gsc->gsc_id >= HW_SCAL0) {
585         ret = exynos_sc_free_and_close(gsc->scaler);
586         Exynos_gsc_Out();
587         return ret;
588     }
589 
590     memset(&reqbuf, 0, sizeof(struct v4l2_requestbuffers));
591     if (gsc->mode == GSC_OUTPUT_MODE)
592 	    reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
593     else
594 	    reqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
595 
596     reqbuf.memory = V4L2_MEMORY_DMABUF;
597     reqbuf.count  = 0;
598 
599     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
600         ALOGE("%s::request buffers failed", __func__);
601         return -1;
602     }
603 
604     exynos_gsc_destroy(gsc);
605     Exynos_gsc_Out();
606 
607     return 0;
608 }
609