exynos_gscaler.c revision bcd3f11d136665f5f508aa802d27e9f4ed888b4e
1/*
2 * Copyright (C) 2008 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      exynos_gscaler.c
20 * \brief     header file for Gscaler HAL
21 * \author    ShinWon Lee (shinwon.lee@samsung.com)
22 * \date      2012/01/09
23 *
24 * <b>Revision History: </b>
25 * - 2012.01.09 : ShinWon Lee(shinwon.lee@samsung.com) \n
26 *   Create
27 *
28 * - 2012.02.07 : ShinWon Lee(shinwon.lee@samsung.com) \n
29 *   Change file name to exynos_gscaler.h
30 *
31 * - 2012.02.09 : Sangwoo, Parkk(sw5771.park@samsung.com) \n
32 *   Use Multiple Gscaler by Multiple Process
33 *
34 * - 2012.02.20 : Sangwoo, Park(sw5771.park@samsung.com) \n
35 *   Add exynos_gsc_set_rotation() API
36 *
37 * - 2012.02.20 : ShinWon Lee(shinwon.lee@samsung.com) \n
38 *   Add size constrain
39 *
40 */
41
42//#define LOG_NDEBUG 0
43#include "exynos_gsc_utils.h"
44#include "content_protect.h"
45
46static int exynos_gsc_m2m_wait_frame_done(void *handle);
47static int exynos_gsc_m2m_stop(void *handle);
48
49static unsigned int m_gsc_get_plane_count(
50    int v4l_pixel_format)
51{
52    int plane_count = 0;
53
54    switch (v4l_pixel_format) {
55    case V4L2_PIX_FMT_RGB32:
56    case V4L2_PIX_FMT_BGR32:
57    case V4L2_PIX_FMT_RGB24:
58    case V4L2_PIX_FMT_RGB565:
59    case V4L2_PIX_FMT_RGB555X:
60    case V4L2_PIX_FMT_RGB444:
61    case V4L2_PIX_FMT_YUYV:
62    case V4L2_PIX_FMT_UYVY:
63    case V4L2_PIX_FMT_NV16:
64    case V4L2_PIX_FMT_NV61:
65        plane_count = 1;
66        break;
67    case V4L2_PIX_FMT_NV12M:
68    case V4L2_PIX_FMT_NV12MT_16X16:
69    case V4L2_PIX_FMT_NV12:
70    case V4L2_PIX_FMT_NV21:
71    case V4L2_PIX_FMT_NV21M:
72        plane_count = 2;
73        break;
74    case V4L2_PIX_FMT_YVU420M:
75    case V4L2_PIX_FMT_YUV422P:
76    case V4L2_PIX_FMT_YUV420M:
77        plane_count = 3;
78        break;
79    default:
80        ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
81             __func__, v4l_pixel_format);
82        plane_count = -1;
83        break;
84    }
85
86    return plane_count;
87}
88
89static unsigned int m_gsc_get_plane_size(
90    unsigned int *plane_size,
91    unsigned int  width,
92    unsigned int  height,
93    int           v4l_pixel_format)
94{
95    switch (v4l_pixel_format) {
96    /* 1 plane */
97    case V4L2_PIX_FMT_RGB32:
98    case V4L2_PIX_FMT_BGR32:
99        plane_size[0] = width * height * 4;
100        plane_size[1] = 0;
101        plane_size[2] = 0;
102        break;
103    case V4L2_PIX_FMT_RGB24:
104        plane_size[0] = width * height * 3;
105        plane_size[1] = 0;
106        plane_size[2] = 0;
107        break;
108    case V4L2_PIX_FMT_RGB565:
109    case V4L2_PIX_FMT_RGB555X:
110    case V4L2_PIX_FMT_RGB444:
111    case V4L2_PIX_FMT_YUYV:
112    case V4L2_PIX_FMT_UYVY:
113        plane_size[0] = width * height * 2;
114        plane_size[1] = 0;
115        plane_size[2] = 0;
116        break;
117    /* 2 planes */
118    case V4L2_PIX_FMT_NV12M:
119    case V4L2_PIX_FMT_NV12:
120    case V4L2_PIX_FMT_NV21:
121    case V4L2_PIX_FMT_NV21M:
122        plane_size[0] = width * height;
123        plane_size[1] = width * (height / 2);
124        plane_size[2] = 0;
125        break;
126    case V4L2_PIX_FMT_NV16:
127    case V4L2_PIX_FMT_NV61:
128        plane_size[0] = width * height * 2;
129        plane_size[1] = 0;
130        plane_size[2] = 0;
131        break;
132    case V4L2_PIX_FMT_NV12MT_16X16:
133        plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
134        plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
135        plane_size[2] = 0;
136        break;
137    /* 3 planes */
138    case V4L2_PIX_FMT_YVU420M:
139    case V4L2_PIX_FMT_YUV422P:
140        plane_size[0] = width * height;
141        plane_size[1] = (width / 2) * (height / 2);
142        plane_size[2] = (width / 2) * (height / 2);
143        break;
144    default:
145        ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
146             __func__, v4l_pixel_format);
147        return -1;
148        break;
149    }
150
151    return 0;
152}
153
154static int m_exynos_gsc_multiple_of_n(
155    int number, int N)
156{
157    int result = number;
158    switch (N) {
159    case 1:
160    case 2:
161    case 4:
162    case 8:
163    case 16:
164    case 32:
165    case 64:
166    case 128:
167    case 256:
168        result = (number - (number & (N-1)));
169        break;
170    default:
171        result = number - (number % N);
172        break;
173    }
174    return result;
175}
176
177static bool m_exynos_gsc_check_src_size(
178    unsigned int *w,      unsigned int *h,
179    unsigned int *crop_x, unsigned int *crop_y,
180    unsigned int *crop_w, unsigned int *crop_h,
181    int v4l2_colorformat)
182{
183    if (*w < GSC_MIN_W_SIZE || *h < GSC_MIN_H_SIZE) {
184        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
185            __func__, GSC_MIN_W_SIZE, *w, GSC_MIN_H_SIZE, *h);
186        return false;
187    }
188
189    if (*crop_w < GSC_MIN_W_SIZE || *crop_h < GSC_MIN_H_SIZE) {
190        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
191            __func__, GSC_MIN_W_SIZE,* crop_w, GSC_MIN_H_SIZE, *crop_h);
192        return false;
193    }
194
195    switch (v4l2_colorformat) {
196    // YUV420
197    case V4L2_PIX_FMT_YUV420M:
198    case V4L2_PIX_FMT_YVU420M:
199    case V4L2_PIX_FMT_NV12M:
200    case V4L2_PIX_FMT_NV12MT:
201    case V4L2_PIX_FMT_NV21:
202    case V4L2_PIX_FMT_NV21M:
203        *w = (*w + 15) & ~15;
204        *h = (*h + 15) & ~15;
205        //*w      = m_exynos_gsc_multiple_of_n(*w, 16);
206        //*h      = m_exynos_gsc_multiple_of_n(*h, 16);
207        *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 4);
208        *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 4);
209        break;
210    // YUV422
211    case V4L2_PIX_FMT_YUYV:
212    case V4L2_PIX_FMT_YUV422P:
213    case V4L2_PIX_FMT_UYVY:
214    case V4L2_PIX_FMT_NV16:
215    case V4L2_PIX_FMT_YVYU:
216    case V4L2_PIX_FMT_VYUY:
217        *h = (*h + 7) & ~7;
218        //*h      = m_exynos_gsc_multiple_of_n(*h, 8);
219        *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 4);
220        *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 2);
221        break;
222    // RGB
223    case V4L2_PIX_FMT_RGB32:
224    case V4L2_PIX_FMT_RGB24:
225    case V4L2_PIX_FMT_RGB565:
226    case V4L2_PIX_FMT_BGR32:
227    case V4L2_PIX_FMT_RGB555X:
228    case V4L2_PIX_FMT_RGB444:
229    default:
230        *h = (*h + 7) & ~7;
231        //*h      = m_exynos_gsc_multiple_of_n(*h, 8);
232        *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 2);
233        *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 2);
234        break;
235    }
236
237    return true;
238}
239
240static bool m_exynos_gsc_check_dst_size(
241    unsigned int *w,      unsigned int *h,
242    unsigned int *crop_x, unsigned int *crop_y,
243    unsigned int *crop_w, unsigned int *crop_h,
244    int v4l2_colorformat,
245    int rotation)
246{
247    unsigned int *new_w;
248    unsigned int *new_h;
249    unsigned int *new_crop_w;
250    unsigned int *new_crop_h;
251
252        new_w = w;
253        new_h = h;
254        new_crop_w = crop_w;
255        new_crop_h = crop_h;
256
257    if (*w < GSC_MIN_W_SIZE || *h < GSC_MIN_H_SIZE) {
258        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
259            __func__, GSC_MIN_W_SIZE, *w, GSC_MIN_H_SIZE, *h);
260        return false;
261    }
262
263    if (*crop_w < GSC_MIN_W_SIZE || *crop_h < GSC_MIN_H_SIZE) {
264        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
265            __func__, GSC_MIN_W_SIZE,* crop_w, GSC_MIN_H_SIZE, *crop_h);
266        return false;
267    }
268
269    switch (v4l2_colorformat) {
270    // YUV420
271    case V4L2_PIX_FMT_NV12M:
272    case V4L2_PIX_FMT_NV12MT:
273    case V4L2_PIX_FMT_NV21:
274    case V4L2_PIX_FMT_NV21M:
275    case V4L2_PIX_FMT_YUV420M:
276    case V4L2_PIX_FMT_YVU420M:
277        *new_w = m_exynos_gsc_multiple_of_n(*new_w, 2);
278        *new_h = m_exynos_gsc_multiple_of_n(*new_h, 2);
279        break;
280    // YUV422
281    case V4L2_PIX_FMT_YUYV:
282    case V4L2_PIX_FMT_YUV422P:
283    case V4L2_PIX_FMT_UYVY:
284    case V4L2_PIX_FMT_NV16:
285    case V4L2_PIX_FMT_YVYU:
286    case V4L2_PIX_FMT_VYUY:
287        *new_w = m_exynos_gsc_multiple_of_n(*new_w, 2);
288        break;
289    // RGB
290    case V4L2_PIX_FMT_RGB32:
291    case V4L2_PIX_FMT_RGB24:
292    case V4L2_PIX_FMT_RGB565:
293    case V4L2_PIX_FMT_BGR32:
294    case V4L2_PIX_FMT_RGB555X:
295    case V4L2_PIX_FMT_RGB444:
296    default:
297        break;
298    }
299
300    return true;
301}
302
303static int m_exynos_gsc_output_create(
304    struct GSC_HANDLE *gsc_handle,
305    int dev_num,
306    int out_mode)
307{
308    struct media_device *media0;
309    struct media_entity *gsc_sd_entity;
310    struct media_entity *gsc_vd_entity;
311    struct media_entity *sink_sd_entity;
312    struct media_link *links;
313    char node[32];
314    char devname[32];
315    unsigned int cap;
316    int         i;
317    int         fd = 0;
318
319    Exynos_gsc_In();
320
321    if ((out_mode != GSC_OUT_FIMD) &&
322        (out_mode != GSC_OUT_TV))
323        return -1;
324
325    gsc_handle->out_mode = out_mode;
326    /* GSCX => FIMD_WINX : arbitrary linking is not allowed */
327    if ((out_mode == GSC_OUT_FIMD) &&
328        (dev_num > 2))
329        return -1;
330
331    /* media0 */
332    sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
333    media0 = exynos_media_open(node);
334    if (media0 == NULL) {
335        ALOGE("%s::exynos_media_open failed (node=%s)", __func__, node);
336        return false;
337    }
338
339    /* Get the sink subdev entity by name and make the node of sink subdev*/
340    if (out_mode == GSC_OUT_FIMD)
341        sprintf(devname, PFX_FIMD_ENTITY, dev_num);
342    else
343        sprintf(devname, PFX_MXR_ENTITY, 0);
344
345    sink_sd_entity = exynos_media_get_entity_by_name(media0, devname, strlen(devname));
346    sink_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
347    if ( sink_sd_entity->fd < 0) {
348        ALOGE("%s:: failed to open sink subdev node", __func__);
349        goto gsc_output_err;
350    }
351
352    /* get GSC video dev & sub dev entity by name*/
353    sprintf(devname, PFX_GSC_VIDEODEV_ENTITY, dev_num);
354    gsc_vd_entity= exynos_media_get_entity_by_name(media0, devname, strlen(devname));
355
356    sprintf(devname, PFX_GSC_SUBDEV_ENTITY, dev_num);
357    gsc_sd_entity= exynos_media_get_entity_by_name(media0, devname, strlen(devname));
358
359    /* gsc sub-dev open */
360    sprintf(devname, PFX_GSC_SUBDEV_ENTITY, dev_num);
361    gsc_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
362
363    /* setup link : GSC : video device --> sub device */
364    for (i = 0; i < (int) gsc_vd_entity->num_links; i++) {
365        links = &gsc_vd_entity->links[i];
366
367        if (links == NULL ||
368            links->source->entity != gsc_vd_entity ||
369            links->sink->entity   != gsc_sd_entity) {
370            continue;
371        } else if (exynos_media_setup_link(media0,  links->source,  links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
372            ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
373                  __func__, links->source->entity->info.id, links->sink->entity->info.id);
374            return -1;
375        }
376    }
377
378    /* setup link : GSC: sub device --> sink device */
379    for (i = 0; i < (int) gsc_sd_entity->num_links; i++) {
380        links = &gsc_sd_entity->links[i];
381
382        if (links == NULL || links->source->entity != gsc_sd_entity ||
383                             links->sink->entity   != sink_sd_entity) {
384            continue;
385        } else if (exynos_media_setup_link(media0,  links->source,  links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
386            ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
387                  __func__, links->source->entity->info.id, links->sink->entity->info.id);
388            return -1;
389        }
390    }
391
392    /* gsc video-dev open */
393    sprintf(devname, PFX_GSC_VIDEODEV_ENTITY, dev_num);
394    gsc_vd_entity->fd = exynos_v4l2_open_devname(devname, O_RDWR);
395    cap = V4L2_CAP_STREAMING |
396          V4L2_CAP_VIDEO_OUTPUT_MPLANE;
397
398    if (exynos_v4l2_querycap(gsc_vd_entity->fd, cap) == false) {
399        ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
400        goto gsc_output_err;
401    }
402    gsc_handle->gsc_sd_entity = gsc_sd_entity;
403    gsc_handle->gsc_vd_entity = gsc_vd_entity;
404    gsc_handle->sink_sd_entity = sink_sd_entity;
405    gsc_handle->media0 = media0;
406
407    Exynos_gsc_Out();
408
409    return 0;
410
411gsc_output_err:
412    /* to do */
413    return -1;
414
415}
416
417static int m_exynos_gsc_m2m_create(
418    int dev)
419{
420    int          fd = 0;
421    int          video_node_num;
422    unsigned int cap;
423    char         node[32];
424
425    Exynos_gsc_In();
426
427    switch(dev) {
428    case 0:
429        video_node_num = NODE_NUM_GSC_0;
430        break;
431    case 1:
432        video_node_num = NODE_NUM_GSC_1;
433        break;
434    case 2:
435        video_node_num = NODE_NUM_GSC_2;
436        break;
437    case 3:
438        video_node_num = NODE_NUM_GSC_3;
439        break;
440    default:
441        ALOGE("%s::unexpected dev(%d) fail", __func__, dev);
442        return -1;
443        break;
444    }
445
446    sprintf(node, "%s%d", PFX_NODE_GSC, video_node_num);
447    fd = exynos_v4l2_open(node, O_RDWR);
448    if (fd < 0) {
449        ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
450        return -1;
451    }
452
453    cap = V4L2_CAP_STREAMING |
454          V4L2_CAP_VIDEO_OUTPUT_MPLANE |
455          V4L2_CAP_VIDEO_CAPTURE_MPLANE;
456
457    if (exynos_v4l2_querycap(fd, cap) == false) {
458        ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
459        if (0 < fd)
460            close(fd);
461        fd = 0;
462        return -1;
463    }
464
465    Exynos_gsc_Out();
466
467    return fd;
468}
469
470
471static bool m_exynos_gsc_out_destroy(struct GSC_HANDLE *gsc_handle)
472{
473    struct media_link * links;
474    int i;
475
476    Exynos_gsc_In();
477
478    if (gsc_handle == NULL) {
479        ALOGE("%s::gsc_handle is NULL", __func__);
480        return false;
481    }
482
483    if (gsc_handle->src.stream_on == true) {
484        if (exynos_gsc_out_stop((void *)gsc_handle) < 0)
485            ALOGE("%s::exynos_gsc_out_stop() fail", __func__);
486
487            gsc_handle->src.stream_on = false;
488    }
489
490    /* unlink : gscaler-out --> fimd */
491        for (i = 0; i < (int) gsc_handle->gsc_sd_entity->num_links; i++) {
492            links = &gsc_handle->gsc_sd_entity->links[i];
493
494            if (links == NULL || links->source->entity != gsc_handle->gsc_sd_entity ||
495                                 links->sink->entity   != gsc_handle->sink_sd_entity) {
496                continue;
497            } else if (exynos_media_setup_link(gsc_handle->media0,  links->source,
498                                                                        links->sink, 0) < 0) {
499                ALOGE("%s::exynos_media_setup_unlink [src.entity=%d->sink.entity=%d] failed",
500                      __func__, links->source->entity->info.id, links->sink->entity->info.id);
501            }
502        }
503
504        close(gsc_handle->gsc_vd_entity->fd);
505        close(gsc_handle->gsc_sd_entity->fd);
506        gsc_handle->gsc_vd_entity->fd = -1;
507        gsc_handle->gsc_vd_entity->fd = -1;
508
509        Exynos_gsc_Out();
510
511        return true;
512
513}
514
515static bool m_exynos_gsc_destroy(
516    struct GSC_HANDLE *gsc_handle)
517{
518    Exynos_gsc_In();
519
520    /* just in case, we call stop here because we cannot afford to leave
521     * secure side protection on if things failed.
522     */
523    exynos_gsc_m2m_stop(gsc_handle);
524
525    if (0 < gsc_handle->gsc_fd)
526        close(gsc_handle->gsc_fd);
527    gsc_handle->gsc_fd = 0;
528
529    Exynos_gsc_Out();
530
531    return true;
532}
533
534bool m_exynos_gsc_find_and_trylock_and_create(
535    struct GSC_HANDLE *gsc_handle)
536{
537    int          i                 = 0;
538    bool         flag_find_new_gsc = false;
539    unsigned int total_sleep_time  = 0;
540
541    Exynos_gsc_In();
542
543    do {
544        for (i = 0; i < NUM_OF_GSC_HW; i++) {
545            // HACK : HWComposer, HDMI uses gscaler with their own code.
546            //        So, This obj_mutex cannot defense their open()
547            if (i == 0 || i == 3)
548                continue;
549
550            if (exynos_mutex_trylock(gsc_handle->obj_mutex[i]) == true) {
551
552                // destroy old one.
553                m_exynos_gsc_destroy(gsc_handle);
554
555                // create new one.
556                gsc_handle->gsc_id = i;
557                gsc_handle->gsc_fd = m_exynos_gsc_m2m_create(i);
558                if (gsc_handle->gsc_fd < 0) {
559                    gsc_handle->gsc_fd = 0;
560                    exynos_mutex_unlock(gsc_handle->obj_mutex[i]);
561                    continue;
562                }
563
564                if (gsc_handle->cur_obj_mutex)
565                    exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
566
567                gsc_handle->cur_obj_mutex = gsc_handle->obj_mutex[i];
568
569                flag_find_new_gsc = true;
570                break;
571            }
572        }
573
574        // waiting for another process doesn't use gscaler.
575        // we need to make decision how to do.
576        if (flag_find_new_gsc == false) {
577            usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
578            total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
579            ALOGV("%s::waiting for anthere process doens't use gscaler", __func__);
580        }
581
582    } while(   flag_find_new_gsc == false
583            && total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
584
585    if (flag_find_new_gsc == false)
586        ALOGE("%s::we don't have no available gsc.. fail", __func__);
587
588    Exynos_gsc_Out();
589
590    return flag_find_new_gsc;
591}
592
593static bool m_exynos_gsc_set_format(
594    int              fd,
595    struct gsc_info *info)
596{
597    Exynos_gsc_In();
598
599    struct v4l2_requestbuffers req_buf;
600    int                        plane_count;
601
602    plane_count = m_gsc_get_plane_count(info->v4l2_colorformat);
603    if (plane_count < 0) {
604        ALOGE("%s::not supported v4l2_colorformat", __func__);
605        return false;
606    }
607
608    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
609        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
610        return false;
611    }
612
613    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_VFLIP, info->flip_horizontal) < 0) {
614        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__);
615        return false;
616    }
617
618    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_HFLIP, info->flip_vertical) < 0) {
619        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
620        return false;
621    }
622
623    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CSC_RANGE, info->csc_range) < 0) {
624        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
625        return false;
626    }
627    info->format.type = info->buf_type;
628    info->format.fmt.pix_mp.width       = info->width;
629    info->format.fmt.pix_mp.height      = info->height;
630    info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
631    info->format.fmt.pix_mp.field       = V4L2_FIELD_ANY;
632    info->format.fmt.pix_mp.num_planes  = plane_count;
633
634    if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
635        ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
636        return false;
637    }
638
639    info->crop.type     = info->buf_type;
640    info->crop.c.left   = info->crop_left;
641    info->crop.c.top    = info->crop_top;
642    info->crop.c.width  = info->crop_width;
643    info->crop.c.height = info->crop_height;
644
645    if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
646        ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
647        return false;
648    }
649
650    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
651        ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
652        return false;
653    }
654
655    req_buf.count  = 1;
656    req_buf.type   = info->buf_type;
657    req_buf.memory = V4L2_MEMORY_DMABUF;
658    if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
659        ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
660        return false;
661    }
662
663    Exynos_gsc_Out();
664
665    return true;
666}
667
668static bool m_exynos_gsc_set_addr(
669    int              fd,
670    struct gsc_info *info)
671{
672    unsigned int i;
673    unsigned int plane_size[NUM_OF_GSC_PLANES];
674
675    m_gsc_get_plane_size(plane_size,
676                         info->width,
677                         info->height,
678                         info->v4l2_colorformat);
679
680    info->buffer.index    = 0;
681    info->buffer.flags    = V4L2_BUF_FLAG_USE_SYNC;
682    info->buffer.type     = info->buf_type;
683    info->buffer.memory   = V4L2_MEMORY_DMABUF;
684    info->buffer.m.planes = info->planes;
685    info->buffer.length   = info->format.fmt.pix_mp.num_planes;
686    info->buffer.reserved = info->acquireFenceFd;
687
688    for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
689        info->buffer.m.planes[i].m.fd = (int)info->addr[i];
690        info->buffer.m.planes[i].length    = plane_size[i];
691        info->buffer.m.planes[i].bytesused = 0;
692    }
693
694    if (exynos_v4l2_qbuf(fd, &info->buffer) < 0) {
695        ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
696        return false;
697    }
698    info->buffer_queued = true;
699
700    info->releaseFenceFd = info->buffer.reserved;
701
702    return true;
703}
704
705void *exynos_gsc_create(
706    void)
707{
708    int i     = 0;
709    int op_id = 0;
710    char mutex_name[32];
711
712    Exynos_gsc_In();
713
714    struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
715    if (gsc_handle == NULL) {
716        ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
717        goto err;
718    }
719
720    gsc_handle->gsc_fd = 0;
721    memset(&gsc_handle->src, 0, sizeof(struct gsc_info));
722    memset(&gsc_handle->dst, 0, sizeof(struct gsc_info));
723
724    gsc_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
725    gsc_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
726
727    gsc_handle->op_mutex = NULL;
728    for (i = 0; i < NUM_OF_GSC_HW; i++)
729        gsc_handle->obj_mutex[i] = NULL;
730
731    gsc_handle->cur_obj_mutex = NULL;
732    gsc_handle->flag_local_path = false;
733    gsc_handle->flag_exclusive_open = false;
734
735    srand(time(NULL));
736    op_id = rand() % 1000000; // just make random id
737    sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
738    gsc_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
739    if (gsc_handle->op_mutex == NULL) {
740        ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
741        goto err;
742    }
743
744    exynos_mutex_lock(gsc_handle->op_mutex);
745
746    // check if it is available
747    for (i = 0; i < NUM_OF_GSC_HW; i++) {
748        sprintf(mutex_name, "%sObject%d", LOG_TAG, i);
749
750        gsc_handle->obj_mutex[i] = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
751        if (gsc_handle->obj_mutex[i] == NULL) {
752            ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
753            goto err;
754        }
755    }
756
757    if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle) == false) {
758        ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__);
759        goto err;
760    }
761
762    exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
763    exynos_mutex_unlock(gsc_handle->op_mutex);
764
765    return (void *)gsc_handle;
766
767err:
768    if (gsc_handle) {
769        m_exynos_gsc_destroy(gsc_handle);
770
771        if (gsc_handle->cur_obj_mutex)
772            exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
773
774        for (i = 0; i < NUM_OF_GSC_HW; i++) {
775            if ((gsc_handle->obj_mutex[i] != NULL) &&
776                (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
777                if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
778                    ALOGE("%s::exynos_mutex_destroy() fail", __func__);
779            }
780        }
781
782        if (gsc_handle->op_mutex)
783            exynos_mutex_unlock(gsc_handle->op_mutex);
784
785        if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
786            ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
787
788        free(gsc_handle);
789    }
790
791    Exynos_gsc_Out();
792
793    return NULL;
794}
795
796void *exynos_gsc_reserve(int dev_num)
797{
798    char mutex_name[32];
799    unsigned int total_sleep_time  = 0;
800    bool    gsc_flag = false;
801
802    if ((dev_num < 0) || (dev_num >= NUM_OF_GSC_HW)) {
803        ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
804        return NULL;
805    }
806
807    struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
808    if (gsc_handle == NULL) {
809        ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
810        goto err;
811    }
812
813    gsc_handle->gsc_fd = -1;
814    gsc_handle->op_mutex = NULL;
815    gsc_handle->cur_obj_mutex = NULL;
816
817    sprintf(mutex_name, "%sObject%d", LOG_TAG, dev_num);
818    gsc_handle->cur_obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
819    if (gsc_handle->cur_obj_mutex == NULL) {
820        ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
821        goto err;
822    }
823
824    do {
825        if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == true) {
826            gsc_flag = true;
827            break;
828        }
829        usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
830        total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
831        ALOGV("%s::waiting for another process to release the requested gscaler", __func__);
832    } while(total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
833
834    if (gsc_flag == true)
835         return (void *)gsc_handle;
836
837err:
838    if (gsc_handle) {
839        free(gsc_handle);
840    }
841
842    return NULL;
843}
844
845void exynos_gsc_release(void *handle)
846{
847    struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)handle;
848
849    if (handle == NULL) {
850        ALOGE("%s::handle == NULL() fail", __func__);
851        return;
852    }
853
854    exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
855    exynos_mutex_destroy(gsc_handle->cur_obj_mutex);
856    free(gsc_handle);
857    return;
858}
859
860void *exynos_gsc_create_exclusive(
861    int dev_num,
862    int mode,
863    int out_mode,
864    int allow_drm)
865{
866    int i     = 0;
867    int op_id = 0;
868    char mutex_name[32];
869    unsigned int total_sleep_time  = 0;
870    bool    gsc_flag = false;
871    int ret = 0;
872
873    Exynos_gsc_In();
874
875    if ((dev_num < 0) || (dev_num >= NUM_OF_GSC_HW)) {
876        ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
877        return NULL;
878    }
879
880    if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
881        ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
882        return NULL;
883    }
884
885    /* currently only gscalers 0 and 3 are DRM capable */
886    if (allow_drm && (dev_num != 0 && dev_num != 3)) {
887        ALOGE("%s::fail:: gscaler %d does not support drm\n", __func__,
888              dev_num);
889        return NULL;
890    }
891
892    struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
893    if (gsc_handle == NULL) {
894        ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
895        goto err;
896    }
897    memset(gsc_handle, 0, sizeof(struct GSC_HANDLE));
898    gsc_handle->gsc_fd = -1;
899    gsc_handle->gsc_mode = mode;
900    gsc_handle->gsc_id = dev_num;
901    gsc_handle->allow_drm = allow_drm;
902
903    gsc_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
904    gsc_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
905
906    gsc_handle->op_mutex = NULL;
907    for (i = 0; i < NUM_OF_GSC_HW; i++)
908        gsc_handle->obj_mutex[i] = NULL;
909
910    gsc_handle->cur_obj_mutex = NULL;
911    gsc_handle->flag_local_path = false;
912    gsc_handle->flag_exclusive_open = true;
913
914    srand(time(NULL));
915    op_id = rand() % 1000000; // just make random id
916    sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
917    gsc_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
918    if (gsc_handle->op_mutex == NULL) {
919        ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
920        goto err;
921    }
922
923    exynos_mutex_lock(gsc_handle->op_mutex);
924
925    sprintf(mutex_name, "%sObject%d", LOG_TAG, dev_num);
926    gsc_handle->cur_obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
927    if (gsc_handle->cur_obj_mutex == NULL) {
928        ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
929        goto err;
930    }
931
932    do {
933        if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == true) {
934            if (mode == GSC_M2M_MODE) {
935                gsc_handle->gsc_fd = m_exynos_gsc_m2m_create(dev_num);
936                if (gsc_handle->gsc_fd < 0) {
937                    ALOGE("%s::m_exynos_gsc_m2m_create(%i) fail", __func__, dev_num);
938                    goto err;
939                }
940            } else if (mode == GSC_OUTPUT_MODE) {
941                ret = m_exynos_gsc_output_create(gsc_handle, dev_num, out_mode);
942                if (ret < 0) {
943                    ALOGE("%s::m_exynos_gsc_output_create(%i) fail", __func__, dev_num);
944                    goto err;
945                }
946            }
947            /*else
948                gsc_handle->gsc_fd = m_exynos_gsc_capture_create(dev_num);*/
949
950            gsc_flag = true;
951            break;
952        }
953        usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
954        total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
955        ALOGV("%s::waiting for anthere process doens't use gscaler", __func__);
956    } while(total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
957
958    exynos_mutex_unlock(gsc_handle->op_mutex);
959    if (gsc_flag == true) {
960        Exynos_gsc_Out();
961        return (void *)gsc_handle;
962        }
963
964err:
965    if (gsc_handle) {
966        m_exynos_gsc_destroy(gsc_handle);
967
968        if (gsc_handle->cur_obj_mutex)
969            exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
970
971        for (i = 0; i < NUM_OF_GSC_HW; i++) {
972            if ((gsc_handle->obj_mutex[i] != NULL) &&
973                (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
974                if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
975                    ALOGE("%s::exynos_mutex_destroy() fail", __func__);
976            }
977        }
978
979        if (gsc_handle->op_mutex)
980            exynos_mutex_unlock(gsc_handle->op_mutex);
981
982        if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
983            ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
984
985        free(gsc_handle);
986    }
987
988    Exynos_gsc_Out();
989
990    return NULL;
991}
992
993void exynos_gsc_destroy(
994    void *handle)
995{
996    int i = 0;
997    struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)handle;
998
999    Exynos_gsc_In();
1000
1001    if (handle == NULL) {
1002        ALOGE("%s::handle == NULL() fail", __func__);
1003        return;
1004    }
1005
1006    exynos_mutex_lock(gsc_handle->op_mutex);
1007
1008    if (gsc_handle->flag_exclusive_open == false)
1009        exynos_mutex_lock(gsc_handle->cur_obj_mutex);
1010
1011    if (gsc_handle->gsc_mode == GSC_OUTPUT_MODE)
1012        m_exynos_gsc_out_destroy(gsc_handle);
1013    else
1014        m_exynos_gsc_destroy(gsc_handle);
1015
1016    exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
1017
1018    for (i = 0; i < NUM_OF_GSC_HW; i++) {
1019        if ((gsc_handle->obj_mutex[i] != NULL) &&
1020            (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
1021            if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
1022                ALOGE("%s::exynos_mutex_destroy(obj_mutex) fail", __func__);
1023        }
1024    }
1025
1026    exynos_mutex_unlock(gsc_handle->op_mutex);
1027
1028    if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
1029        ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
1030
1031    if (gsc_handle)
1032        free(gsc_handle);
1033
1034    Exynos_gsc_Out();
1035
1036}
1037
1038int exynos_gsc_set_src_format(
1039    void        *handle,
1040    unsigned int width,
1041    unsigned int height,
1042    unsigned int crop_left,
1043    unsigned int crop_top,
1044    unsigned int crop_width,
1045    unsigned int crop_height,
1046    unsigned int v4l2_colorformat,
1047    unsigned int cacheable,
1048    unsigned int mode_drm)
1049{
1050    Exynos_gsc_In();
1051
1052    struct GSC_HANDLE *gsc_handle;
1053    gsc_handle = (struct GSC_HANDLE *)handle;
1054
1055    if (handle == NULL) {
1056        ALOGE("%s::handle == NULL() fail", __func__);
1057        return -1;
1058    }
1059
1060    exynos_mutex_lock(gsc_handle->op_mutex);
1061
1062    gsc_handle->src.width            = width;
1063    gsc_handle->src.height           = height;
1064    gsc_handle->src.crop_left        = crop_left;
1065    gsc_handle->src.crop_top         = crop_top;
1066    gsc_handle->src.crop_width       = crop_width;
1067    gsc_handle->src.crop_height      = crop_height;
1068    gsc_handle->src.v4l2_colorformat = v4l2_colorformat;
1069    gsc_handle->src.cacheable        = cacheable;
1070    gsc_handle->src.mode_drm         = mode_drm;
1071    gsc_handle->src.dirty            = true;
1072
1073
1074    exynos_mutex_unlock(gsc_handle->op_mutex);
1075
1076    Exynos_gsc_Out();
1077
1078    return 0;
1079}
1080
1081int exynos_gsc_set_dst_format(
1082    void        *handle,
1083    unsigned int width,
1084    unsigned int height,
1085    unsigned int crop_left,
1086    unsigned int crop_top,
1087    unsigned int crop_width,
1088    unsigned int crop_height,
1089    unsigned int v4l2_colorformat,
1090    unsigned int cacheable,
1091    unsigned int mode_drm,
1092    unsigned int narrowRgb)
1093{
1094    Exynos_gsc_In();
1095
1096    struct GSC_HANDLE *gsc_handle;
1097    gsc_handle = (struct GSC_HANDLE *)handle;
1098
1099    if (handle == NULL) {
1100        ALOGE("%s::handle == NULL() fail", __func__);
1101        return -1;
1102    }
1103
1104    exynos_mutex_lock(gsc_handle->op_mutex);
1105
1106    gsc_handle->dst.width            = width;
1107    gsc_handle->dst.height           = height;
1108    gsc_handle->dst.crop_left        = crop_left;
1109    gsc_handle->dst.crop_top         = crop_top;
1110    gsc_handle->dst.crop_width       = crop_width;
1111    gsc_handle->dst.crop_height      = crop_height;
1112    gsc_handle->dst.v4l2_colorformat = v4l2_colorformat;
1113    gsc_handle->dst.cacheable        = cacheable;
1114    gsc_handle->dst.mode_drm         = mode_drm;
1115    gsc_handle->dst.dirty            = true;
1116    gsc_handle->dst.csc_range        = !narrowRgb;
1117
1118    exynos_mutex_unlock(gsc_handle->op_mutex);
1119
1120    Exynos_gsc_Out();
1121    return 0;
1122}
1123
1124int exynos_gsc_set_rotation(
1125    void *handle,
1126    int   rotation,
1127    int   flip_horizontal,
1128    int   flip_vertical)
1129{
1130    int ret = -1;
1131    struct GSC_HANDLE *gsc_handle;
1132    gsc_handle = (struct GSC_HANDLE *)handle;
1133
1134    if (handle == NULL) {
1135        ALOGE("%s::handle == NULL() fail", __func__);
1136        return ret;
1137    }
1138
1139    exynos_mutex_lock(gsc_handle->op_mutex);
1140
1141    int new_rotation = rotation % 360;
1142
1143    if (new_rotation % 90 != 0) {
1144        ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__, rotation);
1145        goto done;
1146    }
1147
1148    if(new_rotation < 0)
1149        new_rotation = -new_rotation;
1150
1151    gsc_handle->dst.rotation        = new_rotation;
1152    gsc_handle->dst.flip_horizontal = flip_horizontal;
1153    gsc_handle->dst.flip_vertical   = flip_vertical;
1154
1155    ret = 0;
1156done:
1157    exynos_mutex_unlock(gsc_handle->op_mutex);
1158
1159    return ret;
1160}
1161
1162int exynos_gsc_set_src_addr(
1163    void *handle,
1164    void *addr[3],
1165    int acquireFenceFd)
1166{
1167    struct GSC_HANDLE *gsc_handle;
1168    gsc_handle = (struct GSC_HANDLE *)handle;
1169
1170    Exynos_gsc_In();
1171
1172    if (handle == NULL) {
1173        ALOGE("%s::handle == NULL() fail", __func__);
1174        return -1;
1175    }
1176
1177    exynos_mutex_lock(gsc_handle->op_mutex);
1178
1179    gsc_handle->src.addr[0] = addr[0];
1180    gsc_handle->src.addr[1] = addr[1];
1181    gsc_handle->src.addr[2] = addr[2];
1182    gsc_handle->src.acquireFenceFd = acquireFenceFd;
1183
1184    exynos_mutex_unlock(gsc_handle->op_mutex);
1185
1186    Exynos_gsc_Out();
1187
1188    return 0;
1189}
1190
1191int exynos_gsc_set_dst_addr(
1192    void *handle,
1193    void *addr[3],
1194    int acquireFenceFd)
1195{
1196    struct GSC_HANDLE *gsc_handle;
1197    gsc_handle = (struct GSC_HANDLE *)handle;
1198    int ret = 0;
1199
1200    Exynos_gsc_In();
1201
1202    if (handle == NULL) {
1203        ALOGE("%s::handle == NULL() fail", __func__);
1204        return -1;
1205    }
1206
1207    exynos_mutex_lock(gsc_handle->op_mutex);
1208
1209    gsc_handle->dst.addr[0] = addr[0];
1210    gsc_handle->dst.addr[1] = addr[1];
1211    gsc_handle->dst.addr[2] = addr[2];
1212    gsc_handle->dst.acquireFenceFd = acquireFenceFd;
1213
1214
1215    exynos_mutex_unlock(gsc_handle->op_mutex);
1216
1217    Exynos_gsc_Out();
1218
1219    return ret;
1220}
1221
1222static void rotateValueHAL2GSC(unsigned int transform,
1223    unsigned int *rotate,
1224    unsigned int *hflip,
1225    unsigned int *vflip)
1226{
1227    int rotate_flag = transform & 0x7;
1228    *rotate = 0;
1229    *hflip = 0;
1230    *vflip = 0;
1231
1232    switch (rotate_flag) {
1233    case HAL_TRANSFORM_ROT_90:
1234        *rotate = 90;
1235        break;
1236    case HAL_TRANSFORM_ROT_180:
1237        *rotate = 180;
1238        break;
1239    case HAL_TRANSFORM_ROT_270:
1240        *rotate = 270;
1241        break;
1242    case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
1243        *rotate = 90;
1244        *vflip = 1; /* set vflip to compensate the rot & flip order. */
1245        break;
1246    case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
1247        *rotate = 90;
1248        *hflip = 1; /* set hflip to compensate the rot & flip order. */
1249        break;
1250    case HAL_TRANSFORM_FLIP_H:
1251        *hflip = 1;
1252         break;
1253    case HAL_TRANSFORM_FLIP_V:
1254        *vflip = 1;
1255         break;
1256    default:
1257        break;
1258    }
1259}
1260
1261static bool get_plane_size(int V4L2_PIX,
1262    unsigned int * size,
1263    unsigned int frame_size,
1264    int src_planes)
1265{
1266    unsigned int frame_ratio = 1;
1267    int src_bpp    = get_yuv_bpp(V4L2_PIX);
1268
1269    src_planes = (src_planes == -1) ? 1 : src_planes;
1270    frame_ratio = 8 * (src_planes -1) / (src_bpp - 8);
1271
1272    switch (src_planes) {
1273    case 1:
1274        switch (V4L2_PIX) {
1275        case V4L2_PIX_FMT_BGR32:
1276        case V4L2_PIX_FMT_RGB32:
1277            size[0] = frame_size << 2;
1278            break;
1279        case V4L2_PIX_FMT_RGB565X:
1280        case V4L2_PIX_FMT_NV16:
1281        case V4L2_PIX_FMT_NV61:
1282        case V4L2_PIX_FMT_YUYV:
1283        case V4L2_PIX_FMT_UYVY:
1284        case V4L2_PIX_FMT_VYUY:
1285        case V4L2_PIX_FMT_YVYU:
1286            size[0] = frame_size << 1;
1287            break;
1288        case V4L2_PIX_FMT_YUV420:
1289        case V4L2_PIX_FMT_NV12:
1290        case V4L2_PIX_FMT_NV21:
1291        case V4L2_PIX_FMT_NV21M:
1292            size[0] = (frame_size * 3) >> 1;
1293            break;
1294        default:
1295            ALOGE("%s::invalid color type", __func__);
1296            return false;
1297            break;
1298        }
1299        size[1] = 0;
1300        size[2] = 0;
1301        break;
1302    case 2:
1303        size[0] = frame_size;
1304        size[1] = frame_size / frame_ratio;
1305        size[2] = 0;
1306        break;
1307    case 3:
1308        size[0] = frame_size;
1309        size[1] = frame_size / frame_ratio;
1310        size[2] = frame_size / frame_ratio;
1311        break;
1312    default:
1313        ALOGE("%s::invalid color foarmt", __func__);
1314        return false;
1315        break;
1316    }
1317
1318    return true;
1319}
1320
1321int exynos_gsc_m2m_config(void *handle,
1322    exynos_gsc_img *src_img,
1323    exynos_gsc_img *dst_img)
1324{
1325    struct GSC_HANDLE *gsc_handle;
1326    int32_t      src_color_space;
1327    int32_t      dst_color_space;
1328    int ret;
1329    unsigned int rotate;
1330    unsigned int hflip;
1331    unsigned int vflip;
1332
1333    Exynos_gsc_In();
1334
1335    gsc_handle = (struct GSC_HANDLE *)handle;
1336    if (gsc_handle == NULL) {
1337        ALOGE("%s::gsc_handle == NULL() fail", __func__);
1338        return -1;
1339    }
1340
1341    if ((src_img->drmMode && !gsc_handle->allow_drm) ||
1342        (src_img->drmMode != dst_img->drmMode)) {
1343        ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
1344              __func__, gsc_handle->gsc_id,
1345              src_img->drmMode, dst_img->drmMode);
1346        return -1;
1347    }
1348
1349    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1350    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1351    rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1352    exynos_gsc_set_rotation(gsc_handle, rotate, hflip, vflip);
1353
1354    ret = exynos_gsc_set_src_format(gsc_handle,  src_img->fw, src_img->fh,
1355                                  src_img->x, src_img->y, src_img->w, src_img->h,
1356                                  src_color_space, src_img->cacheable, src_img->drmMode);
1357    if (ret < 0) {
1358        ALOGE("%s: fail: exynos_gsc_set_src_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1359            __func__, src_img->fw, src_img->fh, src_img->x, src_img->y, src_img->w, src_img->h,
1360            src_color_space, src_img->rot);
1361        return -1;
1362    }
1363
1364    ret = exynos_gsc_set_dst_format(gsc_handle, dst_img->fw, dst_img->fh,
1365                                  dst_img->x, dst_img->y, dst_img->w, dst_img->h,
1366                                  dst_color_space, dst_img->cacheable, dst_img->drmMode,
1367                                  dst_img->narrowRgb);
1368    if (ret < 0) {
1369        ALOGE("%s: fail: exynos_gsc_set_dst_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1370            __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y, dst_img->w, dst_img->h,
1371            src_color_space, dst_img->rot);
1372        return -1;
1373    }
1374
1375    Exynos_gsc_Out();
1376
1377    return 0;
1378}
1379
1380int exynos_gsc_out_config(void *handle,
1381    exynos_gsc_img *src_img,
1382    exynos_gsc_img *dst_img)
1383{
1384    struct GSC_HANDLE *gsc_handle;
1385    struct v4l2_format  fmt;
1386    struct v4l2_crop    crop;
1387    struct v4l2_requestbuffers reqbuf;
1388    struct v4l2_subdev_format sd_fmt;
1389    struct v4l2_subdev_crop   sd_crop;
1390    int i;
1391    unsigned int rotate;
1392    unsigned int hflip;
1393    unsigned int vflip;
1394    unsigned int plane_size[NUM_OF_GSC_PLANES];
1395    bool rgb;
1396    int csc_range = !dst_img->narrowRgb;
1397
1398    struct v4l2_rect dst_rect;
1399    int32_t      src_color_space;
1400    int32_t      dst_color_space;
1401    int32_t      src_planes;
1402
1403    gsc_handle = (struct GSC_HANDLE *)handle;
1404     if (gsc_handle == NULL) {
1405        ALOGE("%s::gsc_handle == NULL() fail", __func__);
1406        return -1;
1407    }
1408
1409    Exynos_gsc_In();
1410
1411     if (gsc_handle->src.stream_on != false) {
1412        ALOGE("Error: Src is already streamed on !!!!");
1413        return -1;
1414     }
1415
1416    memcpy(&gsc_handle->src_img, src_img, sizeof(exynos_gsc_img));
1417    memcpy(&gsc_handle->dst_img, dst_img, sizeof(exynos_gsc_img));
1418    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1419    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1420    src_planes = get_yuv_planes(src_color_space);
1421    src_planes = (src_planes == -1) ? 1 : src_planes;
1422    rgb = get_yuv_planes(dst_color_space) == -1;
1423    rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1424
1425    if (m_exynos_gsc_check_src_size(&gsc_handle->src_img.fw, &gsc_handle->src_img.fh,
1426                                        &gsc_handle->src_img.x, &gsc_handle->src_img.y,
1427                                        &gsc_handle->src_img.w, &gsc_handle->src_img.h,
1428                                        src_color_space) == false) {
1429            ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__);
1430            return -1;
1431    }
1432
1433    if (m_exynos_gsc_check_dst_size(&gsc_handle->dst_img.fw, &gsc_handle->dst_img.fh,
1434                                        &gsc_handle->dst_img.x, &gsc_handle->dst_img.y,
1435                                        &gsc_handle->dst_img.w, &gsc_handle->dst_img.h,
1436                                        dst_color_space,
1437                                        rotate) == false) {
1438            ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__);
1439            return -1;
1440    }
1441
1442    /*set: src v4l2_buffer*/
1443    gsc_handle->src.src_buf_idx = 0;
1444    gsc_handle->src.qbuf_cnt = 0;
1445    /* set format: src pad of GSC sub-dev*/
1446    sd_fmt.pad   = GSCALER_SUBDEV_PAD_SOURCE;
1447    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1448    if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1449        sd_fmt.format.width  = gsc_handle->dst_img.fw;
1450        sd_fmt.format.height = gsc_handle->dst_img.fh;
1451    } else {
1452        sd_fmt.format.width  = gsc_handle->dst_img.w;
1453        sd_fmt.format.height = gsc_handle->dst_img.h;
1454    }
1455    sd_fmt.format.code   = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1456                                    V4L2_MBUS_FMT_YUV8_1X24;
1457    if (exynos_subdev_s_fmt(gsc_handle->gsc_sd_entity->fd, &sd_fmt) < 0) {
1458            ALOGE("%s::GSC subdev set format failed", __func__);
1459            return -1;
1460    }
1461
1462    /* set crop: src crop of GSC sub-dev*/
1463    sd_crop.pad   = GSCALER_SUBDEV_PAD_SOURCE;
1464    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1465    if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1466        sd_crop.rect.left   = gsc_handle->dst_img.x;
1467        sd_crop.rect.top    = gsc_handle->dst_img.y;
1468        sd_crop.rect.width  = gsc_handle->dst_img.w;
1469        sd_crop.rect.height = gsc_handle->dst_img.h;
1470    } else {
1471        sd_crop.rect.left   = 0;
1472        sd_crop.rect.top    = 0;
1473        sd_crop.rect.width  = gsc_handle->dst_img.w;
1474        sd_crop.rect.height = gsc_handle->dst_img.h;
1475    }
1476    if (exynos_subdev_s_crop(gsc_handle->gsc_sd_entity->fd, &sd_crop) < 0) {
1477            ALOGE("%s::GSC subdev set crop failed", __func__);
1478            return -1;
1479    }
1480
1481    /* sink pad is connected to GSC out */
1482    /*  set format: sink sub-dev */
1483    if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1484        sd_fmt.pad   = FIMD_SUBDEV_PAD_SINK;
1485        sd_fmt.format.width  = gsc_handle->dst_img.w;
1486        sd_fmt.format.height = gsc_handle->dst_img.h;
1487    } else {
1488        sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SINK;
1489        sd_fmt.format.width  = gsc_handle->dst_img.w + gsc_handle->dst_img.x*2;
1490        sd_fmt.format.height = gsc_handle->dst_img.h + gsc_handle->dst_img.y*2;
1491    }
1492
1493    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1494    sd_fmt.format.code   = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1495                                    V4L2_MBUS_FMT_YUV8_1X24;
1496    if (exynos_subdev_s_fmt(gsc_handle->sink_sd_entity->fd, &sd_fmt) < 0) {
1497        ALOGE("%s::sink:set format failed (PAD=%d)", __func__, sd_fmt.pad);
1498        return -1;
1499    }
1500
1501    /*  set crop: sink sub-dev */
1502    if (gsc_handle->out_mode == GSC_OUT_FIMD)
1503        sd_crop.pad   = FIMD_SUBDEV_PAD_SINK;
1504    else
1505        sd_crop.pad   = MIXER_V_SUBDEV_PAD_SINK;
1506
1507    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1508    if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1509        sd_crop.rect.left   = gsc_handle->dst_img.x;
1510        sd_crop.rect.top    = gsc_handle->dst_img.y;
1511        sd_crop.rect.width  = gsc_handle->dst_img.w;
1512        sd_crop.rect.height = gsc_handle->dst_img.h;
1513    } else {
1514        sd_crop.rect.left   = 0;
1515        sd_crop.rect.top    = 0;
1516        sd_crop.rect.width  = gsc_handle->dst_img.w;
1517        sd_crop.rect.height = gsc_handle->dst_img.h;
1518    }
1519    if (exynos_subdev_s_crop(gsc_handle->sink_sd_entity->fd, &sd_crop) < 0) {
1520            ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__, sd_crop.pad);
1521            return -1;
1522    }
1523
1524    if (gsc_handle->out_mode != GSC_OUT_FIMD) {
1525        sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SOURCE;
1526        sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1527        sd_fmt.format.width  = gsc_handle->dst_img.w + gsc_handle->dst_img.x*2;
1528        sd_fmt.format.height = gsc_handle->dst_img.h + gsc_handle->dst_img.y*2;
1529        sd_fmt.format.code   = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
1530        if (exynos_subdev_s_fmt(gsc_handle->sink_sd_entity->fd, &sd_fmt) < 0) {
1531            ALOGE("%s::sink:set format failed (PAD=%d)", __func__, sd_fmt.pad);
1532            return -1;
1533        }
1534
1535        sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SOURCE;
1536        sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1537        sd_crop.rect.left   = gsc_handle->dst_img.x;
1538        sd_crop.rect.top    = gsc_handle->dst_img.y;
1539        sd_crop.rect.width  = gsc_handle->dst_img.w;
1540        sd_crop.rect.height = gsc_handle->dst_img.h;
1541        if (exynos_subdev_s_crop(gsc_handle->sink_sd_entity->fd, &sd_crop) < 0) {
1542            ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__, sd_crop.pad);
1543            return -1;
1544        }
1545    }
1546
1547    /*set GSC ctrls */
1548    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_ROTATE, rotate) < 0) {
1549        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed", __func__,  rotate);
1550        return -1;
1551    }
1552
1553    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_HFLIP, hflip) < 0) {
1554        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed", __func__,  hflip);
1555        return -1;
1556    }
1557
1558    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_VFLIP, vflip) < 0) {
1559        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed", __func__,  vflip);
1560        return -1;
1561    }
1562
1563     if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_CACHEABLE, 1) < 0) {
1564        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed", __func__);
1565        return -1;
1566    }
1567
1568    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd,
1569        V4L2_CID_CONTENT_PROTECTION, gsc_handle->src_img.drmMode) < 0) {
1570        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail", __func__);
1571        return -1;
1572    }
1573
1574    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_CSC_RANGE,
1575            csc_range)) {
1576        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail", __func__,
1577                csc_range);
1578        return -1;
1579    }
1580
1581      /* set src format  :GSC video dev*/
1582    fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1583    fmt.fmt.pix_mp.width            = gsc_handle->src_img.fw;
1584    fmt.fmt.pix_mp.height           = gsc_handle->src_img.fh;
1585    fmt.fmt.pix_mp.pixelformat    = src_color_space;
1586    fmt.fmt.pix_mp.field              = V4L2_FIELD_NONE;
1587    fmt.fmt.pix_mp.num_planes   = src_planes;
1588
1589    if (exynos_v4l2_s_fmt(gsc_handle->gsc_vd_entity->fd, &fmt) < 0) {
1590            ALOGE("%s::videodev set format failed", __func__);
1591            return -1;
1592    }
1593
1594    /* set src crop info :GSC video dev*/
1595    crop.type     = fmt.type;
1596    crop.c.left    = gsc_handle->src_img.x;
1597    crop.c.top     = gsc_handle->src_img.y;
1598    crop.c.width  = gsc_handle->src_img.w;
1599    crop.c.height = gsc_handle->src_img.h;
1600
1601    if (exynos_v4l2_s_crop(gsc_handle->gsc_vd_entity->fd, &crop) < 0) {
1602        ALOGE("%s::videodev set crop failed", __func__);
1603        return -1;
1604    }
1605
1606    reqbuf.type   = fmt.type;
1607    reqbuf.memory = V4L2_MEMORY_DMABUF;
1608    reqbuf.count  = MAX_BUFFERS_GSCALER_OUT;
1609
1610    if (exynos_v4l2_reqbufs(gsc_handle->gsc_vd_entity->fd, &reqbuf) < 0) {
1611        ALOGE("%s::request buffers failed", __func__);
1612        return -1;
1613    }
1614
1615    Exynos_gsc_Out();
1616
1617    return 0;
1618}
1619
1620static int exynos_gsc_out_run(void *handle,
1621    exynos_gsc_img *src_img)
1622{
1623    struct GSC_HANDLE *gsc_handle;
1624    struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
1625    struct v4l2_buffer buf;
1626    int32_t      src_color_space;
1627    int32_t      src_planes;
1628    int             i;
1629    unsigned int plane_size[NUM_OF_GSC_PLANES];
1630
1631    gsc_handle = (struct GSC_HANDLE *)handle;
1632    if (handle == NULL) {
1633        ALOGE("%s::handle == NULL() fail", __func__);
1634        return -1;
1635    }
1636
1637    /* All buffers have been queued, dequeue one */
1638    if (gsc_handle->src.qbuf_cnt == MAX_BUFFERS_GSCALER_OUT) {
1639        memset(&buf, 0, sizeof(struct v4l2_buffer));
1640        for (i = 0; i < MAX_BUFFERS_GSCALER_OUT; i++)
1641            memset(&planes[i], 0, sizeof(struct v4l2_plane));
1642
1643        buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1644        buf.memory   = V4L2_MEMORY_DMABUF;
1645        buf.length   = src_planes;
1646        buf.m.planes = planes;
1647
1648        if (exynos_v4l2_dqbuf(gsc_handle->gsc_vd_entity->fd, &buf) < 0) {
1649            ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)", __func__,
1650                gsc_handle->src.src_buf_idx, MAX_BUFFERS_GSCALER_OUT);
1651            return -1;
1652        }
1653        gsc_handle->src.qbuf_cnt--;
1654    }
1655
1656    memset(&buf, 0, sizeof(struct v4l2_buffer));
1657    for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1658        memset(&planes[i], 0, sizeof(struct v4l2_plane));
1659
1660    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc_handle->src_img.format);
1661    src_planes = get_yuv_planes(src_color_space);
1662    src_planes = (src_planes == -1) ? 1 : src_planes;
1663
1664    buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1665    buf.memory   = V4L2_MEMORY_DMABUF;
1666    buf.flags    = V4L2_BUF_FLAG_USE_SYNC;
1667    buf.length   = src_planes;
1668    buf.index    = gsc_handle->src.src_buf_idx;
1669    buf.m.planes = planes;
1670    buf.reserved = src_img->acquireFenceFd;
1671
1672    gsc_handle->src.addr[0] = src_img->yaddr;
1673    gsc_handle->src.addr[1] = src_img->uaddr;
1674    gsc_handle->src.addr[2] = src_img->vaddr;
1675
1676    if (get_plane_size(src_color_space, plane_size,
1677        gsc_handle->src_img.fw * gsc_handle->src_img.fh, src_planes) != true) {
1678        ALOGE("%s:get_plane_size:fail", __func__);
1679        return -1;
1680    }
1681
1682    for (i = 0; i < buf.length; i++) {
1683        buf.m.planes[i].m.fd = (int)gsc_handle->src.addr[i];
1684        buf.m.planes[i].length    = plane_size[i];
1685        buf.m.planes[i].bytesused = plane_size[i];
1686    }
1687
1688    /* Queue the buf */
1689    if (exynos_v4l2_qbuf(gsc_handle->gsc_vd_entity->fd, &buf) < 0) {
1690        ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)", __func__,
1691            gsc_handle->src.src_buf_idx, MAX_BUFFERS_GSCALER_OUT);
1692        return -1;
1693    }
1694    gsc_handle->src.src_buf_idx++;
1695    gsc_handle->src.src_buf_idx = gsc_handle->src.src_buf_idx % MAX_BUFFERS_GSCALER_OUT;
1696    gsc_handle->src.qbuf_cnt++;
1697
1698    if (gsc_handle->src.stream_on == false) {
1699        if (exynos_v4l2_streamon(gsc_handle->gsc_vd_entity->fd, buf.type) < 0) {
1700            ALOGE("%s::stream on failed", __func__);
1701            return -1;
1702        }
1703        gsc_handle->src.stream_on = true;
1704    }
1705
1706    src_img->releaseFenceFd = buf.reserved;
1707    return 0;
1708}
1709
1710int exynos_gsc_out_stop(void *handle)
1711{
1712    struct GSC_HANDLE *gsc_handle;
1713    struct v4l2_requestbuffers reqbuf;
1714    struct v4l2_buffer buf;
1715    struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
1716    int i;
1717
1718    Exynos_gsc_In();
1719
1720    gsc_handle = (struct GSC_HANDLE *)handle;
1721    if (handle == NULL) {
1722        ALOGE("%s::handle == NULL() fail", __func__);
1723        return -1;
1724    }
1725
1726    if (gsc_handle->src.stream_on == true) {
1727        if (exynos_v4l2_streamoff(gsc_handle->gsc_vd_entity->fd,
1728                                V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
1729            ALOGE("%s::stream off failed", __func__);
1730            return -1;
1731        }
1732        gsc_handle->src.stream_on = false;
1733    }
1734
1735    gsc_handle->src.src_buf_idx = 0;
1736    gsc_handle->src.qbuf_cnt = 0;
1737
1738    reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1739    reqbuf.memory = V4L2_MEMORY_DMABUF;
1740    reqbuf.count  = 0;
1741
1742    if (exynos_v4l2_reqbufs(gsc_handle->gsc_vd_entity->fd, &reqbuf) < 0) {
1743        ALOGE("%s::request buffers failed", __func__);
1744        return -1;
1745    }
1746
1747    Exynos_gsc_Out();
1748
1749    return 0;
1750}
1751
1752static int exynos_gsc_m2m_run_core(void *handle)
1753{
1754    struct GSC_HANDLE *gsc_handle;
1755    bool is_dirty;
1756    bool is_drm;
1757
1758    gsc_handle = (struct GSC_HANDLE *)handle;
1759
1760    Exynos_gsc_In();
1761
1762    if (handle == NULL) {
1763        ALOGE("%s::handle == NULL() fail", __func__);
1764        return -1;
1765    }
1766
1767    is_dirty = gsc_handle->src.dirty || gsc_handle->dst.dirty;
1768    is_drm = gsc_handle->src.mode_drm;
1769
1770    if (is_dirty && (gsc_handle->src.mode_drm != gsc_handle->dst.mode_drm)) {
1771        ALOGE("%s: drm mode mismatch between src and dst, gsc%d (s=%d d=%d)",
1772              __func__, gsc_handle->gsc_id, gsc_handle->src.mode_drm,
1773              gsc_handle->dst.mode_drm);
1774        return -1;
1775    } else if (is_drm && !gsc_handle->allow_drm) {
1776        ALOGE("%s: drm mode is not supported on gsc%d", __func__,
1777              gsc_handle->gsc_id);
1778        return -1;
1779    }
1780
1781    if (m_exynos_gsc_check_src_size(&gsc_handle->src.width, &gsc_handle->src.height,
1782                                    &gsc_handle->src.crop_left, &gsc_handle->src.crop_top,
1783                                    &gsc_handle->src.crop_width, &gsc_handle->src.crop_height,
1784                                    gsc_handle->src.v4l2_colorformat) == false) {
1785        ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__);
1786        return -1;
1787    }
1788
1789    if (m_exynos_gsc_check_dst_size(&gsc_handle->dst.width, &gsc_handle->dst.height,
1790                                    &gsc_handle->dst.crop_left, &gsc_handle->dst.crop_top,
1791                                    &gsc_handle->dst.crop_width, &gsc_handle->dst.crop_height,
1792                                    gsc_handle->dst.v4l2_colorformat,
1793                                    gsc_handle->dst.rotation) == false) {
1794        ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__);
1795        return -1;
1796    }
1797
1798    /* dequeue buffers from previous work if necessary */
1799    if (gsc_handle->src.stream_on == true) {
1800        if (exynos_gsc_m2m_wait_frame_done(handle) < 0) {
1801            ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__);
1802            return -1;
1803        }
1804    }
1805
1806    /*
1807     * need to set the content protection flag before doing reqbufs
1808     * in set_format
1809     */
1810    if (is_dirty && gsc_handle->allow_drm && is_drm) {
1811        if (exynos_v4l2_s_ctrl(gsc_handle->gsc_fd,
1812                               V4L2_CID_CONTENT_PROTECTION, is_drm) < 0) {
1813            ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
1814            return -1;
1815        }
1816    }
1817
1818    /*
1819     * from this point on, we have to ensure to call stop to clean up whatever
1820     * state we have set.
1821     */
1822
1823    if (gsc_handle->src.dirty) {
1824        if (m_exynos_gsc_set_format(gsc_handle->gsc_fd, &gsc_handle->src) == false) {
1825            ALOGE("%s::m_exynos_gsc_set_format(src) fail", __func__);
1826            goto done;
1827        }
1828        gsc_handle->src.dirty = false;
1829    }
1830
1831    if (gsc_handle->dst.dirty) {
1832        if (m_exynos_gsc_set_format(gsc_handle->gsc_fd, &gsc_handle->dst) == false) {
1833            ALOGE("%s::m_exynos_gsc_set_format(dst) fail", __func__);
1834            goto done;
1835        }
1836        gsc_handle->dst.dirty = false;
1837    }
1838
1839    /* if we are enabling drm, make sure to enable hw protection.
1840     * Need to do this before queuing buffers so that the mmu is reserved
1841     * and power domain is kept on.
1842     */
1843    if (is_dirty && gsc_handle->allow_drm && is_drm) {
1844        unsigned int protect_id = 0;
1845
1846        if (gsc_handle->gsc_id == 0) {
1847            protect_id = CP_PROTECT_GSC0;
1848        } else if (gsc_handle->gsc_id == 3) {
1849            protect_id = CP_PROTECT_GSC3;
1850        } else {
1851            ALOGE("%s::invalid gscaler id %d for content protection", __func__,
1852                  gsc_handle->gsc_id);
1853            goto done;
1854        }
1855
1856        if (CP_Enable_Path_Protection(protect_id) != 0) {
1857            ALOGE("%s::CP_Enable_Path_Protection failed", __func__);
1858            goto done;
1859        }
1860        gsc_handle->protection_enabled = true;
1861    }
1862
1863    if (m_exynos_gsc_set_addr(gsc_handle->gsc_fd, &gsc_handle->src) == false) {
1864        ALOGE("%s::m_exynos_gsc_set_addr(src) fail", __func__);
1865        goto done;
1866    }
1867
1868    if (m_exynos_gsc_set_addr(gsc_handle->gsc_fd, &gsc_handle->dst) == false) {
1869        ALOGE("%s::m_exynos_gsc_set_addr(dst) fail", __func__);
1870        goto done;
1871    }
1872
1873    if (gsc_handle->src.stream_on == false) {
1874        if (exynos_v4l2_streamon(gsc_handle->gsc_fd, gsc_handle->src.buf_type) < 0) {
1875            ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
1876            goto done;
1877        }
1878        gsc_handle->src.stream_on = true;
1879    }
1880
1881    if (gsc_handle->dst.stream_on == false) {
1882        if (exynos_v4l2_streamon(gsc_handle->gsc_fd, gsc_handle->dst.buf_type) < 0) {
1883            ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
1884            goto done;
1885        }
1886        gsc_handle->dst.stream_on = true;
1887    }
1888
1889    Exynos_gsc_Out();
1890
1891    return 0;
1892
1893done:
1894    exynos_gsc_m2m_stop(handle);
1895    return -1;
1896}
1897
1898static int exynos_gsc_m2m_wait_frame_done(void *handle)
1899{
1900    struct GSC_HANDLE *gsc_handle;
1901
1902    gsc_handle = (struct GSC_HANDLE *)handle;
1903
1904    Exynos_gsc_In();
1905
1906    if (handle == NULL) {
1907        ALOGE("%s::handle == NULL() fail", __func__);
1908        return -1;
1909    }
1910
1911    if ((gsc_handle->src.stream_on == false) || (gsc_handle->dst.stream_on == false)) {
1912        ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
1913        return -1;
1914    }
1915
1916    if (gsc_handle->src.buffer_queued) {
1917        if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->src.buffer) < 0) {
1918            ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
1919            return -1;
1920        }
1921        gsc_handle->src.buffer_queued = false;
1922    }
1923
1924    if (gsc_handle->dst.buffer_queued) {
1925        if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->dst.buffer) < 0) {
1926            ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
1927            return -1;
1928        }
1929        gsc_handle->dst.buffer_queued = false;
1930    }
1931
1932    Exynos_gsc_Out();
1933
1934    return 0;
1935}
1936
1937static int exynos_gsc_m2m_stop(void *handle)
1938{
1939    struct GSC_HANDLE *gsc_handle;
1940    struct v4l2_requestbuffers req_buf;
1941    int ret = 0;
1942
1943    gsc_handle = (struct GSC_HANDLE *)handle;
1944
1945    Exynos_gsc_In();
1946
1947    if (!gsc_handle->src.stream_on && !gsc_handle->dst.stream_on) {
1948        /* wasn't streaming, return success */
1949        return 0;
1950    } else if (gsc_handle->src.stream_on != gsc_handle->dst.stream_on) {
1951        ALOGE("%s: invalid state, queue stream state doesn't match (%d != %d)",
1952              __func__, gsc_handle->src.stream_on, gsc_handle->dst.stream_on);
1953        ret = -1;
1954    }
1955
1956    /*
1957     * we need to plow forward on errors below to make sure that if we had
1958     * turned on content protection on secure side, we turn it off.
1959     *
1960     * also, if we only failed to turn on one of the streams, we'll turn
1961     * the other one off correctly.
1962     */
1963    if (gsc_handle->src.stream_on == true) {
1964        if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->src.buf_type) < 0) {
1965            ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
1966            ret = -1;
1967        }
1968        gsc_handle->src.stream_on = false;
1969    }
1970
1971
1972    if (gsc_handle->dst.stream_on == true) {
1973        if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->dst.buf_type) < 0) {
1974            ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
1975            ret = -1;
1976        }
1977        gsc_handle->dst.stream_on = false;
1978    }
1979
1980    /* if drm is enabled */
1981    if (gsc_handle->allow_drm && gsc_handle->protection_enabled) {
1982        unsigned int protect_id = 0;
1983
1984        if (gsc_handle->gsc_id == 0)
1985            protect_id = CP_PROTECT_GSC0;
1986        else if (gsc_handle->gsc_id == 3)
1987            protect_id = CP_PROTECT_GSC3;
1988
1989        CP_Disable_Path_Protection(protect_id);
1990        gsc_handle->protection_enabled = false;
1991    }
1992
1993    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_fd,
1994                           V4L2_CID_CONTENT_PROTECTION, 0) < 0) {
1995        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
1996              __func__);
1997        ret = -1;
1998    }
1999
2000    /* src: clear_buf */
2001    req_buf.count  = 0;
2002    req_buf.type   = gsc_handle->src.buf_type;
2003    req_buf.memory = V4L2_MEMORY_DMABUF;
2004    if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
2005        ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
2006        ret = -1;
2007    }
2008
2009    /* dst: clear_buf */
2010    req_buf.count  = 0;
2011    req_buf.type   = gsc_handle->dst.buf_type;
2012    req_buf.memory = V4L2_MEMORY_DMABUF;
2013    if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
2014        ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
2015        ret = -1;
2016    }
2017
2018    Exynos_gsc_Out();
2019
2020    return ret;
2021}
2022
2023int exynos_gsc_convert(
2024    void *handle)
2025{
2026    struct GSC_HANDLE *gsc_handle;
2027    int ret    = -1;
2028    gsc_handle = (struct GSC_HANDLE *)handle;
2029
2030    Exynos_gsc_In();
2031
2032    if (handle == NULL) {
2033        ALOGE("%s::handle == NULL() fail", __func__);
2034        return -1;
2035    }
2036
2037    exynos_mutex_lock(gsc_handle->op_mutex);
2038
2039    if (gsc_handle->flag_local_path == true) {
2040        ALOGE("%s::this exynos_gsc is connected by another hw internaly. So, don't call exynos_gsc_convert()", __func__);
2041            goto done;
2042        }
2043
2044    if (exynos_gsc_m2m_run_core(handle) < 0) {
2045        ALOGE("%s::exynos_gsc_run_core fail", __func__);
2046            goto done;
2047        }
2048
2049    if (exynos_gsc_m2m_wait_frame_done(handle) < 0) {
2050        ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
2051        goto done;
2052    }
2053
2054    if (gsc_handle->src.releaseFenceFd >= 0) {
2055        close(gsc_handle->src.releaseFenceFd);
2056        gsc_handle->src.releaseFenceFd = -1;
2057    }
2058
2059    if (gsc_handle->dst.releaseFenceFd >= 0) {
2060        close(gsc_handle->dst.releaseFenceFd);
2061        gsc_handle->dst.releaseFenceFd = -1;
2062    }
2063
2064    if (exynos_gsc_m2m_stop(handle) < 0) {
2065        ALOGE("%s::exynos_gsc_m2m_stop", __func__);
2066        goto done;
2067    }
2068
2069    ret = 0;
2070
2071done:
2072    if (gsc_handle->flag_exclusive_open == false) {
2073        if (gsc_handle->flag_local_path == false)
2074            exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
2075    }
2076
2077    exynos_mutex_unlock(gsc_handle->op_mutex);
2078
2079    Exynos_gsc_Out();
2080
2081    return ret;
2082}
2083
2084int exynos_gsc_m2m_run(void *handle,
2085    exynos_gsc_img *src_img,
2086    exynos_gsc_img *dst_img)
2087{
2088    struct GSC_HANDLE *gsc_handle = handle;
2089    void *addr[3] = {NULL, NULL, NULL};
2090    int ret = 0;
2091
2092    Exynos_gsc_In();
2093
2094    addr[0] = (void *)src_img->yaddr;
2095    addr[1] = (void *)src_img->uaddr;
2096    addr[2] = (void *)src_img->vaddr;
2097    ret = exynos_gsc_set_src_addr(handle, addr, src_img->acquireFenceFd);
2098    if (ret < 0) {
2099        ALOGE("%s::fail: exynos_gsc_set_src_addr[%x %x %x]", __func__,
2100            (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]);
2101        return -1;
2102    }
2103
2104    addr[0] = (void *)dst_img->yaddr;
2105    addr[1] = (void *)dst_img->uaddr;
2106    addr[2] = (void *)dst_img->vaddr;
2107    ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->acquireFenceFd);
2108    if (ret < 0) {
2109        ALOGE("%s::fail: exynos_gsc_set_dst_addr[%x %x %x]", __func__,
2110            (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]);
2111        return -1;
2112    }
2113
2114    ret = exynos_gsc_m2m_run_core(handle);
2115     if (ret < 0) {
2116        ALOGE("%s::fail: exynos_gsc_m2m_run_core", __func__);
2117        return -1;
2118    }
2119
2120    if (src_img->acquireFenceFd >= 0) {
2121        close(src_img->acquireFenceFd);
2122        src_img->acquireFenceFd = -1;
2123    }
2124
2125    if (dst_img->acquireFenceFd >= 0) {
2126        close(dst_img->acquireFenceFd);
2127        dst_img->acquireFenceFd = -1;
2128    }
2129
2130    src_img->releaseFenceFd = gsc_handle->src.releaseFenceFd;
2131    dst_img->releaseFenceFd = gsc_handle->dst.releaseFenceFd;
2132
2133    Exynos_gsc_Out();
2134
2135    return 0;
2136}
2137
2138int exynos_gsc_config_exclusive(void *handle,
2139    exynos_gsc_img *src_img,
2140    exynos_gsc_img *dst_img)
2141{
2142
2143    Exynos_gsc_In();
2144
2145     struct GSC_HANDLE *gsc_handle;
2146    int ret = 0;
2147    gsc_handle = (struct GSC_HANDLE *)handle;
2148    if (handle == NULL) {
2149        ALOGE("%s::handle == NULL() fail", __func__);
2150        return -1;
2151    }
2152
2153    switch (gsc_handle->gsc_mode) {
2154    case GSC_M2M_MODE:
2155        ret = exynos_gsc_m2m_config(handle, src_img, dst_img);
2156        break;
2157    case GSC_OUTPUT_MODE:
2158        ret = exynos_gsc_out_config(handle, src_img, dst_img);
2159        break;
2160    case  GSC_CAPTURE_MODE:
2161        //to do
2162        break;
2163    default:
2164        break;
2165    }
2166
2167    Exynos_gsc_Out();
2168
2169    return ret;
2170
2171}
2172
2173int exynos_gsc_run_exclusive(void *handle,
2174    exynos_gsc_img *src_img,
2175    exynos_gsc_img *dst_img)
2176{
2177    struct GSC_HANDLE *gsc_handle;
2178    int ret = 0;
2179
2180    Exynos_gsc_In();
2181
2182    gsc_handle = (struct GSC_HANDLE *)handle;
2183    if (handle == NULL) {
2184        ALOGE("%s::handle == NULL() fail", __func__);
2185        return -1;
2186    }
2187
2188    switch (gsc_handle->gsc_mode) {
2189    case GSC_M2M_MODE:
2190        ret = exynos_gsc_m2m_run(handle, src_img, dst_img);
2191        break;
2192    case GSC_OUTPUT_MODE:
2193        ret = exynos_gsc_out_run(handle, src_img);
2194        break;
2195    case  GSC_CAPTURE_MODE:
2196        //to do
2197        break;
2198    default:
2199        break;
2200    }
2201
2202    Exynos_gsc_Out();
2203
2204    return ret;
2205}
2206
2207int exynos_gsc_wait_frame_done_exclusive(void *handle)
2208{
2209    struct GSC_HANDLE *gsc_handle;
2210    int ret = 0;
2211    gsc_handle = (struct GSC_HANDLE *)handle;
2212
2213    Exynos_gsc_In();
2214
2215    if (handle == NULL) {
2216        ALOGE("%s::handle == NULL() fail", __func__);
2217        return -1;
2218    }
2219
2220    if (gsc_handle->gsc_mode == GSC_M2M_MODE)
2221        ret = exynos_gsc_m2m_wait_frame_done(handle);
2222
2223    Exynos_gsc_Out();
2224
2225    return ret;
2226}
2227
2228int exynos_gsc_stop_exclusive(void *handle)
2229{
2230    struct GSC_HANDLE *gsc_handle;
2231    int ret = 0;
2232    gsc_handle = (struct GSC_HANDLE *)handle;
2233
2234    Exynos_gsc_In();
2235
2236    if (handle == NULL) {
2237        ALOGE("%s::handle == NULL() fail", __func__);
2238        return -1;
2239    }
2240
2241    switch (gsc_handle->gsc_mode) {
2242    case GSC_M2M_MODE:
2243        ret = exynos_gsc_m2m_stop(handle);
2244        break;
2245    case GSC_OUTPUT_MODE:
2246        ret = exynos_gsc_out_stop(handle);
2247        break;
2248    case  GSC_CAPTURE_MODE:
2249        //to do
2250        break;
2251    default:
2252        break;
2253    }
2254
2255    Exynos_gsc_Out();
2256
2257    return ret;
2258}
2259
2260int exynos_gsc_connect(
2261    void *handle,
2262    void *hw)
2263{
2264    struct GSC_HANDLE *gsc_handle;
2265    int ret    = -1;
2266    gsc_handle = (struct GSC_HANDLE *)handle;
2267
2268    Exynos_gsc_In();
2269
2270    if (handle == NULL) {
2271        ALOGE("%s::handle == NULL() fail", __func__);
2272        return -1;
2273    }
2274
2275    exynos_mutex_lock(gsc_handle->op_mutex);
2276
2277    gsc_handle->flag_local_path = true;
2278
2279    if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == false) {
2280        if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle) == false) {
2281            ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__);
2282            goto done;
2283        }
2284    }
2285
2286    ret = 0;
2287
2288    Exynos_gsc_Out();
2289
2290done:
2291    exynos_mutex_unlock(gsc_handle->op_mutex);
2292
2293    return ret;
2294}
2295
2296int exynos_gsc_disconnect(
2297    void *handle,
2298    void *hw)
2299{
2300    struct GSC_HANDLE *gsc_handle;
2301    gsc_handle = (struct GSC_HANDLE *)handle;
2302
2303    Exynos_gsc_In();
2304
2305    if (handle == NULL) {
2306        ALOGE("%s::handle == NULL() fail", __func__);
2307        return -1;
2308    }
2309
2310    exynos_mutex_lock(gsc_handle->op_mutex);
2311
2312    gsc_handle->flag_local_path = false;
2313
2314    exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
2315
2316    exynos_mutex_unlock(gsc_handle->op_mutex);
2317
2318    Exynos_gsc_Out();
2319
2320    return 0;
2321}
2322