Home | History | Annotate | Download | only in librotator
      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_rotator.c
     20  * \brief     source file for exynos_rotator HAL
     21  * \author    Sunmi Lee (carrotsm.lee (at) samsung.com)
     22  * \date      2012/03/05
     23  *
     24  * <b>Revision History: </b>
     25  * - 2012/03/05 : Sunmi Lee (carrotsm.lee (at) samsung.com) \n
     26  *   Create
     27  *
     28  */
     29 
     30 //#define LOG_NDEBUG 0
     31 #define LOG_TAG "libexynosrotator"
     32 #include <cutils/log.h>
     33 
     34 #include <sys/types.h>
     35 #include <sys/ioctl.h>
     36 #include <videodev2.h>
     37 #include <fcntl.h>
     38 #include <stdbool.h>
     39 #include <string.h>
     40 #include <unistd.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <time.h>
     44 
     45 #include "exynos_rotator.h"
     46 
     47 #include "exynos_format.h"
     48 #include "ExynosMutex.h"
     49 #include "exynos_v4l2.h"
     50 
     51 #define NUM_OF_ROTATOR_PLANES           (3)
     52 #define NODE_NUM_ROTATOR                (21)
     53 #define PFX_NODE_ROTATOR                "/dev/video"
     54 
     55 #define ROTATOR_MIN_W_SIZE (8)
     56 #define ROTATOR_MIN_H_SIZE (8)
     57 
     58 #define MAX_ROTATOR_WAITING_TIME_FOR_TRYLOCK (16000) // 16msec
     59 #define ROTATOR_WAITING_TIME_FOR_TRYLOCK      (8000) //  8msec
     60 
     61 struct rotator_info {
     62     unsigned int       width;
     63     unsigned int       height;
     64     unsigned int       crop_left;
     65     unsigned int       crop_top;
     66     unsigned int       crop_width;
     67     unsigned int       crop_height;
     68     unsigned int       v4l2_colorformat;
     69     unsigned int       cacheable;
     70 
     71     int                rotation;
     72 
     73     void              *addr[NUM_OF_ROTATOR_PLANES];
     74     bool               stream_on;
     75 
     76     enum v4l2_buf_type buf_type;
     77     struct v4l2_format format;
     78     struct v4l2_buffer buffer;
     79     struct v4l2_plane  planes[NUM_OF_ROTATOR_PLANES];
     80     struct v4l2_crop   crop;
     81 };
     82 
     83 struct ROTATOR_HANDLE {
     84     int              rotator_fd;
     85     struct rotator_info  src;
     86     struct rotator_info  dst;
     87     void                *op_mutex;
     88     void                *obj_mutex;
     89     void                *cur_obj_mutex;
     90 };
     91 
     92 static unsigned int m_rotator_get_plane_count(
     93     int v4l_pixel_format)
     94 {
     95     int plane_count = 0;
     96 
     97     switch (v4l_pixel_format) {
     98     case V4L2_PIX_FMT_RGB32:
     99     case V4L2_PIX_FMT_BGR32:
    100     case V4L2_PIX_FMT_RGB24:
    101     case V4L2_PIX_FMT_RGB565:
    102     case V4L2_PIX_FMT_RGB555X:
    103     case V4L2_PIX_FMT_RGB444:
    104         plane_count = 1;
    105         break;
    106     case V4L2_PIX_FMT_NV12M:
    107     case V4L2_PIX_FMT_NV12MT_16X16:
    108     case V4L2_PIX_FMT_NV21:
    109     case V4L2_PIX_FMT_NV16:
    110     case V4L2_PIX_FMT_NV61:
    111         plane_count = 2;
    112         break;
    113     case V4L2_PIX_FMT_YVU420M:
    114     case V4L2_PIX_FMT_YUV422P:
    115     case V4L2_PIX_FMT_YUYV:
    116     case V4L2_PIX_FMT_UYVY:
    117         plane_count = 3;
    118         break;
    119     default:
    120         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)",
    121              __func__, v4l_pixel_format);
    122         plane_count = -1;
    123         break;
    124     }
    125 
    126     return plane_count;
    127 }
    128 
    129 static unsigned int m_rotator_get_plane_size(
    130     unsigned int *plane_size,
    131     unsigned int  width,
    132     unsigned int  height,
    133     int           v4l_pixel_format)
    134 {
    135     switch (v4l_pixel_format) {
    136     case V4L2_PIX_FMT_RGB32:
    137     case V4L2_PIX_FMT_BGR32:
    138         plane_size[0] = width * height * 4;
    139         break;
    140     case V4L2_PIX_FMT_RGB24:
    141         plane_size[0] = width * height * 3;
    142         break;
    143     case V4L2_PIX_FMT_RGB565:
    144     case V4L2_PIX_FMT_RGB555X:
    145     case V4L2_PIX_FMT_RGB444:
    146         plane_size[0] = width * height * 2;
    147         break;
    148     case V4L2_PIX_FMT_NV12M:
    149     case V4L2_PIX_FMT_NV21:
    150     case V4L2_PIX_FMT_NV16:
    151     case V4L2_PIX_FMT_NV61:
    152         plane_size[0] = width * height;
    153         plane_size[1] = width * (height / 2);
    154         break;
    155     case V4L2_PIX_FMT_NV12MT_16X16:
    156         plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
    157         plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
    158         break;
    159     case V4L2_PIX_FMT_YVU420M:
    160     case V4L2_PIX_FMT_YUV422P:
    161     case V4L2_PIX_FMT_YUYV:
    162     case V4L2_PIX_FMT_UYVY:
    163         plane_size[0] = width * height;
    164         plane_size[1] = (width / 2) * (height / 2);
    165         plane_size[2] = (width / 2) * (height / 2);
    166         break;
    167     default:
    168         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)",
    169              __func__, v4l_pixel_format);
    170         return -1;
    171         break;
    172     }
    173 
    174     return 0;
    175 }
    176 
    177 static int m_exynos_rotator_multiple_of_n(
    178     int number, int N)
    179 {
    180     int result = number;
    181     switch (N) {
    182     case 1:
    183     case 2:
    184     case 4:
    185     case 8:
    186     case 16:
    187     case 32:
    188     case 64:
    189     case 128:
    190     case 256:
    191         result = (number - (number & (N-1)));
    192         break;
    193     default:
    194         result = number - (number % N);
    195         break;
    196     }
    197     return result;
    198 }
    199 
    200 static bool m_exynos_rotator_check_src_size(
    201     unsigned int *w,      unsigned int *h,
    202     unsigned int *crop_x, unsigned int *crop_y,
    203     unsigned int *crop_w, unsigned int *crop_h,
    204     int v4l2_colorformat)
    205 {
    206     if (*w < ROTATOR_MIN_W_SIZE || *h < ROTATOR_MIN_H_SIZE) {
    207         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
    208             __func__, ROTATOR_MIN_W_SIZE, *w, ROTATOR_MIN_H_SIZE, *h);
    209         return false;
    210     }
    211 
    212     if (*crop_w < ROTATOR_MIN_W_SIZE || *crop_h < ROTATOR_MIN_H_SIZE) {
    213         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
    214             __func__, ROTATOR_MIN_W_SIZE,* crop_w, ROTATOR_MIN_H_SIZE, *crop_h);
    215         return false;
    216     }
    217 
    218     switch (v4l2_colorformat) {
    219     // YUV420 3p
    220     case V4L2_PIX_FMT_YUV420M:
    221     case V4L2_PIX_FMT_YVU420M:
    222         *w = ALIGN(*w, 16);
    223         *h = ALIGN(*h, 16);
    224         break;
    225     // YUV420 2p
    226     case V4L2_PIX_FMT_NV12M:
    227     case V4L2_PIX_FMT_NV12MT:
    228     case V4L2_PIX_FMT_NV21M:
    229         *w = ALIGN(*w, 8);
    230         *h = ALIGN(*h, 8);
    231         break;
    232     // YUV422
    233     case V4L2_PIX_FMT_YUYV:
    234     case V4L2_PIX_FMT_YUV422P:
    235     case V4L2_PIX_FMT_UYVY:
    236     case V4L2_PIX_FMT_NV21:
    237     case V4L2_PIX_FMT_NV16:
    238     case V4L2_PIX_FMT_YVYU:
    239     case V4L2_PIX_FMT_VYUY:
    240     // RGB
    241     case V4L2_PIX_FMT_RGB32:
    242     case V4L2_PIX_FMT_RGB24:
    243     case V4L2_PIX_FMT_RGB565:
    244     case V4L2_PIX_FMT_BGR32:
    245     case V4L2_PIX_FMT_RGB555X:
    246     case V4L2_PIX_FMT_RGB444:
    247     default:
    248         *w = ALIGN(*w, 4);
    249         *h = ALIGN(*h, 4);
    250         break;
    251     }
    252     *crop_w = m_exynos_rotator_multiple_of_n(*crop_w, 4);
    253     *crop_h = m_exynos_rotator_multiple_of_n(*crop_h, 4);
    254 
    255     return true;
    256 }
    257 
    258 static bool m_exynos_rotator_check_dst_size(
    259     unsigned int *w,      unsigned int *h,
    260     unsigned int *crop_x, unsigned int *crop_y,
    261     unsigned int *crop_w, unsigned int *crop_h,
    262     int v4l2_colorformat,
    263     int rotation)
    264 {
    265     unsigned int *new_w;
    266     unsigned int *new_h;
    267     unsigned int *new_crop_w;
    268     unsigned int *new_crop_h;
    269 
    270     if (rotation == 90 || rotation == 270) {
    271         new_w = h;
    272         new_h = w;
    273         new_crop_w = crop_h;
    274         new_crop_h = crop_w;
    275     } else {
    276         new_w = w;
    277         new_h = h;
    278         new_crop_w = crop_w;
    279         new_crop_h = crop_h;
    280     }
    281 
    282     if (*w < ROTATOR_MIN_W_SIZE || *h < ROTATOR_MIN_H_SIZE) {
    283         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
    284             __func__, ROTATOR_MIN_W_SIZE, *w, ROTATOR_MIN_H_SIZE, *h);
    285         return false;
    286     }
    287 
    288     if (*crop_w < ROTATOR_MIN_W_SIZE || *crop_h < ROTATOR_MIN_H_SIZE) {
    289         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
    290             __func__, ROTATOR_MIN_W_SIZE,* crop_w, ROTATOR_MIN_H_SIZE, *crop_h);
    291         return false;
    292     }
    293 
    294     switch (v4l2_colorformat) {
    295     // YUV420 3p
    296     case V4L2_PIX_FMT_YUV420M:
    297     case V4L2_PIX_FMT_YVU420M:
    298         *new_w = ALIGN(*new_w, 16);
    299         *new_h = ALIGN(*new_h, 16);
    300         break;
    301     // YUV420 2p
    302     case V4L2_PIX_FMT_NV12M:
    303     case V4L2_PIX_FMT_NV12MT:
    304     case V4L2_PIX_FMT_NV21M:
    305         *new_w = ALIGN(*new_w, 8);
    306         *new_h = ALIGN(*new_h, 8);
    307         break;
    308     // YUV422
    309     case V4L2_PIX_FMT_YUYV:
    310     case V4L2_PIX_FMT_YUV422P:
    311     case V4L2_PIX_FMT_UYVY:
    312     case V4L2_PIX_FMT_NV21:
    313     case V4L2_PIX_FMT_NV16:
    314     case V4L2_PIX_FMT_YVYU:
    315     case V4L2_PIX_FMT_VYUY:
    316     // RGB
    317     case V4L2_PIX_FMT_RGB32:
    318     case V4L2_PIX_FMT_RGB24:
    319     case V4L2_PIX_FMT_RGB565:
    320     case V4L2_PIX_FMT_BGR32:
    321     case V4L2_PIX_FMT_RGB555X:
    322     case V4L2_PIX_FMT_RGB444:
    323     default:
    324         *new_w = ALIGN(*new_w, 4);
    325         *new_h = ALIGN(*new_h, 4);
    326         break;
    327     }
    328     *new_crop_w = m_exynos_rotator_multiple_of_n(*new_crop_w, 4);
    329     *new_crop_h = m_exynos_rotator_multiple_of_n(*new_crop_h, 4);
    330 
    331     return true;
    332 }
    333 
    334 static int m_exynos_rotator_create(void)
    335 {
    336     int          fd = 0;
    337     unsigned int cap;
    338     char         node[32];
    339 
    340     sprintf(node, "%s%d", PFX_NODE_ROTATOR, NODE_NUM_ROTATOR);
    341     fd = exynos_v4l2_open(node, O_RDWR);
    342     if (fd < 0) {
    343         ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
    344         return -1;
    345     }
    346 
    347     cap = V4L2_CAP_STREAMING |
    348           V4L2_CAP_VIDEO_OUTPUT_MPLANE |
    349           V4L2_CAP_VIDEO_CAPTURE_MPLANE;
    350 
    351     if (exynos_v4l2_querycap(fd, cap) == false) {
    352         ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
    353         if (0 < fd)
    354             close(fd);
    355         fd = 0;
    356         return -1;
    357     }
    358     return fd;
    359 }
    360 
    361 static bool m_exynos_rotator_destroy(
    362     struct ROTATOR_HANDLE *rotator_handle)
    363 {
    364     if (rotator_handle->src.stream_on == true) {
    365         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0)
    366             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
    367 
    368         rotator_handle->src.stream_on = false;
    369     }
    370 
    371     if (rotator_handle->dst.stream_on == true) {
    372         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0)
    373             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
    374 
    375         rotator_handle->dst.stream_on = false;
    376     }
    377 
    378     if (0 < rotator_handle->rotator_fd)
    379         close(rotator_handle->rotator_fd);
    380     rotator_handle->rotator_fd = 0;
    381 
    382     return true;
    383 }
    384 
    385 bool m_exynos_rotator_find_and_trylock_and_create(
    386     struct ROTATOR_HANDLE *rotator_handle)
    387 {
    388     int          i                 = 0;
    389     bool         flag_find_new_rotator = false;
    390     unsigned int total_sleep_time  = 0;
    391 
    392     do {
    393         if (exynos_mutex_trylock(rotator_handle->obj_mutex) == true) {
    394 
    395             // destroy old one.
    396             m_exynos_rotator_destroy(rotator_handle);
    397 
    398             // create new one.
    399             rotator_handle->rotator_fd = m_exynos_rotator_create();
    400             if (rotator_handle->rotator_fd < 0) {
    401                 rotator_handle->rotator_fd = 0;
    402                 exynos_mutex_unlock(rotator_handle->obj_mutex);
    403                 continue;
    404             }
    405 
    406             if (rotator_handle->cur_obj_mutex)
    407                 exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    408 
    409             rotator_handle->cur_obj_mutex = rotator_handle->obj_mutex;
    410 
    411             flag_find_new_rotator = true;
    412             break;
    413         }
    414 
    415         // waiting for another process doesn't use rotator.
    416         // we need to make decision how to do.
    417         if (flag_find_new_rotator == false) {
    418             usleep(ROTATOR_WAITING_TIME_FOR_TRYLOCK);
    419             total_sleep_time += ROTATOR_WAITING_TIME_FOR_TRYLOCK;
    420             ALOGV("%s::waiting for anthere process doens't use rotator", __func__);
    421         }
    422 
    423     } while(   flag_find_new_rotator == false
    424             && total_sleep_time < MAX_ROTATOR_WAITING_TIME_FOR_TRYLOCK);
    425 
    426     if (flag_find_new_rotator == false)
    427         ALOGE("%s::we don't have no available rotator.. fail", __func__);
    428 
    429     return flag_find_new_rotator;
    430 }
    431 
    432 static bool m_exynos_rotator_set_format(
    433     int                  fd,
    434     struct rotator_info *info,
    435     bool                 force)
    436 {
    437     struct v4l2_requestbuffers req_buf;
    438     int                        plane_count;
    439 
    440     plane_count = m_rotator_get_plane_count(info->v4l2_colorformat);
    441     if (plane_count < 0) {
    442         ALOGE("%s::not supported v4l2_colorformat", __func__);
    443         return false;
    444     }
    445 
    446     if (force == false) {
    447         // format
    448         info->format.type = info->buf_type;
    449         if (exynos_v4l2_g_fmt(fd, &info->format) < 0) {
    450             ALOGE("%s::exynos_v4l2_g_fmt() fail type=%d", __func__, info->buf_type);
    451             return false;
    452         }
    453 
    454         if (info->width            != info->format.fmt.pix_mp.width ||
    455             info->height           != info->format.fmt.pix_mp.height ||
    456             info->v4l2_colorformat != info->format.fmt.pix_mp.pixelformat) {
    457             ALOGV("%s::info is different..)", __func__);
    458             goto set_hw;
    459         }
    460 
    461         // crop
    462         if (info->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    463         info->crop.type = info->buf_type;
    464         if (exynos_v4l2_g_crop(fd, &info->crop) < 0) {
    465             ALOGE("%s::exynos_v4l2_g_crop() fail", __func__);
    466             return false;
    467         }
    468 
    469         if (info->crop_left   != info->crop.c.left ||
    470             info->crop_top    != info->crop.c.top ||
    471             info->crop_width  != info->crop.c.width ||
    472             info->crop_height != info->crop.c.height) {
    473             ALOGV("%s::crop is different..", __func__);
    474             goto set_hw;
    475         }
    476         }
    477 
    478         // rotation value;
    479 
    480         int value = 0;
    481 
    482         if (exynos_v4l2_g_ctrl(fd, V4L2_CID_ROTATE, &value) < 0) {
    483             ALOGE("%s::exynos_v4l2_g_ctrl(V4L2_CID_ROTATE) fail", __func__);
    484             return false;
    485         }
    486 
    487         if (info->rotation != value) {
    488             ALOGV("%s::rotation is different..", __func__);
    489             goto set_hw;
    490         }
    491 
    492         // skip s_fmt
    493         ALOGV("%s::fmt, crop is same with old-one, so skip s_fmt crop..", __func__);
    494         return true;
    495     }
    496 
    497 set_hw:
    498 
    499     if (info->stream_on == true) {
    500         if (exynos_v4l2_streamoff(fd, info->buf_type) < 0) {
    501             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
    502             return false;
    503         }
    504         info->stream_on = false;
    505     }
    506 
    507     if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
    508         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
    509         return false;
    510     }
    511 
    512     info->format.fmt.pix_mp.width       = info->width;
    513     info->format.fmt.pix_mp.height      = info->height;
    514     info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
    515     info->format.fmt.pix_mp.field       = V4L2_FIELD_ANY;
    516     info->format.fmt.pix_mp.num_planes  = plane_count;
    517 
    518     if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
    519         ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
    520         return false;
    521     }
    522 
    523     if (info->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    524     info->crop.type     = info->buf_type;
    525     info->crop.c.left   = info->crop_left;
    526     info->crop.c.top    = info->crop_top;
    527     info->crop.c.width  = info->crop_width;
    528     info->crop.c.height = info->crop_height;
    529 
    530     if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
    531         ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
    532         return false;
    533     }
    534     }
    535 
    536     if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
    537         ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
    538         return false;
    539     }
    540 
    541     req_buf.count  = 1;
    542     req_buf.type   = info->buf_type;
    543     req_buf.memory = V4L2_MEMORY_USERPTR;
    544     if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
    545         ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
    546         return false;
    547     }
    548 
    549     return true;
    550 }
    551 
    552 static bool m_exynos_rotator_set_addr(
    553     int                  fd,
    554     struct rotator_info *info)
    555 {
    556     unsigned int i;
    557     unsigned int plane_size[NUM_OF_ROTATOR_PLANES];
    558 
    559     m_rotator_get_plane_size(plane_size,
    560                          info->width,
    561                          info->height,
    562                          info->v4l2_colorformat);
    563 
    564     info->buffer.index    = 0;
    565     info->buffer.type     = info->buf_type;
    566     info->buffer.memory   = V4L2_MEMORY_USERPTR;
    567     info->buffer.m.planes = info->planes;
    568     info->buffer.length   = info->format.fmt.pix_mp.num_planes;
    569 
    570     for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
    571         info->buffer.m.planes[i].m.userptr = (unsigned long)info->addr[i];
    572         info->buffer.m.planes[i].length    = plane_size[i];
    573         info->buffer.m.planes[i].bytesused = 0;
    574     }
    575 
    576     if (exynos_v4l2_qbuf(fd, &info->buffer) < 0) {
    577         ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
    578         return false;
    579     }
    580 
    581     return true;
    582 }
    583 
    584 void *exynos_rotator_create(void)
    585 {
    586     int i     = 0;
    587     int op_id = 0;
    588     char mutex_name[32];
    589 
    590     struct ROTATOR_HANDLE *rotator_handle = (struct ROTATOR_HANDLE *)malloc(sizeof(struct ROTATOR_HANDLE));
    591     if (rotator_handle == NULL) {
    592         ALOGE("%s::malloc(struct ROTATOR_HANDLE) fail", __func__);
    593         goto err;
    594     }
    595 
    596     rotator_handle->rotator_fd = 0;
    597     memset(&rotator_handle->src, 0, sizeof(struct rotator_info));
    598     memset(&rotator_handle->dst, 0, sizeof(struct rotator_info));
    599 
    600     rotator_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    601     rotator_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    602 
    603     rotator_handle->op_mutex = NULL;
    604     rotator_handle->obj_mutex = NULL;
    605     rotator_handle->cur_obj_mutex = NULL;
    606 
    607     srand(time(NULL));
    608     op_id = rand() % 1000000; // just make random id
    609     sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
    610     rotator_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
    611     if (rotator_handle->op_mutex == NULL) {
    612         ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
    613         goto err;
    614     }
    615 
    616     exynos_mutex_lock(rotator_handle->op_mutex);
    617 
    618     sprintf(mutex_name, "%sObject%d", LOG_TAG, i);
    619 
    620     rotator_handle->obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
    621     if (rotator_handle->obj_mutex == NULL) {
    622         ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
    623         goto err;
    624     }
    625 
    626     if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
    627         ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
    628         goto err;
    629     }
    630 
    631     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    632     exynos_mutex_unlock(rotator_handle->op_mutex);
    633 
    634     return (void *)rotator_handle;
    635 
    636 err:
    637     if (rotator_handle) {
    638         m_exynos_rotator_destroy(rotator_handle);
    639 
    640         if (rotator_handle->cur_obj_mutex)
    641             exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    642 
    643         if ((rotator_handle->obj_mutex != NULL) &&
    644             (exynos_mutex_get_created_status(rotator_handle->obj_mutex) == true)) {
    645             if (exynos_mutex_destroy(rotator_handle->obj_mutex) == false)
    646                 ALOGE("%s::exynos_mutex_destroy() fail", __func__);
    647         }
    648 
    649         if (rotator_handle->op_mutex)
    650             exynos_mutex_unlock(rotator_handle->op_mutex);
    651 
    652         free(rotator_handle);
    653     }
    654 
    655     return NULL;
    656 }
    657 
    658 void exynos_rotator_destroy(
    659     void *handle)
    660 {
    661     int i = 0;
    662     struct ROTATOR_HANDLE *rotator_handle = (struct ROTATOR_HANDLE *)handle;
    663 
    664     if (handle == NULL) {
    665         ALOGE("%s::handle == NULL() fail", __func__);
    666         return;
    667     }
    668 
    669     exynos_mutex_lock(rotator_handle->op_mutex);
    670     exynos_mutex_lock(rotator_handle->cur_obj_mutex);
    671 
    672     m_exynos_rotator_destroy(rotator_handle);
    673 
    674     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    675 
    676     if ((rotator_handle->obj_mutex != NULL) &&
    677         (exynos_mutex_get_created_status(rotator_handle->obj_mutex) == true)) {
    678         if (exynos_mutex_destroy(rotator_handle->obj_mutex) == false)
    679             ALOGE("%s::exynos_mutex_destroy() fail", __func__);
    680     }
    681 
    682     exynos_mutex_unlock(rotator_handle->op_mutex);
    683 
    684     if (rotator_handle)
    685         free(rotator_handle);
    686 }
    687 
    688 int exynos_rotator_set_src_format(
    689     void        *handle,
    690     unsigned int width,
    691     unsigned int height,
    692     unsigned int crop_left,
    693     unsigned int crop_top,
    694     unsigned int crop_width,
    695     unsigned int crop_height,
    696     unsigned int v4l2_colorformat,
    697     unsigned int cacheable)
    698 {
    699     struct ROTATOR_HANDLE *rotator_handle;
    700     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    701 
    702     if (handle == NULL) {
    703         ALOGE("%s::handle == NULL() fail", __func__);
    704         return -1;
    705     }
    706 
    707     exynos_mutex_lock(rotator_handle->op_mutex);
    708 
    709     rotator_handle->src.width            = width;
    710     rotator_handle->src.height           = height;
    711     rotator_handle->src.crop_left        = crop_left;
    712     rotator_handle->src.crop_top         = crop_top;
    713     rotator_handle->src.crop_width       = crop_width;
    714     rotator_handle->src.crop_height      = crop_height;
    715     rotator_handle->src.v4l2_colorformat = v4l2_colorformat;
    716     rotator_handle->src.cacheable        = cacheable;
    717 
    718     exynos_mutex_unlock(rotator_handle->op_mutex);
    719 
    720     return 0;
    721 }
    722 
    723 int exynos_rotator_set_dst_format(
    724     void        *handle,
    725     unsigned int width,
    726     unsigned int height,
    727     unsigned int crop_left,
    728     unsigned int crop_top,
    729     unsigned int v4l2_colorformat,
    730     unsigned int cacheable)
    731 {
    732     struct ROTATOR_HANDLE *rotator_handle;
    733     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    734 
    735     if (handle == NULL) {
    736         ALOGE("%s::handle == NULL() fail", __func__);
    737         return -1;
    738     }
    739 
    740     exynos_mutex_lock(rotator_handle->op_mutex);
    741 
    742     rotator_handle->dst.width            = width;
    743     rotator_handle->dst.height           = height;
    744     rotator_handle->dst.crop_left        = crop_left;
    745     rotator_handle->dst.crop_top         = crop_top;
    746     rotator_handle->dst.crop_width       = rotator_handle->src.crop_width;
    747     rotator_handle->dst.crop_height      = rotator_handle->src.crop_height;
    748     rotator_handle->dst.v4l2_colorformat = v4l2_colorformat;
    749     rotator_handle->dst.cacheable        = cacheable;
    750 
    751     exynos_mutex_unlock(rotator_handle->op_mutex);
    752 
    753     return 0;
    754 }
    755 
    756 int exynos_rotator_set_rotation(
    757     void *handle,
    758     int   rotation)
    759 {
    760     int ret = -1;
    761     struct ROTATOR_HANDLE *rotator_handle;
    762     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    763 
    764     if (handle == NULL) {
    765         ALOGE("%s::handle == NULL() fail", __func__);
    766         return ret;
    767     }
    768 
    769     exynos_mutex_lock(rotator_handle->op_mutex);
    770 
    771     int new_rotation = rotation % 360;
    772 
    773     if (new_rotation % 90 != 0) {
    774         ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__, rotation);
    775         goto done;
    776     }
    777 
    778     if(new_rotation < 0)
    779         new_rotation = -new_rotation;
    780 
    781     rotator_handle->src.rotation = new_rotation;
    782     rotator_handle->dst.rotation = new_rotation;
    783 
    784     ret = 0;
    785 done:
    786     exynos_mutex_unlock(rotator_handle->op_mutex);
    787 
    788     return ret;
    789 }
    790 
    791 int exynos_rotator_set_src_addr(
    792     void *handle,
    793     void *addr[3])
    794 {
    795     struct ROTATOR_HANDLE *rotator_handle;
    796     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    797 
    798     if (handle == NULL) {
    799         ALOGE("%s::handle == NULL() fail", __func__);
    800         return -1;
    801     }
    802 
    803     exynos_mutex_lock(rotator_handle->op_mutex);
    804 
    805     rotator_handle->src.addr[0] = addr[0];
    806     rotator_handle->src.addr[1] = addr[1];
    807     rotator_handle->src.addr[2] = addr[2];
    808 
    809     exynos_mutex_unlock(rotator_handle->op_mutex);
    810 
    811     return 0;
    812 }
    813 
    814 int exynos_rotator_set_dst_addr(
    815     void *handle,
    816     void *addr[3])
    817 {
    818     struct ROTATOR_HANDLE *rotator_handle;
    819     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    820 
    821     if (handle == NULL) {
    822         ALOGE("%s::handle == NULL() fail", __func__);
    823         return -1;
    824     }
    825 
    826     exynos_mutex_lock(rotator_handle->op_mutex);
    827 
    828     rotator_handle->dst.addr[0] = addr[0];
    829     rotator_handle->dst.addr[1] = addr[1];
    830     rotator_handle->dst.addr[2] = addr[2];
    831 
    832     exynos_mutex_unlock(rotator_handle->op_mutex);
    833 
    834     return 0;
    835 }
    836 
    837 int exynos_rotator_convert(
    838     void *handle)
    839 {
    840     struct ROTATOR_HANDLE *rotator_handle;
    841     int ret    = -1;
    842     int i      = 0;
    843     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    844 
    845     if (handle == NULL) {
    846         ALOGE("%s::handle == NULL() fail", __func__);
    847         return -1;
    848     }
    849 
    850     char mutex_name[32];
    851     bool flag_new_rotator = false;
    852 
    853     exynos_mutex_lock(rotator_handle->op_mutex);
    854 
    855     if (exynos_mutex_trylock(rotator_handle->cur_obj_mutex) == false) {
    856         if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
    857             ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
    858             goto done;
    859         }
    860         flag_new_rotator = true;
    861     }
    862 
    863     if (m_exynos_rotator_check_src_size(&rotator_handle->src.width, &rotator_handle->src.width,
    864                                     &rotator_handle->src.crop_left, &rotator_handle->src.crop_top,
    865                                     &rotator_handle->src.crop_width, &rotator_handle->src.crop_height,
    866                                     rotator_handle->src.v4l2_colorformat) == false) {
    867         ALOGE("%s::m_exynos_rotator_check_size(src) fail", __func__);
    868         goto done;
    869     }
    870 
    871     if (m_exynos_rotator_check_dst_size(&rotator_handle->dst.width, &rotator_handle->dst.height,
    872                                     &rotator_handle->dst.crop_left, &rotator_handle->dst.crop_top,
    873                                     &rotator_handle->dst.crop_width, &rotator_handle->dst.crop_height,
    874                                     rotator_handle->dst.v4l2_colorformat,
    875                                     rotator_handle->dst.rotation) == false) {
    876         ALOGE("%s::m_exynos_rotator_check_size(dst) fail", __func__);
    877         goto done;
    878     }
    879 
    880     if (m_exynos_rotator_set_format(rotator_handle->rotator_fd, &rotator_handle->src, flag_new_rotator) == false) {
    881         ALOGE("%s::m_exynos_rotator_set_format(src) fail", __func__);
    882         goto done;
    883     }
    884 
    885     if (m_exynos_rotator_set_format(rotator_handle->rotator_fd, &rotator_handle->dst, flag_new_rotator) == false) {
    886         ALOGE("%s::m_exynos_rotator_set_format(dst) fail", __func__);
    887         goto done;
    888     }
    889 
    890     if (m_exynos_rotator_set_addr(rotator_handle->rotator_fd, &rotator_handle->src) == false) {
    891         ALOGE("%s::m_exynos_rotator_set_addr(src) fail", __func__);
    892         goto done;
    893     }
    894 
    895     if (m_exynos_rotator_set_addr(rotator_handle->rotator_fd, &rotator_handle->dst) == false) {
    896         ALOGE("%s::m_exynos_rotator_set_addr(dst) fail", __func__);
    897         goto done;
    898     }
    899 
    900     if (rotator_handle->src.stream_on == false) {
    901         if (exynos_v4l2_streamon(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0) {
    902             ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
    903             goto done;
    904         }
    905         rotator_handle->src.stream_on = true;
    906     }
    907 
    908     if (rotator_handle->dst.stream_on == false) {
    909         if (exynos_v4l2_streamon(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0) {
    910             ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
    911             goto done;
    912         }
    913         rotator_handle->dst.stream_on = true;
    914     }
    915 
    916     if (exynos_v4l2_dqbuf(rotator_handle->rotator_fd, &rotator_handle->src.buffer) < 0) {
    917         ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
    918         goto done;
    919     }
    920 
    921     if (exynos_v4l2_dqbuf(rotator_handle->rotator_fd, &rotator_handle->dst.buffer) < 0) {
    922         ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
    923         goto done;
    924     }
    925 
    926     if (rotator_handle->src.stream_on == true) {
    927         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0) {
    928             ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
    929             goto done;
    930         }
    931         rotator_handle->src.stream_on = false;
    932     }
    933 
    934     if (rotator_handle->dst.stream_on == true) {
    935         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0) {
    936             ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
    937             goto done;
    938         }
    939         rotator_handle->dst.stream_on = false;
    940     }
    941 
    942     ret = 0;
    943 
    944 done:
    945     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    946     exynos_mutex_unlock(rotator_handle->op_mutex);
    947 
    948     return ret;
    949 }
    950 
    951 int exynos_rotator_connect(
    952     void *handle,
    953     void *hw)
    954 {
    955     struct ROTATOR_HANDLE *rotator_handle;
    956     int ret    = -1;
    957     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    958 
    959     if (handle == NULL) {
    960         ALOGE("%s::handle == NULL() fail", __func__);
    961         return -1;
    962     }
    963 
    964     exynos_mutex_lock(rotator_handle->op_mutex);
    965 
    966     if (exynos_mutex_trylock(rotator_handle->cur_obj_mutex) == false) {
    967         if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
    968             ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
    969             goto done;
    970         }
    971     }
    972 
    973     ret = 0;
    974 
    975 done:
    976     exynos_mutex_unlock(rotator_handle->op_mutex);
    977 
    978     return ret;
    979 }
    980 
    981 int exynos_rotator_disconnect(
    982     void *handle,
    983     void *hw)
    984 {
    985     struct ROTATOR_HANDLE *rotator_handle;
    986     rotator_handle = (struct ROTATOR_HANDLE *)handle;
    987 
    988     if (handle == NULL) {
    989         ALOGE("%s::handle == NULL() fail", __func__);
    990         return -1;
    991     }
    992 
    993     exynos_mutex_lock(rotator_handle->op_mutex);
    994 
    995     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
    996     exynos_mutex_unlock(rotator_handle->op_mutex);
    997 
    998     return 0;
    999 }
   1000