Home | History | Annotate | Download | only in libcsc
      1 /*
      2  *
      3  * Copyright 2012 Samsung Electronics S.LSI 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        csc.c
     20  *
     21  * @brief       color space convertion abstract source
     22  *
     23  * @author      Pyoungjae Jung(pjet.jung (at) samsung.com)
     24  *
     25  * @version     1.0.0
     26  *
     27  * @history
     28  *   2012.1.11 : Create
     29  */
     30 #define LOG_TAG "libcsc"
     31 #include <cutils/log.h>
     32 
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <utils/Log.h>
     36 #include <system/graphics.h>
     37 
     38 #include "csc.h"
     39 #include "exynos_format.h"
     40 #include "swconverter.h"
     41 
     42 #ifdef EXYNOS_OMX
     43 #include "Exynos_OMX_Def.h"
     44 #else
     45 #include "SEC_OMX_Def.h"
     46 #endif
     47 
     48 #ifdef ENABLE_FIMC
     49 #include "hwconverter_wrapper.h"
     50 #endif
     51 
     52 #ifdef ENABLE_GSCALER
     53 #include "exynos_gscaler.h"
     54 #endif
     55 
     56 #ifdef ENABLE_G2D
     57 #include <fcntl.h>
     58 #include <sys/ioctl.h>
     59 #include "fimg2d.h"
     60 
     61 typedef struct
     62 {
     63     struct fimg2d_image src;
     64     struct fimg2d_image dst;
     65     int fd;
     66 } g2d_data;
     67 #endif
     68 
     69 #define GSCALER_IMG_ALIGN 16
     70 #define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
     71 
     72 typedef enum _CSC_PLANE {
     73     CSC_Y_PLANE = 0,
     74     CSC_RGB_PLANE = 0,
     75     CSC_U_PLANE = 1,
     76     CSC_UV_PLANE = 1,
     77     CSC_V_PLANE = 2
     78 } CSC_PLANE;
     79 
     80 typedef struct _CSC_FORMAT {
     81     unsigned int width;
     82     unsigned int height;
     83     unsigned int crop_left;
     84     unsigned int crop_top;
     85     unsigned int crop_width;
     86     unsigned int crop_height;
     87     unsigned int color_format;
     88     unsigned int cacheable;
     89     unsigned int mode_drm;
     90 } CSC_FORMAT;
     91 
     92 typedef struct _CSC_BUFFER {
     93     void *planes[CSC_MAX_PLANES];
     94 } CSC_BUFFER;
     95 
     96 typedef struct _CSC_HW_PROPERTY {
     97     int fixed_node;
     98     int mode_drm;
     99 } CSC_HW_PROPERTY;
    100 
    101 typedef struct _CSC_HANDLE {
    102     CSC_FORMAT      dst_format;
    103     CSC_FORMAT      src_format;
    104     CSC_BUFFER      dst_buffer;
    105     CSC_BUFFER      src_buffer;
    106     CSC_METHOD      csc_method;
    107     CSC_HW_TYPE     csc_hw_type;
    108     void           *csc_hw_handle;
    109     CSC_HW_PROPERTY hw_property;
    110 } CSC_HANDLE;
    111 
    112 /* source is RGB888 */
    113 static CSC_ERRORCODE conv_sw_src_argb888(
    114     CSC_HANDLE *handle)
    115 {
    116     CSC_ERRORCODE ret = CSC_ErrorNone;
    117 
    118     switch (handle->dst_format.color_format) {
    119     case HAL_PIXEL_FORMAT_YCbCr_420_P:
    120         csc_ARGB8888_to_YUV420P(
    121             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    122             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
    123             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
    124             (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
    125             handle->src_format.width,
    126             handle->src_format.height);
    127         ret = CSC_ErrorNone;
    128         break;
    129     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    130         csc_ARGB8888_to_YUV420SP_NEON(
    131             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    132             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
    133             (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
    134             handle->src_format.width,
    135             handle->src_format.height);
    136         ret = CSC_ErrorNone;
    137         break;
    138     default:
    139         ret = CSC_ErrorUnsupportFormat;
    140         break;
    141     }
    142 
    143     return ret;
    144 }
    145 
    146 /* source is NV12T */
    147 static CSC_ERRORCODE conv_sw_src_nv12t(
    148     CSC_HANDLE *handle)
    149 {
    150     CSC_ERRORCODE ret = CSC_ErrorNone;
    151 
    152     switch (handle->dst_format.color_format) {
    153     case HAL_PIXEL_FORMAT_YCbCr_420_P:
    154         csc_tiled_to_linear_y_neon(
    155             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    156             (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    157             handle->src_format.width,
    158             handle->src_format.height);
    159         csc_tiled_to_linear_uv_deinterleave_neon(
    160             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
    161             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
    162             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
    163             handle->src_format.width,
    164             handle->src_format.height / 2);
    165         ret = CSC_ErrorNone;
    166         break;
    167     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    168         csc_tiled_to_linear_y_neon(
    169             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    170             (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    171             handle->src_format.width,
    172             handle->src_format.height);
    173         csc_tiled_to_linear_uv_neon(
    174             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
    175             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
    176             handle->src_format.width,
    177             handle->src_format.height / 2);
    178         ret = CSC_ErrorNone;
    179         break;
    180     default:
    181         ret = CSC_ErrorUnsupportFormat;
    182         break;
    183     }
    184 
    185     return ret;
    186 }
    187 
    188 /* source is YUV420P */
    189 static CSC_ERRORCODE conv_sw_src_yuv420p(
    190     CSC_HANDLE *handle)
    191 {
    192     CSC_ERRORCODE ret = CSC_ErrorNone;
    193 
    194     switch (handle->dst_format.color_format) {
    195     case HAL_PIXEL_FORMAT_YCbCr_420_P:  /* bypass */
    196         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    197                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    198                handle->src_format.width * handle->src_format.height);
    199         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
    200                (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
    201                (handle->src_format.width * handle->src_format.height) >> 2);
    202         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
    203                (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
    204                (handle->src_format.width * handle->src_format.height) >> 2);
    205         ret = CSC_ErrorNone;
    206         break;
    207     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    208         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    209                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    210                handle->src_format.width * handle->src_format.height);
    211         csc_interleave_memcpy_neon(
    212             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
    213             (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
    214             (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
    215             (handle->src_format.width * handle->src_format.height) >> 2);
    216         ret = CSC_ErrorNone;
    217         break;
    218     default:
    219         ret = CSC_ErrorUnsupportFormat;
    220         break;
    221     }
    222 
    223     return ret;
    224 }
    225 
    226 /* source is YUV420SP */
    227 static CSC_ERRORCODE conv_sw_src_yuv420sp(
    228     CSC_HANDLE *handle)
    229 {
    230     CSC_ERRORCODE ret = CSC_ErrorNone;
    231 
    232     switch (handle->dst_format.color_format) {
    233     case HAL_PIXEL_FORMAT_YCbCr_420_P:
    234         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    235                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    236                handle->src_format.width * handle->src_format.height);
    237         csc_deinterleave_memcpy(
    238             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
    239             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
    240             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
    241             handle->src_format.width * handle->src_format.height >> 1);
    242         ret = CSC_ErrorNone;
    243         break;
    244     case HAL_PIXEL_FORMAT_YCbCr_420_SP: /* bypass */
    245         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
    246                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
    247                handle->src_format.width * handle->src_format.height);
    248         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
    249                (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
    250                handle->src_format.width * handle->src_format.height >> 1);
    251         ret = CSC_ErrorNone;
    252         break;
    253     default:
    254         ret = CSC_ErrorUnsupportFormat;
    255         break;
    256     }
    257 
    258     return ret;
    259 }
    260 
    261 static CSC_ERRORCODE conv_sw(
    262     CSC_HANDLE *handle)
    263 {
    264     CSC_ERRORCODE ret = CSC_ErrorNone;
    265 
    266     switch (handle->src_format.color_format) {
    267     case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
    268         ret = conv_sw_src_nv12t(handle);
    269         break;
    270     case HAL_PIXEL_FORMAT_YCbCr_420_P:
    271         ret = conv_sw_src_yuv420p(handle);
    272         break;
    273     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    274         ret = conv_sw_src_yuv420sp(handle);
    275         break;
    276     case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
    277         ret = conv_sw_src_argb888(handle);
    278         break;
    279     default:
    280         ret = CSC_ErrorUnsupportFormat;
    281         break;
    282     }
    283 
    284     return ret;
    285 }
    286 
    287 static CSC_ERRORCODE conv_hw(
    288     CSC_HANDLE *handle)
    289 {
    290     CSC_ERRORCODE ret = CSC_ErrorNone;
    291     switch (handle->csc_hw_type) {
    292 #ifdef ENABLE_FIMC
    293     case CSC_HW_TYPE_FIMC:
    294     {
    295         void *src_addr[3];
    296         void *dst_addr[3];
    297         OMX_COLOR_FORMATTYPE src_omx_format;
    298         OMX_COLOR_FORMATTYPE dst_omx_format;
    299         src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE];
    300         src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE];
    301         dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE];
    302         dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE];
    303         dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE];
    304         src_omx_format = hal_2_omx_pixel_format(handle->src_format.color_format);
    305         dst_omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format);
    306         csc_hwconverter_convert_nv12t(
    307             handle->csc_hw_handle,
    308             dst_addr,
    309             src_addr,
    310             handle->dst_format.width,
    311             handle->dst_format.height,
    312             dst_omx_format,
    313             src_omx_format);
    314         break;
    315     }
    316 #endif
    317 #ifdef ENABLE_GSCALER
    318     case CSC_HW_TYPE_GSCALER:
    319         if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
    320             ALOGE("%s:: exynos_gsc_convert() fail", __func__);
    321             ret = CSC_Error;
    322         }
    323         break;
    324 #endif
    325 #ifdef ENABLE_G2D
    326     case CSC_HW_TYPE_G2D:
    327     {
    328         g2d_data *g2d = (g2d_data *)handle->csc_hw_handle;
    329         struct fimg2d_blit blit;
    330         int err;
    331 
    332         memset(&blit, 0, sizeof(blit));
    333         blit.op = BLIT_OP_SRC_COPY;
    334         blit.param.g_alpha = 0xFF;
    335         blit.src = &g2d->src;
    336         blit.dst = &g2d->dst;
    337         blit.sync = BLIT_SYNC;
    338 
    339         err = ioctl(g2d->fd, FIMG2D_BITBLT_BLIT, &blit);
    340         if (err < 0) {
    341             ALOGE("FIMG2D_BITBLT_BLIT ioctl failed: %s", strerror(errno));
    342             ret = CSC_Error;
    343         }
    344 
    345         break;
    346     }
    347 #endif
    348     default:
    349         ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
    350         ret = CSC_ErrorNotImplemented;
    351         break;
    352     }
    353 
    354     return ret;
    355 }
    356 
    357 static CSC_ERRORCODE csc_init_hw(
    358     void *handle)
    359 {
    360     CSC_HANDLE *csc_handle;
    361     CSC_ERRORCODE ret = CSC_ErrorNone;
    362 
    363     csc_handle = (CSC_HANDLE *)handle;
    364     if (csc_handle->csc_method == CSC_METHOD_HW) {
    365         switch (csc_handle->csc_hw_type) {
    366 #ifdef ENABLE_FIMC
    367         case CSC_HW_TYPE_FIMC:
    368             csc_handle->csc_hw_handle = csc_hwconverter_open();
    369             ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
    370             break;
    371 #endif
    372 #ifdef ENABLE_GSCALER
    373         case CSC_HW_TYPE_GSCALER:
    374             if (csc_handle->hw_property.fixed_node >= 0)
    375                 csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
    376             else
    377             csc_handle->csc_hw_handle = exynos_gsc_create();
    378             ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
    379             break;
    380 #endif
    381 #ifdef ENABLE_G2D
    382         case CSC_HW_TYPE_G2D:
    383         {
    384             g2d_data *g2d = calloc(1, sizeof(g2d_data));
    385             if (!g2d) {
    386                 ALOGE("failed to allocate G2D data");
    387                 break;
    388             }
    389             g2d->fd = open("/dev/fimg2d", O_RDWR);
    390             if (g2d->fd < 0) {
    391                 ALOGE("failed to open G2D: %s", strerror(errno));
    392                 free(g2d);
    393             } else {
    394                 csc_handle->csc_hw_handle = g2d;
    395             }
    396             break;
    397         }
    398 #endif
    399         default:
    400             ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
    401             csc_handle->csc_hw_handle = NULL;
    402             break;
    403         }
    404     }
    405 
    406     if (csc_handle->csc_method == CSC_METHOD_HW) {
    407         if (csc_handle->csc_hw_handle == NULL) {
    408             ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
    409             ret = CSC_Error;
    410         }
    411     }
    412 
    413     ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
    414 
    415     return ret;
    416 }
    417 
    418 static CSC_ERRORCODE csc_set_format(
    419     void *handle)
    420 {
    421     CSC_HANDLE *csc_handle;
    422     CSC_ERRORCODE ret = CSC_ErrorNone;
    423 
    424     if (handle == NULL)
    425         return CSC_ErrorNotInit;
    426 
    427     csc_handle = (CSC_HANDLE *)handle;
    428     if (csc_handle->csc_method == CSC_METHOD_HW) {
    429         switch (csc_handle->csc_hw_type) {
    430         case CSC_HW_TYPE_FIMC:
    431             break;
    432 #ifdef ENABLE_GSCALER
    433         case CSC_HW_TYPE_GSCALER:
    434             exynos_gsc_set_src_format(
    435                 csc_handle->csc_hw_handle,
    436                 ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN),
    437                 ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN),
    438                 csc_handle->src_format.crop_left,
    439                 csc_handle->src_format.crop_top,
    440                 csc_handle->src_format.crop_width,
    441                 csc_handle->src_format.crop_height,
    442                 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format),
    443                 csc_handle->src_format.cacheable,
    444                 csc_handle->hw_property.mode_drm);
    445 
    446             exynos_gsc_set_dst_format(
    447                 csc_handle->csc_hw_handle,
    448                 ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN),
    449                 ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN),
    450                 csc_handle->dst_format.crop_left,
    451                 csc_handle->dst_format.crop_top,
    452                 csc_handle->dst_format.crop_width,
    453                 csc_handle->dst_format.crop_height,
    454                 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
    455                 csc_handle->dst_format.cacheable,
    456                 csc_handle->hw_property.mode_drm,
    457                 0);
    458             break;
    459 #endif
    460 #ifdef ENABLE_G2D
    461         case CSC_HW_TYPE_G2D:
    462         {
    463             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
    464 
    465             g2d->src.width = ALIGN(csc_handle->src_format.width,
    466                     GSCALER_IMG_ALIGN);
    467             g2d->src.height = csc_handle->src_format.height;
    468             g2d->src.stride = g2d->src.width *
    469                     hal_2_g2d_bpp(csc_handle->src_format.color_format) >> 3;
    470             g2d->src.order = hal_2_g2d_pixel_order(csc_handle->src_format.color_format);
    471             g2d->src.fmt = hal_2_g2d_color_format(csc_handle->src_format.color_format);
    472             g2d->src.rect.x1 = csc_handle->src_format.crop_left;
    473             g2d->src.rect.y1 = csc_handle->src_format.crop_top;
    474             g2d->src.rect.x2 = csc_handle->src_format.crop_left +
    475                     csc_handle->src_format.crop_width;
    476             g2d->src.rect.y2 = csc_handle->src_format.crop_top +
    477                     csc_handle->src_format.crop_height;
    478 
    479             g2d->dst.width = ALIGN(csc_handle->dst_format.width,
    480                     GSCALER_IMG_ALIGN);
    481             g2d->dst.height = csc_handle->dst_format.height;
    482             g2d->dst.stride = g2d->dst.width *
    483                     hal_2_g2d_bpp(csc_handle->dst_format.color_format) >> 3;
    484             g2d->dst.order = hal_2_g2d_pixel_order(csc_handle->dst_format.color_format);
    485             g2d->dst.fmt = hal_2_g2d_color_format(csc_handle->dst_format.color_format);
    486             g2d->dst.rect.x1 = csc_handle->dst_format.crop_left;
    487             g2d->dst.rect.y1 = csc_handle->dst_format.crop_top;
    488             g2d->dst.rect.x2 = csc_handle->dst_format.crop_left +
    489                     csc_handle->dst_format.crop_width;
    490             g2d->dst.rect.y2 = csc_handle->dst_format.crop_top +
    491                     csc_handle->dst_format.crop_height;
    492 
    493             break;
    494         }
    495 #endif
    496         default:
    497             ALOGE("%s:: unsupported csc_hw_type", __func__);
    498             break;
    499         }
    500     }
    501 
    502     return ret;
    503 }
    504 
    505 static CSC_ERRORCODE csc_set_buffer(
    506     void *handle)
    507 {
    508     CSC_HANDLE *csc_handle;
    509     CSC_ERRORCODE ret = CSC_ErrorNone;
    510 
    511     if (handle == NULL)
    512         return CSC_ErrorNotInit;
    513 
    514     csc_handle = (CSC_HANDLE *)handle;
    515     if (csc_handle->csc_method == CSC_METHOD_HW) {
    516         switch (csc_handle->csc_hw_type) {
    517         case CSC_HW_TYPE_FIMC:
    518             break;
    519 #ifdef ENABLE_GSCALER
    520         case CSC_HW_TYPE_GSCALER:
    521             exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1);
    522             exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1);
    523             break;
    524 #endif
    525 #ifdef ENABLE_G2D
    526         case CSC_HW_TYPE_G2D:
    527         {
    528             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
    529 
    530             g2d->src.addr.type = ADDR_DMA_BUF;
    531             g2d->src.addr.fd[0] = (int)csc_handle->src_buffer.planes[0];
    532             g2d->src.addr.fd[1] = (int)csc_handle->src_buffer.planes[1];
    533 
    534             g2d->dst.addr.type = ADDR_DMA_BUF;
    535             g2d->dst.addr.fd[0] = (int)csc_handle->dst_buffer.planes[0];
    536             g2d->dst.addr.fd[1] = (int)csc_handle->dst_buffer.planes[1];
    537 
    538             break;
    539         }
    540 #endif
    541         default:
    542             ALOGE("%s:: unsupported csc_hw_type", __func__);
    543             break;
    544         }
    545     }
    546 
    547     return ret;
    548 }
    549 
    550 void *csc_init(
    551     CSC_METHOD method)
    552 {
    553     CSC_HANDLE *csc_handle;
    554     csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE));
    555     if (csc_handle == NULL)
    556         return NULL;
    557 
    558     memset(csc_handle, 0, sizeof(CSC_HANDLE));
    559     csc_handle->hw_property.fixed_node = -1;
    560     csc_handle->hw_property.mode_drm = 0;
    561     csc_handle->csc_method = method;
    562 
    563     return (void *)csc_handle;
    564 }
    565 
    566 CSC_ERRORCODE csc_deinit(
    567     void *handle)
    568 {
    569     CSC_ERRORCODE ret = CSC_ErrorNone;
    570     CSC_HANDLE *csc_handle;
    571 
    572     csc_handle = (CSC_HANDLE *)handle;
    573     if (csc_handle->csc_hw_handle) {
    574         switch (csc_handle->csc_hw_type) {
    575 #ifdef ENABLE_FIMC
    576         case CSC_HW_TYPE_FIMC:
    577             csc_hwconverter_close(csc_handle->csc_hw_handle);
    578             break;
    579 #endif
    580 #ifdef ENABLE_GSCALER
    581         case CSC_HW_TYPE_GSCALER:
    582             exynos_gsc_destroy(csc_handle->csc_hw_handle);
    583             break;
    584 #endif
    585 #ifdef ENABLE_G2D
    586         case CSC_HW_TYPE_G2D:
    587         {
    588             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
    589             close(g2d->fd);
    590             free(g2d);
    591             break;
    592         }
    593 #endif
    594         default:
    595             ALOGE("%s:: unsupported csc_hw_type", __func__);
    596             break;
    597         }
    598     }
    599 
    600     if (csc_handle != NULL) {
    601         free(csc_handle);
    602         ret = CSC_ErrorNone;
    603     }
    604 
    605     return ret;
    606 }
    607 
    608 CSC_ERRORCODE csc_get_method(
    609     void           *handle,
    610     CSC_METHOD     *method)
    611 {
    612     CSC_HANDLE *csc_handle;
    613     CSC_ERRORCODE ret = CSC_ErrorNone;
    614 
    615     if (handle == NULL)
    616         return CSC_ErrorNotInit;
    617 
    618     csc_handle = (CSC_HANDLE *)handle;
    619     *method = csc_handle->csc_method;
    620 
    621     return ret;
    622 }
    623 
    624 CSC_ERRORCODE csc_set_method(
    625     void           *handle,
    626     CSC_METHOD     method)
    627 {
    628     CSC_HANDLE *csc_handle;
    629     CSC_ERRORCODE ret = CSC_ErrorNone;
    630 
    631     if (handle == NULL)
    632         return CSC_ErrorNotInit;
    633 
    634     csc_handle = (CSC_HANDLE *)handle;
    635     csc_handle->csc_method = method;
    636 
    637     return ret;
    638 }
    639 
    640 CSC_ERRORCODE csc_set_hw_property(
    641     void                *handle,
    642     CSC_HW_PROPERTY_TYPE property,
    643     int                  value)
    644 {
    645     CSC_HANDLE *csc_handle;
    646     CSC_ERRORCODE ret = CSC_ErrorNone;
    647 
    648     if (handle == NULL)
    649         return CSC_ErrorNotInit;
    650 
    651     csc_handle = (CSC_HANDLE *)handle;
    652 
    653     if (csc_handle->csc_hw_handle) {
    654         ALOGE("%s:: cannot set hw property after hw is already initialized", __func__);
    655         return CSC_ErrorUnsupportFormat;
    656     }
    657 
    658     switch (property) {
    659     case CSC_HW_PROPERTY_FIXED_NODE:
    660         csc_handle->hw_property.fixed_node = value;
    661         break;
    662     case CSC_HW_PROPERTY_MODE_DRM:
    663         csc_handle->hw_property.mode_drm = value;
    664         break;
    665     case CSC_HW_PROPERTY_HW_TYPE:
    666         csc_handle->csc_hw_type = value;
    667         break;
    668     default:
    669         ALOGE("%s:: not supported hw property", __func__);
    670         ret = CSC_ErrorUnsupportFormat;
    671     }
    672 
    673     return ret;
    674 }
    675 
    676 CSC_ERRORCODE csc_get_src_format(
    677     void           *handle,
    678     unsigned int   *width,
    679     unsigned int   *height,
    680     unsigned int   *crop_left,
    681     unsigned int   *crop_top,
    682     unsigned int   *crop_width,
    683     unsigned int   *crop_height,
    684     unsigned int   *color_format,
    685     unsigned int   *cacheable)
    686 {
    687     CSC_HANDLE *csc_handle;
    688     CSC_ERRORCODE ret = CSC_ErrorNone;
    689 
    690     if (handle == NULL)
    691         return CSC_ErrorNotInit;
    692 
    693     csc_handle = (CSC_HANDLE *)handle;
    694     *width = csc_handle->src_format.width;
    695     *height = csc_handle->src_format.height;
    696     *crop_left = csc_handle->src_format.crop_left;
    697     *crop_top = csc_handle->src_format.crop_top;
    698     *crop_width = csc_handle->src_format.crop_width;
    699     *crop_height = csc_handle->src_format.crop_height;
    700     *color_format = csc_handle->src_format.color_format;
    701     *cacheable = csc_handle->src_format.cacheable;
    702 
    703     return ret;
    704 }
    705 
    706 CSC_ERRORCODE csc_set_src_format(
    707     void           *handle,
    708     unsigned int    width,
    709     unsigned int    height,
    710     unsigned int    crop_left,
    711     unsigned int    crop_top,
    712     unsigned int    crop_width,
    713     unsigned int    crop_height,
    714     unsigned int    color_format,
    715     unsigned int    cacheable)
    716 {
    717     CSC_HANDLE *csc_handle;
    718     CSC_ERRORCODE ret = CSC_ErrorNone;
    719 
    720     if (handle == NULL)
    721         return CSC_ErrorNotInit;
    722 
    723     csc_handle = (CSC_HANDLE *)handle;
    724     csc_handle->src_format.width = width;
    725     csc_handle->src_format.height = height;
    726     csc_handle->src_format.crop_left = crop_left;
    727     csc_handle->src_format.crop_top = crop_top;
    728     csc_handle->src_format.crop_width = crop_width;
    729     csc_handle->src_format.crop_height = crop_height;
    730     csc_handle->src_format.color_format = color_format;
    731     csc_handle->src_format.cacheable = cacheable;
    732 
    733     return ret;
    734 }
    735 
    736 CSC_ERRORCODE csc_get_dst_format(
    737     void           *handle,
    738     unsigned int   *width,
    739     unsigned int   *height,
    740     unsigned int   *crop_left,
    741     unsigned int   *crop_top,
    742     unsigned int   *crop_width,
    743     unsigned int   *crop_height,
    744     unsigned int   *color_format,
    745     unsigned int   *cacheable)
    746 {
    747     CSC_HANDLE *csc_handle;
    748     CSC_ERRORCODE ret = CSC_ErrorNone;
    749 
    750     if (handle == NULL)
    751         return CSC_ErrorNotInit;
    752 
    753     csc_handle = (CSC_HANDLE *)handle;
    754     *width = csc_handle->dst_format.width;
    755     *height = csc_handle->dst_format.height;
    756     *crop_left = csc_handle->dst_format.crop_left;
    757     *crop_top = csc_handle->dst_format.crop_top;
    758     *crop_width = csc_handle->dst_format.crop_width;
    759     *crop_height = csc_handle->dst_format.crop_height;
    760     *color_format = csc_handle->dst_format.color_format;
    761     *cacheable = csc_handle->dst_format.cacheable;
    762 
    763     return ret;
    764 }
    765 
    766 CSC_ERRORCODE csc_set_dst_format(
    767     void           *handle,
    768     unsigned int    width,
    769     unsigned int    height,
    770     unsigned int    crop_left,
    771     unsigned int    crop_top,
    772     unsigned int    crop_width,
    773     unsigned int    crop_height,
    774     unsigned int    color_format,
    775     unsigned int    cacheable)
    776 {
    777     CSC_HANDLE *csc_handle;
    778     CSC_ERRORCODE ret = CSC_ErrorNone;
    779 
    780     if (handle == NULL)
    781         return CSC_ErrorNotInit;
    782 
    783     csc_handle = (CSC_HANDLE *)handle;
    784     csc_handle->dst_format.width = width;
    785     csc_handle->dst_format.height = height;
    786     csc_handle->dst_format.crop_left = crop_left;
    787     csc_handle->dst_format.crop_top = crop_top;
    788     csc_handle->dst_format.crop_width = crop_width;
    789     csc_handle->dst_format.crop_height = crop_height;
    790     csc_handle->dst_format.color_format = color_format;
    791     csc_handle->dst_format.cacheable = cacheable;
    792 
    793     return ret;
    794 }
    795 
    796 CSC_ERRORCODE csc_set_src_buffer(
    797     void *handle,
    798     void *addr[3])
    799 {
    800     CSC_HANDLE *csc_handle;
    801     CSC_ERRORCODE ret = CSC_ErrorNone;
    802 
    803     if (handle == NULL)
    804         return CSC_ErrorNotInit;
    805 
    806     csc_handle = (CSC_HANDLE *)handle;
    807     csc_handle->src_buffer.planes[CSC_Y_PLANE] = addr[0];
    808     csc_handle->src_buffer.planes[CSC_U_PLANE] = addr[1];
    809     csc_handle->src_buffer.planes[CSC_V_PLANE] = addr[2];
    810 
    811     return ret;
    812 }
    813 
    814 CSC_ERRORCODE csc_set_dst_buffer(
    815     void *handle,
    816     void *addr[3])
    817 {
    818     CSC_HANDLE *csc_handle;
    819     CSC_ERRORCODE ret = CSC_ErrorNone;
    820 
    821     if (handle == NULL)
    822         return CSC_ErrorNotInit;
    823 
    824     csc_handle = (CSC_HANDLE *)handle;
    825     csc_handle->dst_buffer.planes[CSC_Y_PLANE] = addr[0];
    826     csc_handle->dst_buffer.planes[CSC_U_PLANE] = addr[1];
    827     csc_handle->dst_buffer.planes[CSC_V_PLANE] = addr[2];
    828 
    829     return ret;
    830 }
    831 
    832 CSC_ERRORCODE csc_convert(
    833     void *handle)
    834 {
    835     CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle;
    836     CSC_ERRORCODE ret = CSC_ErrorNone;
    837 
    838     if (csc_handle == NULL)
    839         return CSC_ErrorNotInit;
    840 
    841     if ((csc_handle->csc_method == CSC_METHOD_HW) &&
    842         (csc_handle->csc_hw_handle == NULL)) {
    843         ret = csc_init_hw(handle);
    844         if (ret != CSC_ErrorNone)
    845             return ret;
    846     }
    847 
    848     ret = csc_set_format(csc_handle);
    849     if (ret != CSC_ErrorNone)
    850         return ret;
    851 
    852     ret = csc_set_buffer(csc_handle);
    853     if (ret != CSC_ErrorNone)
    854         return ret;
    855 
    856     if (csc_handle->csc_method == CSC_METHOD_HW)
    857         ret = conv_hw(csc_handle);
    858     else
    859         ret = conv_sw(csc_handle);
    860 
    861     return ret;
    862 }
    863