Merge tag 'android-m-preview-2'
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libcsc / csc.c
index c29716bcacb7a92fabdce469f79011785e3e82e6..d619641e984f5e13d63832a97582da67629e1e49 100644 (file)
  */
 #define LOG_TAG "libcsc"
 #include <cutils/log.h>
+#include <errno.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <utils/Log.h>
+#include <system/graphics.h>
 
 #include "csc.h"
 #include "exynos_format.h"
 #include "SEC_OMX_Def.h"
 #endif
 
-#ifdef USE_FIMC
+#ifdef ENABLE_FIMC
 #include "hwconverter_wrapper.h"
 #endif
 
-#ifdef USE_GSCALER
+#ifdef ENABLE_GSCALER
 #include "exynos_gscaler.h"
 #endif
 
+#ifdef ENABLE_G2D
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "fimg2d.h"
+
+typedef struct
+{
+    struct fimg2d_image src;
+    struct fimg2d_image dst;
+    int fd;
+} g2d_data;
+#endif
+
 #define GSCALER_IMG_ALIGN 16
-#define CSC_MAX_PLANES 3
 #define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
 
 typedef enum _CSC_PLANE {
@@ -64,11 +79,6 @@ typedef enum _CSC_PLANE {
     CSC_V_PLANE = 2
 } CSC_PLANE;
 
-typedef enum _CSC_HW_TYPE {
-    CSC_HW_TYPE_FIMC = 0,
-    CSC_HW_TYPE_GSCALER
-} CSC_HW_TYPE;
-
 typedef struct _CSC_FORMAT {
     unsigned int width;
     unsigned int height;
@@ -78,13 +88,18 @@ typedef struct _CSC_FORMAT {
     unsigned int crop_height;
     unsigned int color_format;
     unsigned int cacheable;
+    unsigned int mode_drm;
 } CSC_FORMAT;
 
 typedef struct _CSC_BUFFER {
-    unsigned char *planes[CSC_MAX_PLANES];
-    int ion_fd;
+    void *planes[CSC_MAX_PLANES];
 } CSC_BUFFER;
 
+typedef struct _CSC_HW_PROPERTY {
+    int fixed_node;
+    int mode_drm;
+} CSC_HW_PROPERTY;
+
 typedef struct _CSC_HANDLE {
     CSC_FORMAT      dst_format;
     CSC_FORMAT      src_format;
@@ -93,56 +108,9 @@ typedef struct _CSC_HANDLE {
     CSC_METHOD      csc_method;
     CSC_HW_TYPE     csc_hw_type;
     void           *csc_hw_handle;
+    CSC_HW_PROPERTY hw_property;
 } CSC_HANDLE;
 
-OMX_COLOR_FORMATTYPE hal_2_omx_pixel_format(
-    unsigned int hal_format)
-{
-    OMX_COLOR_FORMATTYPE omx_format;
-    switch (hal_format) {
-    case HAL_PIXEL_FORMAT_YCbCr_420_P:
-        omx_format = OMX_COLOR_FormatYUV420Planar;
-        break;
-    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        omx_format = OMX_COLOR_FormatYUV420SemiPlanar;
-        break;
-    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-        omx_format = OMX_SEC_COLOR_FormatNV12Tiled;
-        break;
-    case HAL_PIXEL_FORMAT_ARGB888:
-        omx_format = OMX_COLOR_Format32bitARGB8888;
-        break;
-    default:
-        omx_format = OMX_COLOR_FormatYUV420Planar;
-        break;
-    }
-    return omx_format;
-}
-
-unsigned int omx_2_hal_pixel_format(
-    OMX_COLOR_FORMATTYPE omx_format)
-{
-    unsigned int hal_format;
-    switch (omx_format) {
-    case OMX_COLOR_FormatYUV420Planar:
-        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P;
-        break;
-    case OMX_COLOR_FormatYUV420SemiPlanar:
-        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
-        break;
-    case OMX_SEC_COLOR_FormatNV12Tiled:
-        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
-        break;
-    case OMX_COLOR_Format32bitARGB8888:
-        hal_format = HAL_PIXEL_FORMAT_ARGB888;
-        break;
-    default:
-        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P;
-        break;
-    }
-    return hal_format;
-}
-
 /* source is RGB888 */
 static CSC_ERRORCODE conv_sw_src_argb888(
     CSC_HANDLE *handle)
@@ -307,7 +275,7 @@ static CSC_ERRORCODE conv_sw(
     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
         ret = conv_sw_src_yuv420sp(handle);
         break;
-    case HAL_PIXEL_FORMAT_ARGB888:
+    case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
         ret = conv_sw_src_argb888(handle);
         break;
     default:
@@ -322,102 +290,277 @@ static CSC_ERRORCODE conv_hw(
     CSC_HANDLE *handle)
 {
     CSC_ERRORCODE ret = CSC_ErrorNone;
-
     switch (handle->csc_hw_type) {
-#ifdef USE_FIMC
+#ifdef ENABLE_FIMC
     case CSC_HW_TYPE_FIMC:
     {
         void *src_addr[3];
         void *dst_addr[3];
-        OMX_COLOR_FORMATTYPE omx_format;
+        OMX_COLOR_FORMATTYPE src_omx_format;
+        OMX_COLOR_FORMATTYPE dst_omx_format;
         src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE];
         src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE];
         dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE];
         dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE];
         dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE];
-        omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format);
+        src_omx_format = hal_2_omx_pixel_format(handle->src_format.color_format);
+        dst_omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format);
         csc_hwconverter_convert_nv12t(
             handle->csc_hw_handle,
             dst_addr,
             src_addr,
             handle->dst_format.width,
             handle->dst_format.height,
-            omx_format);
+            dst_omx_format,
+            src_omx_format);
         break;
     }
 #endif
-#ifdef USE_GSCALER
+#ifdef ENABLE_GSCALER
     case CSC_HW_TYPE_GSCALER:
-        exynos_gsc_convert(handle->csc_hw_handle);
+        if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
+            ALOGE("%s:: exynos_gsc_convert() fail", __func__);
+            ret = CSC_Error;
+        }
+        break;
+#endif
+#ifdef ENABLE_G2D
+    case CSC_HW_TYPE_G2D:
+    {
+        g2d_data *g2d = (g2d_data *)handle->csc_hw_handle;
+        struct fimg2d_blit blit;
+        int err;
+
+        memset(&blit, 0, sizeof(blit));
+        blit.op = BLIT_OP_SRC_COPY;
+        blit.param.g_alpha = 0xFF;
+        blit.src = &g2d->src;
+        blit.dst = &g2d->dst;
+        blit.sync = BLIT_SYNC;
+
+        err = ioctl(g2d->fd, FIMG2D_BITBLT_BLIT, &blit);
+        if (err < 0) {
+            ALOGE("FIMG2D_BITBLT_BLIT ioctl failed: %s", strerror(errno));
+            ret = CSC_Error;
+        }
+
         break;
+    }
 #endif
     default:
-        ALOGE("%s:: unsupported csc_hw_type", __func__);
+        ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
+        ret = CSC_ErrorNotImplemented;
         break;
     }
 
-    return CSC_ErrorNotImplemented;
+    return ret;
 }
 
-void *csc_init(
-    CSC_METHOD *method)
+static CSC_ERRORCODE csc_init_hw(
+    void *handle)
 {
     CSC_HANDLE *csc_handle;
-    csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE));
-    if (csc_handle == NULL)
-        return NULL;
-
-    memset(csc_handle, 0, sizeof(CSC_HANDLE));
-
-    csc_handle->csc_method = *method;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
 
-    if (csc_handle->csc_method == CSC_METHOD_HW ||
-        csc_handle->csc_method == CSC_METHOD_PREFER_HW) {
-#ifdef USE_FIMC
-        csc_handle->csc_hw_type = CSC_HW_TYPE_FIMC;
-#endif
-#ifdef USE_GSCALER
-        csc_handle->csc_hw_type = CSC_HW_TYPE_GSCALER;
-#endif
+    csc_handle = (CSC_HANDLE *)handle;
+    if (csc_handle->csc_method == CSC_METHOD_HW) {
         switch (csc_handle->csc_hw_type) {
-#ifdef USE_FIMC
+#ifdef ENABLE_FIMC
         case CSC_HW_TYPE_FIMC:
             csc_handle->csc_hw_handle = csc_hwconverter_open();
-            ALOGD("%s:: CSC_HW_TYPE_FIMC", __func__);
+            ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
             break;
 #endif
-#ifdef USE_GSCALER
+#ifdef ENABLE_GSCALER
         case CSC_HW_TYPE_GSCALER:
+            if (csc_handle->hw_property.fixed_node >= 0)
+                csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
+            else
             csc_handle->csc_hw_handle = exynos_gsc_create();
-            ALOGD("%s:: CSC_HW_TYPE_GSCALER", __func__);
+            ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
+            break;
+#endif
+#ifdef ENABLE_G2D
+        case CSC_HW_TYPE_G2D:
+        {
+            g2d_data *g2d = calloc(1, sizeof(g2d_data));
+            if (!g2d) {
+                ALOGE("failed to allocate G2D data");
+                break;
+            }
+            g2d->fd = open("/dev/fimg2d", O_RDWR);
+            if (g2d->fd < 0) {
+                ALOGE("failed to open G2D: %s", strerror(errno));
+                free(g2d);
+            } else {
+                csc_handle->csc_hw_handle = g2d;
+            }
             break;
+        }
 #endif
         default:
             ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
-            csc_handle->csc_hw_handle == NULL;
+            csc_handle->csc_hw_handle = NULL;
             break;
         }
     }
 
-    if (csc_handle->csc_method == CSC_METHOD_PREFER_HW) {
+    if (csc_handle->csc_method == CSC_METHOD_HW) {
         if (csc_handle->csc_hw_handle == NULL) {
-            csc_handle->csc_method = CSC_METHOD_SW;
-            *method = CSC_METHOD_SW;
-        } else {
-            csc_handle->csc_method = CSC_METHOD_HW;
-            *method = CSC_METHOD_HW;
+            ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
+            ret = CSC_Error;
         }
     }
 
+    ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
+
+    return ret;
+}
+
+static CSC_ERRORCODE csc_set_format(
+    void *handle)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
     if (csc_handle->csc_method == CSC_METHOD_HW) {
-        if (csc_handle->csc_hw_handle == NULL) {
-            ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
-            free(csc_handle);
-            csc_handle = NULL;
+        switch (csc_handle->csc_hw_type) {
+        case CSC_HW_TYPE_FIMC:
+            break;
+#ifdef ENABLE_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            exynos_gsc_set_src_format(
+                csc_handle->csc_hw_handle,
+                ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN),
+                ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN),
+                csc_handle->src_format.crop_left,
+                csc_handle->src_format.crop_top,
+                csc_handle->src_format.crop_width,
+                csc_handle->src_format.crop_height,
+                HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format),
+                csc_handle->src_format.cacheable,
+                csc_handle->hw_property.mode_drm);
+
+            exynos_gsc_set_dst_format(
+                csc_handle->csc_hw_handle,
+                ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN),
+                ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN),
+                csc_handle->dst_format.crop_left,
+                csc_handle->dst_format.crop_top,
+                csc_handle->dst_format.crop_width,
+                csc_handle->dst_format.crop_height,
+                HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
+                csc_handle->dst_format.cacheable,
+                csc_handle->hw_property.mode_drm,
+                0);
+            break;
+#endif
+#ifdef ENABLE_G2D
+        case CSC_HW_TYPE_G2D:
+        {
+            g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
+
+            g2d->src.width = ALIGN(csc_handle->src_format.width,
+                    GSCALER_IMG_ALIGN);
+            g2d->src.height = csc_handle->src_format.height;
+            g2d->src.stride = g2d->src.width *
+                    hal_2_g2d_bpp(csc_handle->src_format.color_format) >> 3;
+            g2d->src.order = hal_2_g2d_pixel_order(csc_handle->src_format.color_format);
+            g2d->src.fmt = hal_2_g2d_color_format(csc_handle->src_format.color_format);
+            g2d->src.rect.x1 = csc_handle->src_format.crop_left;
+            g2d->src.rect.y1 = csc_handle->src_format.crop_top;
+            g2d->src.rect.x2 = csc_handle->src_format.crop_left +
+                    csc_handle->src_format.crop_width;
+            g2d->src.rect.y2 = csc_handle->src_format.crop_top +
+                    csc_handle->src_format.crop_height;
+
+            g2d->dst.width = ALIGN(csc_handle->dst_format.width,
+                    GSCALER_IMG_ALIGN);
+            g2d->dst.height = csc_handle->dst_format.height;
+            g2d->dst.stride = g2d->dst.width *
+                    hal_2_g2d_bpp(csc_handle->dst_format.color_format) >> 3;
+            g2d->dst.order = hal_2_g2d_pixel_order(csc_handle->dst_format.color_format);
+            g2d->dst.fmt = hal_2_g2d_color_format(csc_handle->dst_format.color_format);
+            g2d->dst.rect.x1 = csc_handle->dst_format.crop_left;
+            g2d->dst.rect.y1 = csc_handle->dst_format.crop_top;
+            g2d->dst.rect.x2 = csc_handle->dst_format.crop_left +
+                    csc_handle->dst_format.crop_width;
+            g2d->dst.rect.y2 = csc_handle->dst_format.crop_top +
+                    csc_handle->dst_format.crop_height;
+
+            break;
+        }
+#endif
+        default:
+            ALOGE("%s:: unsupported csc_hw_type", __func__);
+            break;
         }
     }
 
-    ALOGD("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
+    return ret;
+}
+
+static CSC_ERRORCODE csc_set_buffer(
+    void *handle)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    if (csc_handle->csc_method == CSC_METHOD_HW) {
+        switch (csc_handle->csc_hw_type) {
+        case CSC_HW_TYPE_FIMC:
+            break;
+#ifdef ENABLE_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1);
+            exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1);
+            break;
+#endif
+#ifdef ENABLE_G2D
+        case CSC_HW_TYPE_G2D:
+        {
+            g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
+
+            g2d->src.addr.type = ADDR_DMA_BUF;
+            g2d->src.addr.fd[0] = (int)csc_handle->src_buffer.planes[0];
+            g2d->src.addr.fd[1] = (int)csc_handle->src_buffer.planes[1];
+
+            g2d->dst.addr.type = ADDR_DMA_BUF;
+            g2d->dst.addr.fd[0] = (int)csc_handle->dst_buffer.planes[0];
+            g2d->dst.addr.fd[1] = (int)csc_handle->dst_buffer.planes[1];
+
+            break;
+        }
+#endif
+        default:
+            ALOGE("%s:: unsupported csc_hw_type", __func__);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+void *csc_init(
+    CSC_METHOD method)
+{
+    CSC_HANDLE *csc_handle;
+    csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE));
+    if (csc_handle == NULL)
+        return NULL;
+
+    memset(csc_handle, 0, sizeof(CSC_HANDLE));
+    csc_handle->hw_property.fixed_node = -1;
+    csc_handle->hw_property.mode_drm = 0;
+    csc_handle->csc_method = method;
 
     return (void *)csc_handle;
 }
@@ -429,17 +572,26 @@ CSC_ERRORCODE csc_deinit(
     CSC_HANDLE *csc_handle;
 
     csc_handle = (CSC_HANDLE *)handle;
-    if (csc_handle->csc_method == CSC_METHOD_HW) {
+    if (csc_handle->csc_hw_handle) {
         switch (csc_handle->csc_hw_type) {
-#ifdef USE_FIMC
+#ifdef ENABLE_FIMC
         case CSC_HW_TYPE_FIMC:
             csc_hwconverter_close(csc_handle->csc_hw_handle);
             break;
 #endif
-#ifdef USE_GSCALER
+#ifdef ENABLE_GSCALER
         case CSC_HW_TYPE_GSCALER:
             exynos_gsc_destroy(csc_handle->csc_hw_handle);
             break;
+#endif
+#ifdef ENABLE_G2D
+        case CSC_HW_TYPE_G2D:
+        {
+            g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
+            close(g2d->fd);
+            free(g2d);
+            break;
+        }
 #endif
         default:
             ALOGE("%s:: unsupported csc_hw_type", __func__);
@@ -471,6 +623,58 @@ CSC_ERRORCODE csc_get_method(
     return ret;
 }
 
+CSC_ERRORCODE csc_set_method(
+    void           *handle,
+    CSC_METHOD     method)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    csc_handle->csc_method = method;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_hw_property(
+    void                *handle,
+    CSC_HW_PROPERTY_TYPE property,
+    int                  value)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+
+    if (csc_handle->csc_hw_handle) {
+        ALOGE("%s:: cannot set hw property after hw is already initialized", __func__);
+        return CSC_ErrorUnsupportFormat;
+    }
+
+    switch (property) {
+    case CSC_HW_PROPERTY_FIXED_NODE:
+        csc_handle->hw_property.fixed_node = value;
+        break;
+    case CSC_HW_PROPERTY_MODE_DRM:
+        csc_handle->hw_property.mode_drm = value;
+        break;
+    case CSC_HW_PROPERTY_HW_TYPE:
+        csc_handle->csc_hw_type = value;
+        break;
+    default:
+        ALOGE("%s:: not supported hw property", __func__);
+        ret = CSC_ErrorUnsupportFormat;
+    }
+
+    return ret;
+}
+
 CSC_ERRORCODE csc_get_src_format(
     void           *handle,
     unsigned int   *width,
@@ -528,30 +732,6 @@ CSC_ERRORCODE csc_set_src_format(
     csc_handle->src_format.color_format = color_format;
     csc_handle->src_format.cacheable = cacheable;
 
-    if (csc_handle->csc_method == CSC_METHOD_HW) {
-        switch (csc_handle->csc_hw_type) {
-        case CSC_HW_TYPE_FIMC:
-            break;
-#ifdef USE_GSCALER
-        case CSC_HW_TYPE_GSCALER:
-            exynos_gsc_set_src_format(
-                csc_handle->csc_hw_handle,
-                ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN),
-                ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN),
-                csc_handle->src_format.crop_left,
-                csc_handle->src_format.crop_top,
-                ALIGN(csc_handle->src_format.crop_width, GSCALER_IMG_ALIGN),
-                ALIGN(csc_handle->src_format.crop_height, GSCALER_IMG_ALIGN),
-                HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format),
-                csc_handle->src_format.cacheable);
-            break;
-#endif
-        default:
-            ALOGE("%s:: unsupported csc_hw_type", __func__);
-            break;
-        }
-    }
-
     return ret;
 }
 
@@ -612,111 +792,41 @@ CSC_ERRORCODE csc_set_dst_format(
     csc_handle->dst_format.color_format = color_format;
     csc_handle->dst_format.cacheable = cacheable;
 
-    if (csc_handle->csc_method == CSC_METHOD_HW) {
-        switch (csc_handle->csc_hw_type) {
-        case CSC_HW_TYPE_FIMC:
-            break;
-#ifdef USE_GSCALER
-        case CSC_HW_TYPE_GSCALER:
-            exynos_gsc_set_dst_format(
-                csc_handle->csc_hw_handle,
-                ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN),
-                ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN),
-                csc_handle->dst_format.crop_left,
-                csc_handle->dst_format.crop_top,
-                ALIGN(csc_handle->dst_format.crop_width, GSCALER_IMG_ALIGN),
-                ALIGN(csc_handle->dst_format.crop_height, GSCALER_IMG_ALIGN),
-                HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
-                csc_handle->dst_format.cacheable);
-            break;
-#endif
-        default:
-            ALOGE("%s:: unsupported csc_hw_type", __func__);
-            break;
-        }
-    }
-
     return ret;
 }
 
 CSC_ERRORCODE csc_set_src_buffer(
-    void           *handle,
-    unsigned char  *y,
-    unsigned char  *u,
-    unsigned char  *v,
-    int             ion_fd)
+    void *handle,
+    void *addr[3])
 {
     CSC_HANDLE *csc_handle;
     CSC_ERRORCODE ret = CSC_ErrorNone;
-    void *addr[3] = {NULL, };
 
     if (handle == NULL)
         return CSC_ErrorNotInit;
 
     csc_handle = (CSC_HANDLE *)handle;
-    csc_handle->src_buffer.planes[CSC_Y_PLANE] = y;
-    csc_handle->src_buffer.planes[CSC_U_PLANE] = u;
-    csc_handle->src_buffer.planes[CSC_V_PLANE] = v;
-
-    if (csc_handle->csc_method == CSC_METHOD_HW) {
-        addr[0] = csc_handle->src_buffer.planes[CSC_Y_PLANE];
-        addr[1] = csc_handle->src_buffer.planes[CSC_U_PLANE];
-        addr[2] = csc_handle->src_buffer.planes[CSC_V_PLANE];
-
-        switch (csc_handle->csc_hw_type) {
-        case CSC_HW_TYPE_FIMC:
-            break;
-#ifdef USE_GSCALER
-        case CSC_HW_TYPE_GSCALER:
-            exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, addr);
-            break;
-#endif
-        default:
-            ALOGE("%s:: unsupported csc_hw_type", __func__);
-            break;
-        }
-    }
+    csc_handle->src_buffer.planes[CSC_Y_PLANE] = addr[0];
+    csc_handle->src_buffer.planes[CSC_U_PLANE] = addr[1];
+    csc_handle->src_buffer.planes[CSC_V_PLANE] = addr[2];
 
     return ret;
 }
 
 CSC_ERRORCODE csc_set_dst_buffer(
-    void           *handle,
-    unsigned char  *y,
-    unsigned char  *u,
-    unsigned char  *v,
-    int             ion_fd)
+    void *handle,
+    void *addr[3])
 {
     CSC_HANDLE *csc_handle;
     CSC_ERRORCODE ret = CSC_ErrorNone;
-    void *addr[3] = {NULL, };
 
     if (handle == NULL)
         return CSC_ErrorNotInit;
 
     csc_handle = (CSC_HANDLE *)handle;
-    csc_handle->dst_buffer.planes[CSC_Y_PLANE] = y;
-    csc_handle->dst_buffer.planes[CSC_U_PLANE] = u;
-    csc_handle->dst_buffer.planes[CSC_V_PLANE] = v;
-
-    if (csc_handle->csc_method == CSC_METHOD_HW) {
-        addr[0] = csc_handle->dst_buffer.planes[CSC_Y_PLANE];
-        addr[1] = csc_handle->dst_buffer.planes[CSC_U_PLANE];
-        addr[2] = csc_handle->dst_buffer.planes[CSC_V_PLANE];
-
-        switch (csc_handle->csc_hw_type) {
-        case CSC_HW_TYPE_FIMC:
-            break;
-#ifdef USE_GSCALER
-        case CSC_HW_TYPE_GSCALER:
-            exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, addr);
-            break;
-#endif
-        default:
-            ALOGE("%s:: unsupported csc_hw_type", __func__);
-            break;
-        }
-    }
+    csc_handle->dst_buffer.planes[CSC_Y_PLANE] = addr[0];
+    csc_handle->dst_buffer.planes[CSC_U_PLANE] = addr[1];
+    csc_handle->dst_buffer.planes[CSC_V_PLANE] = addr[2];
 
     return ret;
 }
@@ -730,6 +840,21 @@ CSC_ERRORCODE csc_convert(
     if (csc_handle == NULL)
         return CSC_ErrorNotInit;
 
+    if ((csc_handle->csc_method == CSC_METHOD_HW) &&
+        (csc_handle->csc_hw_handle == NULL)) {
+        ret = csc_init_hw(handle);
+        if (ret != CSC_ErrorNone)
+            return ret;
+    }
+
+    ret = csc_set_format(csc_handle);
+    if (ret != CSC_ErrorNone)
+        return ret;
+
+    ret = csc_set_buffer(csc_handle);
+    if (ret != CSC_ErrorNone)
+        return ret;
+
     if (csc_handle->csc_method == CSC_METHOD_HW)
         ret = conv_hw(csc_handle);
     else