csc: support hardware CSC with G2D

Change-Id: Id6d16e4f79245e1895e8bc66372eef27509722b9
Signed-off-by: Greg Hackmann <ghackmann@google.com>
diff --git a/libcsc/csc.c b/libcsc/csc.c
index 11c5b1c..0831f61 100644
--- a/libcsc/csc.c
+++ b/libcsc/csc.c
@@ -53,6 +53,19 @@
 #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 ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
 
@@ -309,6 +322,29 @@
         }
         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(%d)", __func__, handle->csc_hw_type);
         ret = CSC_ErrorNotImplemented;
@@ -342,9 +378,27 @@
             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;
         }
     }
@@ -403,6 +457,42 @@
                 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;
@@ -432,6 +522,22 @@
             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;
@@ -476,6 +582,15 @@
             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__);
             break;