• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_obj.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 <cstdio>
30 #include <cerrno>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <linux/v4l2-mediabus.h>
35 
36 #include <exynos_scaler.h>
37 
38 #include "libgscaler_media.h"
39 #include "libgscaler_obj.h"
40 
41 // Definitions of values that are not present in enum v4l2_mbus_pixelcode
42 #define V4L2_MBUS_FMT_XRGB8888_4X8_LE 0x1009
43 #define V4L2_MBUS_FMT_YUV8_1X24       0x2014
44 
45 #define V4L2_CID_EXYNOS_BASE            (V4L2_CTRL_CLASS_USER | 0x2000)
46 #define V4L2_CID_CSC_EQ_MODE            (V4L2_CID_EXYNOS_BASE + 100)
47 #define V4L2_CID_CSC_EQ                 (V4L2_CID_EXYNOS_BASE + 101)
48 #define V4L2_CID_CSC_RANGE              (V4L2_CID_EXYNOS_BASE + 102)
49 #define V4L2_CID_CONTENT_PROTECTION     (V4L2_CID_EXYNOS_BASE + 201)
50 #define V4L2_CID_CACHEABLE              (V4L2_CID_EXYNOS_BASE + 10)
51 
52 #define V4L2_PIX_FMT_NV12N              v4l2_fourcc('N', 'N', '1', '2')
53 #define V4L2_PIX_FMT_NV12NT             v4l2_fourcc('T', 'N', '1', '2')
54 #define V4L2_PIX_FMT_YUV420N            v4l2_fourcc('Y', 'N', '1', '2')
55 #define V4L2_PIX_FMT_NV12N_10B          v4l2_fourcc('B', 'N', '1', '2')
56 
57 #define V4L2_BUF_FLAG_USE_SYNC          0x00008000
58 
v4l2_pixfmt_to_yuvinfo(unsigned int v4l2_pixel_format,unsigned int * bpp,unsigned int * planes)59 static int v4l2_pixfmt_to_yuvinfo(unsigned int v4l2_pixel_format, unsigned int * bpp, unsigned int * planes)
60 {
61     switch (v4l2_pixel_format) {
62     case V4L2_PIX_FMT_NV12:
63     case V4L2_PIX_FMT_NV21:
64     case V4L2_PIX_FMT_NV12N:
65     case V4L2_PIX_FMT_NV12NT:
66     case V4L2_PIX_FMT_YUV420:
67     case V4L2_PIX_FMT_YVU420:
68     case V4L2_PIX_FMT_YUV420N:
69         *bpp    = 12;
70         *planes = 1;
71         break;
72 
73     case V4L2_PIX_FMT_NV12M:
74     case V4L2_PIX_FMT_NV21M:
75     case V4L2_PIX_FMT_NV12MT:
76     case V4L2_PIX_FMT_NV12MT_16X16:
77         *bpp    = 12;
78         *planes = 2;
79         break;
80 
81     case V4L2_PIX_FMT_YUV420M:
82     case V4L2_PIX_FMT_YVU420M:
83         *bpp    = 12;
84         *planes = 3;
85         break;
86 
87     case V4L2_PIX_FMT_YUYV:
88     case V4L2_PIX_FMT_YVYU:
89     case V4L2_PIX_FMT_UYVY:
90     case V4L2_PIX_FMT_VYUY:
91     case V4L2_PIX_FMT_NV16:
92     case V4L2_PIX_FMT_NV61:
93         *bpp    = 16;
94         *planes = 1;
95         break;
96         break;
97     default:
98         return -1;
99         break;
100     }
101 
102     return 0;
103 }
104 
gsc_get_yuv_bpp(unsigned int v4l2_pixel_format)105 static int gsc_get_yuv_bpp(unsigned int v4l2_pixel_format)
106 {
107     unsigned int bpp, planes;
108 
109     if (v4l2_pixfmt_to_yuvinfo(v4l2_pixel_format, &bpp, &planes) < 0)
110         bpp = -1;
111 
112     return bpp;
113 }
114 
gsc_get_yuv_planes(unsigned int v4l2_pixel_format)115 static int gsc_get_yuv_planes(unsigned int v4l2_pixel_format)
116 {
117     unsigned int bpp, planes;
118 
119     if (v4l2_pixfmt_to_yuvinfo(v4l2_pixel_format, &bpp, &planes) < 0)
120         planes = -1;
121 
122     return planes;
123 }
124 
125 #define VIDEODEV_MAX 255
exynos_v4l2_open_devname(const char * devname,int oflag,...)126 static int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
127 {
128     bool found = false;
129     int fd = -1;
130     struct stat s;
131     va_list ap;
132     FILE *stream_fd;
133     char filename[64], name[64];
134     int i = 0;
135 
136     do {
137         if (i > VIDEODEV_MAX)
138             break;
139 
140         /* video device node */
141         snprintf(filename, sizeof(filename), "/dev/video%d", i);
142 
143         /* if the node is video device */
144         if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
145                 ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
146             ALOGD("try node: %s", filename);
147             /* open sysfs entry */
148             snprintf(filename, sizeof(filename), "/sys/class/video4linux/video%d/name", i);
149             if (S_ISLNK(s.st_mode)) {
150                 ALOGE("symbolic link detected");
151                 return -1;
152             }
153             stream_fd = fopen(filename, "r");
154             if (stream_fd == NULL) {
155                 ALOGE("failed to open sysfs entry for videodev (%d - %s)", errno, strerror(errno));
156                 i++;
157                 continue;   /* try next */
158             }
159 
160             /* read sysfs entry for device name */
161             char *p = fgets(name, sizeof(name), stream_fd);
162             fclose(stream_fd);
163 
164             /* check read size */
165             if (p == NULL) {
166                 ALOGE("failed to read sysfs entry for videodev");
167             } else {
168                 /* matched */
169                 if (strncmp(name, devname, strlen(devname)) == 0) {
170                     ALOGI("node found for device %s: /dev/video%d", devname, i);
171                     found = true;
172                     break;
173                 }
174             }
175         }
176         i++;
177     } while (found == false);
178 
179     if (found) {
180         snprintf(filename, sizeof(filename), "/dev/video%d", i);
181         va_start(ap, oflag);
182         fd = open(filename, oflag, ap);
183         va_end(ap);
184 
185         if (fd > 0)
186             ALOGI("open video device %s", filename);
187         else
188             ALOGE("failed to open video device %s", filename);
189     } else {
190         ALOGE("no video device found");
191     }
192 
193     return fd;
194 }
195 
m_gsc_m2m_create(int dev)196 int CGscaler::m_gsc_m2m_create(int dev)
197 {
198     Exynos_gsc_In();
199 
200     int          fd = 0;
201     int          video_node_num;
202     char         node[32];
203 
204     switch(dev) {
205     case 0:
206         video_node_num = NODE_NUM_GSC_0;
207         break;
208     case 1:
209         video_node_num = NODE_NUM_GSC_1;
210         break;
211 #ifndef USES_ONLY_GSC0_GSC1
212     case 2:
213         video_node_num = NODE_NUM_GSC_2;
214         break;
215     case 3:
216         video_node_num = NODE_NUM_GSC_3;
217         break;
218 #endif
219     default:
220         ALOGE("%s::unexpected dev(%d) fail", __func__, dev);
221         return -1;
222         break;
223     }
224 
225     snprintf(node, sizeof(node), "%s%d", PFX_NODE_GSC, video_node_num);
226     fd = open(node, O_RDWR);
227     if (fd < 0) {
228         ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
229         return -1;
230     }
231 
232     Exynos_gsc_Out();
233 
234     return fd;
235 }
236 
m_gsc_find_and_create(void * handle)237 bool CGscaler::m_gsc_find_and_create(void *handle)
238 {
239     Exynos_gsc_In();
240 
241     int          i                 = 0;
242     bool         flag_find_new_gsc = false;
243     unsigned int total_sleep_time  = 0;
244     CGscaler* gsc = GetGscaler(handle);
245     if (gsc == NULL) {
246         ALOGE("%s::handle == NULL() fail", __func__);
247         return false;
248     }
249 
250     do {
251         for (i = 0; i < NUM_OF_GSC_HW; i++) {
252 #ifndef USES_ONLY_GSC0_GSC1
253             if (i == 0 || i == 3)
254 #else
255             if (i == 0)
256 #endif
257                 continue;
258 
259             gsc->gsc_id = i;
260             gsc->gsc_fd = gsc->m_gsc_m2m_create(i);
261             if (gsc->gsc_fd < 0) {
262                 gsc->gsc_fd = 0;
263                 continue;
264             }
265 
266             flag_find_new_gsc = true;
267             break;
268         }
269 
270         if (flag_find_new_gsc == false) {
271             usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
272             total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
273             ALOGV("%s::waiting for the gscaler availability", __func__);
274         }
275 
276     } while(flag_find_new_gsc == false
277             && total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
278 
279     if (flag_find_new_gsc == false)
280         ALOGE("%s::we don't have any available gsc.. fail", __func__);
281 
282     Exynos_gsc_Out();
283 
284     return flag_find_new_gsc;
285 }
286 
m_gsc_m2m_destroy(void * handle)287 bool CGscaler::m_gsc_m2m_destroy(void *handle)
288 {
289     Exynos_gsc_In();
290 
291     CGscaler* gsc = GetGscaler(handle);
292     if (gsc == NULL) {
293         ALOGE("%s::handle == NULL() fail", __func__);
294         return false;
295     }
296 
297     /*
298      * just in case, we call stop here because we cannot afford to leave
299      * secure side protection on if things failed.
300      */
301     gsc->m_gsc_m2m_stop(handle);
302 
303     if (gsc->gsc_id >= HW_SCAL0) {
304         bool ret = exynos_sc_free_and_close(gsc->scaler);
305         Exynos_gsc_Out();
306         return ret;
307     }
308 
309     if (0 < gsc->gsc_fd)
310         close(gsc->gsc_fd);
311     gsc->gsc_fd = 0;
312 
313     Exynos_gsc_Out();
314 
315     return true;
316 }
317 
m_gsc_m2m_stop(void * handle)318 int CGscaler::m_gsc_m2m_stop(void *handle)
319 {
320     Exynos_gsc_In();
321 
322     struct v4l2_requestbuffers req_buf;
323     int ret = 0;
324     CGscaler* gsc = GetGscaler(handle);
325     if (gsc == NULL) {
326         ALOGE("%s::handle == NULL() fail", __func__);
327         return -1;
328     }
329 
330     if (!gsc->src_info.stream_on && !gsc->dst_info.stream_on) {
331         /* wasn't streaming, return success */
332         return 0;
333     } else if (gsc->src_info.stream_on != gsc->dst_info.stream_on) {
334         ALOGE("%s: invalid state, queue stream state doesn't match \
335                 (%d != %d)", __func__, gsc->src_info.stream_on,
336                 gsc->dst_info.stream_on);
337         ret = -1;
338     }
339 
340     /*
341      * we need to plow forward on errors below to make sure that if we had
342      * turned on content protection on secure side, we turn it off.
343      *
344      * also, if we only failed to turn on one of the streams, we'll turn
345      * the other one off correctly.
346      */
347     if (gsc->src_info.stream_on == true) {
348         if (ioctl(gsc->gsc_fd, VIDIOC_STREAMOFF, &gsc->src_info.buf.buf_type) < 0) {
349             ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
350             ret = -1;
351         }
352         gsc->src_info.stream_on = false;
353     }
354 
355     if (gsc->dst_info.stream_on == true) {
356         if (ioctl(gsc->gsc_fd, VIDIOC_STREAMOFF, &gsc->dst_info.buf.buf_type) < 0) {
357             ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
358             ret = -1;
359         }
360         gsc->dst_info.stream_on = false;
361     }
362 
363     /* Secure DRM support by GScaler is removed out */
364 
365     struct v4l2_control ctrl;
366 
367     ctrl.id = V4L2_CID_CONTENT_PROTECTION;
368     ctrl.value = 0;
369     if (ioctl(gsc->gsc_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
370         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
371               __func__);
372         ret = -1;
373     }
374 
375     /* src: clear_buf */
376     req_buf.count  = 0;
377     req_buf.type   = gsc->src_info.buf.buf_type;
378     req_buf.memory = gsc->src_info.buf.mem_type;
379     if (ioctl(gsc->gsc_fd, VIDIOC_REQBUFS, &req_buf) < 0) {
380         ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
381         ret = -1;
382     }
383 
384     /* dst: clear_buf */
385     req_buf.count  = 0;
386     req_buf.type   = gsc->dst_info.buf.buf_type;
387     req_buf.memory = gsc->dst_info.buf.mem_type;;
388     if (ioctl(gsc->gsc_fd, VIDIOC_REQBUFS, &req_buf) < 0) {
389         ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
390         ret = -1;
391     }
392 
393     Exynos_gsc_Out();
394 
395     return ret;
396 }
397 
m_gsc_m2m_run_core(void * handle)398 int CGscaler::m_gsc_m2m_run_core(void *handle)
399 {
400     Exynos_gsc_In();
401 
402     unsigned int rotate, hflip, vflip;
403     bool is_dirty;
404     bool is_drm;
405     CGscaler* gsc = GetGscaler(handle);
406     if (gsc == NULL) {
407         ALOGE("%s::handle == NULL() fail", __func__);
408         return -1;
409     }
410 
411     is_dirty = gsc->src_info.dirty || gsc->dst_info.dirty;
412     is_drm = gsc->src_info.mode_drm;
413 
414     if (is_dirty && (gsc->src_info.mode_drm != gsc->dst_info.mode_drm)) {
415         ALOGE("%s: drm mode mismatch between src and dst, \
416                 gsc%d (s=%d d=%d)", __func__, gsc->gsc_id,
417                 gsc->src_info.mode_drm, gsc->dst_info.mode_drm);
418         return -1;
419     } else if (is_drm && !gsc->allow_drm) {
420         ALOGE("%s: drm mode is not supported on gsc%d", __func__,
421               gsc->gsc_id);
422         return -1;
423     }
424 
425     CGscaler::rotateValueHAL2GSC(gsc->dst_img.rot, &rotate, &hflip, &vflip);
426 
427     if (CGscaler::m_gsc_check_src_size(&gsc->src_info.width,
428             &gsc->src_info.height, &gsc->src_info.crop_left,
429             &gsc->src_info.crop_top, &gsc->src_info.crop_width,
430             &gsc->src_info.crop_height, gsc->src_info.v4l2_colorformat,
431             (rotate == 90 || rotate == 270)) == false) {
432         ALOGE("%s::m_gsc_check_src_size() fail", __func__);
433         return -1;
434     }
435 
436     if (CGscaler::m_gsc_check_dst_size(&gsc->dst_info.width,
437             &gsc->dst_info.height, &gsc->dst_info.crop_left,
438             &gsc->dst_info.crop_top, &gsc->dst_info.crop_width,
439             &gsc->dst_info.crop_height, gsc->dst_info.v4l2_colorformat,
440             gsc->dst_info.rotation) == false) {
441         ALOGE("%s::m_gsc_check_dst_size() fail", __func__);
442         return -1;
443     }
444 
445     /* dequeue buffers from previous work if necessary */
446     if (gsc->src_info.stream_on == true) {
447         if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
448             ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__);
449             return -1;
450         }
451     }
452 
453     /*
454      * need to set the content protection flag before doing reqbufs
455      * in set_format
456      */
457     if (is_dirty && gsc->allow_drm && is_drm) {
458         struct v4l2_control ctrl;
459 
460         ctrl.id = V4L2_CID_CONTENT_PROTECTION;
461         ctrl.value = is_drm;
462         if (ioctl(gsc->gsc_fd,VIDIOC_S_CTRL, &ctrl) < 0) {
463             ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
464             return -1;
465         }
466     }
467 
468     /*
469      * from this point on, we have to ensure to call stop to clean up
470      * whatever state we have set.
471      */
472 
473     if (gsc->src_info.dirty) {
474         if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->src_info) == false) {
475             ALOGE("%s::m_gsc_set_format(src) fail", __func__);
476             goto done;
477         }
478         gsc->src_info.dirty = false;
479     }
480 
481     if (gsc->dst_info.dirty) {
482         if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->dst_info) == false) {
483             ALOGE("%s::m_gsc_set_format(dst) fail", __func__);
484             goto done;
485         }
486         gsc->dst_info.dirty = false;
487     }
488 
489     /*
490      * set up csc equation property
491      */
492     if (is_dirty) {
493         struct v4l2_control ctrl;
494 
495         ctrl.id = V4L2_CID_CSC_EQ_MODE;
496         ctrl.value = gsc->eq_auto;
497         if (ioctl(gsc->gsc_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
498             ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
499             return -1;
500         }
501 
502         ctrl.id = V4L2_CID_CSC_EQ;
503         ctrl.value = gsc->v4l2_colorspace;
504         if (ioctl(gsc->gsc_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
505             ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
506             return -1;
507         }
508 
509         ctrl.id = V4L2_CID_CSC_RANGE;
510         ctrl.value = gsc->range_full;
511         if (ioctl(gsc->gsc_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
512             ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
513             return -1;
514         }
515     }
516 
517     /* if we are enabling drm, make sure to enable hw protection.
518      * Need to do this before queuing buffers so that the mmu is reserved
519      * and power domain is kept on.
520      */
521     /* Secure DRM upport by GScaler is removed out */
522 
523     if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->src_info) == false) {
524         ALOGE("%s::m_gsc_set_addr(src) fail", __func__);
525         goto done;
526     }
527 
528     if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->dst_info) == false) {
529         ALOGE("%s::m_gsc_set_addr(dst) fail", __func__);
530         goto done;
531     }
532 
533     if (gsc->src_info.stream_on == false) {
534         if (ioctl(gsc->gsc_fd, VIDIOC_STREAMON, &gsc->src_info.buf.buf_type) < 0) {
535             ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
536             goto done;
537         }
538         gsc->src_info.stream_on = true;
539     }
540 
541     if (gsc->dst_info.stream_on == false) {
542         if (ioctl(gsc->gsc_fd, VIDIOC_STREAMON, &gsc->dst_info.buf.buf_type) < 0) {
543             ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
544             goto done;
545         }
546         gsc->dst_info.stream_on = true;
547     }
548 
549     Exynos_gsc_Out();
550 
551     return 0;
552 
553 done:
554     gsc->m_gsc_m2m_stop(handle);
555     return -1;
556 }
557 
m_gsc_check_src_size(unsigned int * w,unsigned int * h,unsigned int __UNUSED__ * crop_x,unsigned int __UNUSED__ * crop_y,unsigned int __UNUSED__ * crop_w,unsigned int __UNUSED__ * crop_h,int v4l2_colorformat,bool rotation)558 bool CGscaler::m_gsc_check_src_size(
559     unsigned int *w,      unsigned int *h,
560     unsigned int __UNUSED__ *crop_x, unsigned int __UNUSED__ *crop_y,
561     unsigned int __UNUSED__ *crop_w, unsigned int __UNUSED__ *crop_h,
562     int v4l2_colorformat, bool rotation)
563 {
564     unsigned int minWidth, minHeight, shift = 0;
565     if (v4l2_colorformat == V4L2_PIX_FMT_RGB32 || v4l2_colorformat == V4L2_PIX_FMT_RGB565)
566         shift = 1;
567     if (rotation) {
568         minWidth = GSC_MIN_SRC_H_SIZE >> shift;
569         minHeight = GSC_MIN_SRC_W_SIZE >> shift;
570     } else {
571         minWidth = GSC_MIN_SRC_W_SIZE >> shift;
572         minHeight = GSC_MIN_SRC_H_SIZE >> shift;
573     }
574 
575     if (*w < minWidth || *h < minHeight) {
576         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
577             __func__, GSC_MIN_SRC_W_SIZE, *w, GSC_MIN_SRC_H_SIZE, *h);
578         return false;
579     }
580 
581     if (*crop_w < minWidth || *crop_h < minHeight) {
582         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
583             __func__, GSC_MIN_SRC_W_SIZE,* crop_w, GSC_MIN_SRC_H_SIZE, *crop_h);
584         return false;
585     }
586 
587     return true;
588 }
589 
m_gsc_check_dst_size(unsigned int * w,unsigned int * h,unsigned int __UNUSED__ * crop_x,unsigned int __UNUSED__ * crop_y,unsigned int __UNUSED__ * crop_w,unsigned int __UNUSED__ * crop_h,int __UNUSED__ v4l2_colorformat,int __UNUSED__ rotation)590 bool CGscaler::m_gsc_check_dst_size(
591     unsigned int *w,      unsigned int *h,
592     unsigned int __UNUSED__ *crop_x, unsigned int __UNUSED__ *crop_y,
593     unsigned int __UNUSED__ *crop_w, unsigned int __UNUSED__ *crop_h,
594     int __UNUSED__ v4l2_colorformat, int __UNUSED__ rotation)
595 {
596     if (*w < GSC_MIN_DST_W_SIZE || *h < GSC_MIN_DST_H_SIZE) {
597         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
598             __func__, GSC_MIN_DST_W_SIZE, *w, GSC_MIN_DST_H_SIZE, *h);
599         return false;
600     }
601 
602     if (*crop_w < GSC_MIN_DST_W_SIZE || *crop_h < GSC_MIN_DST_H_SIZE) {
603         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
604             __func__, GSC_MIN_DST_W_SIZE,* crop_w, GSC_MIN_DST_H_SIZE, *crop_h);
605         return false;
606     }
607 
608     return true;
609 }
610 
611 
m_gsc_multiple_of_n(int number,int N)612 int CGscaler::m_gsc_multiple_of_n(int number, int N)
613 {
614     int result = number;
615     switch (N) {
616     case 1:
617     case 2:
618     case 4:
619     case 8:
620     case 16:
621     case 32:
622     case 64:
623     case 128:
624     case 256:
625         result = (number - (number & (N-1)));
626         break;
627     default:
628         result = number - (number % N);
629         break;
630     }
631     return result;
632 }
633 
m_gsc_m2m_wait_frame_done(void * handle)634 int CGscaler::m_gsc_m2m_wait_frame_done(void *handle)
635 {
636     Exynos_gsc_In();
637 
638     CGscaler* gsc = GetGscaler(handle);
639     if (gsc == NULL) {
640         ALOGE("%s::handle == NULL() fail", __func__);
641         return -1;
642     }
643 
644     if ((gsc->src_info.stream_on == false) ||
645         (gsc->dst_info.stream_on == false)) {
646         ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
647         return -1;
648     }
649 
650     if (gsc->src_info.buf.buffer_queued) {
651         if (ioctl(gsc->gsc_fd, VIDIOC_DQBUF, &gsc->src_info.buf.buffer) < 0) {
652             ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
653             return -1;
654         }
655         gsc->src_info.buf.buffer_queued = false;
656     }
657 
658     if (gsc->dst_info.buf.buffer_queued) {
659         if (ioctl(gsc->gsc_fd, VIDIOC_DQBUF, &gsc->dst_info.buf.buffer) < 0) {
660             ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
661             return -1;
662         }
663         gsc->dst_info.buf.buffer_queued = false;
664     }
665 
666     Exynos_gsc_Out();
667 
668     return 0;
669 }
670 
m_gsc_set_format(int fd,GscInfo * info)671 bool CGscaler::m_gsc_set_format(int fd, GscInfo *info)
672 {
673     Exynos_gsc_In();
674 
675     struct v4l2_requestbuffers req_buf;
676     int                        plane_count;
677 
678     plane_count = m_gsc_get_plane_count(info->v4l2_colorformat);
679     if (plane_count < 0) {
680         ALOGE("%s::not supported v4l2_colorformat", __func__);
681         return false;
682     }
683 
684     struct v4l2_control ctrl;
685 
686     ctrl.id = V4L2_CID_ROTATE;
687     ctrl.value = info->rotation;
688     if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
689         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
690         return false;
691     }
692 
693     ctrl.id = V4L2_CID_VFLIP;
694     ctrl.value = info->flip_horizontal;
695     if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
696         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__);
697         return false;
698     }
699 
700     ctrl.id = V4L2_CID_HFLIP;
701     ctrl.value = info->flip_vertical;
702     if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
703         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
704         return false;
705     }
706 
707     info->format.type = info->buf.buf_type;
708     info->format.fmt.pix_mp.width       = info->width;
709     info->format.fmt.pix_mp.height      = info->height;
710     info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
711     info->format.fmt.pix_mp.field       = V4L2_FIELD_ANY;
712     info->format.fmt.pix_mp.num_planes  = plane_count;
713 
714     if (ioctl(fd, VIDIOC_S_FMT, &info->format) < 0) {
715         ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
716         return false;
717     }
718 
719     info->crop.type     = info->buf.buf_type;
720     info->crop.c.left   = info->crop_left;
721     info->crop.c.top    = info->crop_top;
722     info->crop.c.width  = info->crop_width;
723     info->crop.c.height = info->crop_height;
724 
725     if (ioctl(fd, VIDIOC_S_CROP, &info->crop) < 0) {
726         ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
727         return false;
728     }
729 
730     ctrl.id = V4L2_CID_CACHEABLE;
731     ctrl.value = info->cacheable;
732     if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
733         ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
734         return false;
735     }
736 
737     req_buf.count  = 1;
738     req_buf.type   = info->buf.buf_type;
739     req_buf.memory = info->buf.mem_type;
740     if (ioctl(fd, VIDIOC_REQBUFS, &req_buf) < 0) {
741         ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
742         return false;
743     }
744 
745     Exynos_gsc_Out();
746 
747     return true;
748 }
749 
m_gsc_get_plane_count(int v4l_pixel_format)750 unsigned int CGscaler::m_gsc_get_plane_count(int v4l_pixel_format)
751 {
752     int plane_count = 0;
753 
754     switch (v4l_pixel_format) {
755     case V4L2_PIX_FMT_RGB32:
756     case V4L2_PIX_FMT_BGR32:
757     case V4L2_PIX_FMT_RGB24:
758     case V4L2_PIX_FMT_RGB565:
759     case V4L2_PIX_FMT_RGB555X:
760     case V4L2_PIX_FMT_RGB444:
761     case V4L2_PIX_FMT_YUYV:
762     case V4L2_PIX_FMT_UYVY:
763     case V4L2_PIX_FMT_NV16:
764     case V4L2_PIX_FMT_NV61:
765     case V4L2_PIX_FMT_YVU420:
766     case V4L2_PIX_FMT_YUV420:
767     case V4L2_PIX_FMT_NV12:
768     case V4L2_PIX_FMT_NV21:
769     case V4L2_PIX_FMT_YUV422P:
770         plane_count = 1;
771         break;
772     case V4L2_PIX_FMT_NV12M:
773     case V4L2_PIX_FMT_NV12MT_16X16:
774     case V4L2_PIX_FMT_NV21M:
775         plane_count = 2;
776         break;
777     case V4L2_PIX_FMT_YVU420M:
778     case V4L2_PIX_FMT_YUV420M:
779         plane_count = 3;
780         break;
781     default:
782         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
783              __func__, v4l_pixel_format);
784         plane_count = -1;
785         break;
786     }
787 
788     return plane_count;
789 }
790 
m_gsc_set_addr(int fd,GscInfo * info)791 bool CGscaler::m_gsc_set_addr(int fd, GscInfo *info)
792 {
793     unsigned int i;
794     unsigned int plane_size[NUM_OF_GSC_PLANES];
795 
796     CGscaler::m_gsc_get_plane_size(plane_size, info->width,
797                          info->height, info->v4l2_colorformat);
798 
799     info->buf.buffer.index    = 0;
800     info->buf.buffer.flags    = V4L2_BUF_FLAG_USE_SYNC;
801     info->buf.buffer.type     = info->buf.buf_type;
802     info->buf.buffer.memory   = info->buf.mem_type;
803     info->buf.buffer.m.planes = info->buf.planes;
804     info->buf.buffer.length   = info->format.fmt.pix_mp.num_planes;
805     info->buf.buffer.reserved = info->acquireFenceFd;
806 
807     for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
808         if (info->buf.buffer.memory == V4L2_MEMORY_DMABUF)
809             info->buf.buffer.m.planes[i].m.fd = (long)info->buf.addr[i];
810         else
811             info->buf.buffer.m.planes[i].m.userptr =
812                 (unsigned long)info->buf.addr[i];
813         info->buf.buffer.m.planes[i].length    = plane_size[i];
814         info->buf.buffer.m.planes[i].bytesused = 0;
815     }
816 
817     if (ioctl(fd, VIDIOC_QBUF, &info->buf.buffer) < 0) {
818         ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
819         return false;
820     }
821     info->buf.buffer_queued = true;
822 
823     info->releaseFenceFd = info->buf.buffer.reserved;
824 
825     return true;
826 }
827 
m_gsc_get_plane_size(unsigned int * plane_size,unsigned int width,unsigned int height,int v4l_pixel_format)828 unsigned int CGscaler::m_gsc_get_plane_size(
829     unsigned int *plane_size,
830     unsigned int  width,
831     unsigned int  height,
832     int           v4l_pixel_format)
833 {
834     switch (v4l_pixel_format) {
835     /* 1 plane */
836     case V4L2_PIX_FMT_RGB32:
837     case V4L2_PIX_FMT_BGR32:
838         plane_size[0] = width * height * 4;
839         plane_size[1] = 0;
840         plane_size[2] = 0;
841         break;
842     case V4L2_PIX_FMT_RGB24:
843         plane_size[0] = width * height * 3;
844         plane_size[1] = 0;
845         plane_size[2] = 0;
846         break;
847     case V4L2_PIX_FMT_RGB565:
848     case V4L2_PIX_FMT_RGB555X:
849     case V4L2_PIX_FMT_RGB444:
850     case V4L2_PIX_FMT_YUYV:
851     case V4L2_PIX_FMT_UYVY:
852         plane_size[0] = width * height * 2;
853         plane_size[1] = 0;
854         plane_size[2] = 0;
855         break;
856     /* 2 planes */
857     case V4L2_PIX_FMT_NV12M:
858     case V4L2_PIX_FMT_NV21M:
859         plane_size[0] = width * height;
860         plane_size[1] = width * (height / 2);
861         plane_size[2] = 0;
862         break;
863     case V4L2_PIX_FMT_NV12:
864     case V4L2_PIX_FMT_NV21:
865         plane_size[0] = width * height * 3 / 2;
866         plane_size[1] = 0;
867         plane_size[2] = 0;
868 	break;
869     case V4L2_PIX_FMT_NV16:
870     case V4L2_PIX_FMT_NV61:
871     case V4L2_PIX_FMT_YUV422P:
872         plane_size[0] = width * height * 2;
873         plane_size[1] = 0;
874         plane_size[2] = 0;
875         break;
876     case V4L2_PIX_FMT_NV12MT_16X16:
877         plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
878         plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
879         plane_size[2] = 0;
880         break;
881     /* 3 planes */
882     case V4L2_PIX_FMT_YUV420M:
883         plane_size[0] = width * height;
884         plane_size[1] = (width / 2) * (height / 2);
885         plane_size[2] = (width / 2) * (height / 2);
886         break;
887     case V4L2_PIX_FMT_YVU420:
888         plane_size[0] = ALIGN(width, 16) * height + ALIGN(width / 2, 16) * height;
889         plane_size[1] = 0;
890         plane_size[2] = 0;
891         break;
892     case V4L2_PIX_FMT_YUV420:
893         plane_size[0] = width * height * 3 / 2;
894         plane_size[1] = 0;
895         plane_size[2] = 0;
896         break;
897     case V4L2_PIX_FMT_YVU420M:
898         plane_size[0] = ALIGN(width, 16) * height;
899         plane_size[1] = ALIGN(width / 2, 16) * (height / 2);
900         plane_size[2] = plane_size[1];
901         break;
902     default:
903         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
904              __func__, v4l_pixel_format);
905         return -1;
906     }
907 
908     return 0;
909 }
910 
m_gsc_m2m_config(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)911 int CGscaler::m_gsc_m2m_config(void *handle,
912     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
913 {
914     Exynos_gsc_In();
915 
916     int32_t      src_color_space;
917     int32_t      dst_color_space;
918     int ret;
919     unsigned int rotate;
920     unsigned int hflip;
921     unsigned int vflip;
922     CGscaler* gsc = GetGscaler(handle);
923     if (gsc == NULL) {
924         ALOGE("%s::handle == NULL() fail", __func__);
925         return -1;
926     }
927 
928     if ((src_img->drmMode && !gsc->allow_drm) ||
929         (src_img->drmMode != dst_img->drmMode)) {
930         ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
931               __func__, gsc->gsc_id, src_img->drmMode, dst_img->drmMode);
932         return -1;
933     }
934 
935     src_color_space = hal_pixfmt_to_v4l2(src_img->format);
936     dst_color_space = hal_pixfmt_to_v4l2(dst_img->format);
937     CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
938     exynos_gsc_set_rotation(gsc, rotate, hflip, vflip);
939 
940     ret = exynos_gsc_set_src_format(gsc,  src_img->fw, src_img->fh,
941           src_img->x, src_img->y, src_img->w, src_img->h,
942           src_color_space, src_img->cacheable, src_img->drmMode);
943     if (ret < 0) {
944         ALOGE("%s: fail: exynos_gsc_set_src_format \
945             [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
946             __func__, src_img->fw, src_img->fh, src_img->x, src_img->y,
947             src_img->w, src_img->h, src_color_space, src_img->rot);
948         return -1;
949     }
950 
951     ret = exynos_gsc_set_dst_format(gsc, dst_img->fw, dst_img->fh,
952           dst_img->x, dst_img->y, dst_img->w, dst_img->h,
953           dst_color_space, dst_img->cacheable, dst_img->drmMode);
954     if (ret < 0) {
955         ALOGE("%s: fail: exynos_gsc_set_dst_format \
956             [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
957             __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y,
958             dst_img->w, dst_img->h, src_color_space, dst_img->rot);
959         return -1;
960     }
961 
962     Exynos_gsc_Out();
963 
964     return 0;
965 }
966 
m_gsc_out_config(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)967 int CGscaler::m_gsc_out_config(void *handle,
968     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
969 {
970     Exynos_gsc_In();
971 
972     struct v4l2_format  fmt;
973     struct v4l2_crop    crop;
974     struct v4l2_requestbuffers reqbuf;
975     struct v4l2_subdev_format sd_fmt;
976     struct v4l2_subdev_crop   sd_crop;
977     unsigned int rotate;
978     unsigned int hflip;
979     unsigned int vflip;
980     bool rgb;
981 
982     int32_t      src_color_space;
983     int32_t      dst_color_space;
984     int32_t      src_planes;
985 
986     CGscaler* gsc = GetGscaler(handle);
987     if (gsc == NULL) {
988         ALOGE("%s::handle == NULL() fail", __func__);
989         return -1;
990     }
991 
992     if (gsc->src_info.stream_on != false) {
993         ALOGE("Error: Src is already streamed on !!!!");
994         return -1;
995     }
996 
997     memcpy(&gsc->src_img, src_img, sizeof(exynos_mpp_img));
998     memcpy(&gsc->dst_img, dst_img, sizeof(exynos_mpp_img));
999     src_color_space = hal_pixfmt_to_v4l2(src_img->format);
1000     dst_color_space = hal_pixfmt_to_v4l2(dst_img->format);
1001     src_planes = m_gsc_get_plane_count(src_color_space);
1002     src_planes = (src_planes == -1) ? 1 : src_planes;
1003     rgb = gsc_get_yuv_planes(dst_color_space) == -1;
1004     CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1005 
1006     if (CGscaler::m_gsc_check_src_size(&gsc->src_img.fw,
1007             &gsc->src_img.fh, &gsc->src_img.x, &gsc->src_img.y,
1008             &gsc->src_img.w, &gsc->src_img.h, src_color_space,
1009             (rotate == 90 || rotate == 270)) == false) {
1010             ALOGE("%s::m_gsc_check_src_size() fail", __func__);
1011             return -1;
1012     }
1013 
1014     /*set: src v4l2_buffer*/
1015     gsc->src_info.buf.buf_idx = 0;
1016     gsc->src_info.qbuf_cnt = 0;
1017     /* set format: src pad of GSC sub-dev*/
1018     sd_fmt.pad   = GSCALER_SUBDEV_PAD_SOURCE;
1019     sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1020     if (gsc->out_mode == GSC_OUT_FIMD) {
1021         sd_fmt.format.width  = gsc->dst_img.fw;
1022         sd_fmt.format.height = gsc->dst_img.fh;
1023     } else {
1024         sd_fmt.format.width  = gsc->dst_img.w;
1025         sd_fmt.format.height = gsc->dst_img.h;
1026     }
1027     sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1028                                V4L2_MBUS_FMT_YUV8_1X24;
1029     if (exynos_subdev_s_fmt(gsc->mdev.gsc_sd_entity->fd, &sd_fmt) < 0) {
1030             ALOGE("%s::GSC subdev set format failed", __func__);
1031             return -1;
1032     }
1033 
1034     /* set crop: src crop of GSC sub-dev*/
1035     sd_crop.pad   = GSCALER_SUBDEV_PAD_SOURCE;
1036     sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1037     if (gsc->out_mode == GSC_OUT_FIMD) {
1038         sd_crop.rect.left   = gsc->dst_img.x;
1039         sd_crop.rect.top    = gsc->dst_img.y;
1040         sd_crop.rect.width  = gsc->dst_img.w;
1041         sd_crop.rect.height = gsc->dst_img.h;
1042     } else {
1043         sd_crop.rect.left   = 0;
1044         sd_crop.rect.top    = 0;
1045         sd_crop.rect.width  = gsc->dst_img.w;
1046         sd_crop.rect.height = gsc->dst_img.h;
1047     }
1048 
1049     /* sink pad is connected to GSC out */
1050     /*  set format: sink sub-dev */
1051     if (gsc->out_mode == GSC_OUT_FIMD) {
1052         sd_fmt.pad   = FIMD_SUBDEV_PAD_SINK;
1053         sd_fmt.format.width  = gsc->dst_img.w;
1054         sd_fmt.format.height = gsc->dst_img.h;
1055     } else {
1056         sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SINK;
1057         sd_fmt.format.width  = gsc->dst_img.w + gsc->dst_img.x*2;
1058         sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
1059     }
1060 
1061     sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1062     sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1063                                V4L2_MBUS_FMT_YUV8_1X24;
1064     if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
1065         ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
1066         sd_fmt.pad);
1067         return -1;
1068     }
1069 
1070     /*  set crop: sink sub-dev */
1071     if (gsc->out_mode == GSC_OUT_FIMD)
1072         sd_crop.pad   = FIMD_SUBDEV_PAD_SINK;
1073     else
1074         sd_crop.pad   = MIXER_V_SUBDEV_PAD_SINK;
1075 
1076     sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1077     if (gsc->out_mode == GSC_OUT_FIMD) {
1078         sd_crop.rect.left   = gsc->dst_img.x;
1079         sd_crop.rect.top    = gsc->dst_img.y;
1080         sd_crop.rect.width  = gsc->dst_img.w;
1081         sd_crop.rect.height = gsc->dst_img.h;
1082     } else {
1083         sd_crop.rect.left   = 0;
1084         sd_crop.rect.top    = 0;
1085         sd_crop.rect.width  = gsc->dst_img.w;
1086         sd_crop.rect.height = gsc->dst_img.h;
1087     }
1088 
1089     if (gsc->out_mode != GSC_OUT_FIMD) {
1090         sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
1091         sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1092         sd_fmt.format.width = gsc->dst_img.w + gsc->dst_img.x*2;
1093         sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
1094         sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
1095         if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
1096             ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
1097             sd_fmt.pad);
1098             return -1;
1099         }
1100 
1101         sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SOURCE;
1102         sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1103         sd_crop.rect.left   = gsc->dst_img.x;
1104         sd_crop.rect.top    = gsc->dst_img.y;
1105         sd_crop.rect.width  = gsc->dst_img.w;
1106         sd_crop.rect.height = gsc->dst_img.h;
1107         if (exynos_subdev_s_crop(gsc->mdev.sink_sd_entity->fd, &sd_crop) < 0) {
1108             ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__,
1109             sd_crop.pad);
1110             return -1;
1111         }
1112     }
1113 
1114     /*set GSC ctrls */
1115     struct v4l2_control ctrl;
1116 
1117     ctrl.id = V4L2_CID_ROTATE;
1118     ctrl.value = rotate;
1119     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1120         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed",
1121             __func__,  rotate);
1122         return -1;
1123     }
1124 
1125     ctrl.id = V4L2_CID_HFLIP;
1126     ctrl.value = vflip;
1127     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1128         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed",
1129             __func__,  vflip);
1130         return -1;
1131     }
1132 
1133     ctrl.id = V4L2_CID_VFLIP;
1134     ctrl.value = hflip;
1135     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1136         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed",
1137             __func__,  hflip);
1138         return -1;
1139     }
1140 
1141     ctrl.id = V4L2_CID_CACHEABLE;
1142     ctrl.value = 1;
1143     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1144         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed",
1145             __func__);
1146         return -1;
1147     }
1148 
1149     ctrl.id = V4L2_CID_CONTENT_PROTECTION;
1150     ctrl.value = gsc->src_img.drmMode;
1151     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1152         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
1153             __func__);
1154         return -1;
1155     }
1156 
1157     ctrl.id = V4L2_CID_CSC_EQ_MODE;
1158     ctrl.value = gsc->eq_auto;
1159     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1160         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
1161         return -1;
1162     }
1163 
1164     ctrl.id = V4L2_CID_CSC_EQ;
1165     ctrl.value = gsc->v4l2_colorspace;
1166     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1167         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
1168         return -1;
1169     }
1170 
1171     ctrl.id = V4L2_CID_CSC_RANGE;
1172     ctrl.value = gsc->range_full;
1173     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1174         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
1175         return -1;
1176     }
1177 
1178       /* set src format  :GSC video dev*/
1179     fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1180     fmt.fmt.pix_mp.width            = gsc->src_img.fw;
1181     fmt.fmt.pix_mp.height           = gsc->src_img.fh;
1182     fmt.fmt.pix_mp.pixelformat    = src_color_space;
1183     fmt.fmt.pix_mp.field              = V4L2_FIELD_NONE;
1184     fmt.fmt.pix_mp.num_planes   = src_planes;
1185 
1186     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_FMT, &fmt) < 0) {
1187         ALOGE("%s::videodev set format failed", __func__);
1188         return -1;
1189     }
1190 
1191     /* set src crop info :GSC video dev*/
1192     crop.type     = fmt.type;
1193     crop.c.left    = gsc->src_img.x;
1194     crop.c.top     = gsc->src_img.y;
1195     crop.c.width  = gsc->src_img.w;
1196     crop.c.height = gsc->src_img.h;
1197 
1198     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CROP, &crop) < 0) {
1199         ALOGE("%s::videodev set crop failed", __func__);
1200         return -1;
1201     }
1202 
1203     reqbuf.type   = fmt.type;
1204     reqbuf.memory = V4L2_MEMORY_DMABUF;
1205     reqbuf.count  = MAX_BUFFERS_GSCALER_OUT;
1206 
1207     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
1208         ALOGE("%s::request buffers failed", __func__);
1209         return -1;
1210     }
1211 
1212     Exynos_gsc_Out();
1213 
1214     return 0;
1215 }
1216 
m_gsc_cap_config(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)1217 int CGscaler::m_gsc_cap_config(void *handle,
1218     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1219 {
1220     Exynos_gsc_In();
1221 
1222     struct v4l2_format  fmt;
1223     struct v4l2_crop    crop;
1224     struct v4l2_requestbuffers reqbuf;
1225     struct v4l2_subdev_format sd_fmt;
1226     struct v4l2_subdev_crop   sd_crop;
1227     unsigned int rotate;
1228     unsigned int hflip;
1229     unsigned int vflip;
1230     bool rgb;
1231 
1232     int32_t      src_color_space;
1233     int32_t      dst_color_space;
1234     int32_t      dst_planes;
1235 
1236     CGscaler* gsc = GetGscaler(handle);
1237     if (gsc == NULL) {
1238         ALOGE("%s::handle == NULL() fail", __func__);
1239         return -1;
1240     }
1241 
1242     memcpy(&gsc->src_img, src_img, sizeof(exynos_mpp_img));
1243     memcpy(&gsc->dst_img, dst_img, sizeof(exynos_mpp_img));
1244     src_color_space = hal_pixfmt_to_v4l2(src_img->format);
1245     dst_color_space = hal_pixfmt_to_v4l2(dst_img->format);
1246     dst_planes = m_gsc_get_plane_count(dst_color_space);
1247     dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1248     rgb = gsc_get_yuv_planes(src_color_space) == -1;
1249     CGscaler::rotateValueHAL2GSC(src_img->rot, &rotate, &hflip, &vflip);
1250 
1251     if (CGscaler::m_gsc_check_src_size(&gsc->src_img.fw,
1252             &gsc->src_img.fh, &gsc->src_img.x, &gsc->src_img.y,
1253             &gsc->src_img.w, &gsc->src_img.h, src_color_space,
1254             (rotate == 90 || rotate == 270)) == false) {
1255             ALOGE("%s::m_gsc_check_src_size() fail", __func__);
1256             return -1;
1257     }
1258 
1259     /*set GSC ctrls */
1260     struct v4l2_control ctrl;
1261 
1262     ctrl.id = V4L2_CID_ROTATE;
1263     ctrl.value = rotate;
1264     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1265         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed",
1266             __func__,  rotate);
1267         return -1;
1268     }
1269 
1270     ctrl.id = V4L2_CID_HFLIP;
1271     ctrl.value = vflip;
1272     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1273         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed",
1274             __func__,  vflip);
1275         return -1;
1276     }
1277 
1278     ctrl.id = V4L2_CID_VFLIP;
1279     ctrl.value = hflip;
1280     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1281         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed",
1282             __func__,  hflip);
1283         return -1;
1284     }
1285 
1286     ctrl.id = V4L2_CID_CACHEABLE;
1287     ctrl.value = 1;
1288     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1289         ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed",
1290             __func__);
1291         return -1;
1292     }
1293 
1294     ctrl.id = V4L2_CID_CONTENT_PROTECTION;
1295     ctrl.value = gsc->src_img.drmMode;
1296     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1297         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
1298             __func__);
1299         return -1;
1300     }
1301 
1302     ctrl.id = V4L2_CID_CSC_RANGE;
1303     ctrl.value = gsc->range_full;
1304     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1305         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail",
1306             __func__, gsc->range_full);
1307         return -1;
1308     }
1309       /* set format: source pad of Decon-TV sub-dev*/
1310     sd_fmt.pad   = DECON_TV_WB_PAD;
1311     sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1312     sd_fmt.format.width  = gsc->src_img.w;
1313     sd_fmt.format.height = gsc->src_img.h;
1314     sd_fmt.format.code = WB_PATH_FORMAT;
1315     if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
1316             ALOGE("%s::Decon-TV subdev set format failed", __func__);
1317             return -1;
1318     }
1319 
1320     fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1321     if (!gsc->dst_info.stream_on) {
1322         /* set src format: GSC video dev*/
1323 	fmt.fmt.pix_mp.width            = gsc->dst_img.fw;
1324 	fmt.fmt.pix_mp.height           = gsc->dst_img.fh;
1325 	fmt.fmt.pix_mp.pixelformat    = dst_color_space;
1326 	fmt.fmt.pix_mp.field              = V4L2_FIELD_NONE;
1327 	fmt.fmt.pix_mp.num_planes   = dst_planes;
1328 
1329 	if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_FMT, &fmt) < 0) {
1330 	    ALOGE("%s::videodev set format failed", __func__);
1331 	    return -1;
1332 	}
1333         gsc->dst_info.buf.buf_idx = 0;
1334         gsc->dst_info.qbuf_cnt = 0;
1335     }
1336 
1337     /* set format: sink pad of GSC sub-dev*/
1338 	sd_fmt.pad   = GSCALER_SUBDEV_PAD_SINK;
1339 	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1340 	sd_fmt.format.width  = gsc->src_img.w;
1341 	sd_fmt.format.height = gsc->src_img.h;
1342 	sd_fmt.format.code = WB_PATH_FORMAT;
1343 	if (exynos_subdev_s_fmt(gsc->mdev.gsc_sd_entity->fd, &sd_fmt) < 0) {
1344             ALOGE("%s::GSC subdev set format failed", __func__);
1345 	    return -1;
1346 	}
1347 
1348     /* set src crop info :GSC video dev*/
1349     crop.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1350     crop.c.left    = gsc->dst_img.x;
1351     crop.c.top     = gsc->dst_img.y;
1352     crop.c.width  = gsc->dst_img.w;
1353     crop.c.height = gsc->dst_img.h;
1354     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CROP, &crop) < 0) {
1355         ALOGE("%s::videodev set crop failed", __func__);
1356         return -1;
1357     }
1358 
1359     /* set crop: src crop of GSC sub-dev*/
1360     sd_crop.pad   = GSCALER_SUBDEV_PAD_SINK;
1361     sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1362     sd_crop.rect.left   = 0;
1363     sd_crop.rect.top    = 0;
1364     sd_crop.rect.width  = gsc->src_img.w;
1365     sd_crop.rect.height = gsc->src_img.h;
1366 
1367     if (exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop) < 0) {
1368         ALOGE("%s::GSC subdev set crop failed(PAD=%d)", __func__,
1369         sd_crop.pad);
1370         return -1;
1371     }
1372     reqbuf.type   = fmt.type;
1373     reqbuf.memory = V4L2_MEMORY_DMABUF;
1374     reqbuf.count  = MAX_BUFFERS_GSCALER_CAP;
1375 
1376     if (!gsc->dst_info.stream_on) {
1377         if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
1378 	    ALOGE("%s::request buffers failed", __func__);
1379             return -1;
1380         }
1381     }
1382 
1383     Exynos_gsc_Out();
1384 
1385     return 0;
1386 }
1387 
1388 
rotateValueHAL2GSC(unsigned int transform,unsigned int * rotate,unsigned int * hflip,unsigned int * vflip)1389 void CGscaler::rotateValueHAL2GSC(unsigned int transform,
1390     unsigned int *rotate, unsigned int *hflip, unsigned int *vflip)
1391 {
1392     int rotate_flag = transform & 0x7;
1393     *rotate = 0;
1394     *hflip = 0;
1395     *vflip = 0;
1396 
1397     switch (rotate_flag) {
1398     case HAL_TRANSFORM_ROT_90:
1399         *rotate = 90;
1400         break;
1401     case HAL_TRANSFORM_ROT_180:
1402         *rotate = 180;
1403         break;
1404     case HAL_TRANSFORM_ROT_270:
1405         *rotate = 270;
1406         break;
1407     case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
1408         *rotate = 90;
1409         *vflip = 1; /* set vflip to compensate the rot & flip order. */
1410         break;
1411     case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
1412         *rotate = 90;
1413         *hflip = 1; /* set hflip to compensate the rot & flip order. */
1414         break;
1415     case HAL_TRANSFORM_FLIP_H:
1416         *hflip = 1;
1417          break;
1418     case HAL_TRANSFORM_FLIP_V:
1419         *vflip = 1;
1420          break;
1421     default:
1422         break;
1423     }
1424 }
1425 
m_gsc_m2m_run(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)1426 int CGscaler::m_gsc_m2m_run(void *handle,
1427     exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1428 {
1429     Exynos_gsc_In();
1430 
1431     CGscaler* gsc = GetGscaler(handle);
1432     if (gsc == NULL) {
1433         ALOGE("%s::handle == NULL() fail", __func__);
1434         return -1;
1435     }
1436     void *addr[3] = {NULL, NULL, NULL};
1437     int ret = 0;
1438 
1439     addr[0] = (void *)src_img->yaddr;
1440     addr[1] = (void *)src_img->uaddr;
1441     addr[2] = (void *)src_img->vaddr;
1442     ret = exynos_gsc_set_src_addr(handle, addr, src_img->mem_type,
1443             src_img->acquireFenceFd);
1444     if (ret < 0) {
1445         ALOGE("%s::fail: exynos_gsc_set_src_addr[%p %p %p]", __func__,
1446             addr[0], addr[1], addr[2]);
1447         return -1;
1448     }
1449 
1450     addr[0] = (void *)dst_img->yaddr;
1451     addr[1] = (void *)dst_img->uaddr;
1452     addr[2] = (void *)dst_img->vaddr;
1453     ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->mem_type,
1454             dst_img->acquireFenceFd);
1455     if (ret < 0) {
1456         ALOGE("%s::fail: exynos_gsc_set_dst_addr[%p %p %p]", __func__,
1457             addr[0], addr[1], addr[2]);
1458         return -1;
1459     }
1460 
1461     ret = gsc->m_gsc_m2m_run_core(handle);
1462      if (ret < 0) {
1463         ALOGE("%s::fail: m_gsc_m2m_run_core", __func__);
1464         return -1;
1465     }
1466 
1467     if (src_img->acquireFenceFd >= 0) {
1468         close(src_img->acquireFenceFd);
1469         src_img->acquireFenceFd = -1;
1470     }
1471 
1472     if (dst_img->acquireFenceFd >= 0) {
1473         close(dst_img->acquireFenceFd);
1474         dst_img->acquireFenceFd = -1;
1475     }
1476 
1477     src_img->releaseFenceFd = gsc->src_info.releaseFenceFd;
1478     dst_img->releaseFenceFd = gsc->dst_info.releaseFenceFd;
1479 
1480     Exynos_gsc_Out();
1481 
1482     return 0;
1483 }
1484 
m_gsc_out_run(void * handle,exynos_mpp_img * src_img)1485 int CGscaler::m_gsc_out_run(void *handle, exynos_mpp_img *src_img)
1486 {
1487     struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
1488     struct v4l2_buffer buf;
1489     int32_t      src_color_space;
1490     int32_t      src_planes;
1491     unsigned int i;
1492     unsigned int plane_size[NUM_OF_GSC_PLANES];
1493     int ret = 0;
1494     unsigned int dq_retry_cnt = 0;
1495 
1496     CGscaler* gsc = GetGscaler(handle);
1497     if (gsc == NULL) {
1498         ALOGE("%s::handle == NULL() fail", __func__);
1499         return -1;
1500     }
1501 
1502     /* All buffers have been queued, dequeue one */
1503     if (gsc->src_info.qbuf_cnt == MAX_BUFFERS_GSCALER_OUT) {
1504         memset(&buf, 0, sizeof(struct v4l2_buffer));
1505         for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1506             memset(&planes[i], 0, sizeof(struct v4l2_plane));
1507 
1508         buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1509         buf.memory   = V4L2_MEMORY_DMABUF;
1510         buf.m.planes = planes;
1511 
1512         src_color_space = hal_pixfmt_to_v4l2(gsc->src_img.format);
1513         src_planes = m_gsc_get_plane_count(src_color_space);
1514         src_planes = (src_planes == -1) ? 1 : src_planes;
1515         buf.length   = src_planes;
1516 
1517 
1518         do {
1519             ret = ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_DQBUF, &buf);
1520             if (ret == -EAGAIN) {
1521                 ALOGE("%s::Retry DQbuf(index=%d)", __func__, buf.index);
1522                 usleep(10000);
1523                 dq_retry_cnt++;
1524                 continue;
1525             }
1526             break;
1527         } while (dq_retry_cnt <= 10);
1528 
1529         if (ret < 0) {
1530             ALOGE("%s::dq buffer failed (index=%d)", __func__, buf.index);
1531             return -1;
1532         }
1533         gsc->src_info.qbuf_cnt--;
1534     }
1535 
1536     memset(&buf, 0, sizeof(struct v4l2_buffer));
1537     for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1538         memset(&planes[i], 0, sizeof(struct v4l2_plane));
1539 
1540     src_color_space = hal_pixfmt_to_v4l2(gsc->src_img.format);
1541     src_planes = m_gsc_get_plane_count(src_color_space);
1542     src_planes = (src_planes == -1) ? 1 : src_planes;
1543 
1544     buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1545     buf.memory   = V4L2_MEMORY_DMABUF;
1546     buf.flags    = 0;
1547     buf.length   = src_planes;
1548     buf.index    = gsc->src_info.buf.buf_idx;
1549     buf.m.planes = planes;
1550     buf.reserved = -1;
1551 
1552     gsc->src_info.buf.addr[0] = (void*)src_img->yaddr;
1553     gsc->src_info.buf.addr[1] = (void*)src_img->uaddr;
1554     gsc->src_info.buf.addr[2] = (void*)src_img->vaddr;
1555 
1556     if (CGscaler::tmp_get_plane_size(src_color_space, plane_size,
1557         gsc->src_img.fw,  gsc->src_img.fh, src_planes) != true) {
1558         ALOGE("%s:get_plane_size:fail", __func__);
1559         return -1;
1560     }
1561 
1562     for (i = 0; i < buf.length; i++) {
1563         buf.m.planes[i].m.fd = (long)gsc->src_info.buf.addr[i];
1564         buf.m.planes[i].length    = plane_size[i];
1565         buf.m.planes[i].bytesused = plane_size[i];
1566     }
1567 
1568     /* Queue the buf */
1569     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_QBUF, &buf) < 0) {
1570         ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)",
1571                 __func__, gsc->src_info.buf.buf_idx,
1572                 MAX_BUFFERS_GSCALER_OUT);
1573         return -1;
1574     }
1575     gsc->src_info.buf.buf_idx++;
1576     gsc->src_info.buf.buf_idx =
1577         gsc->src_info.buf.buf_idx % MAX_BUFFERS_GSCALER_OUT;
1578     gsc->src_info.qbuf_cnt++;
1579 
1580     if (gsc->src_info.stream_on == false) {
1581         if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_STREAMON, &buf.type) < 0) {
1582             ALOGE("%s::stream on failed", __func__);
1583             return -1;
1584         }
1585         gsc->src_info.stream_on = true;
1586     }
1587 
1588     return 0;
1589 }
1590 
m_gsc_cap_run(void * handle,exynos_mpp_img * dst_img)1591 int CGscaler::m_gsc_cap_run(void *handle, exynos_mpp_img *dst_img)
1592 {
1593     struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
1594     struct v4l2_buffer buf;
1595     int32_t      dst_color_space;
1596     int32_t      dst_planes;
1597     unsigned int i;
1598     unsigned int plane_size[NUM_OF_GSC_PLANES];
1599     CGscaler* gsc = GetGscaler(handle);
1600     if (gsc == NULL) {
1601         ALOGE("%s::handle == NULL() fail", __func__);
1602         return -1;
1603     }
1604 
1605     /* All buffers have been queued, dequeue one */
1606     if (gsc->dst_info.qbuf_cnt == MAX_BUFFERS_GSCALER_CAP) {
1607         memset(&buf, 0, sizeof(struct v4l2_buffer));
1608         for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1609             memset(&planes[i], 0, sizeof(struct v4l2_plane));
1610 
1611         buf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1612         buf.memory   = V4L2_MEMORY_DMABUF;
1613         buf.m.planes = planes;
1614 
1615         dst_color_space = hal_pixfmt_to_v4l2(gsc->dst_img.format);
1616         dst_planes = m_gsc_get_plane_count(dst_color_space);
1617         dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1618         buf.length   = dst_planes;
1619 
1620 
1621         if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_DQBUF, &buf) < 0) {
1622             ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)",
1623                     __func__, gsc->src_info.buf.buf_idx,
1624                     MAX_BUFFERS_GSCALER_CAP);
1625             return -1;
1626         }
1627         gsc->dst_info.qbuf_cnt--;
1628     }
1629 
1630     memset(&buf, 0, sizeof(struct v4l2_buffer));
1631     for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1632         memset(&planes[i], 0, sizeof(struct v4l2_plane));
1633 
1634     dst_color_space = hal_pixfmt_to_v4l2(gsc->dst_img.format);
1635     dst_planes = m_gsc_get_plane_count(dst_color_space);
1636     dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1637 
1638     buf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1639     buf.memory   = V4L2_MEMORY_DMABUF;
1640     buf.flags    = V4L2_BUF_FLAG_USE_SYNC;
1641     buf.length   = dst_planes;
1642     buf.index    = gsc->dst_info.buf.buf_idx;
1643     buf.m.planes = planes;
1644     buf.reserved = dst_img->acquireFenceFd;
1645 
1646     gsc->dst_info.buf.addr[0] = (void*)dst_img->yaddr;
1647     gsc->dst_info.buf.addr[1] = (void*)dst_img->uaddr;
1648     gsc->dst_info.buf.addr[2] = (void*)dst_img->vaddr;
1649 
1650     if (CGscaler::tmp_get_plane_size(dst_color_space, plane_size,
1651         gsc->dst_img.fw,  gsc->dst_img.fh, dst_planes) != true) {
1652         ALOGE("%s:get_plane_size:fail", __func__);
1653         return -1;
1654     }
1655 
1656     for (i = 0; i < buf.length; i++) {
1657         buf.m.planes[i].m.fd = (int)(long)gsc->dst_info.buf.addr[i];
1658         buf.m.planes[i].length    = plane_size[i];
1659         buf.m.planes[i].bytesused = plane_size[i];
1660     }
1661 
1662     /* Queue the buf */
1663     if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_QBUF, &buf) < 0) {
1664         ALOGE("%s::queue buffer failed (index=%d)(mDstBufNum=%d)",
1665                 __func__, gsc->dst_info.buf.buf_idx,
1666                 MAX_BUFFERS_GSCALER_CAP);
1667         return -1;
1668     }
1669 
1670     gsc->dst_info.buf.buf_idx++;
1671     gsc->dst_info.buf.buf_idx =
1672         gsc->dst_info.buf.buf_idx % MAX_BUFFERS_GSCALER_CAP;
1673     gsc->dst_info.qbuf_cnt++;
1674 
1675     if (gsc->dst_info.stream_on == false) {
1676         if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_STREAMON, &buf.type) < 0) {
1677             ALOGE("%s::stream on failed", __func__);
1678             return -1;
1679         }
1680         gsc->dst_info.stream_on = true;
1681     }
1682 
1683     dst_img->releaseFenceFd = buf.reserved;
1684     return 0;
1685 }
1686 
tmp_get_plane_size(int V4L2_PIX,unsigned int * size,unsigned int width,unsigned int height,int src_planes)1687 bool CGscaler::tmp_get_plane_size(int V4L2_PIX,
1688     unsigned int * size, unsigned int width, unsigned int height, int src_planes)
1689 {
1690     unsigned int frame_ratio = 1;
1691     int src_bpp    = gsc_get_yuv_bpp(V4L2_PIX);
1692     unsigned int frame_size = width * height;
1693 
1694     src_planes = (src_planes == -1) ? 1 : src_planes;
1695     frame_ratio = 8 * (src_planes -1) / (src_bpp - 8);
1696 
1697     switch (src_planes) {
1698     case 1:
1699         switch (V4L2_PIX) {
1700         case V4L2_PIX_FMT_BGR32:
1701         case V4L2_PIX_FMT_RGB32:
1702             size[0] = frame_size << 2;
1703             break;
1704 	case V4L2_PIX_FMT_RGB565:
1705         case V4L2_PIX_FMT_NV16:
1706         case V4L2_PIX_FMT_NV61:
1707         case V4L2_PIX_FMT_YUYV:
1708         case V4L2_PIX_FMT_UYVY:
1709         case V4L2_PIX_FMT_VYUY:
1710         case V4L2_PIX_FMT_YVYU:
1711             size[0] = frame_size << 1;
1712             break;
1713         case V4L2_PIX_FMT_YUV420:
1714         case V4L2_PIX_FMT_NV12:
1715         case V4L2_PIX_FMT_NV21:
1716         case V4L2_PIX_FMT_NV21M:
1717             size[0] = (frame_size * 3) >> 1;
1718             break;
1719         case V4L2_PIX_FMT_YVU420:
1720             size[0] = frame_size + (ALIGN((width >> 1), 16) * ((height >> 1) * 2));
1721             break;
1722         default:
1723             ALOGE("%s::invalid color type (%x)", __func__, V4L2_PIX);
1724             return false;
1725             break;
1726         }
1727         size[1] = 0;
1728         size[2] = 0;
1729         break;
1730     case 2:
1731         size[0] = frame_size;
1732         size[1] = frame_size / frame_ratio;
1733         size[2] = 0;
1734         break;
1735     case 3:
1736         size[0] = frame_size;
1737         size[1] = frame_size / frame_ratio;
1738         size[2] = frame_size / frame_ratio;
1739         break;
1740     default:
1741         ALOGE("%s::invalid color foarmt", __func__);
1742         return false;
1743         break;
1744     }
1745 
1746     return true;
1747 }
1748 
ConfigMpp(void * handle,exynos_mpp_img * src,exynos_mpp_img * dst)1749 int CGscaler::ConfigMpp(void *handle, exynos_mpp_img *src,
1750 					exynos_mpp_img *dst)
1751 {
1752     return exynos_gsc_config_exclusive(handle, src, dst);
1753 }
1754 
ConfigBlendMpp(void * handle,exynos_mpp_img * src,exynos_mpp_img * dst,SrcBlendInfo * srcblendinfo)1755 int CGscaler::ConfigBlendMpp(void *handle, exynos_mpp_img *src,
1756                                            exynos_mpp_img *dst,
1757                                            SrcBlendInfo  *srcblendinfo)
1758 {
1759     return exynos_gsc_config_blend_exclusive(handle, src, dst, srcblendinfo);
1760 }
1761 
RunMpp(void * handle,exynos_mpp_img * src,exynos_mpp_img * dst)1762 int CGscaler::RunMpp(void *handle, exynos_mpp_img *src,
1763 					exynos_mpp_img *dst)
1764 {
1765     return exynos_gsc_run_exclusive(handle, src, dst);
1766 }
1767 
StopMpp(void * handle)1768 int CGscaler::StopMpp(void *handle)
1769 {
1770     return exynos_gsc_stop_exclusive(handle);
1771 }
1772 
DestroyMpp(void * handle)1773 void CGscaler::DestroyMpp(void *handle)
1774 {
1775     return exynos_gsc_destroy(handle);
1776 }
1777 
SetCSCProperty(void * handle,unsigned int eqAuto,unsigned int fullRange,unsigned int colorspace)1778 int CGscaler::SetCSCProperty(void *handle, unsigned int eqAuto,
1779 		   unsigned int fullRange, unsigned int colorspace)
1780 {
1781     return exynos_gsc_set_csc_property(handle, eqAuto, fullRange,
1782 					    colorspace);
1783 }
1784 
FreeMpp(void * handle)1785 int CGscaler::FreeMpp(void *handle)
1786 {
1787     return exynos_gsc_free_and_close(handle);
1788 }
1789 
SetInputCrop(void * handle,exynos_mpp_img * src_img,exynos_mpp_img __UNUSED__ * dst_img)1790 int CGscaler::SetInputCrop(void *handle,
1791         exynos_mpp_img *src_img, exynos_mpp_img __UNUSED__ *dst_img)
1792 {
1793     struct v4l2_crop crop;
1794     CGscaler *gsc = GetGscaler(handle);
1795     if (gsc == NULL) {
1796         ALOGE("%s::handle == NULL() fail", __func__);
1797         return -1;
1798     }
1799 
1800     crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1801     crop.c.left = src_img->x;
1802     crop.c.top = src_img->y;
1803     crop.c.width = src_img->w;
1804     crop.c.height = src_img->h;
1805 
1806     return ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_S_CROP, &crop);
1807 }
1808