Initial version of libexynos-common 80/118980/2 accepted/tizen/unified/20170406.053550 submit/tizen/20170404.094130
authorSejun Park <sejun79.park@samsung.com>
Wed, 15 Mar 2017 04:50:44 +0000 (13:50 +0900)
committerSejun Park <sejun79.park@samsung.com>
Thu, 16 Mar 2017 04:24:12 +0000 (13:24 +0900)
Change-Id: Iee46e0c7bb5146ef516d9652c4c5634022cd4310

48 files changed:
COPYING [new file with mode: 0755]
Makefile.am [new file with mode: 0755]
README [new file with mode: 0755]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0755]
exynos-common.pc [new file with mode: 0755]
include/content_protect.h [new file with mode: 0755]
include/csc.h [new file with mode: 0755]
include/exynos_format.h [new file with mode: 0755]
include/exynos_gscaler.h [new file with mode: 0755]
include/exynos_ion.h [new file with mode: 0755]
include/exynos_log.h [new file with mode: 0755]
include/exynos_scaler.h [new file with mode: 0755]
include/exynos_v4l2.h [new file with mode: 0755]
include/ion.h [new file with mode: 0755]
include/linux/compiler.h [new file with mode: 0755]
include/media.h [new file with mode: 0755]
include/swconverter.h [new file with mode: 0755]
include/system/graphics.h [new file with mode: 0755]
libcsc/Makefile.am [new file with mode: 0755]
libcsc/csc.c [new file with mode: 0755]
libexynos-common.manifest [new file with mode: 0755]
libgscaler/Makefile.am [new file with mode: 0755]
libgscaler/libgscaler.cpp [new file with mode: 0755]
libgscaler/libgscaler_obj.cpp [new file with mode: 0755]
libgscaler/libgscaler_obj.h [new file with mode: 0755]
libion/Makefile.am [new file with mode: 0755]
libion/include/ion/ion.h [new file with mode: 0755]
libion/ion.c [new file with mode: 0755]
libion/kernel-headers/linux/ion.h [new file with mode: 0755]
libswconverter/Makefile.am [new file with mode: 0755]
libswconverter/csc_BGRA8888_to_RGBA8888_NEON.s [new file with mode: 0755]
libswconverter/csc_BGRA8888_to_YUV420SP_NEON.s [new file with mode: 0755]
libswconverter/csc_RGBA8888_to_YUV420SP_NEON.s [new file with mode: 0755]
libswconverter/csc_interleave_memcpy_neon.s [new file with mode: 0755]
libswconverter/csc_linear_to_tiled_crop_neon.s [new file with mode: 0755]
libswconverter/csc_linear_to_tiled_interleave_crop_neon.s [new file with mode: 0755]
libswconverter/csc_tiled_to_linear_crop_neon.s [new file with mode: 0755]
libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s [new file with mode: 0755]
libswconverter/csc_tiled_to_linear_uv_deinterleave_neon.s [new file with mode: 0755]
libswconverter/csc_tiled_to_linear_uv_neon.s [new file with mode: 0755]
libswconverter/csc_tiled_to_linear_y_neon.s [new file with mode: 0755]
libswconverter/swconvertor.c [new file with mode: 0755]
libv4l2/Makefile.am [new file with mode: 0755]
libv4l2/exynos_mc.c [new file with mode: 0755]
libv4l2/exynos_subdev.c [new file with mode: 0755]
libv4l2/exynos_v4l2.c [new file with mode: 0755]
packaging/libexynos-common.spec [new file with mode: 0755]

diff --git a/COPYING b/COPYING
new file mode 100755 (executable)
index 0000000..4a67574
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,203 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100755 (executable)
index 0000000..2bef805
--- /dev/null
@@ -0,0 +1,4 @@
+SUBDIRS = libion libv4l2 libswconverter libcsc libgscaler
+
+pcfiles = exynoes-common.pc
+
diff --git a/README b/README
new file mode 100755 (executable)
index 0000000..cdea039
--- /dev/null
+++ b/README
@@ -0,0 +1,15 @@
+
+1. "libtoolize" to install ltmain.sh
+2. "aclocal" to generate m4 script for autoconf
+3. "autoheader" to generate config.h
+4. "autoconf" to generate configure script
+5. "automake" with "--add-missing" optionto generate Makefile
+
+then assume that your compiler prefix is stored in ${CROSS_COMPILE},
+and your library prefix is ${PREFIX},
+
+./configure --host=arm-linux-gnueabihf --prefix=${PREFIX} CC=${CROSS_COMPILE}gcc CXX=${CROSS_COMPILE}g++
+
+(check your gcc prefix to find the host system it is assumed that "arm-linux-gnueabihf")
+
+then enjoy "make" and "make install"
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..30d679f
--- /dev/null
@@ -0,0 +1,6 @@
+#! /bin/sh
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+autoreconf --force --install --verbose "$srcdir"
+test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100755 (executable)
index 0000000..6adadc5
--- /dev/null
@@ -0,0 +1,70 @@
+AC_PREREQ([2.60])
+AC_INIT([libexynos],
+        [1.0.0],
+        [https://www.tizen.org],
+        [libexynos])
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_INIT_AUTOMAKE([1.10 foreign dist-bzip2])
+AM_MAINTAINER_MODE([enable])
+i
+# Check for programs
+AM_PROG_AS
+AC_PROG_CC
+AC_PROG_CXX
+
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+AC_FUNC_ALLOCA
+
+#AC_CONFIG_MACRO_DIR([m4])
+
+LT_PREREQ([2.2])
+LT_INIT([disable-static])
+
+# Enable quiet compiles on automake 1.11.
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+#PKG_CHECK_MODULES(TDM_EXYNOS, dlog)
+#PKG_CHECK_MODULES(UDEV, libudev, [udev=yes], [udev=no])
+#if test x"$udev" = xyes; then
+#      AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
+#fi
+
+#AC_SUBST(DLOG_LIBS)
+
+# Initialize libtooldnl use dlog ------------------------------------------------------------------
+AC_ARG_ENABLE(dlog, AC_HELP_STRING([--enable-dlog], [using dlog]),
+        [
+          case "${enableval}" in
+           yes) USE_DLOG=yes ;;
+           no)  USE_DLOG=no ;;
+           *)   AC_MSG_ERROR(bad value ${enableval} for --enable-dlog) ;;
+          esac
+        ],[USE_DLOG=no])
+
+if test "x$USE_DLOG" = "xyes"; then
+        PKG_CHECK_MODULES(DLOG, dlog)
+        AC_SUBST(DLOG_CFLAGS)
+        AC_SUBST(DLOG_LIBS)
+fi
+AM_CONDITIONAL(USE_DLOG, test "x$USE_DLOG" = "xyes")
+dnl end -----------------------------------------------------------------------
+
+# set the dir for the tbm module
+DEFAULT_MODULE_PATH="${libdir}"
+
+# For enumerating devices in test case
+AC_OUTPUT([
+       Makefile
+       libv4l2/Makefile
+       libswconverter/Makefile
+       libcsc/Makefile
+       libgscaler/Makefile
+       libion/Makefile])
+
+echo ""
+echo "$PACKAGE_STRING will be compiled with:"
+echo ""
+echo ""
diff --git a/exynos-common.pc b/exynos-common.pc
new file mode 100755 (executable)
index 0000000..d3e44ea
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=/usr
+libdir=/usr/lib
+includedir=/usr/include
+
+Name: Samsung exynos common package
+Description: Samsung exynos common
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -lexynosv4l2 -lexynosgscaler -lcsc -lswconverter -lion
+Cflags: -I${includedir}/libexynos-common
+
diff --git a/include/content_protect.h b/include/content_protect.h
new file mode 100755 (executable)
index 0000000..3cbf31f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CONTENT_PROTECT_H__
+#define __CONTENT_PROTECT_H__
+
+__BEGIN_DECLS
+
+typedef enum {
+       CP_SUCCESS = 0,
+       CP_ERROR_ENABLE_PATH_PROTECTION_FAILED,
+       CP_ERROR_DISABLE_PATH_PROTECTION_FAILED,
+} cpResult_t;
+
+
+/**
+ * protection IP
+ */
+#define CP_PROTECT_MFC         (1 << 0)
+#define CP_PROTECT_GSC0                (1 << 1)
+#define CP_PROTECT_GSC3                (1 << 2)
+#define CP_PROTECT_FIMD                (1 << 3)
+#define CP_PROTECT_MIXER       (1 << 4)
+
+#define CP_PROTECT_MFC1                (1 << 5)
+#define CP_PROTECT_GSC1                (1 << 6)
+#define CP_PROTECT_GSC2                (1 << 7)
+#define CP_PROTECT_HDMI                (1 << 8)
+
+#if 0
+cpResult_t CP_Enable_Path_Protection(uint32_t);
+cpResult_t CP_Disable_Path_Protection(uint32_t);
+#else
+static inline cpResult_t CP_Enable_Path_Protection(uint32_t)
+{
+    return CP_SUCCESS;
+}
+static inline cpResult_t CP_Disable_Path_Protection(uint32_t)
+{
+    return CP_SUCCESS;
+}
+#endif
+
+__END_DECLS
+
+#endif
diff --git a/include/csc.h b/include/csc.h
new file mode 100755 (executable)
index 0000000..7f277d6
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc.h
+ *
+ * @brief   color space convertion abstract header
+ *
+ * @author  Pyoungjae Jung (pjet.jung@samsung.com)
+ *
+ * @version 1.0
+ *
+ * @history
+ *   2011.12.27 : Create
+ */
+
+#ifndef CSC_H
+#define CSC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CSC_MAX_PLANES 3
+
+typedef enum _CSC_ERRORCODE {
+    CSC_ErrorNone = 0,
+    CSC_Error,
+    CSC_ErrorNotInit,
+    CSC_ErrorInvalidAddress,
+    CSC_ErrorUnsupportFormat,
+    CSC_ErrorNotImplemented
+} CSC_ERRORCODE;
+
+typedef enum _CSC_METHOD {
+    CSC_METHOD_SW = 0,
+    CSC_METHOD_HW
+} CSC_METHOD;
+
+typedef enum _CSC_HW_PROPERTY_TYPE {
+    CSC_HW_PROPERTY_FIXED_NODE = 0,
+    CSC_HW_PROPERTY_MODE_DRM,
+} CSC_HW_PROPERTY_TYPE;
+
+typedef enum _CSC_MEMTYPE {
+    CSC_MEMORY_MMAP = 1,
+    CSC_MEMORY_USERPTR,
+    CSC_MEMORY_OVERLAY,
+    CSC_MEMORY_DMABUF,
+    CSC_MEMORY_MFC,
+} CSC_MEMTYPE;
+
+typedef enum _CSC_HW_ID {
+    CSC_HW_GSC0 = 0,
+    CSC_HW_GSC1,
+    CSC_HW_GSC2,
+    CSC_HW_GSC3,
+    CSC_HW_SC0,
+    CSC_HW_SC1,
+    CSC_HW_SC2,
+    CSC_HW_MAX,
+} CSC_HW_ID;
+
+typedef enum _CSC_PLANE {
+    CSC_Y_PLANE = 0,
+    CSC_RGB_PLANE = 0,
+    CSC_U_PLANE = 1,
+    CSC_UV_PLANE = 1,
+    CSC_V_PLANE = 2
+} CSC_PLANE;
+
+typedef enum _CSC_HW_TYPE {
+    CSC_HW_TYPE_FIMC = 0,
+    CSC_HW_TYPE_GSCALER
+} CSC_HW_TYPE;
+
+typedef enum _CSC_EQ_MODE {
+    CSC_EQ_MODE_USER = 0,
+    CSC_EQ_MODE_AUTO
+} CSC_EQ_MODE;
+
+typedef enum _CSC_EQ_COLORSPACE {
+    CSC_EQ_COLORSPACE_SMPTE170M = 1,
+    CSC_EQ_COLORSPACE_SMPTE240M,
+    CSC_EQ_COLORSPACE_REC709,
+    CSC_EQ_COLORSPACE_BT878,
+    CSC_EQ_COLORSPACE_470_SYSTEM_M,
+    CSC_EQ_COLORSPACE_470_SYSTEM_BG
+} CSC_EQ_COLORSPACE;
+
+typedef enum _CSC_EQ_RANGE {
+    CSC_EQ_RANGE_NARROW = 0,
+    CSC_EQ_RANGE_FULL
+} CSC_EQ_RANGE;
+
+typedef enum _CSC_HW_FILTER {
+    CSC_FT_NONE = 0,
+    CSC_FT_BLUR,
+    CSC_FT_240,
+    CSC_FT_480,
+    CSC_FT_720,
+    CSC_FT_1080,
+    CSC_FT_MAX
+} CSC_HW_FILTER;
+
+typedef struct _CSC_FORMAT {
+    unsigned int width;
+    unsigned int height;
+    unsigned int crop_left;
+    unsigned int crop_top;
+    unsigned int crop_width;
+    unsigned int crop_height;
+    unsigned int color_format;
+    unsigned int cacheable;
+    unsigned int mode_drm;
+} CSC_FORMAT;
+
+typedef struct _CSC_BUFFER {
+    void *planes[CSC_MAX_PLANES];
+    int mem_type;
+} 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;
+    CSC_BUFFER      dst_buffer;
+    CSC_BUFFER      src_buffer;
+    CSC_METHOD      csc_method;
+    CSC_HW_TYPE     csc_hw_type;
+    void           *csc_hw_handle;
+    CSC_HW_PROPERTY hw_property;
+
+    /* CSC Equation */
+    CSC_EQ_MODE       csc_mode;
+    CSC_EQ_RANGE      csc_range;
+    CSC_EQ_COLORSPACE colorspace;
+
+    /* Denoising filter */
+    CSC_HW_FILTER    filter;
+} CSC_HANDLE;
+
+/*
+ * change hal pixel format to omx pixel format
+ *
+ * @param hal_format
+ *   hal pixel format[in]
+ *
+ * @return
+ *   omx pixel format
+ */
+unsigned int hal_2_omx_pixel_format(
+    unsigned int hal_format);
+
+/*
+ * change omx pixel format to hal pixel format
+ *
+ * @param hal_format
+ *   omx pixel format[in]
+ *
+ * @return
+ *   hal pixel format
+ */
+unsigned int omx_2_hal_pixel_format(
+    unsigned int omx_format);
+
+/*
+ * Init CSC handle
+ *
+ * @return
+ *   csc handle
+ */
+void *csc_init(
+    CSC_METHOD method);
+
+/*
+ * Deinit CSC handle
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_deinit(
+    void *handle);
+
+/*
+ * get color space converter method
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param method
+ *   CSC method[out]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_get_method(
+    void           *handle,
+    CSC_METHOD     *method);
+
+/*
+ * set color space converter method
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param method
+ *   CSC method[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_method(
+    void           *handle,
+    CSC_METHOD      method);
+
+/*
+ * Set hw property
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param property
+ *   csc hw property[in]
+ *
+ * @param value
+ *   csc hw property value[in]
+ *
+ * @return
+ *   csc handle
+ */
+CSC_ERRORCODE csc_set_hw_property(
+    void                *handle,
+    CSC_HW_PROPERTY_TYPE property,
+    int                  value);
+
+/*
+ * Get csc equation property.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param mode
+ *   csc equation mode[out]
+ *
+ * @param colorspace
+ *   csc color space[out]
+ *
+ * @param range
+ *   csc equation range[out]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_get_eq_property(
+    void              *handle,
+    CSC_EQ_MODE       *csc_mode,
+    CSC_EQ_RANGE      *csc_range,
+    CSC_EQ_COLORSPACE *colorspace);
+
+/*
+ * Set csc equation property.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param mode
+ *   csc equation mode[in]
+ *
+ * @param colorspace
+ *   csc color space[in]
+ *
+ * @param range
+ *   csc equation range[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_eq_property(
+    void              *handle,
+    CSC_EQ_MODE        csc_mode,
+    CSC_EQ_RANGE       csc_range,
+    CSC_EQ_COLORSPACE  colorspace);
+
+/*
+ * Set csc filter property.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param filter
+ *   csc filter info[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_filter_property(
+    void              *handle,
+    CSC_HW_FILTER     filter);
+
+/*
+ * Get source format.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param width
+ *   address of image width[out]
+ *
+ * @param height
+ *   address of image height[out]
+ *
+ * @param crop_left
+ *   address of image left crop size[out]
+ *
+ * @param crop_top
+ *   address of image top crop size[out]
+ *
+ * @param crop_width
+ *   address of cropped image width[out]
+ *
+ * @param crop_height
+ *   address of cropped image height[out]
+ *
+ * @param color_format
+ *   address of source color format(HAL format)[out]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_get_src_format(
+    void           *handle,
+    unsigned int   *width,
+    unsigned int   *height,
+    unsigned int   *crop_left,
+    unsigned int   *crop_top,
+    unsigned int   *crop_width,
+    unsigned int   *crop_height,
+    unsigned int   *color_format,
+    unsigned int   *cacheable);
+
+/*
+ * Set source format.
+ * Don't call each converting time.
+ * Pls call this function as below.
+ *   1. first converting time
+ *   2. format is changed
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param width
+ *   image width[in]
+ *
+ * @param height
+ *   image height[in]
+ *
+ * @param crop_left
+ *   image left crop size[in]
+ *
+ * @param crop_top
+ *   image top crop size[in]
+ *
+ * @param crop_width
+ *   cropped image width[in]
+ *
+ * @param crop_height
+ *   cropped image height[in]
+ *
+ * @param color_format
+ *   source color format(HAL format)[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_src_format(
+    void           *handle,
+    unsigned int    width,
+    unsigned int    height,
+    unsigned int    crop_left,
+    unsigned int    crop_top,
+    unsigned int    crop_width,
+    unsigned int    crop_height,
+    unsigned int    color_format,
+    unsigned int    cacheable);
+
+/*
+ * Get destination format.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param width
+ *   address of image width[out]
+ *
+ * @param height
+ *   address of image height[out]
+ *
+ * @param crop_left
+ *   address of image left crop size[out]
+ *
+ * @param crop_top
+ *   address of image top crop size[out]
+ *
+ * @param crop_width
+ *   address of cropped image width[out]
+ *
+ * @param crop_height
+ *   address of cropped image height[out]
+ *
+ * @param color_format
+ *   address of color format(HAL format)[out]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_get_dst_format(
+    void           *handle,
+    unsigned int   *width,
+    unsigned int   *height,
+    unsigned int   *crop_left,
+    unsigned int   *crop_top,
+    unsigned int   *crop_width,
+    unsigned int   *crop_height,
+    unsigned int   *color_format,
+    unsigned int   *cacheable);
+
+/*
+ * Set destination format
+ * Don't call each converting time.
+ * Pls call this function as below.
+ *   1. first converting time
+ *   2. format is changed
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param width
+ *   image width[in]
+ *
+ * @param height
+ *   image height[in]
+ *
+ * @param crop_left
+ *   image left crop size[in]
+ *
+ * @param crop_top
+ *   image top crop size[in]
+ *
+ * @param crop_width
+ *   cropped image width[in]
+ *
+ * @param crop_height
+ *   cropped image height[in]
+ *
+ * @param color_format
+ *   destination color format(HAL format)[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_dst_format(
+    void           *handle,
+    unsigned int    width,
+    unsigned int    height,
+    unsigned int    crop_left,
+    unsigned int    crop_top,
+    unsigned int    crop_width,
+    unsigned int    crop_height,
+    unsigned int    color_format,
+    unsigned int    cacheable);
+
+/*
+ * Setup source buffer
+ * set_format func should be called before this this func.
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param src_buffer
+ *   source buffer pointer array[in]
+ *
+ * @param y
+ *   y or RGB destination pointer[in]
+ *
+ * @param u
+ *   u or uv destination pointer[in]
+ *
+ * @param v
+ *   v or none destination pointer[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_src_buffer(
+    void *handle,
+    void *addr[CSC_MAX_PLANES],
+    int mem_type);
+
+/*
+ * Setup destination buffer
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @param y
+ *   y or RGB destination pointer[in]
+ *
+ * @param u
+ *   u or uv destination pointer[in]
+ *
+ * @param v
+ *   v or none destination pointer[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_set_dst_buffer(
+    void *handle,
+    void *addr[CSC_MAX_PLANES],
+    int mem_type);
+
+/*
+ * Convert color space with presetup color format
+ *
+ * @param handle
+ *   CSC handle[in]
+ *
+ * @return
+ *   error code
+ */
+CSC_ERRORCODE csc_convert(
+    void *handle);
+
+CSC_ERRORCODE csc_convert_with_rotation(
+    void *handle, int rotation, int flip_horizontal, int flip_vertical);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/exynos_format.h b/include/exynos_format.h
new file mode 100755 (executable)
index 0000000..23a0d0c
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef _EXYNOS_FORMAT_H_
+#define _EXYNOS_FORMAT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+                                                           /* HAL_PIXEL_FORMAT_YCbCr_422_P = 0x100, */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M       = 0x101,   /* HAL_PIXEL_FORMAT_YCbCr_420_P */
+                                                           /* HAL_PIXEL_FORMAT_YCbCr_420_I = 0x102, */
+    HAL_PIXEL_FORMAT_EXYNOS_CbYCrY_422_I        = 0x103,   /* HAL_PIXEL_FORMAT_CbYCrY_422_I */
+                                                           /* HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x104, */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M      = 0x105,   /* HAL_PIXEL_FORMAT_YCbCr_420_SP */
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_SP        = 0x106,   /* HAL_PIXEL_FORMAT_YCrCb_422_SP */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED= 0x107,   /* HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED */
+    HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888           = 0x108,   /* HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888 */
+    // support custom format for zero copy
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP = 0x110 */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP = 0x111, */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED  = 0x112, */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP = 0x113, */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP = 0x114, */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I  = 0x115, */
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I         = 0x116,   /* HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I = 0x117, */
+    HAL_PIXEL_FORMAT_EXYNOS_CrYCbY_422_I        = 0x118,   /* HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I */
+                                                           /* HAL_PIXEL_FORMAT_CUSTOM_CbYCr_422_I = 0x11B, */
+
+    HAL_PIXEL_FORMAT_EXYNOS_YV12_M              = 0x11C,   /* HAL_PIXEL_FORMAT_EXYNOS_YV12 */
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M      = 0x11D,   /* HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP */
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL = 0x11E,   /* HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_FULL */
+
+    /* newly added formats */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P         = 0x11F,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP        = 0x120,
+
+    /* Interlace EXYNOS_YCbCr_420_SP_M */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV = 0x121,
+
+    /* contiguous(single fd) custom formats */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN        = 0x122,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN       = 0x123,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED = 0x124,
+
+    /* 10-bit format (8bit + separated 2bit) */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B = 0x125,
+
+    /* 10-bit contiguous(single fd, 8bit + separated 2bit) custom formats */
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B  = 0x126,
+
+    HAL_PIXEL_FORMAT_EXYNOS_MAX
+};
+
+/* for backward compatibility */
+#define HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M
+#define HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M
+
+// Gamut (colorspace range)
+enum {
+    HAL_PIXEL_GAMUT_DEFAULT = 0,
+    // Values range 0-255
+    HAL_PIXEL_GAMUT_WIDE_8,
+    // Values range 16-235
+    HAL_PIXEL_GAMUT_NARROW_8
+};
+
+// Chromaticities (colorspace parameters)
+enum {
+    HAL_PIXEL_CHROMA_DEFAULT = 0,
+    // BT.601 "Standard Definition" color space
+    HAL_PIXEL_CHROMA_BT601_8,
+    // BT.709 "High Definition" color space
+    HAL_PIXEL_CHROMA_BT709_8
+};
+
+struct ADDRS {
+    unsigned int addr_y;
+    unsigned int addr_cbcr;
+    unsigned int buf_idx;
+    unsigned int reserved;
+};
+
+/* 12  Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12T    v4l2_fourcc('T', 'V', '1', '2')
+
+#define ALIGN_UP(x, a)    (((x) + (a) - 1) & ~((a) - 1))
+#define ALIGN_DOWN(x, a)  ((x) - (x % a))
+#ifndef ALIGN
+#define ALIGN(x, a)       ALIGN_UP(x, a)
+#endif
+#ifndef ALIGN_TO_32B
+#define ALIGN_TO_32B(x)   ((((x) + (1 <<  5) - 1) >>  5) <<  5)
+#endif
+#ifndef ALIGN_TO_128B
+#define ALIGN_TO_128B(x)  ((((x) + (1 <<  7) - 1) >>  7) <<  7)
+#endif
+#ifndef ALIGN_TO_8KB
+#define ALIGN_TO_8KB(x)   ((((x) + (1 << 13) - 1) >> 13) << 13)
+#endif
+
+#define GET_32BPP_FRAME_SIZE(w, h)  (((w) * (h)) << 2)
+#define GET_24BPP_FRAME_SIZE(w, h)  (((w) * (h)) * 3)
+#define GET_16BPP_FRAME_SIZE(w, h)  (((w) * (h)) << 1)
+
+/*
+ * Convert hal_pixel_format to v4l2_pixel_format.
+ *
+ * @param hal_pixel_format
+ *   hal_pixel_format[in]
+ *
+ * @return
+ *   v4l2_pixel_format
+ */
+int HAL_PIXEL_FORMAT_2_V4L2_PIX(
+    int hal_pixel_format);
+
+/*
+ * Convert v4l2_pixel_format to hal_pixel_format.
+ *
+ * @param v4l2_pixel_format
+ *   v4l2_pixel_format[in]
+ *
+ * @return
+ *   hal_pixel_format
+ */
+int V4L2_PIX_2_HAL_PIXEL_FORMAT(
+    int v4l2_pixel_format);
+
+/*
+ * Get frame_size of hal_pixel_format.
+ *
+ * @param hal_pixel_format
+ *   hal_pixel_format[in]
+ *
+ * @param width
+ *   width[in]
+ *
+ * @param height
+ *   height[in]
+ *
+ * @return
+ *   frame_size
+ */
+unsigned int FRAME_SIZE(
+    int hal_pixel_format,
+    int width,
+    int height);
+
+int PLANAR_FRAME_SIZE(
+    int hal_pixel_format,
+    int width,
+    int height,
+    unsigned int *luma_size,
+    unsigned int *chroma_size);
+
+int NUM_PLANES(int hal_pixel_format);
+
+
+/*
+ * Get bpp and plane of v4l2_pixel_format.
+ *
+ * @param v4l2_pixel_format
+ *   v4l2_pixel_format[in]
+ *
+ * @param bpp
+ *   address of bpp[out]
+ *
+ * @param planes
+ *   address of planes[out]
+ *
+ * @return
+ *   error code
+ */
+int V4L2_PIX_2_YUV_INFO(
+    unsigned int  v4l2_pixel_format,
+    unsigned int *bpp,
+    unsigned int *planes);
+
+/*
+ * Get bpp of v4l2_pixel_format.
+ *
+ * @param v4l2_pixel_format
+ *   v4l2_pixel_format[in]
+ *
+ * @return
+ *   bpp
+ */
+int get_yuv_bpp(
+    unsigned int v4l2_pixel_format);
+
+/*
+ * Get plane of v4l2_pixel_format.
+ *
+ * @param v4l2_pixel_format
+ *   v4l2_pixel_format[in]
+ *
+ * @return
+ *   num of plane
+ */
+int get_yuv_planes(
+    unsigned int v4l2_pixel_format);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/exynos_gscaler.h b/include/exynos_gscaler.h
new file mode 100755 (executable)
index 0000000..38b57a4
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_gscaler.h
+ * \brief     header file for Gscaler HAL
+ * \author    ShinWon Lee (shinwon.lee@samsung.com)
+ * \date      2012/01/09
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/09 : ShinWon Lee(shinwon.lee@samsung.com) \n
+ *   Create
+ *
+ * - 2012/02/07 : ShinWon Lee(shinwon.lee@samsung.com) \n
+ *   Change file name to exynos_gscaler.h
+ *
+ * - 2012/02/09 : Sangwoo, Parkk(sw5771.park@samsung.com) \n
+ *   Use Multiple Gscaler by Multiple Process
+ *
+ * - 2012/02/20 : Sangwoo, Park(sw5771.park@samsung.com) \n
+ *   Add exynos_gsc_set_rotation() API
+ *
+ * - 2012/02/20 : ShinWon Lee(shinwon.lee@samsung.com) \n
+ *   Add size constrain
+ *
+ */
+
+/*!
+ * \defgroup exynos_gscaler
+ * \brief API for gscaler
+ * \addtogroup Exynos
+ */
+
+#ifndef EXYNOS_GSCALER_H_
+#define EXYNOS_GSCALER_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define EXYNOS_GSC_TRACE 1
+#ifdef EXYNOS_GSC_TRACE
+#define EXYNOS_GSC_LOG_TAG "Exynos_gscaler"
+#define Exynos_gsc_In() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, EXYNOS_GSC_LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__)
+#define Exynos_gsc_Out() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, EXYNOS_GSC_LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__)
+#else
+#define Exynos_gsc_In() ((void *)0)
+#define Exynos_gsc_Out() ((void *)0)
+#endif
+
+typedef struct {
+    uint32_t x;
+    uint32_t y;
+    uint32_t w;
+    uint32_t h;
+    uint32_t fw;
+    uint32_t fh;
+    uint32_t format;
+    unsigned long yaddr;
+    unsigned long uaddr;
+    unsigned long vaddr;
+    uint32_t rot;
+    uint32_t cacheable;
+    uint32_t drmMode;
+    uint32_t narrowRgb;
+    int      acquireFenceFd;
+    int      releaseFenceFd;
+    int      mem_type;
+    uint32_t pre_multi;
+} exynos_mpp_img;
+
+enum SRC_BL_OP {
+       /* [0, 0] */
+       SRC_BL_OP_CLR = 1,
+       /* [Sa, Sc] */
+       SRC_BL_OP_SRC,
+       /* [Da, Dc] */
+       SRC_BL_OP_DST,
+       /* [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
+       SRC_BL_OP_SRC_OVER,
+       /* [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
+       SRC_BL_OP_DST_OVER,
+       /* [Sa * Da, Sc * Da] */
+       SRC_BL_OP_SRC_IN,
+       /* [Sa * Da, Sa * Dc] */
+       SRC_BL_OP_DST_IN,
+       /* [Sa * (1 - Da), Sc * (1 - Da)] */
+       SRC_BL_OP_SRC_OUT,
+       /* [Da * (1 - Sa), Dc * (1 - Sa)] */
+       SRC_BL_OP_DST_OUT,
+       /* [Da, Sc * Da + (1 - Sa) * Dc] */
+       SRC_BL_OP_SRC_ATOP,
+       /* [Sa, Sc * (1 - Da) + Sa * Dc ] */
+       SRC_BL_OP_DST_ATOP,
+       /* [-(Sa * Da), Sc * (1 - Da) + (1 - Sa) * Dc] */
+       SRC_BL_OP_XOR,
+       /* [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
+       SRC_BL_OP_DARKEN,
+       /* [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
+       SRC_BL_OP_LIGHTEN,
+       /** [Sa * Da, Sc * Dc] */
+       SRC_BL_OP_MULTIPLY,
+       /* [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
+       SRC_BL_OP_SCREEN,
+       /* Saturate(S + D) */
+       SRC_BL_OP_ADD
+};
+
+enum colorspace {
+    COLORSPACE_SMPTE170M,
+    COLORSPACE_SMPTE240M,
+    COLORSPACE_REC709,
+    COLORSPACE_BT878,
+    COLORSPACE_470_SYSTEM_M,
+    COLORSPACE_470_SYSTEM_BG,
+    COLORSPACE_JPEG,
+    COLORSPACE_SRGB,
+};
+
+struct SrcGlobalAlpha {
+       uint32_t enable;
+       unsigned int val;
+};
+
+struct CSC_Spec{
+       uint32_t enable;    // set 'true' for user-defined
+       enum colorspace space;
+       uint32_t wide;
+};
+
+struct SrcBlendInfo {
+       enum SRC_BL_OP blop;
+       unsigned int srcblendfmt;
+       unsigned int srcblendhpos;
+       unsigned int srcblendvpos;
+       unsigned int srcblendpremulti;
+       unsigned int srcblendstride;
+       unsigned int srcblendwidth;
+       unsigned int srcblendheight;
+       struct SrcGlobalAlpha globalalpha;
+       struct CSC_Spec cscspec;
+};
+
+/*
+ * Create libgscaler handle.
+ * Gscaler dev_num is dynamically changed.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \return
+ *   libgscaler handle
+ */
+void *exynos_gsc_create(
+    void);
+
+/*!
+ * Create exclusive libgscaler handle.
+ * Other module can't use dev_num of Gscaler.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param dev_num
+ *   gscaler dev_num[in]
+ * \param gsc_mode
+ *It should be set to GSC_M2M_MODE or GSC_OUTPUT_MODE.
+ *
+ *\param out_mode
+ *It should be set to GSC_OUT_FIMD or GSC_OUT_TV.
+ *
+ * \return
+ *   libgscaler handle
+ */
+void *exynos_gsc_create_exclusive(
+    int dev_num,
+    int gsc_mode,
+    int out_mode,
+    int allow_drm);
+
+/*!
+ * Destroy libgscaler handle
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ */
+void exynos_gsc_destroy(
+    void *handle);
+
+/*!
+ * Set csc equation property
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param eq_auto
+ *   csc mode (0: user, 1: auto)[in]
+ *
+ * \param range_full
+ *   csc range (0: narrow, 1: full)[in]
+ *
+ * \param v4l2_colorspace
+ *   ITU_R v4l2 colorspace(1: 601, 3: 709)[in]
+ */
+int exynos_gsc_set_csc_property(
+    void        *handle,
+    unsigned int eq_auto,
+    unsigned int range_full,
+    unsigned int v4l2_colorspace);
+
+/*!
+ * Set source format.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param width
+ *   image width[in]
+ *
+ * \param height
+ *   image height[in]
+ *
+ * \param crop_left
+ *   image left crop size[in]
+ *
+ * \param crop_top
+ *   image top crop size[in]
+ *
+ * \param crop_width
+ *   cropped image width[in]
+ *
+ * \param crop_height
+ *   cropped image height[in]
+ *
+ * \param v4l2_colorformat
+ *   color format[in]
+ *
+ * \param cacheable
+ *   ccacheable[in]
+ *
+ * \param mode_drm
+ *   mode_drm[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_set_src_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm);
+
+/*!
+ * Set destination format.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param width
+ *   image width[in]
+ *
+ * \param height
+ *   image height[in]
+ *
+ * \param crop_left
+ *   image left crop size[in]
+ *
+ * \param crop_top
+ *   image top crop size[in]
+ *
+ * \param crop_width
+ *   cropped image width[in]
+ *
+ * \param crop_height
+ *   cropped image height[in]
+ *
+ * \param v4l2_colorformat
+ *   color format[in]
+ *
+ * \param cacheable
+ *   ccacheable[in]
+ *
+ * \param mode_drm
+ *   mode_drm[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_set_dst_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm);
+
+/*!
+ * Set rotation.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param rotation
+ *   image rotation. It should be multiple of 90[in]
+ *
+ * \param flip_horizontal
+ *   image flip_horizontal[in]
+ *
+ * \param flip_vertical
+ *   image flip_vertical[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_set_rotation(
+    void *handle,
+    int   rotation,
+    int   flip_horizontal,
+    int   flip_vertical);
+
+/*!
+ * Set source buffer
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param addr
+ *   buffer pointer array[in]
+ *
+ * \param acquireFenceFd
+ *   acquire fence fd for the buffer or -1[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_set_src_addr(
+    void *handle,
+    void *addr[3],
+    int mem_type,
+    int acquireFenceFd);
+
+/*!
+ * Set destination buffer
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \param addr
+ *   buffer pointer array[in]
+ *
+ * \param acquireFenceFd
+ *   acquire fence fd for the buffer or -1[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_set_dst_addr(
+    void *handle,
+    void *addr[3],
+    int mem_type,
+    int acquireFenceFd);
+
+/*!
+ * Convert color space with presetup color format
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param handle
+ *   libgscaler handle[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_gsc_convert(
+    void *handle);
+
+/*
+ * API for setting GSC subdev crop
+ * Used in OTF mode
+ */
+int exynos_gsc_subdev_s_crop(
+        void *handle,
+        exynos_mpp_img *src_img,
+        exynos_mpp_img *dst_img);
+
+/*
+*api for setting the GSC config.
+It configures the GSC for given config
+*/
+int exynos_gsc_config_exclusive(
+    void *handle,
+    exynos_mpp_img *src_img,
+    exynos_mpp_img *dst_img);
+
+/*
+*api for GSC-OUT run.
+It queues the srcBuf to GSC and deques a buf from driver.
+It should be called after configuring the GSC.
+*/
+int exynos_gsc_run_exclusive(
+    void *handle,
+    exynos_mpp_img *src_img,
+    exynos_mpp_img *dst_img);
+
+/*!
+ * Create exclusive libgscaler blend handle.
+ * Other module can't use dev_num of Gscaler.
+ *
+ * \ingroup exynos_gscaler
+ *
+ * \param dev_num
+ *   gscaler dev_num[in]
+ * \param gsc_mode
+ * \return
+ *   libgscaler handle
+ */
+void *exynos_gsc_create_blend_exclusive(
+    int dev_num,
+    int gsc_mode,
+    int out_mode,
+    int allow_drm);
+
+/*
+*api for setting the GSC blend config.
+It configures the GSC for given config
+*/
+int exynos_gsc_config_blend_exclusive(
+    void *handle,
+    exynos_mpp_img *src_img,
+    exynos_mpp_img *dst_img,
+    struct SrcBlendInfo  *srcblendinfo);
+
+/*
+ * Blocks until the current frame is done processing.
+ */
+int exynos_gsc_wait_frame_done_exclusive
+(void *handle);
+
+/*
+*api for GSC stop.
+It stops the GSC OUT streaming.
+*/
+int exynos_gsc_stop_exclusive
+(void *handle);
+
+/*
+*api for GSC free_and_close.
+*/
+int exynos_gsc_free_and_close
+(void *handle);
+
+enum {
+    GSC_M2M_MODE = 0,
+    GSC_OUTPUT_MODE,
+    GSC_CAPTURE_MODE,
+    GSC_RESERVED_MODE,
+};
+
+/*flag info */
+enum {
+    GSC_DUMMY = 0,
+    GSC_OUT_FIMD,
+    GSC_OUT_TV,
+    GSC_RESERVED,
+};
+
+enum {
+    GSC_DONE_CNG_CFG = 0,
+    GSC_NEED_CNG_CFG,
+};
+
+enum {
+    GSC_MEM_MMAP = 1,
+    GSC_MEM_USERPTR,
+    GSC_MEM_OVERLAY,
+    GSC_MEM_DMABUF,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*EXYNOS_GSCALER_H_*/
diff --git a/include/exynos_ion.h b/include/exynos_ion.h
new file mode 100755 (executable)
index 0000000..ed79198
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIB_ION_H_
+#define _LIB_ION_H_
+
+#define ION_HEAP_EXYNOS_CONTIG_MASK     (1 << 4)
+#define ION_EXYNOS_VIDEO_EXT_MASK       (1 << 31)
+#define ION_EXYNOS_VIDEO_EXT2_MASK      (1 << 29)
+#define ION_EXYNOS_FIMD_VIDEO_MASK      (1 << 28)
+#define ION_EXYNOS_GSC_MASK             (1 << 27)
+#define ION_EXYNOS_MFC_OUTPUT_MASK      (1 << 26)
+#define ION_EXYNOS_MFC_INPUT_MASK       (1 << 25)
+#define ION_EXYNOS_G2D_WFD_MASK         (1 << 22)
+#define ION_EXYNOS_VIDEO_MASK           (1 << 21)
+
+enum {
+       ION_EXYNOS_HEAP_ID_CRYPTO           = 1,
+       ION_EXYNOS_HEAP_ID_VIDEO_FW         = 2,
+       ION_EXYNOS_HEAP_ID_VIDEO_STREAM     = 3,
+       ION_EXYNOS_HEAP_ID_RESERVED         = 4,
+       ION_EXYNOS_HEAP_ID_VIDEO_FRAME      = 5,
+       ION_EXYNOS_HEAP_ID_VIDEO_SCALER     = 6,
+       ION_EXYNOS_HEAP_ID_VIDEO_NFW        = 7,
+       ION_EXYNOS_HEAP_ID_GPU_CRC          = 8,
+       ION_EXYNOS_HEAP_ID_GPU_BUFFER       = 9,
+       ION_EXYNOS_HEAP_ID_CAMERA           = 10,
+};
+
+#define EXYNOS_ION_HEAP_CRYPTO_MASK         (1 << ION_EXYNOS_HEAP_ID_CRYPTO)
+#define EXYNOS_ION_HEAP_VIDEO_FW_MASK       (1 << ION_EXYNOS_HEAP_ID_VIDEO_FW)
+#define EXYNOS_ION_HEAP_VIDEO_STREAM_MASK   (1 << ION_EXYNOS_HEAP_ID_VIDEO_STREAM)
+#define EXYNOS_ION_HEAP_VIDEO_FRAME_MASK    (1 << ION_EXYNOS_HEAP_ID_VIDEO_FRAME)
+#define EXYNOS_ION_HEAP_VIDEO_SCALER_MASK   (1 << ION_EXYNOS_HEAP_ID_VIDEO_SCALER)
+#define EXYNOS_ION_HEAP_VIDEO_NFW_MASK      (1 << ION_EXYNOS_HEAP_ID_VIDEO_NFW)
+#define EXYNOS_ION_HEAP_GPU_CRC             (1 << ION_EXYNOS_HEAP_ID_GPU_CRC)
+#define EXYNOS_ION_HEAP_GPU_BUFFER          (1 << ION_EXYNOS_HEAP_ID_GPU_BUFFER)
+#define EXYNOS_ION_HEAP_CAMERA              (1 << ION_EXYNOS_HEAP_ID_CAMERA)
+
+#endif /* _LIB_ION_H_ */
diff --git a/include/exynos_log.h b/include/exynos_log.h
new file mode 100755 (executable)
index 0000000..1b1faee
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _EXYNOS_LOG_H_
+#define _EXYNOS_LOG_H_
+
+#ifdef USE_DLOG
+#include <dlog.h>
+
+static void __log_print(int level, const char *msg, ...) {
+    va_list argptr;
+
+    va_start(argptr, msg);
+
+    switch (level) {
+    case 1:
+        SLOG_VA(LOG_DEBUG, LOG_TAG, msg, argptr);
+        break;
+    case 2:
+        SLOG_VA(LOG_INFO, LOG_TAG, msg, argptr);
+        break;
+    case 3:
+        SLOG_VA(LOG_WARN, LOG_TAG, msg, argptr);
+        break;
+    case 4:
+        SLOG_VA(LOG_ERROR, LOG_TAG, msg, argptr);
+        break;
+    default:
+        SLOG_VA(LOG_DEBUG, LOG_TAG, msg, argptr);
+        break;
+    }
+
+    va_end(argptr);
+}
+
+#undef ALOGV
+#undef ALOGD
+#undef ALOGI
+#undef ALOGW
+#undef ALOGE
+
+#define ALOGV(...) __log_print(1, __VA_ARGS__)
+#define ALOGD(...) __log_print(1, __VA_ARGS__)
+#define ALOGI(...) __log_print(2, __VA_ARGS__)
+#define ALOGW(...) __log_print(3, __VA_ARGS__)
+#define ALOGE(...) __log_print(4, __VA_ARGS__)
+
+#else
+#include <stdio.h>
+
+#define ALOGV(fmt, ...) printf("VERBOS: " fmt "\n", ##__VA_ARGS__)
+#define ALOGD(fmt, ...) printf("DEBUG: " fmt "\n", ##__VA_ARGS__)
+#define ALOGI(fmt, ...) printf("INFO: " fmt "\n", ##__VA_ARGS__)
+#define ALOGW(fmt, ...) printf("WARNING: " fmt "\n", ##__VA_ARGS__)
+#define ALOGE(fmt, ...) printf("ERROR: " fmt "\n", ##__VA_ARGS__)
+#endif  // USE_DLOG
+
+#endif  // _LOG_H_
+
diff --git a/include/exynos_scaler.h b/include/exynos_scaler.h
new file mode 100755 (executable)
index 0000000..1eea919
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_scaler.c
+ * \brief     header file for Scaler HAL
+ * \author    Sunyoung Kang (sy0816.kang@samsung.com)
+ * \date      2013/02/01
+ *
+ * <b>Revision History: </b>
+ * - 2013.02.01 : Sunyoung Kang (sy0816.kang@samsung.com) \n
+ *   Create
+ *
+ * - 2013.04.26 : Cho KyongHo (pullip.cho@samsung.com \n
+ *   Library rewrite
+ *
+ */
+
+#ifndef _EXYNOS_SCALER_H_
+#define _EXYNOS_SCALER_H_
+
+
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <stdbool.h>
+
+#include <exynos_format.h>
+#include <exynos_v4l2.h>
+#include <exynos_gscaler.h>
+
+#define SC_DEV_NODE     "/dev/video"
+#define SC_NODE(x)      (50 + x)
+
+#define SC_NUM_OF_PLANES    (3)
+
+#define V4L2_PIX_FMT_NV12_RGB32 v4l2_fourcc('N', 'V', '1', 'R')
+#define V4L2_PIX_FMT_NV12N_RGB32 v4l2_fourcc('N', 'N', '1', 'R')
+#define V4L2_PIX_FMT_NV12M_RGB32 v4l2_fourcc('N', 'V', 'R', 'G')
+#define V4L2_PIX_FMT_NV12M_BGR32 v4l2_fourcc('N', 'V', 'B', 'G')
+#define V4L2_PIX_FMT_NV12M_RGB565 v4l2_fourcc('N', 'V', 'R', '6')
+#define V4L2_PIX_FMT_NV12M_RGB444 v4l2_fourcc('N', 'V', 'R', '4')
+#define V4L2_PIX_FMT_NV12M_RGB555X v4l2_fourcc('N', 'V', 'R', '5')
+#define V4L2_PIX_FMT_NV12MT_16X16_RGB32 v4l2_fourcc('V', 'M', 'R', 'G')
+
+#define V4L2_CID_2D_SRC_BLEND_SET_FMT (V4L2_CID_EXYNOS_BASE + 116)
+#define V4L2_CID_2D_SRC_BLEND_SET_H_POS (V4L2_CID_EXYNOS_BASE + 117)
+#define V4L2_CID_2D_SRC_BLEND_SET_V_POS (V4L2_CID_EXYNOS_BASE + 118)
+#define V4L2_CID_2D_SRC_BLEND_FMT_PREMULTI (V4L2_CID_EXYNOS_BASE + 119)
+#define V4L2_CID_2D_SRC_BLEND_SET_STRIDE (V4L2_CID_EXYNOS_BASE + 120)
+#define V4L2_CID_2D_SRC_BLEND_SET_WIDTH (V4L2_CID_EXYNOS_BASE + 121)
+#define V4L2_CID_2D_SRC_BLEND_SET_HEIGHT (V4L2_CID_EXYNOS_BASE + 122)
+
+#ifdef SCALER_USE_LOCAL_CID
+#define V4L2_CID_GLOBAL_ALPHA          (V4L2_CID_EXYNOS_BASE + 1)
+#define V4L2_CID_2D_BLEND_OP           (V4L2_CID_EXYNOS_BASE + 103)
+#define V4L2_CID_2D_COLOR_FILL         (V4L2_CID_EXYNOS_BASE + 104)
+#define V4L2_CID_2D_DITH               (V4L2_CID_EXYNOS_BASE + 105)
+#define V4L2_CID_2D_FMT_PREMULTI       (V4L2_CID_EXYNOS_BASE + 106)
+#endif
+
+#define LIBSC_V4L2_CID_DNOISE_FT        (V4L2_CID_EXYNOS_BASE + 150)
+#define LIBSC_M2M1SHOT_OP_FILTER_SHIFT  (28)
+#define LIBSC_M2M1SHOT_OP_FILTER_MASK   (0xf << 28)
+
+// libgscaler's internal use only
+typedef enum _HW_SCAL_ID {
+    HW_SCAL0 = 4,
+    HW_SCAL1,
+    HW_SCAL2,
+    HW_SCAL_MAX,
+} HW_SCAL_ID;
+
+// argument of non-blocking api
+typedef exynos_mpp_img exynos_sc_img;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Create libscaler handle
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param dev_num
+ *  scaler dev_num[in]
+ *
+ * \return
+ * libscaler handle
+ */
+void *exynos_sc_create(int dev_num);
+
+/*!
+ * Destroy libscaler handle
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ */
+int exynos_sc_destroy(void *handle);
+
+/*!
+ * Convert color space with presetup color format
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_convert(void *handle);
+
+/*!
+ * Convert color space with presetup color format
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle
+ *
+ * \param csc_range
+ *   csc narrow/wide property
+ *
+ * \param v4l2_colorspace
+ *   csc equation property
+ *
+ * \param filter
+ *   denoise filter info
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_set_csc_property(
+    void        *handle,
+    unsigned int csc_range,
+    unsigned int v4l2_colorspace,
+    unsigned int filter);
+
+/*!
+ * Set source format.
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \param width
+ *   image width[in]
+ *
+ * \param height
+ *   image height[in]
+ *
+ * \param crop_left
+ *   image left crop size[in]
+ *
+ * \param crop_top
+ *   image top crop size[in]
+ *
+ * \param crop_width
+ *   cropped image width[in]
+ *
+ * \param crop_height
+ *   cropped image height[in]
+ *
+ * \param v4l2_colorformat
+ *   color format[in]
+ *
+ * \param cacheable
+ *   ccacheable[in]
+ *
+ * \param mode_drm
+ *   mode_drm[in]
+ *
+ * \param premultiplied
+ *   pre-multiplied format[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_set_src_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm,
+    unsigned int premultiplied);
+
+/*!
+ * Set destination format.
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \param width
+ *   image width[in]
+ *
+ * \param height
+ *   image height[in]
+ *
+ * \param crop_left
+ *   image left crop size[in]
+ *
+ * \param crop_top
+ *   image top crop size[in]
+ *
+ * \param crop_width
+ *   cropped image width[in]
+ *
+ * \param crop_height
+ *   cropped image height[in]
+ *
+ * \param v4l2_colorformat
+ *   color format[in]
+ *
+ * \param cacheable
+ *   ccacheable[in]
+ *
+ * \param mode_drm
+ *   mode_drm[in]
+ *
+ * \param premultiplied
+ *   pre-multiplied format[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_set_dst_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm,
+    unsigned int premultiplied);
+
+/*!
+ * Set source buffer
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \param addr
+ *   buffer pointer array[in]
+ *
+ * \param mem_type
+ *   memory type[in]
+ *
+ * \param acquireFenceFd
+ *   acquire fence fd for the buffer or -1[in]
+ *
+ * \return
+ *   error code
+ */
+
+int exynos_sc_set_src_addr(
+    void *handle,
+    void *addr[SC_NUM_OF_PLANES],
+    int mem_type,
+    int acquireFenceFd);
+
+/*!
+ * Set destination buffer
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \param addr
+ *   buffer pointer array[in]
+ *
+ * \param mem_type
+ *   memory type[in]
+ *
+ * \param acquireFenceFd
+ *   acquire fence fd for the buffer or -1[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_set_dst_addr(
+    void *handle,
+    void *addr[SC_NUM_OF_PLANES],
+    int mem_type,
+    int acquireFenceFd);
+
+/*!
+ * Set rotation.
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param handle
+ *   libscaler handle[in]
+ *
+ * \param rot
+ *   image rotation. It should be multiple of 90[in]
+ *
+ * \param flip_h
+ *   image flip_horizontal[in]
+ *
+ * \param flip_v
+ *   image flip_vertical[in]
+ *
+ * \return
+ *   error code
+ */
+int exynos_sc_set_rotation(
+    void *handle,
+    int rot,
+    int flip_h,
+    int flip_v);
+
+////// non-blocking /////
+
+void *exynos_sc_create_exclusive(
+    int dev_num,
+    int allow_drm);
+
+int exynos_sc_csc_exclusive(void *handle,
+    unsigned int range_full,
+    unsigned int v4l2_colorspace);
+
+int exynos_sc_config_exclusive(
+    void *handle,
+    exynos_sc_img *src_img,
+    exynos_sc_img *dst_img);
+
+int exynos_sc_run_exclusive(
+    void *handle,
+    exynos_sc_img *src_img,
+    exynos_sc_img *dst_img);
+
+void *exynos_sc_create_blend_exclusive(
+        int dev_num,
+        int allow_drm);
+
+int exynos_sc_config_blend_exclusive(
+    void *handle,
+    exynos_sc_img *src_img,
+    exynos_sc_img *dst_img,
+    struct SrcBlendInfo  *srcblendinfo);
+
+int exynos_sc_wait_frame_done_exclusive
+(void *handle);
+
+int exynos_sc_stop_exclusive
+(void *handle);
+
+int exynos_sc_free_and_close
+(void *handle);
+
+
+/******************************************************************************
+ ******** API for Copy Pixels between RGB data ********************************
+ ******************************************************************************/
+
+/*!
+ * Description of an image for both of the source and the destination.
+ *
+ * \ingroup exynos_scaler
+ */
+struct exynos_sc_pxinfo_img
+{
+    void *addr;
+    unsigned int width;
+    unsigned int height;
+    unsigned int crop_left;
+    unsigned int crop_top;
+    unsigned int crop_width;
+    unsigned int crop_height;
+    unsigned int pxfmt;  // enum EXYNOS_SC_FMT_PXINFO
+};
+
+/*!
+ * Description of a pixel copy
+ *
+ * \ingroup exynos_scaler
+ */
+struct exynos_sc_pxinfo {
+    struct exynos_sc_pxinfo_img src;
+    struct exynos_sc_pxinfo_img dst;
+    unsigned short rotate; // 0 ~ 360
+    char hflip;  // non-zero value for hflip
+    char vflip;  // non-zero value for vflip
+};
+
+/*!
+ * Pixel format definition for pixel copy
+ *
+ * \ingroup exynos_scaler
+ */
+enum SC_FMT_PXINFO {
+    EXYNOS_SC_FMT_RGB32 = 0x10,
+    EXYNOS_SC_FMT_BGR32,
+    EXYNOS_SC_FMT_RGB565,
+    EXYNOS_SC_FMT_RGB555X,
+    EXYNOS_SC_FMT_RGB444,
+};
+
+/*!
+ * Copy pixel data from RGB to RGB
+ *
+ * \ingroup exynos_scaler
+ *
+ * \param pxinfo
+ *   information for pixel data copy [in]
+ *
+ * \param dev_num
+ *   Scaler H/W instance number. Starts from 0 [in]
+ *
+ * \return
+ *   true on success in copying pixel data.
+ *   false on failure.
+ */
+bool exynos_sc_copy_pixels(
+    struct exynos_sc_pxinfo *pxinfo,
+    int dev_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXYNOS_SCALER_H_ */
diff --git a/include/exynos_v4l2.h b/include/exynos_v4l2.h
new file mode 100755 (executable)
index 0000000..6320529
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_v4l2.h
+ * \brief     header file for libv4l2
+ * \author    Jinsung Yang (jsgood.yang@samsung.com)
+ * \date      2011/12/15
+ *
+ * <b>Revision History: </b>
+ * - 2011/12/15 : Jinsung Yang (jsgood.yang@samsung.com) \n
+ *   Initial version
+ *
+ */
+
+/*!
+ * \defgroup exynos_v4l2
+ * \brief API for v4l2
+ * \addtogroup Exynos
+ */
+
+#ifndef __EXYNOS_LIB_V4L2_H__
+#define __EXYNOS_LIB_V4L2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* V4L2 */
+#include <stdbool.h>
+#include <linux/videodev2.h> /* vendor specific videodev2.h */
+
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_open(const char *filename, int oflag, ...);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_open_devname(const char *devname, int oflag, ...);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_close(int fd);
+/*! \ingroup exynos_v4l2 */
+bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_input(int fd, int index);
+/*! \ingroup exynos_v4l2 */
+bool exynos_v4l2_querycap(int fd, unsigned int need_caps);
+/*! \ingroup exynos_v4l2 */
+bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_prepare(int fd, struct v4l2_buffer *arg);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl);
+/*! \ingroup exynos_v4l2 */
+int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl);
+
+/* V4L2_SUBDEV */
+#include <linux/v4l2-subdev.h>
+
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_open(const char *filename, int oflag, ...);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_get_node_num(const char *devname, int oflag, ...);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_open_devname(const char *devname, int oflag, ...);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_close(int fd);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_enum_frame_size(int fd, struct v4l2_subdev_frame_size_enum *frame_size_enum);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_g_fmt(int fd, struct v4l2_subdev_format *fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_s_fmt(int fd, struct v4l2_subdev_format *fmt);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_g_crop(int fd, struct v4l2_subdev_crop *crop);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_s_crop(int fd, struct v4l2_subdev_crop *crop);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_enum_frame_interval(int fd, struct v4l2_subdev_frame_interval_enum *frame_internval_enum);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_g_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval_enum);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_s_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval_enum);
+/*! \ingroup exynos_v4l2 */
+int exynos_subdev_enum_mbus_code(int fd, struct v4l2_subdev_mbus_code_enum *mbus_code_enum);
+
+/* MEDIA CONTORLLER */
+#include "media.h"
+
+/*! media_link
+ * \ingroup exynos_v4l2
+ */
+struct media_link {
+    struct media_pad *source;
+    struct media_pad *sink;
+    struct media_link *twin;
+    __u32 flags;
+    __u32 padding[3];
+};
+
+/*! media_link
+ * \ingroup exynos_v4l2
+ */
+struct media_pad {
+    struct media_entity *entity;
+    __u32 index;
+    __u32 flags;
+    __u32 padding[3];
+};
+
+/*! media_link
+ * \ingroup exynos_v4l2
+ */
+struct media_entity {
+    struct media_device *media;
+    struct media_entity_desc info;
+    struct media_pad *pads;
+    struct media_link *links;
+    unsigned int max_links;
+    unsigned int num_links;
+
+    char devname[32];
+    int fd;
+    __u32 padding[6];
+};
+
+/*! media_link
+ * \ingroup exynos_v4l2
+ */
+struct media_device {
+    int fd;
+    struct media_entity *entities;
+    unsigned int entities_count;
+    void (*debug_handler)(void *, ...);
+    void *debug_priv;
+    __u32 padding[6];
+};
+
+/*! \ingroup exynos_v4l2 */
+struct media_device *exynos_media_open(const char *filename);
+/*! \ingroup exynos_v4l2 */
+void exynos_media_close(struct media_device *media);
+/*! \ingroup exynos_v4l2 */
+struct media_pad *exynos_media_entity_remote_source(struct media_pad *pad);
+/*! \ingroup exynos_v4l2 */
+struct media_entity *exynos_media_get_entity_by_name(struct media_device *media, const char *name, size_t length);
+/*! \ingroup exynos_v4l2 */
+struct media_entity *exynos_media_get_entity_by_id(struct media_device *media, __u32 id);
+/*! \ingroup exynos_v4l2 */
+int exynos_media_setup_link(struct media_device *media, struct media_pad *source, struct media_pad *sink, __u32 flags);
+/*! \ingroup exynos_v4l2 */
+int exynos_media_reset_links(struct media_device *media);
+/*! \ingroup exynos_v4l2 */
+struct media_pad *exynos_media_parse_pad(struct media_device *media, const char *p, char **endp);
+/*! \ingroup exynos_v4l2 */
+struct media_link *exynos_media_parse_link(struct media_device *media, const char *p, char **endp);
+/*! \ingroup exynos_v4l2 */
+int exynos_media_parse_setup_link(struct media_device *media, const char *p, char **endp);
+/*! \ingroup exynos_v4l2 */
+int exynos_media_parse_setup_links(struct media_device *media, const char *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EXYNOS_LIB_V4L2_H__ */
diff --git a/include/ion.h b/include/ion.h
new file mode 100755 (executable)
index 0000000..67161ca
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIB_ION_H_
+#define _LIB_ION_H_
+
+#include <unistd.h> /* size_t */
+
+#define ION_FLAG_CACHED 1
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
+#define ION_FLAG_PRESERVE_KMAP 4
+#define ION_FLAG_NOZEROED 8
+
+#define ION_HEAP_SYSTEM_MASK            (1 << 0)
+#define ION_HEAP_SYSTEM_CONTIG_MASK     (1 << 1)
+#define ION_HEAP_EXYNOS_CONTIG_MASK     (1 << 4)
+#define ION_HEAP_EXYNOS_MASK            (1 << 5)
+#define ION_EXYNOS_VIDEO_MASK     (1 << 21)
+#define ION_EXYNOS_FIMD_VIDEO_MASK    (1 << 28)
+#define ION_EXYNOS_GSC_MASK            (1 << 27)
+#define ION_EXYNOS_MFC_OUTPUT_MASK    (1 << 26)
+#define ION_EXYNOS_MFC_INPUT_MASK    (1 << 25)
+
+
+/* ION_MSYNC_FLAGS
+ * values of @flags parameter to ion_msync()
+ *
+ * IMSYNC_DEV_TO_READ: Device only reads the buffer
+ * IMSYNC_DEV_TO_WRITE: Device may writes to the buffer
+ * IMSYNC_DEV_TO_RW: Device reads and writes to the buffer
+ *
+ * IMSYNC_SYNC_FOR_DEV: ion_msync() for device to access the buffer
+ * IMSYNC_SYNC_FOR_CPU: ion_msync() for CPU to access the buffer after device
+ *                      has accessed it.
+ *
+ * The values must be ORed with one of IMSYNC_DEV_* and one of IMSYNC_SYNC_*.
+ * Otherwise, ion_msync() will not effect.
+ */
+enum ION_MSYNC_FLAGS {
+    IMSYNC_DEV_TO_READ = 0,
+    IMSYNC_DEV_TO_WRITE = 1,
+    IMSYNC_DEV_TO_RW = 2,
+    IMSYNC_SYNC_FOR_DEV = 0x10000,
+    IMSYNC_SYNC_FOR_CPU = 0x20000,
+};
+
+struct ion_preload_object {
+    size_t len;
+    unsigned int count;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ion_client
+ * An ION client is an object or an entity that needs to use the service of
+ * ION and has unique address space. ion_client is an identifier of an ION
+ * client and it represents the ION client.
+ * All operations on ION needs a valid ion_client value and it can be obtained
+ * by ion_client_create().
+ */
+typedef int ion_client;
+
+/* ion_buffer
+ * An identifier of a buffer allocated from ION. You must obtain to access
+ * a buffer allocated from ION. If you have an effective ion_buffer, you have
+ * three options to work with it.
+ * - To access  the buffer, you can request an address (user virtual address)
+ *   of the buffer with ion_map().
+ * - To pass the buffer to the kernel, you can pass the ion_buffer to the
+ *   kernel driver directly, if the kernel driver can work with ION.
+ * - To pass the buffer to other processes, you can pass the ion_buffer to
+ *   other processes through RPC machanism such as socket communication or
+ *   Android Binder because ion_buffer is actually an open file descripotor
+ *   of the current process.
+ */
+typedef int ion_buffer;
+
+typedef unsigned int ion_handle;
+
+/* ion_client_create()
+ * @RETURN: new ion_client.
+ *          netative value if creating new ion_client is failed.
+ *
+ * A call to ion_client_create() must be paired with ion_client_destroy(),
+ * symmetrically. ion_client_destroy() needs a valid ion_client that
+ * is returned by ion_client_create().
+ */
+ion_client ion_client_create(void);
+
+/* ion_client_destroy()
+ * @client: An ion_client value to remove.
+ */
+void ion_client_destroy(ion_client client);
+
+/* ion_alloc() - Allocates new buffer from ION.
+ * @client: A valid ion_client value returned by ion_client_create().
+ * @len: Size of a buffer required in bytes.
+ * @align: Alignment requirements of @len and the start address of the allocated
+ *         buffer. If the @len is not aligned by @align, ION allocates a buffer
+ *         that is aligned by @align and the size of the buffer will be larger
+ *         than @len.
+ * @heap_mask: Mask of heaps which you want this allocation to be served from.
+ * @flags: Additional requirements about buffer. ION_FLAG_CACHED for a
+ *        buffer you want to have a cached mapping of
+ * @RETURN: An ion_buffer that represents the buffer allocated. It is only
+ *          unique in the context of the given client, @client.
+ *          -error if the allocation failed.
+ *          See the description of ion_buffer above for detailed information.
+ */
+ion_buffer ion_alloc(ion_client client, size_t len, size_t align,
+                     unsigned int heap_mask, unsigned int flags);
+
+/* ion_free() - Frees an existing buffer that is allocated by ION
+ * @buffer: An ion_buffer of the buffer to be released.
+ */
+void ion_free(ion_buffer buffer);
+
+/* ion_map() - Obtains a virtual address of the buffer identied by @buffer
+ * @buffer: The buffer to map. The virtual address returned is allocated by the
+ *          kernel.
+ * @len: The size of the buffer to map. This must not exceed the size of the
+ *       buffer represented by @fd_buf. Thus you need to know the size of it
+ *       before calling this function. If @len is less than the size of the
+ *       buffer, this function just map just the size requested (@len) not the
+ *       entire buffer.
+ * @offset: How many pages will be ignored while mapping.@offset number of
+ *       pages from the start of the buffer will not be mapped.
+ * @RETURN: The start virtual addres mapped.
+ *          MAP_FAILED if mapping fails.
+ *
+ * Note that @len + (@offset * PAGE_SIZE) must not exceed the size of the
+ * buffer.
+ */
+void *ion_map(ion_buffer buffer, size_t len, off_t offset);
+
+/* ion_unmap() - Frees the buffer mapped by ion_map()
+ * @addr: The address returned by ion_map().
+ * @len: The size of the buffer mapped by ion_map().
+ * @RETURN: 0 on success, and -1 on failure.
+ *          errno is also set on failure.
+ */
+int ion_unmap(void *addr, size_t len);
+
+/* ion_msync() - Makes sure that data in the buffer are visible to H/W peri.
+ * @client: A valid ion_client value returned by ion_client_create().
+ * @buffer: The buffer to perform ion_msync().
+ * @flags: Direction of access of H/W peri and CPU. See the description of
+ *         ION_MSYNC_FLAGS.
+ * @size: Size to ion_msync() in bytes.
+ * @offset: Where ion_msync() start in @buffer, size in bytes.
+ * @RETURN: 0 if successful. -error, otherwise.
+ *
+ * Note that @offset + @size must not exceed the size of @buffer.
+ */
+int ion_sync(ion_client client, ion_buffer buffer);
+
+/* ion_sync_range() - Make sure the specified range in the buffer are visible to H/W
+ * @client: A valid ion_client value returned by ion_client_create().
+ * @sahre_fd: A valid file descriptor for the buffer(mostely returned by ion_alloc())
+ * @addr: start address of the region to sync.
+          It must be the mapped address of the buffer specified by @dmabuf_fd.
+ * @size: size of the region to sync.
+ */
+int ion_sync_range(ion_client client, int dmabuf_fd, void *addr, size_t size);
+
+int ion_incRef(int fd, int share_fd, ion_handle *handle);
+
+int ion_decRef(int fd, ion_handle handle);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _LIB_ION_H_ */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
new file mode 100755 (executable)
index 0000000..9dd0d8a
--- /dev/null
@@ -0,0 +1,95 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_COMPILER_H
+#define __LINUX_COMPILER_H
+#ifndef __ASSEMBLY__
+#define __user
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __kernel
+#define __safe
+#define __force
+#define __nocast
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __iomem
+#define __chk_user_ptr(x) (void) 0
+#define __chk_io_ptr(x) (void) 0
+#define __builtin_warning(x,y...) (1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __must_hold(x)
+#define __acquires(x)
+#define __releases(x)
+#define __acquire(x) (void) 0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __release(x) (void) 0
+#define __cond_lock(x,c) (c)
+#define __percpu
+#define __rcu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ___PASTE(a,b) a ##b
+#define __PASTE(a,b) ___PASTE(a, b)
+#endif
+#ifndef __attribute_const__
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __attribute_const__
+#endif
+#ifndef __cold
+#define __cold
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#ifndef __section
+#define __section(S) __attribute__((__section__(#S)))
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifndef __visible
+#define __visible
+#endif
+#ifndef __same_type
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __same_type(a,b) __builtin_types_compatible_p(typeof(a), typeof(b))
+#endif
+#ifndef __native_word
+#define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#ifndef __compiletime_object_size
+#define __compiletime_object_size(obj) - 1
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifndef __compiletime_warning
+#define __compiletime_warning(message)
+#endif
+#ifndef __compiletime_error
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __compiletime_error(message)
+#define __compiletime_error_fallback(condition) do { ((void) sizeof(char[1 - 2 * condition])); } while(0)
+#endif
+#ifndef __compiletime_error_fallback
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __compiletime_error_fallback(condition) do { } while(0)
+#endif
+#define __compiletime_assert(condition,msg,prefix,suffix) do { bool __cond = ! (condition); extern void prefix ##suffix(void) __compiletime_error(msg); if(__cond) prefix ##suffix(); __compiletime_error_fallback(__cond); } while(0)
+#define _compiletime_assert(condition,msg,prefix,suffix) __compiletime_assert(condition, msg, prefix, suffix)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define compiletime_assert(condition,msg) _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
+#define compiletime_assert_atomic_type(t) compiletime_assert(__native_word(t), "Need native word sized stores/loads for atomicity.")
+#define ACCESS_ONCE(x) (* (volatile typeof(x) *) & (x))
+#define __kprobes
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define nokprobe_inline inline
+#endif
diff --git a/include/media.h b/include/media.h
new file mode 100755 (executable)
index 0000000..d627bef
--- /dev/null
@@ -0,0 +1,125 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_MEDIA_H
+#define __LINUX_MEDIA_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#include <linux/version.h>
+#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
+struct media_device_info {
+ char driver[16];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ char model[32];
+ char serial[40];
+ char bus_info[32];
+ __u32 media_version;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 hw_revision;
+ __u32 driver_version;
+ __u32 reserved[31];
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_ENT_ID_FLAG_NEXT (1 << 31)
+#define MEDIA_ENT_TYPE_SHIFT 16
+#define MEDIA_ENT_TYPE_MASK 0x00ff0000
+#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT)
+#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1)
+#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2)
+#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4)
+#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT)
+#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1)
+#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3)
+#define MEDIA_ENT_FL_DEFAULT (1 << 0)
+struct media_entity_desc {
+ __u32 id;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ char name[32];
+ __u32 type;
+ __u32 revision;
+ __u32 flags;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 group_id;
+ __u16 pads;
+ __u16 links;
+ __u32 reserved[4];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ union {
+ struct {
+ __u32 major;
+ __u32 minor;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ } v4l;
+ struct {
+ __u32 major;
+ __u32 minor;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ } fb;
+ struct {
+ __u32 card;
+ __u32 device;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 subdevice;
+ } alsa;
+ int dvb;
+ __u8 raw[184];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ };
+};
+#define MEDIA_PAD_FL_SINK (1 << 0)
+#define MEDIA_PAD_FL_SOURCE (1 << 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct media_pad_desc {
+ __u32 entity;
+ __u16 index;
+ __u32 flags;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 reserved[2];
+};
+#define MEDIA_LNK_FL_ENABLED (1 << 0)
+#define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_LNK_FL_DYNAMIC (1 << 2)
+struct media_link_desc {
+ struct media_pad_desc source;
+ struct media_pad_desc sink;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 flags;
+ __u32 reserved[2];
+};
+struct media_links_enum {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 entity;
+ struct media_pad_desc *pads;
+ struct media_link_desc *links;
+ __u32 reserved[4];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+#define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info)
+#define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc)
+#define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc)
+#endif
diff --git a/include/swconverter.h b/include/swconverter.h
new file mode 100755 (executable)
index 0000000..877e4ba
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    swconverter.h
+ * @brief   Exynos_OMX specific define. It support MFC's tiled format.
+ *   NV12T(tiled) layout:
+ *   Each element is not pixel.
+ *   MFC 5.x : It is 64x32 pixel block.
+ *   MFC 6.x : It is 16x16 pixel block.
+ *   uv pixel block is interleaved as u v u v u v ...
+ *   y1    y2    y7    y8    y9    y10   y15   y16
+ *   y3    y4    y5    y6    y11   y12   y13   y14
+ *   y17   y18   y23   y24   y25   y26   y31   y32
+ *   y19   y20   y21   y22   y27   y28   y29   y30
+ *   uv1   uv2   uv7   uv8   uv9   uv10  uv15  uv16
+ *   uv3   uv4   uv5   uv6   uv11  uv12  uv13  uv14
+ *   YUV420Planar(linear) layout:
+ *   Each element is not pixel. It is 64x32 pixel block.
+ *   y1    y2    y3    y4    y5    y6    y7    y8
+ *   y9    y10   y11   y12   y13   y14   y15   y16
+ *   y17   y18   y19   y20   y21   y22   y23   y24
+ *   y25   y26   y27   y28   y29   y30   y31   y32
+ *   u1    u2    u3    u4    u5    u6    u7    u8
+ *   v1    v2    v3    v4    v5    v6    v7    v8
+ *   YUV420Semiplanar(linear) layout:
+ *   Each element is not pixel. It is 64x32 pixel block.
+ *   uv pixel block is interleaved as u v u v u v ...
+ *   y1    y2    y3    y4    y5    y6    y7    y8
+ *   y9    y10   y11   y12   y13   y14   y15   y16
+ *   y17   y18   y19   y20   y21   y22   y23   y24
+ *   y25   y26   y27   y28   y29   y30   y31   y32
+ *   uv1   uv2   uv3   uv4   uv5   uv6   uv7   uv8
+ *   uv9   uv10  uv11  uv12  uv13  uv14  uv15  uv16
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+#ifndef SW_CONVERTOR_H_
+#define SW_CONVERTOR_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Format Conversion API                                                          */
+/*--------------------------------------------------------------------------------*/
+/*
+ * C code only
+ * De-interleaves src to dest1, dest2
+ *
+ * @param dest1
+ *   Address of de-interleaved data[out]
+ *
+ * @param dest2
+ *   Address of de-interleaved data[out]
+ *
+ * @param src
+ *   Address of interleaved data[in]
+ *
+ * @param src_size
+ *   Size of interleaved data[in]
+ */
+void csc_deinterleave_memcpy(
+    unsigned char *dest1,
+    unsigned char *dest2,
+    unsigned char *src,
+    unsigned int src_size);
+
+/*
+ * C code or Neon
+ * Interleaves src1, src2 to dest
+ *
+ * @param dest
+ *   Address of interleaved data[out]
+ *
+ * @param src1
+ *   Address of de-interleaved data[in]
+ *
+ * @param src2
+ *   Address of de-interleaved data[in]
+ *
+ * @param src_size
+ *   Size of de-interleaved data[in]
+ */
+void csc_interleave_memcpy(
+    unsigned char *dest,
+    unsigned char *src1,
+    unsigned char *src2,
+    unsigned int src_size);
+
+/*
+ * C code or Neon
+ * Converts tiled data to linear
+ * 1. y of nv12t to y of yuv420p
+ * 2. y of nv12t to y of yuv420s
+ *
+ * @param dst
+ *   y address of yuv420[out]
+ *
+ * @param src
+ *   y address of nv12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *   it should be even
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *   it should be even.
+ *
+ */
+void csc_tiled_to_linear_y(
+    unsigned char *y_dst,
+    unsigned char *y_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code or Neon
+ * Converts tiled data to linear
+ * 1. uv of nv12t to y of yuv420s
+ *
+ * @param dst
+ *   uv address of yuv420s[out]
+ *
+ * @param src
+ *   uv address of nv12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420s[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420s[in]
+ *
+ */
+void csc_tiled_to_linear_uv(
+    unsigned char *uv_dst,
+    unsigned char *uv_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code or Neon
+ * Converts tiled data to linear
+ * 1. uv of nt12t to uv of yuv420p
+ *
+ * @param u_dst
+ *   u address of yuv420p[out]
+ *
+ * @param v_dst
+ *   v address of yuv420p[out]
+ *
+ * @param uv_src
+ *   uv address of nt12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420p[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420p[in]
+ */
+void csc_tiled_to_linear_uv_deinterleave(
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *uv_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * Neon only
+ * Converts linear data to tiled
+ * 1. y of yuv420 to y of nv12t
+ *
+ * @param dst
+ *   y address of nv12t[out]
+ *
+ * @param src
+ *   y address of yuv420[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *   it should be even
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *   it should be even.
+ *
+ */
+void csc_linear_to_tiled_y(
+    unsigned char *y_dst,
+    unsigned char *y_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * Neon only
+ * Converts and interleaves linear data to tiled
+ * 1. uv of nv12t to uv of yuv420
+ *
+ * @param dst
+ *   uv address of nv12t[out]
+ *
+ * @param src
+ *   u address of yuv420[in]
+ *
+ * @param src
+ *   v address of yuv420[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *
+ */
+void csc_linear_to_tiled_uv(
+    unsigned char *uv_dst,
+    unsigned char *u_src,
+    unsigned char *v_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code only
+ * Converts RGB565 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of RGB565[in]
+ *
+ * @param width
+ *   Width of RGB565[in]
+ *
+ * @param height
+ *   Height of RGB565[in]
+ */
+void csc_RGB565_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    int width,
+    int height);
+
+/*
+ * C code only
+ * Converts RGB565 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of RGB565[in]
+ *
+ * @param width
+ *   Width of RGB565[in]
+ *
+ * @param height
+ *   Height of RGB565[in]
+ */
+void csc_RGB565_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    int width,
+    int height);
+
+/*
+ * C code only
+ * Converts BGRA8888 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of BGRA8888[in]
+ *
+ * @param width
+ *   Width of BGRA8888[in]
+ *
+ * @param height
+ *   Height of BGRA8888[in]
+ */
+void csc_BGRA8888_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code or Neon
+ * Converts BGRA8888 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of BGRA8888[in]
+ *
+ * @param width
+ *   Width of BGRA8888[in]
+ *
+ * @param height
+ *   Height of BGRA8888[in]
+ */
+void csc_BGRA8888_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code only
+ * Converts RGBA8888 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of RGBA8888[in]
+ *
+ * @param width
+ *   Width of RGBA8888[in]
+ *
+ * @param height
+ *   Height of RGBA8888[in]
+ */
+void csc_RGBA8888_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height);
+
+/*
+ * C code or Neon
+ * Converts RGBA8888 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of RGBA8888[in]
+ *
+ * @param width
+ *   Width of RGBA8888[in]
+ *
+ * @param height
+ *   Height of RGBA8888[in]
+ */
+void csc_RGBA8888_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height);
+
+#endif /*COLOR_SPACE_CONVERTOR_H_*/
diff --git a/include/system/graphics.h b/include/system/graphics.h
new file mode 100755 (executable)
index 0000000..afd9f7b
--- /dev/null
@@ -0,0 +1,763 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * If the HAL needs to create service threads to handle graphics related
+ * tasks, these threads need to run at HAL_PRIORITY_URGENT_DISPLAY priority
+ * if they can block the main rendering thread in any way.
+ *
+ * the priority of the current thread can be set with:
+ *
+ *      #include <sys/resource.h>
+ *      setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ *
+ */
+
+#define HAL_PRIORITY_URGENT_DISPLAY     (-8)
+
+/**
+ * pixel format definitions
+ */
+
+enum {
+    /*
+     * "linear" color pixel formats:
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     *
+     * The color space determines, for example, if the formats are linear or
+     * gamma-corrected; or whether any special operations are performed when
+     * reading or writing into a buffer in one of these formats.
+     */
+    HAL_PIXEL_FORMAT_RGBA_8888          = 1,
+    HAL_PIXEL_FORMAT_RGBX_8888          = 2,
+    HAL_PIXEL_FORMAT_RGB_888            = 3,
+    HAL_PIXEL_FORMAT_RGB_565            = 4,
+    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
+
+    /*
+     * 0x100 - 0x1FF
+     *
+     * This range is reserved for pixel formats that are specific to the HAL
+     * implementation.  Implementations can use any value in this range to
+     * communicate video pixel formats between their HAL modules.  These formats
+     * must not have an alpha channel.  Additionally, an EGLimage created from a
+     * gralloc buffer of one of these formats must be supported for use with the
+     * GL_OES_EGL_image_external OpenGL ES extension.
+     */
+
+    /*
+     * Android YUV format:
+     *
+     * This format is exposed outside of the HAL to software decoders and
+     * applications.  EGLImageKHR must support it in conjunction with the
+     * OES_EGL_image_external extension.
+     *
+     * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+     * by (W/2) x (H/2) Cr and Cb planes.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   y_size = stride * height
+     *   c_stride = ALIGN(stride/2, 16)
+     *   c_size = c_stride * height/2
+     *   size = y_size + c_size * 2
+     *   cr_offset = y_size
+     *   cb_offset = y_size + c_size
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
+
+
+    /*
+     * Android Y8 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y8 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 8 bits.
+     *
+     * It is equivalent to just the Y plane from YV12.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   size = stride * height
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    HAL_PIXEL_FORMAT_Y8     = 0x20203859,
+
+    /*
+     * Android Y16 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y16 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 16 bits.
+     *
+     * It is just like Y8, but has double the bits per pixel (little endian).
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer, except that dataSpace field
+     * HAL_DATASPACE_DEPTH indicates that this buffer contains a depth
+     * image where each sample is a distance value measured by a depth camera,
+     * plus an associated confidence value.
+     */
+    HAL_PIXEL_FORMAT_Y16    = 0x20363159,
+
+    /*
+     * Android RAW sensor format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW16 is a single-channel, 16-bit, little endian format, typically
+     * representing raw Bayer-pattern images from an image sensor, with minimal
+     * processing.
+     *
+     * The exact pixel layout of the data in the buffer is sensor-dependent, and
+     * needs to be queried from the camera device.
+     *
+     * Generally, not all 16 bits are used; more common values are 10 or 12
+     * bits. If not all bits are used, the lower-order bits are filled first.
+     * All parameters to interpret the raw data (black and white points,
+     * color space, etc) must be queried from the camera device.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW16 = 0x20,
+
+    /*
+     * Android RAW10 format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW10 is a single-channel, 10-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each 4 consecutive pixels are packed into 5 bytes (40 bits). Each one
+     * of the first 4 bytes contains the top 8 bits of each pixel, The fifth byte
+     * contains the 2 least significant bits of the 4 pixels, the exact layout data
+     * for each 4 consecutive pixels is illustrated below (Pi[j] stands for the jth
+     * bit of the ith pixel):
+     *
+     *          bit 7                                     bit 0
+     *          =====|=====|=====|=====|=====|=====|=====|=====|
+     * Byte 0: |P0[9]|P0[8]|P0[7]|P0[6]|P0[5]|P0[4]|P0[3]|P0[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 1: |P1[9]|P1[8]|P1[7]|P1[6]|P1[5]|P1[4]|P1[3]|P1[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 2: |P2[9]|P2[8]|P2[7]|P2[6]|P2[5]|P2[4]|P2[3]|P2[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 3: |P3[9]|P3[8]|P3[7]|P3[6]|P3[5]|P3[4]|P3[3]|P3[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 4: |P3[1]|P3[0]|P2[1]|P2[0]|P1[1]|P1[0]|P0[1]|P0[0]|
+     *          ===============================================
+     *
+     * This format assumes
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (10 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (10 / 8), padding bytes will be present at the end of each
+     * row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW10 = 0x25,
+
+    /*
+     * Android RAW12 format:
+     *
+     * This format is exposed outside of camera HAL to applications.
+     *
+     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     *
+     *           bit 7                                            bit 0
+     *          ======|======|======|======|======|======|======|======|
+     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
+     *          =======================================================
+     *
+     * This format assumes:
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (12 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (12 / 8), padding bytes will be present at the end of
+     * each row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW12 = 0x26,
+
+    /*
+     * Android opaque RAW format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
+     * image sensor. The actual structure of buffers of this format is
+     * implementation-dependent.
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24,
+
+    /*
+     * Android binary blob graphics buffer format:
+     *
+     * This format is used to carry task-specific data which does not have a
+     * standard image structure. The details of the format are left to the two
+     * endpoints.
+     *
+     * A typical use case is for transporting JPEG-compressed images from the
+     * Camera HAL to the framework or to applications.
+     *
+     * Buffers of this format must have a height of 1, and width equal to their
+     * size in bytes.
+     *
+     * When used with ANativeWindow, the mapping of the dataSpace field to
+     * buffer contents for BLOB is as follows:
+     *
+     *  dataSpace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  HAL_DATASPACE_JFIF            | An encoded JPEG image
+     *  HAL_DATASPACE_DEPTH           | An android_depth_points buffer
+     *  Other                         | Unsupported
+     *
+     */
+    HAL_PIXEL_FORMAT_BLOB = 0x21,
+
+    /*
+     * Android format indicating that the choice of format is entirely up to the
+     * device-specific Gralloc implementation.
+     *
+     * The Gralloc implementation should examine the usage bits passed in when
+     * allocating a buffer with this format, and it should derive the pixel
+     * format from those usage flags.  This format will never be used with any
+     * of the GRALLOC_USAGE_SW_* usage flags.
+     *
+     * If a buffer of this format is to be used as an OpenGL ES texture, the
+     * framework will assume that sampling the texture will always return an
+     * alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
+
+    /*
+     * Android flexible YCbCr 4:2:0 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * struct android_ycbcr (below) is the the struct used to describe it.
+     *
+     * This format must be accepted by the gralloc module when
+     * USAGE_SW_WRITE_* or USAGE_SW_READ_* are set.
+     *
+     * This format is locked for use by gralloc's (*lock_ycbcr) method, and
+     * locking with the (*lock) method will return an error.
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
+
+    /*
+     * Android flexible YCbCr 4:2:2 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:2
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_422_888 = 0x27,
+
+    /*
+     * Android flexible YCbCr 4:4:4 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:4:4
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_444_888 = 0x28,
+
+    /*
+     * Android flexible RGB 888 formats
+     *
+     * This format allows platforms to use an efficient RGB/BGR/RGBX/BGRX
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGB, it can be
+     * used to describe formats with either color ordering and optional
+     * padding, as well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_FLEX_RGB_888 = 0x29,
+
+    /*
+     * Android flexible RGBA 8888 formats
+     *
+     * This format allows platforms to use an efficient RGBA/BGRA/ARGB/ABGR
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGBA, it can be
+     * used to describe formats with any of the component orderings, as
+     * well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_FLEX_RGBA_8888 = 0x2A,
+
+    /* Legacy formats (deprecated), used by ImageFormat.java */
+    HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10, // NV16
+    HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
+    HAL_PIXEL_FORMAT_YCbCr_422_I        = 0x14, // YUY2
+};
+
+/*
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with HAL_PIXEL_FORMAT_YCbCr_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. HAL_PIXEL_FORMAT_YCbCr_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * @y, @cb, and @cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row.  It includes the width of the
+ * image plus padding.
+ * @ystride is the stride of the luma plane.
+ * @cstride is the stride of the chroma planes.
+ *
+ * @chroma_step is the distance in bytes from one chroma pixel value to the
+ * next.  This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+
+struct android_ycbcr {
+    void *y;
+    void *cb;
+    void *cr;
+    size_t ystride;
+    size_t cstride;
+    size_t chroma_step;
+
+    /** reserved for future use, set to 0 by gralloc's (*lock_ycbcr)() */
+    uint32_t reserved[8];
+};
+
+/**
+ * Structure used to define depth point clouds for format HAL_PIXEL_FORMAT_BLOB
+ * with dataSpace value of HAL_DATASPACE_DEPTH.
+ * When locking a native buffer of the above format and dataSpace value,
+ * the vaddr pointer can be cast to this structure.
+ *
+ * A variable-length list of (x,y,z, confidence) 3D points, as floats.  (x, y,
+ * z) represents a measured point's position, with the coordinate system defined
+ * by the data source.  Confidence represents the estimated likelihood that this
+ * measurement is correct. It is between 0.f and 1.f, inclusive, with 1.f ==
+ * 100% confidence.
+ *
+ * @num_points is the number of points in the list
+ *
+ * @xyz_points is the flexible array of floating-point values.
+ *   It contains (num_points) * 4 floats.
+ *
+ *   For example:
+ *     android_depth_points d = get_depth_buffer();
+ *     struct {
+ *       float x; float y; float z; float confidence;
+ *     } firstPoint, lastPoint;
+ *
+ *     firstPoint.x = d.xyzc_points[0];
+ *     firstPoint.y = d.xyzc_points[1];
+ *     firstPoint.z = d.xyzc_points[2];
+ *     firstPoint.confidence = d.xyzc_points[3];
+ *     lastPoint.x = d.xyzc_points[(d.num_points - 1) * 4 + 0];
+ *     lastPoint.y = d.xyzc_points[(d.num_points - 1) * 4 + 1];
+ *     lastPoint.z = d.xyzc_points[(d.num_points - 1) * 4 + 2];
+ *     lastPoint.confidence = d.xyzc_points[(d.num_points - 1) * 4 + 3];
+ */
+
+struct android_depth_points {
+    uint32_t num_points;
+
+    /** reserved for future use, set to 0 by gralloc's (*lock)() */
+    uint32_t reserved[8];
+
+    float xyzc_points[];
+};
+
+/**
+ * Transformation definitions
+ *
+ * IMPORTANT NOTE:
+ * HAL_TRANSFORM_ROT_90 is applied CLOCKWISE and AFTER HAL_TRANSFORM_FLIP_{H|V}.
+ *
+ */
+
+enum {
+    /* flip source image horizontally (around the vertical axis) */
+    HAL_TRANSFORM_FLIP_H    = 0x01,
+    /* flip source image vertically (around the horizontal axis)*/
+    HAL_TRANSFORM_FLIP_V    = 0x02,
+    /* rotate source image 90 degrees clockwise */
+    HAL_TRANSFORM_ROT_90    = 0x04,
+    /* rotate source image 180 degrees */
+    HAL_TRANSFORM_ROT_180   = 0x03,
+    /* rotate source image 270 degrees clockwise */
+    HAL_TRANSFORM_ROT_270   = 0x07,
+    /* don't use. see system/window.h */
+    HAL_TRANSFORM_RESERVED  = 0x08,
+};
+
+/**
+ * Dataspace Definitions
+ * ======================
+ *
+ * Dataspace is the definition of how pixel values should be interpreted.
+ *
+ * For many formats, this is the colorspace of the image data, which includes
+ * primaries (including white point) and the transfer characteristic function,
+ * which describes both gamma curve and numeric range (within the bit depth).
+ *
+ * Other dataspaces include depth measurement data from a depth camera.
+ */
+
+typedef enum android_dataspace {
+    /*
+     * Default-assumption data space, when not explicitly specified.
+     *
+     * It is safest to assume the buffer is an image with sRGB primaries and
+     * encoding ranges, but the consumer and/or the producer of the data may
+     * simply be using defaults. No automatic gamma transform should be
+     * expected, except for a possible display gamma transform when drawn to a
+     * screen.
+     */
+    HAL_DATASPACE_UNKNOWN = 0x0,
+
+    /*
+     * Arbitrary dataspace with manually defined characteristics.  Definition
+     * for colorspaces or other meaning must be communicated separately.
+     *
+     * This is used when specifying primaries, transfer characteristics,
+     * etc. separately.
+     *
+     * A typical use case is in video encoding parameters (e.g. for H.264),
+     * where a colorspace can have separately defined primaries, transfer
+     * characteristics, etc.
+     */
+    HAL_DATASPACE_ARBITRARY = 0x1,
+
+    /*
+     * RGB Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /*
+     * sRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in sRGB space, but
+     * are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     */
+    HAL_DATASPACE_SRGB_LINEAR = 0x200,
+
+    /*
+     * sRGB gamma encoding:
+     *
+     * The red, green and blue components are stored in sRGB space, and
+     * converted to linear space when read, using the standard sRGB to linear
+     * equation:
+     *
+     * Clinear = Csrgb / 12.92                  for Csrgb <= 0.04045
+     *         = (Csrgb + 0.055 / 1.055)^2.4    for Csrgb >  0.04045
+     *
+     * When written the inverse transformation is performed:
+     *
+     * Csrgb = 12.92 * Clinear                  for Clinear <= 0.0031308
+     *       = 1.055 * Clinear^(1/2.4) - 0.055  for Clinear >  0.0031308
+     *
+     *
+     * The alpha component, if present, is always stored in linear space and
+     * is left unmodified when read or written.
+     *
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     *
+     */
+    HAL_DATASPACE_SRGB = 0x201,
+
+    /*
+     * YCbCr Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /*
+     * JPEG File Interchange Format (JFIF)
+     *
+     * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_DATASPACE_JFIF = 0x101,
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 625-line
+     *
+     * Standard-definition television, 625 Lines (PAL)
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_DATASPACE_BT601_625 = 0x102,
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 525-line
+     *
+     * Standard-definition television, 525 Lines (NTSC)
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_DATASPACE_BT601_525 = 0x103,
+
+    /*
+     * ITU-R Recommendation 709 (BT.709)
+     *
+     * High-definition television
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Primaries:       x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_DATASPACE_BT709 = 0x104,
+
+    /*
+     * The buffer contains depth ranging measurements from a depth camera.
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_Y16: 16-bit samples, consisting of a depth measurement
+     *       and an associated confidence value. The 3 MSBs of the sample make
+     *       up the confidence value, and the low 13 LSBs of the sample make up
+     *       the depth measurement.
+     *       For the confidence section, 0 means 100% confidence, 1 means 0%
+     *       confidence. The mapping to a linear float confidence value between
+     *       0.f and 1.f can be obtained with
+     *         float confidence = (((depthSample >> 13) - 1) & 0x7) / 7.0f;
+     *       The depth measurement can be extracted simply with
+     *         uint16_t range = (depthSample & 0x1FFF);
+     *    HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
+     *       a variable-length float (x,y,z, confidence) coordinate point list.
+     *       The point cloud will be represented with the android_depth_points
+     *       structure.
+     */
+    HAL_DATASPACE_DEPTH = 0x1000
+
+} android_dataspace_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H */
diff --git a/libcsc/Makefile.am b/libcsc/Makefile.am
new file mode 100755 (executable)
index 0000000..3293e20
--- /dev/null
@@ -0,0 +1,11 @@
+lib_LTLIBRARIES = libcsc.la
+
+libcsc_la_SOURCES = csc.c
+libcsc_la_CFLAGS = -I$(top_srcdir)/include -DLOG_TAG=\"LIBCSC\"
+if USE_DLOG
+libcsc_la_CFLAGS += $(DLOG_CFLAGS) -DUSE_DLOG
+endif
+
+libcsc_la_LDFLAGS = -L$(top_srcdir)/libswconverter
+
+libcsc_la_LIBADD = -lswconverter $(DLOG_LIBS)
diff --git a/libcsc/csc.c b/libcsc/csc.c
new file mode 100755 (executable)
index 0000000..d90968e
--- /dev/null
@@ -0,0 +1,1309 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file        csc.c
+ *
+ * @brief       color space convertion abstract source
+ *
+ * @author      Pyoungjae Jung(pjet.jung@samsung.com)
+ *
+ * @version     1.0.0
+ *
+ * @history
+ *   2012.1.11 : Create
+ */
+#include <exynos_log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <system/graphics.h>
+
+#include <csc.h>
+#include <exynos_format.h>
+#include <swconverter.h>
+
+#ifdef USES_FIMC
+#include "exynos_fimc.h"
+#endif
+
+#ifdef USES_GSCALER
+#include "exynos_gscaler.h"
+#include "exynos_scaler.h"
+#endif
+
+#define GSCALER_IMG_ALIGN 16
+#define FIMC_IMG_ALIGN_WIDTH 16
+#define FIMC_IMG_ALIGN_HEIGHT 2
+#define MFC_IMG_ALIGN_WIDTH 16
+
+static CSC_ERRORCODE copy_mfc_data(CSC_HANDLE *handle) {
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    int i;
+    char *pSrc = NULL;
+    char *pDst = NULL;
+
+    ALOGV("%s: convert %x to %x", __FUNCTION__, handle->src_format.color_format, handle->dst_format.color_format);
+
+    switch (handle->src_format.color_format) {
+    /* Multi FD to Single FD : decoder */
+    /* remove a padding data */
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc = (char *)handle->src_buffer.planes[CSC_U_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            memcpy(pDst + ((handle->src_format.crop_width >> 1) * i),
+                   pSrc + (ALIGN((handle->src_format.crop_width >> 1), MFC_IMG_ALIGN_WIDTH) * i),
+                   (handle->src_format.crop_width >> 1));
+        }
+
+        pSrc = (char *)handle->src_buffer.planes[CSC_V_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            memcpy(pDst + ((handle->src_format.crop_width >> 1) * i),
+                   pSrc + (ALIGN((handle->src_format.crop_width >> 1), MFC_IMG_ALIGN_WIDTH) * i),
+                   (handle->src_format.crop_width >> 1));
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_UV_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+        break;
+    /* Single FD to Multi FD : encoder */
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_YV12:
+        /* adding a padding data for u/v plane : 420P */
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        if (handle->src_format.width == handle->src_format.crop_width) {
+            memcpy(pDst, pSrc, (handle->src_format.width * handle->src_format.height));
+        } else {
+            for (i = 0; i < (int)handle->src_format.height; i++) {
+                memcpy(pDst + (handle->src_format.width * i),
+                       pSrc + (handle->src_format.crop_width * i),
+                       handle->src_format.crop_width);
+            }
+        }
+
+        pSrc = (char *)handle->src_buffer.planes[CSC_U_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        for (i = 0; i < (int)(handle->src_format.height >> 1); i++) {
+            memcpy(pDst + (ALIGN((handle->src_format.width >> 1), MFC_IMG_ALIGN_WIDTH) * i),
+                   pSrc + ((handle->src_format.crop_width >> 1) * i),
+                   (handle->src_format.crop_width >> 1));
+        }
+
+        pSrc = (char *)handle->src_buffer.planes[CSC_V_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.height >> 1); i++) {
+            memcpy(pDst + (ALIGN((handle->src_format.width >> 1), MFC_IMG_ALIGN_WIDTH) * i),
+                   pSrc + ((handle->src_format.crop_width >> 1) * i),
+                   (handle->src_format.crop_width >> 1));
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        if (handle->src_format.width == handle->src_format.crop_width) {
+            pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+            pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+            memcpy(pDst, pSrc, (handle->src_format.width * handle->src_format.height));
+
+            pSrc = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+            pDst = (char *)handle->dst_buffer.planes[CSC_UV_PLANE];
+            memcpy(pDst, pSrc, (handle->src_format.width * (handle->src_format.height >> 1)));
+        } else {
+            pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+            pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+            for (i = 0; i < (int)handle->src_format.height; i++) {
+                memcpy(pDst + (handle->src_format.width * i),
+                       pSrc + (handle->src_format.crop_width * i),
+                       handle->src_format.crop_width);
+            }
+
+            pSrc = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+            pDst = (char *)handle->dst_buffer.planes[CSC_UV_PLANE];
+            memcpy(pDst, pSrc, (handle->src_format.width * (handle->src_format.height >> 1)));
+            for (i = 0; i < (int)(handle->src_format.height >> 1); i++) {
+                memcpy(pDst + (handle->src_format.width * i),
+                       pSrc + (handle->src_format.crop_width * i),
+                       handle->src_format.crop_width);
+            }
+        }
+        break;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        memcpy(pDst, pSrc, (handle->src_format.width * handle->src_format.height * 4));
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is BRGA888 */
+static CSC_ERRORCODE conv_sw_src_argb888(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            ret = CSC_ErrorUnsupportFormat;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        csc_BGRA8888_to_YUV420P(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        csc_BGRA8888_to_YUV420SP(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        csc_BGRA8888_to_YUV420P(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is RGBA888 */
+static CSC_ERRORCODE conv_sw_src_rgba888(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            ret = CSC_ErrorUnsupportFormat;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        csc_RGBA8888_to_YUV420P(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        csc_RGBA8888_to_YUV420SP(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        csc_RGBA8888_to_YUV420P(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
+            handle->src_format.width,
+            handle->src_format.height);
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+
+/* source is NV12T */
+static CSC_ERRORCODE conv_sw_src_nv12t(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        csc_tiled_to_linear_y(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+            handle->src_format.crop_width,
+            handle->src_format.crop_height);
+        csc_tiled_to_linear_uv_deinterleave(
+            (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
+            handle->src_format.crop_width,
+            handle->src_format.crop_height / 2);
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        csc_tiled_to_linear_y(
+            (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+            handle->src_format.crop_width,
+            handle->src_format.crop_height);
+        csc_tiled_to_linear_uv(
+            (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
+            handle->src_format.crop_width,
+            handle->src_format.crop_height / 2);
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is YUV420P */
+static CSC_ERRORCODE conv_sw_src_yuv420p(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:    /* bypass */
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+                   handle->src_format.width * handle->src_format.height);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
+                   (handle->src_format.width * handle->src_format.height) >> 2);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
+                   (handle->src_format.width * handle->src_format.height) >> 2);
+            ret = CSC_ErrorNone;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+               (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+               handle->src_format.width * handle->src_format.height);
+        csc_interleave_memcpy(
+            (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
+            (handle->src_format.width * handle->src_format.height) >> 2);
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is YVU420P */
+static CSC_ERRORCODE conv_sw_src_yvu420p(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_YV12:  /* bypass */
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+                   handle->src_format.width * handle->src_format.height);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
+                   (handle->src_format.width * handle->src_format.height) >> 2);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
+                   (handle->src_format.width * handle->src_format.height) >> 2);
+            ret = CSC_ErrorNone;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+               (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+               handle->src_format.width * handle->src_format.height);
+        csc_interleave_memcpy(
+            (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
+            (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
+            (handle->src_format.width * handle->src_format.height) >> 2);
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is YUV420SP */
+static CSC_ERRORCODE conv_sw_src_yuv420sp(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    char *pSrc  = NULL;
+    char *pDst  = NULL;
+    char *pDstU = NULL;
+    char *pDstV = NULL;
+    int srcOffset, dstOffset;
+    int i, j;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:    /* bypass */
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+                   handle->src_format.width * handle->src_format.height);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
+                   handle->src_format.width * handle->src_format.height >> 1);
+            ret = CSC_ErrorNone;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+    {
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc  = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+        pDstU = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        pDstV = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            for (j = 0; j < (int)(handle->src_format.crop_width >> 1); j++) {
+                srcOffset = (i * handle->src_format.width) + (j * 2);
+                dstOffset = i * (handle->src_format.crop_width >> 1);
+
+                pDstU[dstOffset + j] = pSrc[srcOffset];
+                pDstV[dstOffset + j] = pSrc[srcOffset + 1];
+            }
+        }
+        ret = CSC_ErrorNone;
+    }
+        break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc  = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+        pDstU = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        pDstV = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            for (j = 0; j < (int)(handle->src_format.crop_width >> 1); j++) {
+                srcOffset = (i * handle->src_format.width) + (j * 2);
+                dstOffset = i * (handle->src_format.crop_width >> 1);
+
+                pDstU[dstOffset + j] = pSrc[srcOffset + 1];
+                pDstV[dstOffset + j] = pSrc[srcOffset];
+            }
+        }
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+/* source is YVU420SP */
+static CSC_ERRORCODE conv_sw_src_yvu420sp(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    char *pSrc  = NULL;
+    char *pDst  = NULL;
+    char *pDstU = NULL;
+    char *pDstV = NULL;
+    int srcOffset, dstOffset;
+    int i, j;
+
+    switch (handle->dst_format.color_format) {
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:  /* bypass */
+    case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+        if (handle->src_buffer.mem_type == CSC_MEMORY_MFC) {
+            ret = copy_mfc_data(handle);
+        } else {
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
+                   handle->src_format.width * handle->src_format.height);
+            memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
+                   (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
+                   handle->src_format.width * handle->src_format.height >> 1);
+            ret = CSC_ErrorNone;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc  = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+        pDstU = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        pDstV = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            for (j = 0; j < (int)(handle->src_format.crop_width >> 1); j++) {
+                srcOffset = (i * handle->src_format.width) + (j * 2);
+                dstOffset = i * (handle->src_format.crop_width >> 1);
+
+                pDstU[dstOffset + j] = pSrc[srcOffset + 1];
+                pDstV[dstOffset + j] = pSrc[srcOffset];
+            }
+        }
+        ret = CSC_ErrorNone;
+        break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        pSrc = (char *)handle->src_buffer.planes[CSC_Y_PLANE];
+        pDst = (char *)handle->dst_buffer.planes[CSC_Y_PLANE];
+        for (i = 0; i < (int)handle->src_format.crop_height; i++) {
+            memcpy(pDst + (handle->src_format.crop_width * i),
+                   pSrc + (handle->src_format.width * i),
+                   handle->src_format.crop_width);
+        }
+
+        pSrc  = (char *)handle->src_buffer.planes[CSC_UV_PLANE];
+        pDstU = (char *)handle->dst_buffer.planes[CSC_U_PLANE];
+        pDstV = (char *)handle->dst_buffer.planes[CSC_V_PLANE];
+        for (i = 0; i < (int)(handle->src_format.crop_height >> 1); i++) {
+            for (j = 0; j < (int)(handle->src_format.crop_width >> 1); j++) {
+                srcOffset = (i * handle->src_format.width) + (j * 2);
+                dstOffset = i * (handle->src_format.crop_width >> 1);
+
+                pDstU[dstOffset + j] = pSrc[srcOffset];
+                pDstV[dstOffset + j] = pSrc[srcOffset + 1];
+            }
+        }
+        ret = CSC_ErrorNone;
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+static CSC_ERRORCODE conv_sw(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    switch (handle->src_format.color_format) {
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED:
+        ret = conv_sw_src_nv12t(handle);
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        ret = conv_sw_src_yuv420p(handle);
+        break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+        ret = conv_sw_src_yvu420p(handle);
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        ret = conv_sw_src_yuv420sp(handle);
+        break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+        ret = conv_sw_src_yvu420sp(handle);
+        break;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        ret = conv_sw_src_argb888(handle);
+        break;
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+        ret = conv_sw_src_rgba888(handle);
+        break;
+    case HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888:
+        ret = copy_mfc_data(handle);
+        break;
+    default:
+        ret = CSC_ErrorUnsupportFormat;
+        break;
+    }
+
+    return ret;
+}
+
+static CSC_ERRORCODE conv_hw(
+    CSC_HANDLE *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+    switch (handle->csc_hw_type) {
+#ifdef USES_FIMC
+    case CSC_HW_TYPE_FIMC:
+        if (exynos_fimc_convert(handle->csc_hw_handle) != 0) {
+            ALOGE("%s:: exynos_fimc_convert() fail", __func__);
+            ret = CSC_Error;
+        }
+        break;
+#endif
+#ifdef USES_GSCALER
+    case CSC_HW_TYPE_GSCALER:
+        if (handle->hw_property.fixed_node < CSC_HW_SC0) {
+            if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
+                ALOGE("%s:: exynos_gsc_convert() fail", __func__);
+                ret = CSC_Error;
+            }
+        } else {
+            if (exynos_sc_convert(handle->csc_hw_handle) != 0) {
+                ALOGE("%s:: exynos_sc_convert() fail", __func__);
+                ret = CSC_Error;
+            }
+        }
+        break;
+#endif
+    default:
+        ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
+        ret = CSC_ErrorNotImplemented;
+        break;
+    }
+
+    return ret;
+}
+
+static CSC_ERRORCODE csc_init_hw(
+    void *handle)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    if (csc_handle->csc_method == CSC_METHOD_HW) {
+#ifdef USES_FIMC
+        csc_handle->csc_hw_type = CSC_HW_TYPE_FIMC;
+#endif
+#ifdef USES_GSCALER
+        csc_handle->csc_hw_type = CSC_HW_TYPE_GSCALER;
+#endif
+        switch (csc_handle->csc_hw_type) {
+#ifdef USES_FIMC
+        case CSC_HW_TYPE_FIMC:
+            if (csc_handle->hw_property.fixed_node >= 0)
+                csc_handle->csc_hw_handle = exynos_fimc_create_exclusive(csc_handle->hw_property.fixed_node, FIMC_M2M_MODE, 0, 0);
+            else
+            csc_handle->csc_hw_handle = exynos_fimc_create();
+            ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
+            break;
+#endif
+#ifdef USES_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            if (csc_handle->hw_property.fixed_node >= 0) {
+                if (csc_handle->hw_property.fixed_node < CSC_HW_SC0)
+                    csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
+                else if (csc_handle->hw_property.fixed_node < CSC_HW_MAX)
+                    csc_handle->csc_hw_handle = exynos_sc_create(csc_handle->hw_property.fixed_node - CSC_HW_SC0);
+                else
+                    csc_handle->csc_hw_handle = NULL;
+            } else {
+                csc_handle->csc_hw_handle = exynos_gsc_create();
+            }
+            ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
+            break;
+#endif
+        default:
+            ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
+            csc_handle->csc_hw_handle = NULL;
+            break;
+        }
+    }
+
+    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;
+        }
+    }
+    if (csc_handle)
+      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) {
+        switch (csc_handle->csc_hw_type) {
+#ifdef USES_FIMC
+        case CSC_HW_TYPE_FIMC:
+            exynos_fimc_set_src_format(
+                csc_handle->csc_hw_handle,
+                ALIGN(csc_handle->src_format.width, FIMC_IMG_ALIGN_WIDTH),
+                ALIGN(csc_handle->src_format.height, FIMC_IMG_ALIGN_HEIGHT),
+                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_fimc_set_dst_format(
+                csc_handle->csc_hw_handle,
+                ALIGN(csc_handle->dst_format.width, FIMC_IMG_ALIGN_WIDTH),
+                ALIGN(csc_handle->dst_format.height, FIMC_IMG_ALIGN_HEIGHT),
+                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 USES_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            if (csc_handle->hw_property.fixed_node < CSC_HW_SC0) {
+                exynos_gsc_set_csc_property(
+                    csc_handle->csc_hw_handle,
+                    csc_handle->csc_mode,
+                    csc_handle->csc_range,
+                    csc_handle->colorspace);
+
+                exynos_gsc_set_src_format(
+                    csc_handle->csc_hw_handle,
+                    csc_handle->src_format.width,
+                    csc_handle->src_format.height,
+                    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,
+                    csc_handle->dst_format.width,
+                    csc_handle->dst_format.height,
+                    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);
+            } else {
+                exynos_sc_set_csc_property(
+                    csc_handle->csc_hw_handle,
+                    csc_handle->csc_range,
+                    csc_handle->colorspace,
+                    csc_handle->filter);
+
+                exynos_sc_set_src_format(
+                    csc_handle->csc_hw_handle,
+                    csc_handle->src_format.width,
+                    csc_handle->src_format.height,
+                    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,
+                    1);
+
+                exynos_sc_set_dst_format(
+                    csc_handle->csc_hw_handle,
+                    csc_handle->dst_format.width,
+                    csc_handle->dst_format.height,
+                    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,
+                    1);
+            }
+            break;
+#endif
+        default:
+            ALOGE("%s:: unsupported csc_hw_type", __func__);
+            break;
+        }
+    }
+
+    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) {
+#ifdef USES_FIMC
+        case CSC_HW_TYPE_FIMC:
+            exynos_fimc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, csc_handle->src_buffer.mem_type, -1);
+            exynos_fimc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, csc_handle->dst_buffer.mem_type, -1);
+            break;
+#endif
+#ifdef USES_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            if (csc_handle->hw_property.fixed_node < CSC_HW_SC0) {
+                exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, csc_handle->src_buffer.mem_type, -1);
+                exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, csc_handle->dst_buffer.mem_type, -1);
+            } else {
+                exynos_sc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, csc_handle->src_buffer.mem_type, -1);
+                exynos_sc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, csc_handle->dst_buffer.mem_type, -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));
+#ifdef USES_DEFAULT_CSC_HW_SCALER
+    csc_handle->hw_property.fixed_node = DEFAULT_CSC_HW;       /* CSC_HW_SC1 == 5 */
+#else
+    csc_handle->hw_property.fixed_node = -1;
+#endif
+    csc_handle->hw_property.mode_drm = 0;
+    csc_handle->csc_method = method;
+
+    return (void *)csc_handle;
+}
+
+CSC_ERRORCODE csc_deinit(
+    void *handle)
+{
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+    CSC_HANDLE *csc_handle;
+
+    if (handle == NULL)
+        return ret;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    if (csc_handle->csc_method == CSC_METHOD_HW) {
+        switch (csc_handle->csc_hw_type) {
+#ifdef USES_FIMC
+        case CSC_HW_TYPE_FIMC:
+            exynos_fimc_destroy(csc_handle->csc_hw_handle);
+            break;
+#endif
+#ifdef USES_GSCALER
+        case CSC_HW_TYPE_GSCALER:
+            if (csc_handle->hw_property.fixed_node < CSC_HW_SC0)
+                exynos_gsc_destroy(csc_handle->csc_hw_handle);
+            else
+                exynos_sc_destroy(csc_handle->csc_hw_handle);
+            break;
+#endif
+        default:
+            ALOGE("%s:: unsupported csc_hw_type", __func__);
+            break;
+        }
+    }
+
+    free(csc_handle);
+    ret = CSC_ErrorNone;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_get_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;
+    *method = csc_handle->csc_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;
+
+    switch (method) {
+    case CSC_METHOD_SW:
+    case CSC_METHOD_HW:
+        csc_handle->csc_method = method;
+        break;
+    default:
+        ret = CSC_Error;
+        break;
+    }
+
+    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;
+    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;
+    default:
+        ALOGE("%s:: not supported hw property", __func__);
+        ret = CSC_ErrorUnsupportFormat;
+    }
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_get_eq_property(
+    void              *handle,
+    CSC_EQ_MODE       *csc_mode,
+    CSC_EQ_RANGE      *csc_range,
+    CSC_EQ_COLORSPACE *colorspace)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    *csc_mode = csc_handle->csc_mode;
+    *csc_range = csc_handle->csc_range;
+    *colorspace = csc_handle->colorspace;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_eq_property(
+    void              *handle,
+    CSC_EQ_MODE        csc_mode,
+    CSC_EQ_RANGE       csc_range,
+    CSC_EQ_COLORSPACE  colorspace)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_Error;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    csc_handle->csc_mode = csc_mode;
+    csc_handle->csc_range = csc_range;
+    csc_handle->colorspace = colorspace;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_filter_property(
+    void              *handle,
+    CSC_HW_FILTER    filter)
+{
+    CSC_HANDLE *csc_handle;
+
+    if (handle == NULL)
+        return CSC_Error;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    if (filter >= CSC_FT_MAX)
+        return CSC_Error;
+
+    csc_handle->filter = filter;
+    csc_handle->hw_property.fixed_node = CSC_HW_SC1;
+
+    return 0;
+}
+
+CSC_ERRORCODE csc_get_src_format(
+    void           *handle,
+    unsigned int   *width,
+    unsigned int   *height,
+    unsigned int   *crop_left,
+    unsigned int   *crop_top,
+    unsigned int   *crop_width,
+    unsigned int   *crop_height,
+    unsigned int   *color_format,
+    unsigned int   *cacheable)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    *width = csc_handle->src_format.width;
+    *height = csc_handle->src_format.height;
+    *crop_left = csc_handle->src_format.crop_left;
+    *crop_top = csc_handle->src_format.crop_top;
+    *crop_width = csc_handle->src_format.crop_width;
+    *crop_height = csc_handle->src_format.crop_height;
+    *color_format = csc_handle->src_format.color_format;
+    *cacheable = csc_handle->src_format.cacheable;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_src_format(
+    void           *handle,
+    unsigned int    width,
+    unsigned int    height,
+    unsigned int    crop_left,
+    unsigned int    crop_top,
+    unsigned int    crop_width,
+    unsigned int    crop_height,
+    unsigned int    color_format,
+    unsigned int    cacheable)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    csc_handle->src_format.width = width;
+    csc_handle->src_format.height = height;
+    csc_handle->src_format.crop_left = crop_left;
+    csc_handle->src_format.crop_top = crop_top;
+    csc_handle->src_format.crop_width = crop_width;
+    csc_handle->src_format.crop_height = crop_height;
+    csc_handle->src_format.color_format = color_format;
+    csc_handle->src_format.cacheable = cacheable;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_get_dst_format(
+    void           *handle,
+    unsigned int   *width,
+    unsigned int   *height,
+    unsigned int   *crop_left,
+    unsigned int   *crop_top,
+    unsigned int   *crop_width,
+    unsigned int   *crop_height,
+    unsigned int   *color_format,
+    unsigned int   *cacheable)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    *width = csc_handle->dst_format.width;
+    *height = csc_handle->dst_format.height;
+    *crop_left = csc_handle->dst_format.crop_left;
+    *crop_top = csc_handle->dst_format.crop_top;
+    *crop_width = csc_handle->dst_format.crop_width;
+    *crop_height = csc_handle->dst_format.crop_height;
+    *color_format = csc_handle->dst_format.color_format;
+    *cacheable = csc_handle->dst_format.cacheable;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_dst_format(
+    void           *handle,
+    unsigned int    width,
+    unsigned int    height,
+    unsigned int    crop_left,
+    unsigned int    crop_top,
+    unsigned int    crop_width,
+    unsigned int    crop_height,
+    unsigned int    color_format,
+    unsigned int    cacheable)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    csc_handle->dst_format.width = width;
+    csc_handle->dst_format.height = height;
+    csc_handle->dst_format.crop_left = crop_left;
+    csc_handle->dst_format.crop_top = crop_top;
+    csc_handle->dst_format.crop_width = crop_width;
+    csc_handle->dst_format.crop_height = crop_height;
+    csc_handle->dst_format.color_format = color_format;
+    csc_handle->dst_format.cacheable = cacheable;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_src_buffer(
+    void *handle,
+    void *addr[3],
+    int mem_type)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    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];
+    csc_handle->src_buffer.mem_type = mem_type;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_set_dst_buffer(
+    void *handle,
+    void *addr[3],
+    int mem_type)
+{
+    CSC_HANDLE *csc_handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (handle == NULL)
+        return CSC_ErrorNotInit;
+
+    csc_handle = (CSC_HANDLE *)handle;
+    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];
+    csc_handle->dst_buffer.mem_type = mem_type;
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_convert(
+    void *handle)
+{
+    CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (csc_handle == NULL)
+        return CSC_ErrorNotInit;
+
+    if ((csc_handle->csc_method == CSC_METHOD_HW) &&
+        (csc_handle->csc_hw_handle == NULL))
+        csc_init_hw(handle);
+
+    csc_set_format(csc_handle);
+    csc_set_buffer(csc_handle);
+
+    if (csc_handle->csc_method == CSC_METHOD_HW)
+        ret = conv_hw(csc_handle);
+    else
+        ret = conv_sw(csc_handle);
+
+    return ret;
+}
+
+CSC_ERRORCODE csc_convert_with_rotation(
+    void *handle, int rotation, int flip_horizontal, int flip_vertical)
+{
+    CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle;
+    CSC_ERRORCODE ret = CSC_ErrorNone;
+
+    if (csc_handle == NULL)
+        return CSC_ErrorNotInit;
+
+    if ((csc_handle->csc_method == CSC_METHOD_HW) &&
+        (csc_handle->csc_hw_handle == NULL))
+        csc_init_hw(handle);
+
+    csc_set_format(csc_handle);
+    csc_set_buffer(csc_handle);
+
+#ifdef USES_FIMC
+    exynos_fimc_set_rotation(csc_handle->csc_hw_handle, rotation, flip_horizontal, flip_vertical);
+#endif
+#ifdef USES_GSCALER
+    if (csc_handle->hw_property.fixed_node < CSC_HW_SC0)
+        exynos_gsc_set_rotation(csc_handle->csc_hw_handle, rotation, flip_horizontal, flip_vertical);
+    else
+        exynos_sc_set_rotation(csc_handle->csc_hw_handle, rotation, flip_horizontal, flip_vertical);
+#endif
+
+    if (csc_handle->csc_method == CSC_METHOD_HW)
+        ret = conv_hw(csc_handle);
+    else
+        ret = conv_sw(csc_handle);
+
+    return ret;
+}
diff --git a/libexynos-common.manifest b/libexynos-common.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/libgscaler/Makefile.am b/libgscaler/Makefile.am
new file mode 100755 (executable)
index 0000000..afe91ef
--- /dev/null
@@ -0,0 +1,7 @@
+lib_LTLIBRARIES = libexynosgscaler.la
+
+libexynosgscaler_la_SOURCES = libgscaler_obj.cpp libgscaler.cpp
+libexynosgscaler_la_CFLAGS = -DLOG_TAG=\"LIBEXYNOSGSCALER\" -I$(top_srcdir)/include
+libexynosgscaler_la_CXXFLAGS = $(libexynosgscaler_la_CFLAGS)
+libexynosgscaler_la_LDFLAGS = -L$(top_srcdir)/libcsc
+libexynosgscaler_la_LIBADD = -lcsc $(DLOG_LIBS)
diff --git a/libgscaler/libgscaler.cpp b/libgscaler/libgscaler.cpp
new file mode 100755 (executable)
index 0000000..8073e80
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      libgscaler.cpp
+ * \brief     source file for Gscaler HAL
+ * \author    Sungchun Kang (sungchun.kang@samsung.com)
+ * \date      2013/06/01
+ *
+ * <b>Revision History: </b>
+ * - 2013.06.01 : Sungchun Kang (sungchun.kang@samsung.com) \n
+ *   Create
+ */
+
+#include "libgscaler_obj.h"
+
+void *exynos_gsc_create(void)
+{
+    CGscaler *gsc = new CGscaler(GSC_M2M_MODE);
+    if (!gsc) {
+        ALOGE("%s:: failed to allocate Gscaler handle", __func__);
+        return NULL;
+    }
+    if (gsc->m_gsc_find_and_create(gsc) == false) {
+        ALOGE("%s::m_exynos_gsc_find_and_create() fail", __func__);
+        delete gsc;
+        return NULL;
+    }
+
+    return reinterpret_cast<void *>(gsc);
+}
+
+void *exynos_gsc_create_exclusive(
+    int dev_num,
+    int mode,
+    int out_mode,
+    int allow_drm)
+{
+    int i     = 0;
+    int op_id = 0;
+    unsigned int total_sleep_time  = 0;
+    int ret = 0;
+
+    Exynos_gsc_In();
+
+    if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
+        ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
+        return NULL;
+    }
+
+    if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
+        CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
+        if (!gsc) {
+            ALOGE("%s:: failed to allocate Gscaler handle", __func__);
+            return NULL;
+        }
+
+        gsc->scaler = exynos_sc_create_exclusive(dev_num - HW_SCAL0,
+            allow_drm);
+        if (!gsc->scaler) {
+            delete(gsc);
+            ALOGE("%s::exynos_sc_create fail", __func__);
+            return NULL;
+        }
+        Exynos_gsc_Out();
+        return reinterpret_cast<void *>(gsc);
+    }
+
+    if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
+        ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
+        return NULL;
+    }
+
+    CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
+    if (!gsc) {
+        ALOGE("%s:: failed to allocate Gscaler handle", __func__);
+        return NULL;
+    }
+
+    if (mode == GSC_M2M_MODE) {
+        gsc->gsc_fd = gsc->m_gsc_m2m_create(dev_num);
+        if (gsc->gsc_fd < 0) {
+            ALOGE("%s::m_gsc_m2m_create(%i) fail", __func__, dev_num);
+            goto err;
+        }
+    } else if (mode == GSC_OUTPUT_MODE) {
+        ret = gsc->m_gsc_output_create(gsc, dev_num, out_mode);
+        if (ret < 0) {
+            ALOGE("%s::m_gsc_output_create(%i) fail", __func__, dev_num);
+            goto err;
+        }
+    } else if (mode == GSC_CAPTURE_MODE) {
+        ret = gsc->m_gsc_capture_create(gsc, dev_num, out_mode);
+        if (ret < 0) {
+            ALOGE("%s::m_gsc_capture_create(%i) fail", __func__, dev_num);
+            goto err;
+        }
+    } else {
+            ALOGE("%s::Unsupported Mode(%i) fail", __func__, dev_num);
+           goto err;
+    }
+
+    Exynos_gsc_Out();
+
+    return reinterpret_cast<void *>(gsc);
+err:
+    switch (mode) {
+    case GSC_M2M_MODE:
+        gsc->m_gsc_m2m_destroy(gsc);
+        break;
+    case GSC_OUTPUT_MODE:
+        gsc->m_gsc_out_destroy(gsc);
+        break;
+    case GSC_CAPTURE_MODE:
+        gsc->m_gsc_cap_destroy(gsc);
+        break;
+    }
+
+    delete(gsc);
+
+    Exynos_gsc_Out();
+
+    return NULL;
+}
+
+void exynos_gsc_destroy(void *handle)
+{
+    Exynos_gsc_In();
+
+    int i = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return;
+    }
+
+    if (gsc->mode == GSC_OUTPUT_MODE)
+        gsc->m_gsc_out_destroy(gsc);
+    else if (gsc->mode ==GSC_CAPTURE_MODE)
+        gsc->m_gsc_cap_destroy(gsc);
+    else
+        gsc->m_gsc_m2m_destroy(gsc);
+
+    delete(gsc);
+
+    Exynos_gsc_Out();
+}
+
+int exynos_gsc_set_csc_property(
+    void        *handle,
+    unsigned int eq_auto,
+    unsigned int range_full,
+    unsigned int v4l2_colorspace)
+{
+    Exynos_gsc_In();
+
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        int ret;
+        ret = exynos_sc_csc_exclusive(gsc->scaler,
+                            range_full, v4l2_colorspace);
+        Exynos_gsc_Out();
+        return ret;
+    }
+    gsc->eq_auto = eq_auto;
+    gsc->range_full = range_full;
+    gsc->v4l2_colorspace = v4l2_colorspace;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int exynos_gsc_set_src_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm)
+{
+    Exynos_gsc_In();
+
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+    gsc->src_info.width            = width;
+    gsc->src_info.height           = height;
+    gsc->src_info.crop_left        = crop_left;
+    gsc->src_info.crop_top         = crop_top;
+    gsc->src_info.crop_width       = crop_width;
+    gsc->src_info.crop_height      = crop_height;
+    gsc->src_info.v4l2_colorformat = v4l2_colorformat;
+    gsc->src_info.cacheable        = cacheable;
+    gsc->src_info.mode_drm         = mode_drm;
+    gsc->src_info.dirty            = true;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int exynos_gsc_set_dst_format(
+    void        *handle,
+    unsigned int width,
+    unsigned int height,
+    unsigned int crop_left,
+    unsigned int crop_top,
+    unsigned int crop_width,
+    unsigned int crop_height,
+    unsigned int v4l2_colorformat,
+    unsigned int cacheable,
+    unsigned int mode_drm)
+{
+    Exynos_gsc_In();
+
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    gsc->dst_info.width            = width;
+    gsc->dst_info.height           = height;
+    gsc->dst_info.crop_left        = crop_left;
+    gsc->dst_info.crop_top         = crop_top;
+    gsc->dst_info.crop_width       = crop_width;
+    gsc->dst_info.crop_height      = crop_height;
+    gsc->dst_info.v4l2_colorformat = v4l2_colorformat;
+    gsc->dst_info.dirty            = true;
+    gsc->dst_info.cacheable        = cacheable;
+    gsc->dst_info.mode_drm         = mode_drm;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int exynos_gsc_set_rotation(
+    void *handle,
+    int   rotation,
+    int   flip_horizontal,
+    int   flip_vertical)
+{
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    int new_rotation = rotation % 360;
+
+    if (new_rotation % 90 != 0) {
+        ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__,
+            rotation);
+        return -1;
+    }
+
+    if(new_rotation < 0)
+        new_rotation = -new_rotation;
+
+    gsc->dst_info.rotation        = new_rotation;
+    gsc->dst_info.flip_horizontal = flip_horizontal;
+    gsc->dst_info.flip_vertical   = flip_vertical;
+
+    return 0;
+}
+
+int exynos_gsc_set_src_addr(
+    void *handle,
+    void *addr[3],
+    int mem_type,
+    int acquireFenceFd)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    gsc->src_info.buf.addr[0] = addr[0];
+    gsc->src_info.buf.addr[1] = addr[1];
+    gsc->src_info.buf.addr[2] = addr[2];
+    gsc->src_info.acquireFenceFd = acquireFenceFd;
+    gsc->src_info.buf.mem_type = (enum v4l2_memory)mem_type;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int exynos_gsc_set_dst_addr(
+    void *handle,
+    void *addr[3],
+    int mem_type,
+    int acquireFenceFd)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    gsc->dst_info.buf.addr[0] = addr[0];
+    gsc->dst_info.buf.addr[1] = addr[1];
+    gsc->dst_info.buf.addr[2] = addr[2];
+    gsc->dst_info.acquireFenceFd = acquireFenceFd;
+    gsc->dst_info.buf.mem_type = (enum v4l2_memory)mem_type;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int exynos_gsc_convert(void *handle)
+{
+    Exynos_gsc_In();
+
+    int ret    = -1;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return ret;
+    }
+
+    if (gsc->m_gsc_m2m_run_core(handle) < 0) {
+        ALOGE("%s::exynos_gsc_run_core fail", __func__);
+        goto done;
+    }
+
+    if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
+        ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
+        goto done;
+    }
+
+    if (gsc->src_info.releaseFenceFd >= 0) {
+        close(gsc->src_info.releaseFenceFd);
+        gsc->src_info.releaseFenceFd = -1;
+    }
+
+    if (gsc->dst_info.releaseFenceFd >= 0) {
+        close(gsc->dst_info.releaseFenceFd);
+        gsc->dst_info.releaseFenceFd = -1;
+    }
+
+    if (gsc->m_gsc_m2m_stop(handle) < 0) {
+        ALOGE("%s::m_gsc_m2m_stop", __func__);
+        goto done;
+    }
+
+    ret = 0;
+
+done:
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+int exynos_gsc_subdev_s_crop(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    struct v4l2_subdev_crop sd_crop;
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
+    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    sd_crop.rect.left = dst_img->x;
+    sd_crop.rect.top = dst_img->y;
+    sd_crop.rect.width = dst_img->w;
+    sd_crop.rect.height = dst_img->h;
+
+    return exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop);
+}
+
+int exynos_gsc_config_exclusive(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_config_exclusive(gsc->scaler,
+            (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    switch (gsc->mode) {
+    case GSC_M2M_MODE:
+        ret = gsc->m_gsc_m2m_config(handle, src_img, dst_img);
+        break;
+    case GSC_OUTPUT_MODE:
+        ret = gsc->m_gsc_out_config(handle, src_img, dst_img);
+        break;
+    case GSC_CAPTURE_MODE:
+        ret = gsc->m_gsc_cap_config(handle, src_img, dst_img);
+        break;
+    default:
+        break;
+    }
+
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+int exynos_gsc_run_exclusive(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (handle == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_run_exclusive(gsc->scaler,
+            (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    switch (gsc->mode) {
+    case GSC_M2M_MODE:
+        ret = gsc->m_gsc_m2m_run(handle, src_img, dst_img);
+        break;
+    case GSC_OUTPUT_MODE:
+        ret = gsc->m_gsc_out_run(handle, src_img);
+        break;
+    case GSC_CAPTURE_MODE:
+        ret = gsc->m_gsc_cap_run(handle, dst_img);
+        break;
+    default:
+        break;
+    }
+
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+void *exynos_gsc_create_blend_exclusive(int dev_num, int mode, int out_mode,
+                                                                int allow_drm)
+{
+    int i     = 0;
+    int op_id = 0;
+    unsigned int total_sleep_time  = 0;
+    int ret = 0;
+
+    Exynos_gsc_In();
+
+    if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
+        ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
+        return NULL;
+    }
+
+    if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
+        CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
+        if (!gsc) {
+            ALOGE("%s:: failed to allocate Gscaler handle", __func__);
+            return NULL;
+        }
+
+        gsc->scaler = exynos_sc_create_blend_exclusive(dev_num - HW_SCAL0, allow_drm);
+        if (!gsc->scaler) {
+            Exynos_gsc_Out();
+            delete(gsc);
+            ALOGE("%s::exynos_sc_create_blend_exclusive failed", __func__);
+            return NULL;
+        }
+        Exynos_gsc_Out();
+
+        return reinterpret_cast<void *>(gsc);
+    }
+
+    Exynos_gsc_Out();
+
+    return NULL;
+}
+
+int exynos_gsc_config_blend_exclusive(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img,
+    struct SrcBlendInfo  *srcblendinfo)
+{
+    Exynos_gsc_In();
+
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_config_blend_exclusive(gsc->scaler,
+                                               (exynos_sc_img *)src_img,
+                                               (exynos_sc_img *)dst_img,
+                                               srcblendinfo);
+        Exynos_gsc_Out();
+        return ret;
+    }
+        Exynos_gsc_Out();
+        return ret;
+}
+
+int exynos_gsc_wait_frame_done_exclusive(void *handle)
+{
+    Exynos_gsc_In();
+
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (handle == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_wait_frame_done_exclusive(gsc->scaler);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    if (gsc->mode == GSC_M2M_MODE)
+        ret = gsc->m_gsc_m2m_wait_frame_done(handle);
+
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+int exynos_gsc_stop_exclusive(void *handle)
+{
+    Exynos_gsc_In();
+
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (handle == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_stop_exclusive(gsc->scaler);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    switch (gsc->mode) {
+    case GSC_M2M_MODE:
+        ret = gsc->m_gsc_m2m_stop(handle);
+        break;
+    case GSC_OUTPUT_MODE:
+        ret = gsc->m_gsc_out_stop(handle);
+        break;
+    case  GSC_CAPTURE_MODE:
+        ret = gsc->m_gsc_cap_stop(handle);
+        break;
+    default:
+        break;
+    }
+
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+int exynos_gsc_free_and_close(void *handle)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_requestbuffers reqbuf;
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        ret = exynos_sc_free_and_close(gsc->scaler);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    memset(&reqbuf, 0, sizeof(struct v4l2_requestbuffers));
+    if (gsc->mode == GSC_OUTPUT_MODE)
+           reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    else
+           reqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    reqbuf.memory = V4L2_MEMORY_DMABUF;
+    reqbuf.count  = 0;
+
+    if (exynos_v4l2_reqbufs(gsc->mdev.gsc_vd_entity->fd, &reqbuf) < 0) {
+        ALOGE("%s::request buffers failed", __func__);
+        return -1;
+    }
+
+    exynos_gsc_destroy(gsc);
+    Exynos_gsc_Out();
+
+    return 0;
+}
diff --git a/libgscaler/libgscaler_obj.cpp b/libgscaler/libgscaler_obj.cpp
new file mode 100755 (executable)
index 0000000..58b88e0
--- /dev/null
@@ -0,0 +1,2074 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      libgscaler_obj.cpp
+ * \brief     source file for Gscaler HAL
+ * \author    Sungchun Kang (sungchun.kang@samsung.com)
+ * \date      2013/06/01
+ *
+ * <b>Revision History: </b>
+ * - 2013.06.01 : Sungchun Kang (sungchun.kang@samsung.com) \n
+ *   Create
+ */
+
+#include <cerrno>
+#include "libgscaler_obj.h"
+#include <system/graphics.h>
+#include <content_protect.h>
+
+int CGscaler::m_gsc_output_create(void *handle, int dev_num, int out_mode)
+{
+    Exynos_gsc_In();
+
+    struct media_device *media0;
+    struct media_entity *gsc_sd_entity;
+    struct media_entity *gsc_vd_entity;
+    struct media_entity *sink_sd_entity;
+    char node[32];
+    char devname[32];
+    unsigned int cap;
+    int         i;
+    int         fd = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if ((out_mode != GSC_OUT_FIMD) &&
+        (out_mode != GSC_OUT_TV))
+        return -1;
+
+    gsc->out_mode = out_mode;
+    /* GSCX => FIMD_WINX : arbitrary linking is not allowed */
+    if ((out_mode == GSC_OUT_FIMD) &&
+#ifndef USES_ONLY_GSC0_GSC1
+        (dev_num > 2))
+#else
+        (dev_num > 1))
+#endif
+        return -1;
+
+    /* media0 */
+    snprintf(node, sizeof(node), "%s%d", PFX_NODE_MEDIADEV, 0);
+    media0 = exynos_media_open(node);
+    if (media0 == NULL) {
+        ALOGE("%s::exynos_media_open failed (node=%s)", __func__, node);
+        return false;
+    }
+    gsc->mdev.media0 = media0;
+
+    /* Get the sink subdev entity by name and make the node of sink subdev*/
+    if (out_mode == GSC_OUT_FIMD)
+        snprintf(devname, sizeof(devname), PFX_FIMD_ENTITY, dev_num);
+    else
+        snprintf(devname, sizeof(devname), PFX_MXR_ENTITY, 0);
+
+    sink_sd_entity = exynos_media_get_entity_by_name(media0, devname,
+            strlen(devname));
+    if (!sink_sd_entity) {
+        ALOGE("%s:: failed to get the sink sd entity", __func__);
+        goto gsc_output_err;
+    }
+    gsc->mdev.sink_sd_entity = sink_sd_entity;
+
+    sink_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
+    if (sink_sd_entity->fd < 0) {
+        ALOGE("%s:: failed to open sink subdev node", __func__);
+        goto gsc_output_err;
+    }
+
+    /* get GSC video dev & sub dev entity by name*/
+#if defined(USES_DT)
+    switch (dev_num) {
+    case 0:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY0);
+        break;
+    case 1:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY1);
+        break;
+    case 2:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY2);
+        break;
+    }
+#else
+    snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY, dev_num);
+#endif
+    gsc_vd_entity = exynos_media_get_entity_by_name(media0, devname,
+            strlen(devname));
+    if (!gsc_vd_entity) {
+        ALOGE("%s:: failed to get the gsc vd entity", __func__);
+        goto gsc_output_err;
+    }
+    gsc->mdev.gsc_vd_entity = gsc_vd_entity;
+
+    snprintf(devname, sizeof(devname), PFX_GSC_SUBDEV_ENTITY, dev_num);
+    gsc_sd_entity = exynos_media_get_entity_by_name(media0, devname,
+            strlen(devname));
+    if (!gsc_sd_entity) {
+        ALOGE("%s:: failed to get the gsc sd entity", __func__);
+        goto gsc_output_err;
+    }
+    gsc->mdev.gsc_sd_entity = gsc_sd_entity;
+
+    /* gsc sub-dev open */
+    snprintf(devname, sizeof(devname), PFX_GSC_SUBDEV_ENTITY, dev_num);
+    gsc_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
+    if (gsc_sd_entity->fd < 0) {
+        ALOGE("%s: gsc sub-dev open fail", __func__);
+        goto gsc_output_err;
+    }
+
+    /* gsc video-dev open */
+#if defined(USES_DT)
+    switch (dev_num) {
+    case 0:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY0);
+        break;
+    case 1:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY1);
+        break;
+    case 2:
+        snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY2);
+        break;
+    }
+#else
+    snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY, dev_num);
+#endif
+    gsc_vd_entity->fd = exynos_v4l2_open_devname(devname, O_RDWR | O_NONBLOCK);
+    if (gsc_vd_entity->fd < 0) {
+        ALOGE("%s: gsc video-dev open fail", __func__);
+        goto gsc_output_err;
+    }
+
+    cap = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+
+    if (exynos_v4l2_querycap(gsc_vd_entity->fd, cap) == false) {
+        ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
+        goto gsc_output_err;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+
+gsc_output_err:
+    gsc->m_gsc_out_destroy(handle);
+
+    return -1;
+}
+
+int CGscaler::m_gsc_capture_create(void *handle, int dev_num, int out_mode)
+{
+    Exynos_gsc_In();
+
+    struct media_device *media1;
+    struct media_entity *gsc_sd_entity;
+    struct media_entity *gsc_vd_entity;
+    struct media_entity *sink_sd_entity;
+    struct media_link *links;
+    char node[32];
+    char devname[32];
+    unsigned int cap;
+    int         i;
+    int         fd = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    gsc->out_mode = out_mode;
+
+    if (dev_num != 2)
+          return -1;
+
+    /* media1 */
+    snprintf(node, sizeof(node), "%s%d", PFX_NODE_MEDIADEV, 1);
+    media1 = exynos_media_open(node);
+    if (media1 == NULL) {
+        ALOGE("%s::exynos_media_open failed (node=%s)", __func__, node);
+        return false;
+    }
+    gsc->mdev.media1 = media1;
+
+    /* DECON-TV sub-device Open */
+    snprintf(devname, sizeof(devname), DEX_WB_SD_NAME);
+
+    sink_sd_entity = exynos_media_get_entity_by_name(media1, devname,
+            strlen(devname));
+    if (!sink_sd_entity) {
+        ALOGE("%s:: failed to get the sink sd entity", __func__);
+        goto gsc_cap_err;
+    }
+    gsc->mdev.sink_sd_entity = sink_sd_entity;
+
+    sink_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
+    if (sink_sd_entity->fd < 0) {
+        ALOGE("%s:: failed to open sink subdev node", __func__);
+        goto gsc_cap_err;
+    }
+
+    /* Gscaler2 capture video-device Open */
+    snprintf(devname, sizeof(devname), PFX_GSC_CAPTURE_ENTITY);
+    gsc_vd_entity = exynos_media_get_entity_by_name(media1, devname,
+            strlen(devname));
+    if (!gsc_vd_entity) {
+        ALOGE("%s:: failed to get the gsc vd entity", __func__);
+        goto gsc_cap_err;
+    }
+    gsc->mdev.gsc_vd_entity = gsc_vd_entity;
+
+    gsc_vd_entity->fd = exynos_v4l2_open_devname(devname, O_RDWR);
+    if (gsc_vd_entity->fd < 0) {
+        ALOGE("%s: gsc video-dev open fail", __func__);
+        goto gsc_cap_err;
+    }
+
+    /* Gscaler2 capture sub-device Open */
+    snprintf(devname, sizeof(devname), GSC_WB_SD_NAME);
+    gsc_sd_entity = exynos_media_get_entity_by_name(media1, devname,
+            strlen(devname));
+    if (!gsc_sd_entity) {
+        ALOGE("%s:: failed to get the gsc sd entity", __func__);
+        goto gsc_cap_err;
+    }
+    gsc->mdev.gsc_sd_entity = gsc_sd_entity;
+
+    gsc_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
+    if (gsc_sd_entity->fd < 0) {
+        ALOGE("%s: gsc sub-dev open fail", __func__);
+        goto gsc_cap_err;
+    }
+
+    if (exynos_media_setup_link(media1, sink_sd_entity->pads,
+        gsc_sd_entity->pads, MEDIA_LNK_FL_ENABLED) < 0) {
+        ALOGE("%s::exynos_media_setup_link failed", __func__);
+        goto gsc_cap_err;
+    }
+
+    cap = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+    if (exynos_v4l2_querycap(gsc_vd_entity->fd, cap) == false) {
+        ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
+        goto gsc_cap_err;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+
+gsc_cap_err:
+    gsc->m_gsc_cap_destroy(handle);
+
+    return -1;
+}
+
+int CGscaler::m_gsc_out_stop(void *handle)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_requestbuffers reqbuf;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->src_info.stream_on == false) {
+        /* to handle special scenario.*/
+        gsc->src_info.qbuf_cnt = 0;
+        ALOGD("%s::GSC is already stopped", __func__);
+        goto SKIP_STREAMOFF;
+    }
+    gsc->src_info.qbuf_cnt = 0;
+    gsc->src_info.stream_on = false;
+
+    if (exynos_v4l2_streamoff(gsc->mdev.gsc_vd_entity->fd,
+                                V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+        ALOGE("%s::stream off failed", __func__);
+        return -1;
+    }
+
+SKIP_STREAMOFF:
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int CGscaler::m_gsc_cap_stop(void *handle)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->dst_info.stream_on == false) {
+        /* to handle special scenario.*/
+        gsc->dst_info.qbuf_cnt = 0;
+        ALOGD("%s::GSC is already stopped", __func__);
+        goto SKIP_STREAMOFF;
+    }
+    gsc->dst_info.qbuf_cnt = 0;
+    gsc->dst_info.stream_on = false;
+
+    if (exynos_v4l2_streamoff(gsc->mdev.gsc_vd_entity->fd,
+                       V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) < 0) {
+        ALOGE("%s::stream off failed", __func__);
+        return -1;
+    }
+
+SKIP_STREAMOFF:
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+bool CGscaler::m_gsc_out_destroy(void *handle)
+{
+    Exynos_gsc_In();
+
+    int i;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return false;
+    }
+
+    if (gsc->src_info.stream_on == true) {
+        if (gsc->m_gsc_out_stop(gsc) < 0)
+            ALOGE("%s::m_gsc_out_stop() fail", __func__);
+
+            gsc->src_info.stream_on = false;
+    }
+
+    if (gsc->mdev.gsc_vd_entity && gsc->mdev.gsc_vd_entity->fd > 0) {
+        close(gsc->mdev.gsc_vd_entity->fd);
+        gsc->mdev.gsc_vd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.gsc_sd_entity && gsc->mdev.gsc_sd_entity->fd > 0) {
+        close(gsc->mdev.gsc_sd_entity->fd);
+        gsc->mdev.gsc_sd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.sink_sd_entity && gsc->mdev.sink_sd_entity->fd > 0) {
+        close(gsc->mdev.sink_sd_entity->fd);
+        gsc->mdev.sink_sd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.media0)
+        exynos_media_close(gsc->mdev.media0);
+
+    gsc->mdev.media0 = NULL;
+    gsc->mdev.gsc_sd_entity = NULL;
+    gsc->mdev.gsc_vd_entity = NULL;
+    gsc->mdev.sink_sd_entity = NULL;
+
+    Exynos_gsc_Out();
+    return true;
+}
+
+bool CGscaler::m_gsc_cap_destroy(void *handle)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return false;
+    }
+
+    if (gsc->dst_info.stream_on == true) {
+        if (gsc->m_gsc_cap_stop(gsc) < 0)
+            ALOGE("%s::m_gsc_cap_stop() fail", __func__);
+
+            gsc->dst_info.stream_on = false;
+    }
+
+    if (!gsc->mdev.media1 || !gsc->mdev.gsc_sd_entity ||
+        !gsc->mdev.gsc_vd_entity || !gsc->mdev.sink_sd_entity) {
+            ALOGE("%s::gsc->mdev information is null", __func__);
+           return false;
+    }
+
+    if (exynos_media_setup_link(gsc->mdev.media1,
+                gsc->mdev.sink_sd_entity->pads,
+               gsc->mdev.gsc_sd_entity->pads, 0) < 0) {
+                ALOGE("%s::exynos_media_setup_unlin failed", __func__);
+    }
+
+    if (gsc->mdev.gsc_vd_entity && gsc->mdev.gsc_vd_entity->fd > 0) {
+        close(gsc->mdev.gsc_vd_entity->fd);
+        gsc->mdev.gsc_vd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.gsc_sd_entity && gsc->mdev.gsc_sd_entity->fd > 0) {
+        close(gsc->mdev.gsc_sd_entity->fd);
+        gsc->mdev.gsc_sd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.sink_sd_entity && gsc->mdev.sink_sd_entity->fd > 0) {
+        close(gsc->mdev.sink_sd_entity->fd);
+        gsc->mdev.sink_sd_entity->fd = -1;
+    }
+
+    if (gsc->mdev.media1)
+        exynos_media_close(gsc->mdev.media1);
+
+    gsc->mdev.media1 = NULL;
+    gsc->mdev.gsc_sd_entity = NULL;
+    gsc->mdev.gsc_vd_entity = NULL;
+    gsc->mdev.sink_sd_entity = NULL;
+
+    Exynos_gsc_Out();
+    return true;
+}
+
+int CGscaler::m_gsc_m2m_create(int dev)
+{
+    Exynos_gsc_In();
+
+    int          fd = 0;
+    int          video_node_num;
+    unsigned int cap;
+    char         node[32];
+
+    switch(dev) {
+    case 0:
+        video_node_num = NODE_NUM_GSC_0;
+        break;
+    case 1:
+        video_node_num = NODE_NUM_GSC_1;
+        break;
+#ifndef USES_ONLY_GSC0_GSC1
+    case 2:
+        video_node_num = NODE_NUM_GSC_2;
+        break;
+    case 3:
+        video_node_num = NODE_NUM_GSC_3;
+        break;
+#endif
+    default:
+        ALOGE("%s::unexpected dev(%d) fail", __func__, dev);
+        return -1;
+        break;
+    }
+
+    snprintf(node, sizeof(node), "%s%d", PFX_NODE_GSC, video_node_num);
+    fd = exynos_v4l2_open(node, O_RDWR);
+    if (fd < 0) {
+        ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
+        return -1;
+    }
+
+    cap = V4L2_CAP_STREAMING |
+          V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+          V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+    if (exynos_v4l2_querycap(fd, cap) == false) {
+        ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
+        close(fd);
+        fd = 0;
+        return -1;
+    }
+
+    Exynos_gsc_Out();
+
+    return fd;
+}
+
+bool CGscaler::m_gsc_find_and_create(void *handle)
+{
+    Exynos_gsc_In();
+
+    int          i                 = 0;
+    bool         flag_find_new_gsc = false;
+    unsigned int total_sleep_time  = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return false;
+    }
+
+    do {
+        for (i = 0; i < NUM_OF_GSC_HW; i++) {
+#ifndef USES_ONLY_GSC0_GSC1
+            if (i == 0 || i == 3)
+#else
+            if (i == 0)
+#endif
+                continue;
+
+            gsc->gsc_id = i;
+            gsc->gsc_fd = gsc->m_gsc_m2m_create(i);
+            if (gsc->gsc_fd < 0) {
+                gsc->gsc_fd = 0;
+                continue;
+            }
+
+            flag_find_new_gsc = true;
+            break;
+        }
+
+        if (flag_find_new_gsc == false) {
+            usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
+            total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
+            ALOGV("%s::waiting for the gscaler availability", __func__);
+        }
+
+    } while(flag_find_new_gsc == false
+            && total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
+
+    if (flag_find_new_gsc == false)
+        ALOGE("%s::we don't have any available gsc.. fail", __func__);
+
+    Exynos_gsc_Out();
+
+    return flag_find_new_gsc;
+}
+
+bool CGscaler::m_gsc_m2m_destroy(void *handle)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return false;
+    }
+
+    /*
+     * just in case, we call stop here because we cannot afford to leave
+     * secure side protection on if things failed.
+     */
+    gsc->m_gsc_m2m_stop(handle);
+
+    if (gsc->gsc_id >= HW_SCAL0) {
+        bool ret = exynos_sc_free_and_close(gsc->scaler);
+        Exynos_gsc_Out();
+        return ret;
+    }
+
+    if (0 < gsc->gsc_fd)
+        close(gsc->gsc_fd);
+    gsc->gsc_fd = 0;
+
+    Exynos_gsc_Out();
+
+    return true;
+}
+
+int CGscaler::m_gsc_m2m_stop(void *handle)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_requestbuffers req_buf;
+    int ret = 0;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (!gsc->src_info.stream_on && !gsc->dst_info.stream_on) {
+        /* wasn't streaming, return success */
+        return 0;
+    } else if (gsc->src_info.stream_on != gsc->dst_info.stream_on) {
+        ALOGE("%s: invalid state, queue stream state doesn't match \
+                (%d != %d)", __func__, gsc->src_info.stream_on,
+                gsc->dst_info.stream_on);
+        ret = -1;
+    }
+
+    /*
+     * we need to plow forward on errors below to make sure that if we had
+     * turned on content protection on secure side, we turn it off.
+     *
+     * also, if we only failed to turn on one of the streams, we'll turn
+     * the other one off correctly.
+     */
+    if (gsc->src_info.stream_on == true) {
+        if (exynos_v4l2_streamoff(gsc->gsc_fd,
+            gsc->src_info.buf.buf_type) < 0) {
+            ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
+            ret = -1;
+        }
+        gsc->src_info.stream_on = false;
+    }
+
+    if (gsc->dst_info.stream_on == true) {
+        if (exynos_v4l2_streamoff(gsc->gsc_fd,
+            gsc->dst_info.buf.buf_type) < 0) {
+            ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
+            ret = -1;
+        }
+        gsc->dst_info.stream_on = false;
+    }
+
+    /* if drm is enabled */
+    if (gsc->allow_drm && gsc->protection_enabled) {
+        unsigned int protect_id = 0;
+
+        if (gsc->gsc_id == 0)
+            protect_id = CP_PROTECT_GSC0;
+        else if (gsc->gsc_id == 1)
+            protect_id = CP_PROTECT_GSC1;
+        else if (gsc->gsc_id == 2)
+            protect_id = CP_PROTECT_GSC2;
+        else if (gsc->gsc_id == 3)
+            protect_id = CP_PROTECT_GSC3;
+
+        /* CP_Disable_Path_Protection(protect_id); */
+        gsc->protection_enabled = false;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
+                           V4L2_CID_CONTENT_PROTECTION, 0) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
+              __func__);
+        ret = -1;
+    }
+
+    /* src: clear_buf */
+    req_buf.count  = 0;
+    req_buf.type   = gsc->src_info.buf.buf_type;
+    req_buf.memory = gsc->src_info.buf.mem_type;
+    if (exynos_v4l2_reqbufs(gsc->gsc_fd, &req_buf) < 0) {
+        ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
+        ret = -1;
+    }
+
+    /* dst: clear_buf */
+    req_buf.count  = 0;
+    req_buf.type   = gsc->dst_info.buf.buf_type;
+    req_buf.memory = gsc->dst_info.buf.mem_type;;
+    if (exynos_v4l2_reqbufs(gsc->gsc_fd, &req_buf) < 0) {
+        ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
+        ret = -1;
+    }
+
+    Exynos_gsc_Out();
+
+    return ret;
+}
+
+int CGscaler::m_gsc_m2m_run_core(void *handle)
+{
+    Exynos_gsc_In();
+
+    unsigned int rotate, hflip, vflip;
+    bool is_dirty;
+    bool is_drm;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    is_dirty = gsc->src_info.dirty || gsc->dst_info.dirty;
+    is_drm = gsc->src_info.mode_drm;
+
+    if (is_dirty && (gsc->src_info.mode_drm != gsc->dst_info.mode_drm)) {
+        ALOGE("%s: drm mode mismatch between src and dst, \
+                gsc%d (s=%d d=%d)", __func__, gsc->gsc_id,
+                gsc->src_info.mode_drm, gsc->dst_info.mode_drm);
+        return -1;
+    } else if (is_drm && !gsc->allow_drm) {
+        ALOGE("%s: drm mode is not supported on gsc%d", __func__,
+              gsc->gsc_id);
+        return -1;
+    }
+
+    CGscaler::rotateValueHAL2GSC(gsc->dst_img.rot, &rotate, &hflip, &vflip);
+
+    if (CGscaler::m_gsc_check_src_size(&gsc->src_info.width,
+            &gsc->src_info.height, &gsc->src_info.crop_left,
+            &gsc->src_info.crop_top, &gsc->src_info.crop_width,
+            &gsc->src_info.crop_height, gsc->src_info.v4l2_colorformat,
+            (rotate == 90 || rotate == 270)) == false) {
+        ALOGE("%s::m_gsc_check_src_size() fail", __func__);
+        return -1;
+    }
+
+    if (CGscaler::m_gsc_check_dst_size(&gsc->dst_info.width,
+            &gsc->dst_info.height, &gsc->dst_info.crop_left,
+            &gsc->dst_info.crop_top, &gsc->dst_info.crop_width,
+            &gsc->dst_info.crop_height, gsc->dst_info.v4l2_colorformat,
+            gsc->dst_info.rotation) == false) {
+        ALOGE("%s::m_gsc_check_dst_size() fail", __func__);
+        return -1;
+    }
+
+    /* dequeue buffers from previous work if necessary */
+    if (gsc->src_info.stream_on == true) {
+        if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
+            ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__);
+            return -1;
+        }
+    }
+
+    /*
+     * need to set the content protection flag before doing reqbufs
+     * in set_format
+     */
+    if (is_dirty && gsc->allow_drm && is_drm) {
+        if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
+               V4L2_CID_CONTENT_PROTECTION, is_drm) < 0) {
+            ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
+            return -1;
+        }
+    }
+
+    /*
+     * from this point on, we have to ensure to call stop to clean up
+     * whatever state we have set.
+     */
+
+    if (gsc->src_info.dirty) {
+        if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->src_info) == false) {
+            ALOGE("%s::m_gsc_set_format(src) fail", __func__);
+            goto done;
+        }
+        gsc->src_info.dirty = false;
+    }
+
+    if (gsc->dst_info.dirty) {
+        if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->dst_info) == false) {
+            ALOGE("%s::m_gsc_set_format(dst) fail", __func__);
+            goto done;
+        }
+        gsc->dst_info.dirty = false;
+    }
+
+    /*
+     * set up csc equation property
+     */
+    if (is_dirty) {
+        if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
+               V4L2_CID_CSC_EQ_MODE, gsc->eq_auto) < 0) {
+            ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
+            return -1;
+        }
+
+        if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
+               V4L2_CID_CSC_EQ, gsc->v4l2_colorspace) < 0) {
+            ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
+            return -1;
+        }
+
+        if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
+               V4L2_CID_CSC_RANGE, gsc->range_full) < 0) {
+            ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
+            return -1;
+        }
+    }
+
+    /* if we are enabling drm, make sure to enable hw protection.
+     * Need to do this before queuing buffers so that the mmu is reserved
+     * and power domain is kept on.
+     */
+    if (is_dirty && gsc->allow_drm && is_drm) {
+        unsigned int protect_id = 0;
+
+        if (gsc->gsc_id == 0) {
+            protect_id = CP_PROTECT_GSC0;
+        } else if (gsc->gsc_id == 1) {
+            protect_id = CP_PROTECT_GSC1;
+        } else if (gsc->gsc_id == 2) {
+            protect_id = CP_PROTECT_GSC2;
+        } else if (gsc->gsc_id == 3) {
+            protect_id = CP_PROTECT_GSC3;
+        } else {
+            ALOGE("%s::invalid gscaler id %d for content protection",
+            __func__, gsc->gsc_id);
+            goto done;
+        }
+
+        /* if (CP_Enable_Path_Protection(protect_id) != 0) {
+            ALOGE("%s::CP_Enable_Path_Protection failed", __func__);
+            goto done;
+        } */
+        gsc->protection_enabled = true;
+    }
+
+    if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->src_info) == false) {
+        ALOGE("%s::m_gsc_set_addr(src) fail", __func__);
+        goto done;
+    }
+
+    if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->dst_info) == false) {
+        ALOGE("%s::m_gsc_set_addr(dst) fail", __func__);
+        goto done;
+    }
+
+    if (gsc->src_info.stream_on == false) {
+        if (exynos_v4l2_streamon(gsc->gsc_fd, gsc->src_info.buf.buf_type) < 0) {
+            ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
+            goto done;
+        }
+        gsc->src_info.stream_on = true;
+    }
+
+    if (gsc->dst_info.stream_on == false) {
+        if (exynos_v4l2_streamon(gsc->gsc_fd, gsc->dst_info.buf.buf_type) < 0) {
+            ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
+            goto done;
+        }
+        gsc->dst_info.stream_on = true;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+
+done:
+    gsc->m_gsc_m2m_stop(handle);
+    return -1;
+}
+
+bool CGscaler::m_gsc_check_src_size(
+    unsigned int *w,      unsigned int *h,
+    unsigned int *crop_x, unsigned int *crop_y,
+    unsigned int *crop_w, unsigned int *crop_h,
+    int v4l2_colorformat, bool rotation)
+{
+    unsigned int minWidth, minHeight, shift = 0;
+    if (v4l2_colorformat == V4L2_PIX_FMT_RGB32 || v4l2_colorformat == V4L2_PIX_FMT_RGB565)
+        shift = 1;
+    if (rotation) {
+        minWidth = GSC_MIN_SRC_H_SIZE >> shift;
+        minHeight = GSC_MIN_SRC_W_SIZE >> shift;
+    } else {
+        minWidth = GSC_MIN_SRC_W_SIZE >> shift;
+        minHeight = GSC_MIN_SRC_H_SIZE >> shift;
+    }
+
+    if (*w < minWidth || *h < minHeight) {
+        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
+            __func__, GSC_MIN_SRC_W_SIZE, *w, GSC_MIN_SRC_H_SIZE, *h);
+        return false;
+    }
+
+    if (*crop_w < minWidth || *crop_h < minHeight) {
+        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
+            __func__, GSC_MIN_SRC_W_SIZE,* crop_w, GSC_MIN_SRC_H_SIZE, *crop_h);
+        return false;
+    }
+
+    return true;
+}
+
+bool CGscaler::m_gsc_check_dst_size(
+    unsigned int *w,      unsigned int *h,
+    unsigned int *crop_x, unsigned int *crop_y,
+    unsigned int *crop_w, unsigned int *crop_h,
+    int v4l2_colorformat,
+    int rotation)
+{
+    if (*w < GSC_MIN_DST_W_SIZE || *h < GSC_MIN_DST_H_SIZE) {
+        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
+            __func__, GSC_MIN_DST_W_SIZE, *w, GSC_MIN_DST_H_SIZE, *h);
+        return false;
+    }
+
+    if (*crop_w < GSC_MIN_DST_W_SIZE || *crop_h < GSC_MIN_DST_H_SIZE) {
+        ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
+            __func__, GSC_MIN_DST_W_SIZE,* crop_w, GSC_MIN_DST_H_SIZE, *crop_h);
+        return false;
+    }
+
+    return true;
+}
+
+
+int CGscaler::m_gsc_multiple_of_n(int number, int N)
+{
+    int result = number;
+    switch (N) {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+    case 16:
+    case 32:
+    case 64:
+    case 128:
+    case 256:
+        result = (number - (number & (N-1)));
+        break;
+    default:
+        result = number - (number % N);
+        break;
+    }
+    return result;
+}
+
+int CGscaler::m_gsc_m2m_wait_frame_done(void *handle)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if ((gsc->src_info.stream_on == false) ||
+        (gsc->dst_info.stream_on == false)) {
+        ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
+        return -1;
+    }
+
+    if (gsc->src_info.buf.buffer_queued) {
+        if (exynos_v4l2_dqbuf(gsc->gsc_fd, &gsc->src_info.buf.buffer) < 0) {
+            ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
+            return -1;
+        }
+        gsc->src_info.buf.buffer_queued = false;
+    }
+
+    if (gsc->dst_info.buf.buffer_queued) {
+        if (exynos_v4l2_dqbuf(gsc->gsc_fd, &gsc->dst_info.buf.buffer) < 0) {
+            ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
+            return -1;
+        }
+        gsc->dst_info.buf.buffer_queued = false;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+bool CGscaler::m_gsc_set_format(int fd, GscInfo *info)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_requestbuffers req_buf;
+    int                        plane_count;
+
+    plane_count = m_gsc_get_plane_count(info->v4l2_colorformat);
+    if (plane_count < 0) {
+        ALOGE("%s::not supported v4l2_colorformat", __func__);
+        return false;
+    }
+
+    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
+        return false;
+    }
+
+    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_VFLIP, info->flip_horizontal) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__);
+        return false;
+    }
+
+    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_HFLIP, info->flip_vertical) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
+        return false;
+    }
+
+    info->format.type = info->buf.buf_type;
+    info->format.fmt.pix_mp.width       = info->width;
+    info->format.fmt.pix_mp.height      = info->height;
+    info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
+    info->format.fmt.pix_mp.field       = V4L2_FIELD_ANY;
+    info->format.fmt.pix_mp.num_planes  = plane_count;
+
+    if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
+        ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
+        return false;
+    }
+
+    info->crop.type     = info->buf.buf_type;
+    info->crop.c.left   = info->crop_left;
+    info->crop.c.top    = info->crop_top;
+    info->crop.c.width  = info->crop_width;
+    info->crop.c.height = info->crop_height;
+
+    if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
+        ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
+        return false;
+    }
+
+    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
+        return false;
+    }
+
+    req_buf.count  = 1;
+    req_buf.type   = info->buf.buf_type;
+    req_buf.memory = info->buf.mem_type;
+    if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
+        ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
+        return false;
+    }
+
+    Exynos_gsc_Out();
+
+    return true;
+}
+
+unsigned int CGscaler::m_gsc_get_plane_count(int v4l_pixel_format)
+{
+    int plane_count = 0;
+
+    switch (v4l_pixel_format) {
+    case V4L2_PIX_FMT_RGB32:
+    case V4L2_PIX_FMT_BGR32:
+    case V4L2_PIX_FMT_RGB24:
+    case V4L2_PIX_FMT_RGB565:
+    case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_RGB444:
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_UYVY:
+    case V4L2_PIX_FMT_NV16:
+    case V4L2_PIX_FMT_NV61:
+    case V4L2_PIX_FMT_YVU420:
+    case V4L2_PIX_FMT_YUV420:
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV21:
+    case V4L2_PIX_FMT_YUV422P:
+        plane_count = 1;
+        break;
+    case V4L2_PIX_FMT_NV12M:
+    case V4L2_PIX_FMT_NV12MT_16X16:
+    case V4L2_PIX_FMT_NV21M:
+        plane_count = 2;
+        break;
+    case V4L2_PIX_FMT_YVU420M:
+    case V4L2_PIX_FMT_YUV420M:
+        plane_count = 3;
+        break;
+    default:
+        ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
+             __func__, v4l_pixel_format);
+        plane_count = -1;
+        break;
+    }
+
+    return plane_count;
+}
+
+bool CGscaler::m_gsc_set_addr(int fd, GscInfo *info)
+{
+    unsigned int i;
+    unsigned int plane_size[NUM_OF_GSC_PLANES];
+
+    CGscaler::m_gsc_get_plane_size(plane_size, info->width,
+                         info->height, info->v4l2_colorformat);
+
+    info->buf.buffer.index    = 0;
+    info->buf.buffer.flags    = V4L2_BUF_FLAG_USE_SYNC;
+    info->buf.buffer.type     = info->buf.buf_type;
+    info->buf.buffer.memory   = info->buf.mem_type;
+    info->buf.buffer.m.planes = info->buf.planes;
+    info->buf.buffer.length   = info->format.fmt.pix_mp.num_planes;
+    info->buf.buffer.reserved = info->acquireFenceFd;
+
+    for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
+        if (info->buf.buffer.memory == V4L2_MEMORY_DMABUF)
+            info->buf.buffer.m.planes[i].m.fd = (long)info->buf.addr[i];
+        else
+            info->buf.buffer.m.planes[i].m.userptr =
+                (unsigned long)info->buf.addr[i];
+        info->buf.buffer.m.planes[i].length    = plane_size[i];
+        info->buf.buffer.m.planes[i].bytesused = 0;
+    }
+
+    if (exynos_v4l2_qbuf(fd, &info->buf.buffer) < 0) {
+        ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
+        return false;
+    }
+    info->buf.buffer_queued = true;
+
+    info->releaseFenceFd = info->buf.buffer.reserved;
+
+    return true;
+}
+
+unsigned int CGscaler::m_gsc_get_plane_size(
+    unsigned int *plane_size,
+    unsigned int  width,
+    unsigned int  height,
+    int           v4l_pixel_format)
+{
+    switch (v4l_pixel_format) {
+    /* 1 plane */
+    case V4L2_PIX_FMT_RGB32:
+    case V4L2_PIX_FMT_BGR32:
+        plane_size[0] = width * height * 4;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_RGB24:
+        plane_size[0] = width * height * 3;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_RGB565:
+    case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_RGB444:
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_UYVY:
+        plane_size[0] = width * height * 2;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    /* 2 planes */
+    case V4L2_PIX_FMT_NV12M:
+    case V4L2_PIX_FMT_NV21M:
+        plane_size[0] = width * height;
+        plane_size[1] = width * (height / 2);
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV21:
+        plane_size[0] = width * height * 3 / 2;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+       break;
+    case V4L2_PIX_FMT_NV16:
+    case V4L2_PIX_FMT_NV61:
+    case V4L2_PIX_FMT_YUV422P:
+        plane_size[0] = width * height * 2;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_NV12MT_16X16:
+        plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
+        plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
+        plane_size[2] = 0;
+        break;
+    /* 3 planes */
+    case V4L2_PIX_FMT_YUV420M:
+        plane_size[0] = width * height;
+        plane_size[1] = (width / 2) * (height / 2);
+        plane_size[2] = (width / 2) * (height / 2);
+        break;
+    case V4L2_PIX_FMT_YVU420:
+        plane_size[0] = ALIGN(width, 16) * height + ALIGN(width / 2, 16) * height;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_YUV420:
+        plane_size[0] = width * height * 3 / 2;
+        plane_size[1] = 0;
+        plane_size[2] = 0;
+        break;
+    case V4L2_PIX_FMT_YVU420M:
+        plane_size[0] = ALIGN(width, 16) * height;
+        plane_size[1] = ALIGN(width / 2, 16) * (height / 2);
+        plane_size[2] = plane_size[1];
+        break;
+    default:
+        ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
+             __func__, v4l_pixel_format);
+        return -1;
+    }
+
+    return 0;
+}
+
+int CGscaler::m_gsc_m2m_config(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    int32_t      src_color_space;
+    int32_t      dst_color_space;
+    int ret;
+    unsigned int rotate;
+    unsigned int hflip;
+    unsigned int vflip;
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if ((src_img->drmMode && !gsc->allow_drm) ||
+        (src_img->drmMode != dst_img->drmMode)) {
+        ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
+              __func__, gsc->gsc_id, src_img->drmMode, dst_img->drmMode);
+        return -1;
+    }
+
+    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
+    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
+    CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
+    exynos_gsc_set_rotation(gsc, rotate, hflip, vflip);
+
+    ret = exynos_gsc_set_src_format(gsc,  src_img->fw, src_img->fh,
+          src_img->x, src_img->y, src_img->w, src_img->h,
+          src_color_space, src_img->cacheable, src_img->drmMode);
+    if (ret < 0) {
+        ALOGE("%s: fail: exynos_gsc_set_src_format \
+            [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
+            __func__, src_img->fw, src_img->fh, src_img->x, src_img->y,
+            src_img->w, src_img->h, src_color_space, src_img->rot);
+        return -1;
+    }
+
+    ret = exynos_gsc_set_dst_format(gsc, dst_img->fw, dst_img->fh,
+          dst_img->x, dst_img->y, dst_img->w, dst_img->h,
+          dst_color_space, dst_img->cacheable, dst_img->drmMode);
+    if (ret < 0) {
+        ALOGE("%s: fail: exynos_gsc_set_dst_format \
+            [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
+            __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y,
+            dst_img->w, dst_img->h, src_color_space, dst_img->rot);
+        return -1;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int CGscaler::m_gsc_out_config(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_format  fmt;
+    struct v4l2_crop    crop;
+    struct v4l2_requestbuffers reqbuf;
+    struct v4l2_subdev_format sd_fmt;
+    struct v4l2_subdev_crop   sd_crop;
+    int i;
+    unsigned int rotate;
+    unsigned int hflip;
+    unsigned int vflip;
+    unsigned int plane_size[NUM_OF_GSC_PLANES];
+    bool rgb;
+
+    struct v4l2_rect dst_rect;
+    int32_t      src_color_space;
+    int32_t      dst_color_space;
+    int32_t      src_planes;
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if (gsc->src_info.stream_on != false) {
+        ALOGE("Error: Src is already streamed on !!!!");
+        return -1;
+    }
+
+    memcpy(&gsc->src_img, src_img, sizeof(exynos_mpp_img));
+    memcpy(&gsc->dst_img, dst_img, sizeof(exynos_mpp_img));
+    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
+    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
+    src_planes = m_gsc_get_plane_count(src_color_space);
+    src_planes = (src_planes == -1) ? 1 : src_planes;
+    rgb = get_yuv_planes(dst_color_space) == -1;
+    CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
+
+    if (CGscaler::m_gsc_check_src_size(&gsc->src_img.fw,
+            &gsc->src_img.fh, &gsc->src_img.x, &gsc->src_img.y,
+            &gsc->src_img.w, &gsc->src_img.h, src_color_space,
+            (rotate == 90 || rotate == 270)) == false) {
+            ALOGE("%s::m_gsc_check_src_size() fail", __func__);
+            return -1;
+    }
+
+    /*set: src v4l2_buffer*/
+    gsc->src_info.buf.buf_idx = 0;
+    gsc->src_info.qbuf_cnt = 0;
+    /* set format: src pad of GSC sub-dev*/
+    sd_fmt.pad   = GSCALER_SUBDEV_PAD_SOURCE;
+    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    if (gsc->out_mode == GSC_OUT_FIMD) {
+        sd_fmt.format.width  = gsc->dst_img.fw;
+        sd_fmt.format.height = gsc->dst_img.fh;
+    } else {
+        sd_fmt.format.width  = gsc->dst_img.w;
+        sd_fmt.format.height = gsc->dst_img.h;
+    }
+    sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_RGB666_1X18 :
+                               V4L2_MBUS_FMT_YDYUYDYV8_1X16;
+    if (exynos_subdev_s_fmt(gsc->mdev.gsc_sd_entity->fd, &sd_fmt) < 0) {
+            ALOGE("%s::GSC subdev set format failed", __func__);
+            return -1;
+    }
+
+    /* set crop: src crop of GSC sub-dev*/
+    sd_crop.pad   = GSCALER_SUBDEV_PAD_SOURCE;
+    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    if (gsc->out_mode == GSC_OUT_FIMD) {
+        sd_crop.rect.left   = gsc->dst_img.x;
+        sd_crop.rect.top    = gsc->dst_img.y;
+        sd_crop.rect.width  = gsc->dst_img.w;
+        sd_crop.rect.height = gsc->dst_img.h;
+    } else {
+        sd_crop.rect.left   = 0;
+        sd_crop.rect.top    = 0;
+        sd_crop.rect.width  = gsc->dst_img.w;
+        sd_crop.rect.height = gsc->dst_img.h;
+    }
+
+    /* sink pad is connected to GSC out */
+    /*  set format: sink sub-dev */
+    if (gsc->out_mode == GSC_OUT_FIMD) {
+        sd_fmt.pad   = FIMD_SUBDEV_PAD_SINK;
+        sd_fmt.format.width  = gsc->dst_img.w;
+        sd_fmt.format.height = gsc->dst_img.h;
+    } else {
+        sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SINK;
+        sd_fmt.format.width  = gsc->dst_img.w + gsc->dst_img.x*2;
+        sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
+    }
+
+    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_RGB666_1X18 :
+                               V4L2_MBUS_FMT_YDYUYDYV8_1X16;
+    if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
+        ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
+        sd_fmt.pad);
+        return -1;
+    }
+
+    /*  set crop: sink sub-dev */
+    if (gsc->out_mode == GSC_OUT_FIMD)
+        sd_crop.pad   = FIMD_SUBDEV_PAD_SINK;
+    else
+        sd_crop.pad   = MIXER_V_SUBDEV_PAD_SINK;
+
+    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    if (gsc->out_mode == GSC_OUT_FIMD) {
+        sd_crop.rect.left   = gsc->dst_img.x;
+        sd_crop.rect.top    = gsc->dst_img.y;
+        sd_crop.rect.width  = gsc->dst_img.w;
+        sd_crop.rect.height = gsc->dst_img.h;
+    } else {
+        sd_crop.rect.left   = 0;
+        sd_crop.rect.top    = 0;
+        sd_crop.rect.width  = gsc->dst_img.w;
+        sd_crop.rect.height = gsc->dst_img.h;
+    }
+
+    if (gsc->out_mode != GSC_OUT_FIMD) {
+        sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
+        sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+        sd_fmt.format.width = gsc->dst_img.w + gsc->dst_img.x*2;
+        sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
+        sd_fmt.format.code = V4L2_MBUS_FMT_RGB666_1X18;
+        if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
+            ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
+            sd_fmt.pad);
+            return -1;
+        }
+
+        sd_fmt.pad   = MIXER_V_SUBDEV_PAD_SOURCE;
+        sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+        sd_crop.rect.left   = gsc->dst_img.x;
+        sd_crop.rect.top    = gsc->dst_img.y;
+        sd_crop.rect.width  = gsc->dst_img.w;
+        sd_crop.rect.height = gsc->dst_img.h;
+        if (exynos_subdev_s_crop(gsc->mdev.sink_sd_entity->fd, &sd_crop) < 0) {
+            ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__,
+            sd_crop.pad);
+            return -1;
+        }
+    }
+
+    /*set GSC ctrls */
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_ROTATE,
+            rotate) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed",
+            __func__,  rotate);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_HFLIP,
+            vflip) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed",
+            __func__,  vflip);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_VFLIP,
+            hflip) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed",
+            __func__,  hflip);
+        return -1;
+    }
+
+     if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+            V4L2_CID_CACHEABLE, 1) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed",
+            __func__);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+            V4L2_CID_CONTENT_PROTECTION, gsc->src_img.drmMode) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
+            __func__);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+           V4L2_CID_CSC_EQ_MODE, gsc->eq_auto) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+           V4L2_CID_CSC_EQ, gsc->v4l2_colorspace) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
+        return -1;
+    }
+
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+           V4L2_CID_CSC_RANGE, gsc->range_full) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
+        return -1;
+    }
+
+      /* set src format  :GSC video dev*/
+    fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    fmt.fmt.pix_mp.width            = gsc->src_img.fw;
+    fmt.fmt.pix_mp.height           = gsc->src_img.fh;
+    fmt.fmt.pix_mp.pixelformat    = src_color_space;
+    fmt.fmt.pix_mp.field              = V4L2_FIELD_NONE;
+    fmt.fmt.pix_mp.num_planes   = src_planes;
+
+    if (exynos_v4l2_s_fmt(gsc->mdev.gsc_vd_entity->fd, &fmt) < 0) {
+        ALOGE("%s::videodev set format failed", __func__);
+        return -1;
+    }
+
+    /* set src crop info :GSC video dev*/
+    crop.type     = fmt.type;
+    crop.c.left    = gsc->src_img.x;
+    crop.c.top     = gsc->src_img.y;
+    crop.c.width  = gsc->src_img.w;
+    crop.c.height = gsc->src_img.h;
+
+    if (exynos_v4l2_s_crop(gsc->mdev.gsc_vd_entity->fd, &crop) < 0) {
+        ALOGE("%s::videodev set crop failed", __func__);
+        return -1;
+    }
+
+    reqbuf.type   = fmt.type;
+    reqbuf.memory = V4L2_MEMORY_DMABUF;
+    reqbuf.count  = MAX_BUFFERS_GSCALER_OUT;
+
+    if (exynos_v4l2_reqbufs(gsc->mdev.gsc_vd_entity->fd, &reqbuf) < 0) {
+        ALOGE("%s::request buffers failed", __func__);
+        return -1;
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int CGscaler::m_gsc_cap_config(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    struct v4l2_format  fmt;
+    struct v4l2_crop    crop;
+    struct v4l2_requestbuffers reqbuf;
+    struct v4l2_subdev_format sd_fmt;
+    struct v4l2_subdev_crop   sd_crop;
+    int i;
+    unsigned int rotate;
+    unsigned int hflip;
+    unsigned int vflip;
+    unsigned int plane_size[NUM_OF_GSC_PLANES];
+    bool rgb;
+
+    struct v4l2_rect dst_rect;
+    int32_t      src_color_space;
+    int32_t      dst_color_space;
+    int32_t      dst_planes;
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    memcpy(&gsc->src_img, src_img, sizeof(exynos_mpp_img));
+    memcpy(&gsc->dst_img, dst_img, sizeof(exynos_mpp_img));
+    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
+    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
+    dst_planes = m_gsc_get_plane_count(dst_color_space);
+    dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+    rgb = get_yuv_planes(src_color_space) == -1;
+    CGscaler::rotateValueHAL2GSC(src_img->rot, &rotate, &hflip, &vflip);
+
+    if (CGscaler::m_gsc_check_src_size(&gsc->src_img.fw,
+            &gsc->src_img.fh, &gsc->src_img.x, &gsc->src_img.y,
+            &gsc->src_img.w, &gsc->src_img.h, src_color_space,
+            (rotate == 90 || rotate == 270)) == false) {
+            ALOGE("%s::m_gsc_check_src_size() fail", __func__);
+            return -1;
+    }
+
+    /*set GSC ctrls */
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_ROTATE,
+            rotate) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed",
+            __func__,  rotate);
+        return -1;
+    }
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_HFLIP,
+            vflip) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed",
+            __func__,  vflip);
+        return -1;
+    }
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_VFLIP,
+            hflip) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed",
+            __func__,  hflip);
+        return -1;
+    }
+     if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+            V4L2_CID_CACHEABLE, 1) < 0) {
+        ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed",
+            __func__);
+        return -1;
+    }
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+            V4L2_CID_CONTENT_PROTECTION, gsc->src_img.drmMode) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
+            __func__);
+        return -1;
+    }
+    if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
+            V4L2_CID_CSC_RANGE, gsc->range_full)) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail",
+            __func__, gsc->range_full);
+        return -1;
+    }
+      /* set format: source pad of Decon-TV sub-dev*/
+    sd_fmt.pad   = DECON_TV_WB_PAD;
+    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    sd_fmt.format.width  = gsc->src_img.w;
+    sd_fmt.format.height = gsc->src_img.h;
+    sd_fmt.format.code = WB_PATH_FORMAT;
+    if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
+            ALOGE("%s::Decon-TV subdev set format failed", __func__);
+            return -1;
+    }
+
+    if (!gsc->dst_info.stream_on) {
+        /* set src format: GSC video dev*/
+        fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       fmt.fmt.pix_mp.width            = gsc->dst_img.fw;
+       fmt.fmt.pix_mp.height           = gsc->dst_img.fh;
+       fmt.fmt.pix_mp.pixelformat    = dst_color_space;
+       fmt.fmt.pix_mp.field              = V4L2_FIELD_NONE;
+       fmt.fmt.pix_mp.num_planes   = dst_planes;
+
+       if (exynos_v4l2_s_fmt(gsc->mdev.gsc_vd_entity->fd, &fmt) < 0) {
+           ALOGE("%s::videodev set format failed", __func__);
+           return -1;
+       }
+        gsc->dst_info.buf.buf_idx = 0;
+        gsc->dst_info.qbuf_cnt = 0;
+    }
+
+    /* set format: sink pad of GSC sub-dev*/
+       sd_fmt.pad   = GSCALER_SUBDEV_PAD_SINK;
+       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       sd_fmt.format.width  = gsc->src_img.w;
+       sd_fmt.format.height = gsc->src_img.h;
+       sd_fmt.format.code = WB_PATH_FORMAT;
+       if (exynos_subdev_s_fmt(gsc->mdev.gsc_sd_entity->fd, &sd_fmt) < 0) {
+            ALOGE("%s::GSC subdev set format failed", __func__);
+           return -1;
+       }
+
+    /* set src crop info :GSC video dev*/
+    crop.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    crop.c.left    = gsc->dst_img.x;
+    crop.c.top     = gsc->dst_img.y;
+    crop.c.width  = gsc->dst_img.w;
+    crop.c.height = gsc->dst_img.h;
+    if (exynos_v4l2_s_crop(gsc->mdev.gsc_vd_entity->fd, &crop) < 0) {
+        ALOGE("%s::videodev set crop failed", __func__);
+        return -1;
+    }
+
+    /* set crop: src crop of GSC sub-dev*/
+    sd_crop.pad   = GSCALER_SUBDEV_PAD_SINK;
+    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    sd_crop.rect.left   = 0;
+    sd_crop.rect.top    = 0;
+    sd_crop.rect.width  = gsc->src_img.w;
+    sd_crop.rect.height = gsc->src_img.h;
+
+    if (exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop) < 0) {
+        ALOGE("%s::GSC subdev set crop failed(PAD=%d)", __func__,
+        sd_crop.pad);
+        return -1;
+    }
+    reqbuf.type   = fmt.type;
+    reqbuf.memory = V4L2_MEMORY_DMABUF;
+    reqbuf.count  = MAX_BUFFERS_GSCALER_CAP;
+
+    if (!gsc->dst_info.stream_on) {
+        if (exynos_v4l2_reqbufs(gsc->mdev.gsc_vd_entity->fd, &reqbuf) < 0) {
+           ALOGE("%s::request buffers failed", __func__);
+            return -1;
+        }
+    }
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+
+void CGscaler::rotateValueHAL2GSC(unsigned int transform,
+    unsigned int *rotate, unsigned int *hflip, unsigned int *vflip)
+{
+    int rotate_flag = transform & 0x7;
+    *rotate = 0;
+    *hflip = 0;
+    *vflip = 0;
+
+    switch (rotate_flag) {
+    case HAL_TRANSFORM_ROT_90:
+        *rotate = 90;
+        break;
+    case HAL_TRANSFORM_ROT_180:
+        *rotate = 180;
+        break;
+    case HAL_TRANSFORM_ROT_270:
+        *rotate = 270;
+        break;
+    case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
+        *rotate = 90;
+        *vflip = 1; /* set vflip to compensate the rot & flip order. */
+        break;
+    case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
+        *rotate = 90;
+        *hflip = 1; /* set hflip to compensate the rot & flip order. */
+        break;
+    case HAL_TRANSFORM_FLIP_H:
+        *hflip = 1;
+         break;
+    case HAL_TRANSFORM_FLIP_V:
+        *vflip = 1;
+         break;
+    default:
+        break;
+    }
+}
+
+int CGscaler::m_gsc_m2m_run(void *handle,
+    exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    Exynos_gsc_In();
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+    void *addr[3] = {NULL, NULL, NULL};
+    int ret = 0;
+
+    addr[0] = (void *)src_img->yaddr;
+    addr[1] = (void *)src_img->uaddr;
+    addr[2] = (void *)src_img->vaddr;
+    ret = exynos_gsc_set_src_addr(handle, addr, src_img->mem_type,
+            src_img->acquireFenceFd);
+    if (ret < 0) {
+        ALOGE("%s::fail: exynos_gsc_set_src_addr[%p %p %p]", __func__,
+            addr[0], addr[1], addr[2]);
+        return -1;
+    }
+
+    addr[0] = (void *)dst_img->yaddr;
+    addr[1] = (void *)dst_img->uaddr;
+    addr[2] = (void *)dst_img->vaddr;
+    ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->mem_type,
+            dst_img->acquireFenceFd);
+    if (ret < 0) {
+        ALOGE("%s::fail: exynos_gsc_set_dst_addr[%p %p %p]", __func__,
+            addr[0], addr[1], addr[2]);
+        return -1;
+    }
+
+    ret = gsc->m_gsc_m2m_run_core(handle);
+     if (ret < 0) {
+        ALOGE("%s::fail: m_gsc_m2m_run_core", __func__);
+        return -1;
+    }
+
+    if (src_img->acquireFenceFd >= 0) {
+        close(src_img->acquireFenceFd);
+        src_img->acquireFenceFd = -1;
+    }
+
+    if (dst_img->acquireFenceFd >= 0) {
+        close(dst_img->acquireFenceFd);
+        dst_img->acquireFenceFd = -1;
+    }
+
+    src_img->releaseFenceFd = gsc->src_info.releaseFenceFd;
+    dst_img->releaseFenceFd = gsc->dst_info.releaseFenceFd;
+
+    Exynos_gsc_Out();
+
+    return 0;
+}
+
+int CGscaler::m_gsc_out_run(void *handle, exynos_mpp_img *src_img)
+{
+    struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
+    struct v4l2_buffer buf;
+    int32_t      src_color_space;
+    int32_t      src_planes;
+    unsigned int i;
+    unsigned int plane_size[NUM_OF_GSC_PLANES];
+    int ret = 0;
+    unsigned int dq_retry_cnt = 0;
+
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    /* All buffers have been queued, dequeue one */
+    if (gsc->src_info.qbuf_cnt == MAX_BUFFERS_GSCALER_OUT) {
+        memset(&buf, 0, sizeof(struct v4l2_buffer));
+        for (i = 0; i < NUM_OF_GSC_PLANES; i++)
+            memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+        buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+        buf.memory   = V4L2_MEMORY_DMABUF;
+        buf.m.planes = planes;
+
+        src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->src_img.format);
+        src_planes = m_gsc_get_plane_count(src_color_space);
+        src_planes = (src_planes == -1) ? 1 : src_planes;
+        buf.length   = src_planes;
+
+
+        do {
+            ret = exynos_v4l2_dqbuf(gsc->mdev.gsc_vd_entity->fd, &buf);
+            if (ret == -EAGAIN) {
+                ALOGE("%s::Retry DQbuf(index=%d)", __func__, buf.index);
+                usleep(10000);
+                dq_retry_cnt++;
+                continue;
+            }
+            break;
+        } while (dq_retry_cnt <= 10);
+
+        if (ret < 0) {
+            ALOGE("%s::dq buffer failed (index=%d)", __func__, buf.index);
+            return -1;
+        }
+        gsc->src_info.qbuf_cnt--;
+    }
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+    for (i = 0; i < NUM_OF_GSC_PLANES; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->src_img.format);
+    src_planes = m_gsc_get_plane_count(src_color_space);
+    src_planes = (src_planes == -1) ? 1 : src_planes;
+
+    buf.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    buf.memory   = V4L2_MEMORY_DMABUF;
+    buf.flags    = 0;
+    buf.length   = src_planes;
+    buf.index    = gsc->src_info.buf.buf_idx;
+    buf.m.planes = planes;
+    buf.reserved = -1;
+
+    gsc->src_info.buf.addr[0] = (void*)src_img->yaddr;
+    gsc->src_info.buf.addr[1] = (void*)src_img->uaddr;
+    gsc->src_info.buf.addr[2] = (void*)src_img->vaddr;
+
+    if (CGscaler::tmp_get_plane_size(src_color_space, plane_size,
+        gsc->src_img.fw,  gsc->src_img.fh, src_planes) != true) {
+        ALOGE("%s:get_plane_size:fail", __func__);
+        return -1;
+    }
+
+    for (i = 0; i < buf.length; i++) {
+        buf.m.planes[i].m.fd = (long)gsc->src_info.buf.addr[i];
+        buf.m.planes[i].length    = plane_size[i];
+        buf.m.planes[i].bytesused = plane_size[i];
+    }
+
+    /* Queue the buf */
+    if (exynos_v4l2_qbuf(gsc->mdev.gsc_vd_entity->fd, &buf) < 0) {
+        ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)",
+                __func__, gsc->src_info.buf.buf_idx,
+                MAX_BUFFERS_GSCALER_OUT);
+        return -1;
+    }
+    gsc->src_info.buf.buf_idx++;
+    gsc->src_info.buf.buf_idx =
+        gsc->src_info.buf.buf_idx % MAX_BUFFERS_GSCALER_OUT;
+    gsc->src_info.qbuf_cnt++;
+
+    if (gsc->src_info.stream_on == false) {
+        if (exynos_v4l2_streamon(gsc->mdev.gsc_vd_entity->fd,
+            (v4l2_buf_type)buf.type) < 0) {
+            ALOGE("%s::stream on failed", __func__);
+            return -1;
+        }
+        gsc->src_info.stream_on = true;
+    }
+
+    return 0;
+}
+
+int CGscaler::m_gsc_cap_run(void *handle, exynos_mpp_img *dst_img)
+{
+    struct v4l2_plane  planes[NUM_OF_GSC_PLANES];
+    struct v4l2_buffer buf;
+    int32_t      dst_color_space;
+    int32_t      dst_planes;
+    unsigned int i;
+    unsigned int plane_size[NUM_OF_GSC_PLANES];
+    CGscaler* gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    /* All buffers have been queued, dequeue one */
+    if (gsc->dst_info.qbuf_cnt == MAX_BUFFERS_GSCALER_CAP) {
+        memset(&buf, 0, sizeof(struct v4l2_buffer));
+        for (i = 0; i < NUM_OF_GSC_PLANES; i++)
+            memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+        buf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+        buf.memory   = V4L2_MEMORY_DMABUF;
+        buf.m.planes = planes;
+
+        dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->dst_img.format);
+        dst_planes = m_gsc_get_plane_count(dst_color_space);
+        dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+        buf.length   = dst_planes;
+
+
+        if (exynos_v4l2_dqbuf(gsc->mdev.gsc_vd_entity->fd, &buf) < 0) {
+            ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)",
+                    __func__, gsc->src_info.buf.buf_idx,
+                    MAX_BUFFERS_GSCALER_CAP);
+            return -1;
+        }
+        gsc->dst_info.qbuf_cnt--;
+    }
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+    for (i = 0; i < NUM_OF_GSC_PLANES; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->dst_img.format);
+    dst_planes = m_gsc_get_plane_count(dst_color_space);
+    dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+
+    buf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    buf.memory   = V4L2_MEMORY_DMABUF;
+    buf.flags    = V4L2_BUF_FLAG_USE_SYNC;
+    buf.length   = dst_planes;
+    buf.index    = gsc->dst_info.buf.buf_idx;
+    buf.m.planes = planes;
+    buf.reserved = dst_img->acquireFenceFd;
+
+    gsc->dst_info.buf.addr[0] = (void*)dst_img->yaddr;
+    gsc->dst_info.buf.addr[1] = (void*)dst_img->uaddr;
+    gsc->dst_info.buf.addr[2] = (void*)dst_img->vaddr;
+
+    if (CGscaler::tmp_get_plane_size(dst_color_space, plane_size,
+        gsc->dst_img.fw,  gsc->dst_img.fh, dst_planes) != true) {
+        ALOGE("%s:get_plane_size:fail", __func__);
+        return -1;
+    }
+
+    for (i = 0; i < buf.length; i++) {
+        buf.m.planes[i].m.fd = (int)(long)gsc->dst_info.buf.addr[i];
+        buf.m.planes[i].length    = plane_size[i];
+        buf.m.planes[i].bytesused = plane_size[i];
+    }
+
+    /* Queue the buf */
+    if (exynos_v4l2_qbuf(gsc->mdev.gsc_vd_entity->fd, &buf) < 0) {
+        ALOGE("%s::queue buffer failed (index=%d)(mDstBufNum=%d)",
+                __func__, gsc->dst_info.buf.buf_idx,
+                MAX_BUFFERS_GSCALER_CAP);
+        return -1;
+    }
+
+    gsc->dst_info.buf.buf_idx++;
+    gsc->dst_info.buf.buf_idx =
+        gsc->dst_info.buf.buf_idx % MAX_BUFFERS_GSCALER_CAP;
+    gsc->dst_info.qbuf_cnt++;
+
+    if (gsc->dst_info.stream_on == false) {
+        if (exynos_v4l2_streamon(gsc->mdev.gsc_vd_entity->fd,
+            (v4l2_buf_type)buf.type) < 0) {
+            ALOGE("%s::stream on failed", __func__);
+            return -1;
+        }
+        gsc->dst_info.stream_on = true;
+    }
+
+    dst_img->releaseFenceFd = buf.reserved;
+    return 0;
+}
+
+bool CGscaler::tmp_get_plane_size(int V4L2_PIX,
+    unsigned int * size, unsigned int width, unsigned int height, int src_planes)
+{
+    unsigned int frame_ratio = 1;
+    int src_bpp    = get_yuv_bpp(V4L2_PIX);
+    unsigned int frame_size = width * height;
+
+    src_planes = (src_planes == -1) ? 1 : src_planes;
+    frame_ratio = 8 * (src_planes -1) / (src_bpp - 8);
+
+    switch (src_planes) {
+    case 1:
+        switch (V4L2_PIX) {
+        case V4L2_PIX_FMT_BGR32:
+        case V4L2_PIX_FMT_RGB32:
+            size[0] = frame_size << 2;
+            break;
+       case V4L2_PIX_FMT_RGB565:
+        case V4L2_PIX_FMT_NV16:
+        case V4L2_PIX_FMT_NV61:
+        case V4L2_PIX_FMT_YUYV:
+        case V4L2_PIX_FMT_UYVY:
+        case V4L2_PIX_FMT_VYUY:
+        case V4L2_PIX_FMT_YVYU:
+            size[0] = frame_size << 1;
+            break;
+        case V4L2_PIX_FMT_YUV420:
+        case V4L2_PIX_FMT_NV12:
+        case V4L2_PIX_FMT_NV21:
+        case V4L2_PIX_FMT_NV21M:
+            size[0] = (frame_size * 3) >> 1;
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            size[0] = frame_size + (ALIGN((width >> 1), 16) * ((height >> 1) * 2));
+            break;
+        default:
+            ALOGE("%s::invalid color type (%x)", __func__, V4L2_PIX);
+            return false;
+            break;
+        }
+        size[1] = 0;
+        size[2] = 0;
+        break;
+    case 2:
+        size[0] = frame_size;
+        size[1] = frame_size / frame_ratio;
+        size[2] = 0;
+        break;
+    case 3:
+        size[0] = frame_size;
+        size[1] = frame_size / frame_ratio;
+        size[2] = frame_size / frame_ratio;
+        break;
+    default:
+        ALOGE("%s::invalid color foarmt", __func__);
+        return false;
+        break;
+    }
+
+    return true;
+}
+
+int CGscaler::ConfigMpp(void *handle, exynos_mpp_img *src,
+                                       exynos_mpp_img *dst)
+{
+    return exynos_gsc_config_exclusive(handle, src, dst);
+}
+
+int CGscaler::ConfigBlendMpp(void *handle, exynos_mpp_img *src,
+                                           exynos_mpp_img *dst,
+                                           SrcBlendInfo  *srcblendinfo)
+{
+    return exynos_gsc_config_blend_exclusive(handle, src, dst, srcblendinfo);
+}
+
+int CGscaler::RunMpp(void *handle, exynos_mpp_img *src,
+                                       exynos_mpp_img *dst)
+{
+    return exynos_gsc_run_exclusive(handle, src, dst);
+}
+
+int CGscaler::StopMpp(void *handle)
+{
+    return exynos_gsc_stop_exclusive(handle);
+}
+
+void CGscaler::DestroyMpp(void *handle)
+{
+    return exynos_gsc_destroy(handle);
+}
+
+int CGscaler::SetCSCProperty(void *handle, unsigned int eqAuto,
+                  unsigned int fullRange, unsigned int colorspace)
+{
+    return exynos_gsc_set_csc_property(handle, eqAuto, fullRange,
+                                           colorspace);
+}
+
+int CGscaler::FreeMpp(void *handle)
+{
+    return exynos_gsc_free_and_close(handle);
+}
+
+int CGscaler::SetInputCrop(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
+{
+    struct v4l2_crop crop;
+    int ret = 0;
+    CGscaler *gsc = GetGscaler(handle);
+    if (gsc == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    crop.c.left = src_img->x;
+    crop.c.top = src_img->y;
+    crop.c.width = src_img->w;
+    crop.c.height = src_img->h;
+
+    return exynos_v4l2_s_crop(gsc->mdev.gsc_vd_entity->fd, &crop);
+}
diff --git a/libgscaler/libgscaler_obj.h b/libgscaler/libgscaler_obj.h
new file mode 100755 (executable)
index 0000000..e36e397
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef LIBGSCALER_OBJ_H_
+#define LIBGSCALER_OBJ_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/videodev2.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <linux/videodev2_exynos_media.h>
+#include <exynos_gscaler.h>
+
+#include <exynos_format.h>
+#include <exynos_v4l2.h>
+
+#include <exynos_scaler.h>
+#include <exynos_log.h>
+
+#define NUM_OF_GSC_PLANES           (3)
+#define MAX_BUFFERS_GSCALER_OUT     (10)
+#define MAX_BUFFERS_GSCALER_CAP     (1)
+#define GSCALER_SUBDEV_PAD_SINK     (0)
+#define GSCALER_SUBDEV_PAD_SOURCE   (1)
+#define MIXER_V_SUBDEV_PAD_SINK     (0)
+#define MIXER_V_SUBDEV_PAD_SOURCE   (3)
+#define FIMD_SUBDEV_PAD_SINK        (0)
+#define DECON_TV_WB_PAD             (0)
+#define MAX_BUFFERS                 (6)
+
+#define NUM_OF_GSC_HW               (4)
+#define NODE_NUM_GSC_0              (23)
+#define NODE_NUM_GSC_1              (26)
+#define NODE_NUM_GSC_2              (29)
+#define NODE_NUM_GSC_3              (32)
+
+#define PFX_NODE_GSC                "/dev/video"
+#define PFX_NODE_MEDIADEV         "/dev/media"
+#define PFX_MXR_ENTITY              "s5p-mixer%d"
+#define PFX_FIMD_ENTITY             "s3c-fb-window%d"
+#if defined(USES_DT)
+#define PFX_GSC_VIDEODEV_ENTITY0  "13c00000.gsc.output"
+#define PFX_GSC_VIDEODEV_ENTITY1  "13c10000.gsc.output"
+#define PFX_GSC_VIDEODEV_ENTITY2  "13c20000.gsc.output"
+#else
+#define PFX_GSC_VIDEODEV_ENTITY   "exynos-gsc.%d.output"
+#endif
+#define PFX_GSC_CAPTURE_ENTITY   "13c20000.gsc.capture"
+#define PFX_GSC_SUBDEV_ENTITY     "exynos-gsc-sd.%d"
+#define PFX_SUB_DEV            "/dev/v4l-subdev%d"
+#define GSC_WB_SD_NAME         "gsc-wb-sd"
+#define DEX_WB_SD_NAME         "dex-wb-sd"
+#define GSC_VD_PAD_SOURCE      0
+#define GSC_SD_PAD_SINK        0
+#define GSC_SD_PAD_SOURCE      1
+#define GSC_OUT_PAD_SINK       0
+#define WB_PATH_FORMAT         0x100D;
+
+#define GSC_MIN_SRC_W_SIZE (64)
+#define GSC_MIN_SRC_H_SIZE (32)
+#define GSC_MIN_DST_W_SIZE (32)
+#define GSC_MIN_DST_H_SIZE (16)
+
+#define MAX_GSC_WAITING_TIME_FOR_TRYLOCK (16000) // 16msec
+#define GSC_WAITING_TIME_FOR_TRYLOCK      (8000) //  8msec
+
+typedef struct GscalerInfo {
+    unsigned int width;
+    unsigned int height;
+    unsigned int crop_left;
+    unsigned int crop_top;
+    unsigned int crop_width;
+    unsigned int crop_height;
+    unsigned int v4l2_colorformat;
+    unsigned int mode_drm;
+    unsigned int cacheable;
+    int rotation;
+    int flip_horizontal;
+    int flip_vertical;
+    int qbuf_cnt;
+    int acquireFenceFd;
+    int releaseFenceFd;
+    bool stream_on;
+    bool dirty;
+    struct v4l2_format format;
+    struct v4l2_crop crop;
+    struct Buffer_Info {
+        enum v4l2_memory mem_type;
+        enum v4l2_buf_type buf_type;
+        void *addr[NUM_OF_GSC_PLANES];
+        struct v4l2_plane planes[NUM_OF_GSC_PLANES];
+        bool buffer_queued;
+        struct v4l2_buffer buffer;
+        int buf_idx;
+    }buf;
+}GscInfo;
+
+struct MediaDevice {
+    struct media_device *media0;
+    struct media_device *media1;
+    struct media_entity *gsc_sd_entity;
+    struct media_entity *gsc_vd_entity;
+    struct media_entity *sink_sd_entity;
+};
+
+class CGscaler {
+public:
+    GscInfo src_info;
+    GscInfo dst_info;
+    exynos_mpp_img src_img;
+    exynos_mpp_img dst_img;
+    MediaDevice mdev;
+    int out_mode;
+    int gsc_id;
+    bool allow_drm;
+    bool protection_enabled;
+    int gsc_fd;
+    int mode;
+    unsigned int eq_auto;           /* 0: user, 1: auto */
+    unsigned int range_full;        /* 0: narrow, 1: full */
+    unsigned int v4l2_colorspace;   /* 1: 601, 3: 709, see csc.h or videodev2.h */
+    void *scaler;
+
+    void __InitMembers(int __mode, int __out_mode, int __gsc_id,int __allow_drm)
+    {
+        memset(&mdev, 0, sizeof(mdev));
+        scaler = NULL;
+
+        mode = __mode;
+        out_mode = __out_mode;
+        gsc_id = __gsc_id;
+        allow_drm = __allow_drm;
+    }
+
+    CGscaler(int __mode)
+    {
+        memset(&src_info, 0, sizeof(GscInfo));
+        memset(&dst_info, 0, sizeof(GscInfo));
+        memset(&src_img, 0, sizeof(exynos_mpp_img));
+        memset(&dst_img, 0, sizeof(exynos_mpp_img));
+        mode = __mode;
+        protection_enabled = false;
+        gsc_fd = -1;
+        src_info.buf.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+        dst_info.buf.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+        eq_auto = 0;            /* user mode */
+        range_full = 0;         /* narrow */
+        v4l2_colorspace = 1;    /* SMPTE170M (601) */
+        __InitMembers(__mode, 0, 0, 0);
+    }
+    CGscaler(int __mode, int __out_mode, int __gsc_id, int __allow_drm)
+    {
+        memset(&src_info, 0, sizeof(GscInfo));
+        memset(&dst_info, 0, sizeof(GscInfo));
+        memset(&src_img, 0, sizeof(exynos_mpp_img));
+        memset(&dst_img, 0, sizeof(exynos_mpp_img));
+        protection_enabled = false;
+        gsc_fd = -1;
+        src_info.buf.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+        dst_info.buf.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+        eq_auto = 0;            /* user mode */
+        range_full = 0;         /* narrow */
+        v4l2_colorspace = 1;    /* SMPTE170M (601) */
+        __InitMembers(__mode, __out_mode, __gsc_id, __allow_drm);
+    }
+
+    ~CGscaler()
+    {
+        ALOGD("%s", __func__);
+    }
+    virtual int ConfigMpp(void *handle, exynos_mpp_img *src,
+                          exynos_mpp_img *dst);
+     virtual int ConfigBlendMpp(void *handle, exynos_mpp_img *src,
+                                              exynos_mpp_img *dst,
+                                              SrcBlendInfo  *srcblendinfo);
+    virtual int RunMpp(void *handle, exynos_mpp_img *src,
+                          exynos_mpp_img *dst);
+    virtual int StopMpp(void *handle);
+    virtual void DestroyMpp(void *handle);
+    virtual int SetCSCProperty(void *handle, unsigned int eqAuto,
+                  unsigned int fullRange, unsigned int colorspace);
+    virtual int FreeMpp(void *handle);
+    virtual int SetInputCrop(void *handle, exynos_mpp_img *src, exynos_mpp_img *dst);
+    bool m_gsc_find_and_create(void *handle);
+    bool m_gsc_out_destroy(void *handle);
+    bool m_gsc_cap_destroy(void *handle);
+    bool m_gsc_m2m_destroy(void *handle);
+    int m_gsc_m2m_create(int dev);
+    int m_gsc_output_create(void *handle, int dev_num, int out_mode);
+    int m_gsc_capture_create(void *handle, int dev_num, int out_mode);
+    int m_gsc_out_stop(void *handle);
+    int m_gsc_cap_stop(void *handle);
+    int m_gsc_m2m_stop(void *handle);
+    int m_gsc_m2m_run_core(void *handle);
+    int m_gsc_m2m_wait_frame_done(void *handle);
+    int m_gsc_m2m_config(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img);
+    int m_gsc_out_config(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img);
+    int m_gsc_cap_config(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img);
+    int m_gsc_m2m_run(void *handle,
+        exynos_mpp_img *src_img, exynos_mpp_img *dst_img);
+    int m_gsc_out_run(void *handle, exynos_mpp_img *src_img);
+    int m_gsc_cap_run(void *handle, exynos_mpp_img *dst_img);
+    static bool m_gsc_set_format(int fd, GscInfo *info);
+    static unsigned int m_gsc_get_plane_count(int v4l_pixel_format);
+    static bool m_gsc_set_addr(int fd, GscInfo *info);
+    static unsigned int m_gsc_get_plane_size(
+        unsigned int *plane_size, unsigned int width,
+        unsigned int height, int v4l_pixel_format);
+    static bool m_gsc_check_src_size(unsigned int *w, unsigned int *h,
+        unsigned int *crop_x, unsigned int *crop_y,
+        unsigned int *crop_w, unsigned int *crop_h,
+        int v4l2_colorformat, bool rotation);
+    static bool m_gsc_check_dst_size(unsigned int *w, unsigned int *h,
+        unsigned int *crop_x, unsigned int *crop_y,
+        unsigned int *crop_w, unsigned int *crop_h,
+        int v4l2_colorformat, int rotation);
+    static int m_gsc_multiple_of_n(int number, int N);
+    static void rotateValueHAL2GSC(unsigned int transform,
+        unsigned int *rotate, unsigned int *hflip, unsigned int *vflip);
+    static bool tmp_get_plane_size(int V4L2_PIX,
+        unsigned int * size, unsigned int width, unsigned int height, int src_planes);
+};
+
+inline CGscaler *GetGscaler(void* handle)
+{
+    if (handle == NULL) {
+        ALOGE("%s::NULL Scaler handle", __func__);
+        return NULL;
+    }
+
+    CGscaler *gsc = reinterpret_cast<CGscaler *>(handle);
+
+    return gsc;
+}
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libion/Makefile.am b/libion/Makefile.am
new file mode 100755 (executable)
index 0000000..80234e9
--- /dev/null
@@ -0,0 +1,12 @@
+lib_LTLIBRARIES = libion.la
+
+libion_la_SOURCES = ion.c
+libion_la_CFLAGS = -I$(CURDIR)/include \
+                   -I$(CURDIR)/kernel-headers \
+                   -I$(top_srcdir)/include
+libion_la_CFLAGS += -DLOG_TAG=\"LIBION\"
+if USE_DLOG
+libion_la_CFLAGS += $(DLOG_CFLAGS) -DUSE_DLOG
+endif
+
+libion_la_LIBADD = $(DLOG_LIBS)
diff --git a/libion/include/ion/ion.h b/libion/include/ion/ion.h
new file mode 100755 (executable)
index 0000000..6b847e0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  ion.c
+ *
+ * Memory Allocator functions for ion
+ *
+ *   Copyright 2011 Google, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef __SYS_CORE_ION_H
+#define __SYS_CORE_ION_H
+
+#include <sys/types.h>
+#include <linux/ion.h>
+
+__BEGIN_DECLS
+
+struct ion_handle;
+
+int ion_open();
+int ion_close(int fd);
+int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
+              unsigned int flags, ion_user_handle_t *handle);
+int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask,
+              unsigned int flags, int *handle_fd);
+int ion_sync_fd(int fd, int handle_fd);
+int ion_sync_fd_partial(int fd, int handle_fd, off_t offset, size_t len);
+int ion_free(int fd, ion_user_handle_t handle);
+int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
+            int flags, off_t offset, unsigned char **ptr, int *map_fd);
+int ion_share(int fd, ion_user_handle_t handle, int *share_fd);
+int ion_import(int fd, int share_fd, ion_user_handle_t *handle);
+
+__END_DECLS
+
+#endif /* __SYS_CORE_ION_H */
diff --git a/libion/ion.c b/libion/ion.c
new file mode 100755 (executable)
index 0000000..403a585
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  ion.c
+ *
+ * Memory Allocator functions for ion
+ *
+ *   Copyright 2011 Google, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+//#include <cutils/log.h>
+//#define ENABLE_DEBUG_LOG
+#include <exynos_log.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/ion.h>
+#include <ion/ion.h>
+
+int ion_open()
+{
+    int fd = open("/dev/ion", O_RDWR);
+    if (fd < 0)
+        ALOGE("open /dev/ion failed!\n");
+    return fd;
+}
+
+int ion_close(int fd)
+{
+    int ret = close(fd);
+    if (ret < 0)
+        return -errno;
+    return ret;
+}
+
+static int ion_ioctl(int fd, int req, void *arg)
+{
+    int ret = ioctl(fd, req, arg);
+    if (ret < 0) {
+        ALOGE("ioctl %x failed with code %d: %s\n", req,
+              ret, strerror(errno));
+        return -errno;
+    }
+    return ret;
+}
+
+int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
+              unsigned int flags, ion_user_handle_t *handle)
+{
+    int ret;
+    struct ion_allocation_data data = {
+        .len = len,
+        .align = align,
+        .heap_id_mask = heap_mask,
+        .flags = flags,
+    };
+
+    if (handle == NULL)
+        return -EINVAL;
+
+    ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
+    if (ret < 0)
+        return ret;
+    *handle = data.handle;
+    return ret;
+}
+
+int ion_free(int fd, ion_user_handle_t handle)
+{
+    struct ion_handle_data data = {
+        .handle = handle,
+    };
+    return ion_ioctl(fd, ION_IOC_FREE, &data);
+}
+
+int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
+            int flags, off_t offset, unsigned char **ptr, int *map_fd)
+{
+    int ret;
+    unsigned char *tmp_ptr;
+    struct ion_fd_data data = {
+        .handle = handle,
+    };
+
+    if (map_fd == NULL)
+        return -EINVAL;
+    if (ptr == NULL)
+        return -EINVAL;
+
+    ret = ion_ioctl(fd, ION_IOC_MAP, &data);
+    if (ret < 0)
+        return ret;
+    if (data.fd < 0) {
+        ALOGE("map ioctl returned negative fd\n");
+        return -EINVAL;
+    }
+    tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+    if (tmp_ptr == MAP_FAILED) {
+        ALOGE("mmap failed: %s\n", strerror(errno));
+        return -errno;
+    }
+    *map_fd = data.fd;
+    *ptr = tmp_ptr;
+    return ret;
+}
+
+int ion_share(int fd, ion_user_handle_t handle, int *share_fd)
+{
+    int ret;
+    struct ion_fd_data data = {
+        .handle = handle,
+    };
+
+    if (share_fd == NULL)
+        return -EINVAL;
+
+    ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
+    if (ret < 0)
+        return ret;
+    if (data.fd < 0) {
+        ALOGE("share ioctl returned negative fd\n");
+        return -EINVAL;
+    }
+    *share_fd = data.fd;
+    return ret;
+}
+
+int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask,
+                 unsigned int flags, int *handle_fd) {
+    ion_user_handle_t handle;
+    int ret;
+
+    ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
+    if (ret < 0)
+        return ret;
+    ret = ion_share(fd, handle, handle_fd);
+    ion_free(fd, handle);
+    return ret;
+}
+
+int ion_import(int fd, int share_fd, ion_user_handle_t *handle)
+{
+    int ret;
+    struct ion_fd_data data = {
+        .fd = share_fd,
+    };
+
+    if (handle == NULL)
+        return -EINVAL;
+
+    ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
+    if (ret < 0)
+        return ret;
+    *handle = data.handle;
+    return ret;
+}
+
+int ion_sync_fd(int fd, int handle_fd)
+{
+    struct ion_fd_data data = {
+        .fd = handle_fd,
+    };
+    return ion_ioctl(fd, ION_IOC_SYNC, &data);
+}
+
+int ion_sync_fd_partial(int fd, int handle_fd, off_t offset, size_t len)
+{
+    struct ion_fd_partial_data data = {
+        .fd = handle_fd,
+        .offset = offset,
+        .len = len,
+    };
+    return ion_ioctl(fd, ION_IOC_SYNC_PARTIAL, &data);
+}
diff --git a/libion/kernel-headers/linux/ion.h b/libion/kernel-headers/linux/ion.h
new file mode 100755 (executable)
index 0000000..bb145d1
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef int ion_user_handle_t;
+enum ion_heap_type {
+ ION_HEAP_TYPE_SYSTEM,
+ ION_HEAP_TYPE_SYSTEM_CONTIG,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ ION_HEAP_TYPE_CARVEOUT,
+ ION_HEAP_TYPE_CHUNK,
+ ION_HEAP_TYPE_DMA,
+ ION_HEAP_TYPE_CUSTOM,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ ION_NUM_HEAPS = 16,
+};
+#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
+#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
+#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
+#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8
+#define ION_FLAG_CACHED 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
+#define ION_FLAG_PRESERVE_KMAP 4
+#define ION_FLAG_NOZEROED 8
+#define ION_FLAG_PROTECTED 16
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_FLAG_SYNC_FORCE 32
+struct ion_allocation_data {
+ size_t len;
+ size_t align;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned int heap_id_mask;
+ unsigned int flags;
+ ion_user_handle_t handle;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct ion_fd_data {
+ ion_user_handle_t handle;
+ int fd;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct ion_fd_partial_data {
+ ion_user_handle_t handle;
+ int fd;
+ off_t offset;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ size_t len;
+};
+struct ion_handle_data {
+ ion_user_handle_t handle;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+struct ion_custom_data {
+ unsigned int cmd;
+ unsigned long arg;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+struct ion_preload_object {
+ size_t len;
+ unsigned int count;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+struct ion_preload_data {
+ unsigned int heap_id_mask;
+ unsigned int flags;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned int count;
+ struct ion_preload_object *obj;
+};
+#define ION_IOC_MAGIC 'I'
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0,   struct ion_allocation_data)
+#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
+#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
+#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+#define ION_IOC_SYNC_PARTIAL _IOWR(ION_IOC_MAGIC, 9, struct ion_fd_partial_data)
+#define ION_IOC_PRELOAD_ALLOC _IOW(ION_IOC_MAGIC, 8, struct ion_preload_data)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libswconverter/Makefile.am b/libswconverter/Makefile.am
new file mode 100755 (executable)
index 0000000..2a98d0e
--- /dev/null
@@ -0,0 +1,24 @@
+lib_LTLIBRARIES = libswconverter.la
+
+libswconverter_la_SOURCES = swconvertor.c \
+                            csc_BGRA8888_to_RGBA8888_NEON.s \
+                                   csc_BGRA8888_to_YUV420SP_NEON.s \
+                                   csc_RGBA8888_to_YUV420SP_NEON.s \
+                            csc_interleave_memcpy_neon.s \
+                            csc_linear_to_tiled_crop_neon.s \
+                            csc_linear_to_tiled_interleave_crop_neon.s \
+                            csc_tiled_to_linear_crop_neon.s \
+                            csc_tiled_to_linear_deinterleave_crop_neon.s \
+                                   csc_tiled_to_linear_uv_deinterleave_neon.s \
+                                   csc_tiled_to_linear_uv_neon.s \
+                                   csc_tiled_to_linear_y_neon.s
+
+libswconverter_la_CFLAGS = -I$(top_srcdir)/include
+libswconverter_la_CFLAGS += -Wno-unused-variable -Wno-unused-function
+libswconverter_la_CFLAGS += -DLOG_TAG=\"LIBSWCONVERTER\"
+
+libswconverter_la_CCASFLAGS = -march=armv7-a -mfpu=neon-vfpv4
+
+libswconverter_la_LDFLAGS = "-Wl,-z,noexecstack"
+
+libswconverter_la_LIBADD = $(DLOG_LIBS)
diff --git a/libswconverter/csc_BGRA8888_to_RGBA8888_NEON.s b/libswconverter/csc_BGRA8888_to_RGBA8888_NEON.s
new file mode 100755 (executable)
index 0000000..0f4b45b
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *
+ * Copyright 2013 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_BGRA8888_to_RGBA8888.s
+ * @brief   color format converter
+ * @author  Hyungdeok Lee (hd0408.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2013.02.28 : Create
+ */
+
+/*
+ * Source BGRA8888 copy to Dest RGBA8888.
+ * Use neon interleaved load instruction, easly swap R ch to B ch.
+ *
+ * @param dest
+ *   dst address[out]
+ *
+ * @param src
+ *   src address[in]
+ *
+ * @param width
+ *   line width [in]
+ *
+ * @param bpp
+ *   bpp only concerned about 4
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_BGRA8888_RGBA8888_NEON
+    .type   csc_BGRA8888_RGBA8888_NEON, %function
+csc_BGRA8888_RGBA8888_NEON:
+    .fnstart
+
+    @r0     dest
+    @r1     src
+    @r2     width
+    @r3     bpp
+    @r4
+    @r5
+    @r6
+    @r7
+    @r8     temp1
+    @r9     temp2
+    @r10    dest_addr
+    @r11    src_addr
+    @r12    temp_width
+    @r14    i
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+
+    mov         r10, r0
+    mov         r11, r1
+       mov                     r9, r2, lsr #5                  @ r9 = r2 >> 5 (32)
+       and                     r14, r9, #3                             @ r14 = r9 & 3
+       mov                     r12, r2, lsr #7                 @ r12 = r2 >> 7 (128)
+
+    cmp         r12, #0
+    beq         LESS_THAN_128
+
+@ Process d0 to d3 at once. 4 times same operation. := 8 byte * 4 * 4 = 128 byte loop.
+LOOP_128:
+       @pld            [r11]   @ cache line fill. use this for r11 region set by cachable.
+       vld4.8          {d0, d1, d2, d3},       [r11]!
+       vswp            d0, d2
+       vst4.8          {d0, d1, d2, d3},       [r10]!
+
+       vld4.8          {d0, d1, d2, d3},       [r11]!
+       vswp            d0, d2
+       vst4.8          {d0, d1, d2, d3},       [r10]!
+
+       vld4.8          {d0, d1, d2, d3},       [r11]!
+       vswp            d0, d2
+       vst4.8          {d0, d1, d2, d3},       [r10]!
+
+       vld4.8          {d0, d1, d2, d3},       [r11]!
+       vswp            d0, d2
+       vst4.8          {d0, d1, d2, d3},       [r10]!
+
+    subs        r12, #1
+    bne         LOOP_128
+
+LESS_THAN_128:
+       cmp                     r14, #0
+       beq                     END
+
+LOOP_32:
+       vld4.8          {d0, d1, d2, d3},       [r11]!
+       vswp            d0, d2
+       vst4.8          {d0, d1, d2, d3},       [r10]!
+    subs        r14, #1
+    bne         LOOP_32
+
+END:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+    .fnend
diff --git a/libswconverter/csc_BGRA8888_to_YUV420SP_NEON.s b/libswconverter/csc_BGRA8888_to_YUV420SP_NEON.s
new file mode 100755 (executable)
index 0000000..956f553
--- /dev/null
@@ -0,0 +1,365 @@
+
+    .arch armv7-a
+    .text
+    .global csc_BGRA8888_to_YUV420SP_NEON
+    .type   csc_BGRA8888_to_YUV420SP_NEON, %function
+csc_BGRA8888_to_YUV420SP_NEON:
+    .fnstart
+
+    @r0     pDstY
+    @r1     pDstUV
+    @r2     pSrcRGB
+    @r3     nWidth
+    @r4     pDstY2 = pDstY + nWidth
+    @r5     pSrcRGB2 = pSrcRGB + nWidthx2
+    @r6     temp7, nWidth16m
+    @r7     temp6, accumilator
+    @r8     temp5, nWidthTemp
+    @r9     temp4, Raw RGB565
+    @r10    temp3, r,g,b
+    @r11    temp2, immediate operand
+    @r12    temp1, nHeight
+    @r14    temp0, debugging pointer
+
+    .equ CACHE_LINE_SIZE, 32
+    .equ PRE_LOAD_OFFSET, 6
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+    ldr         r12, [sp, #40]           @ load nHeight
+    @ldr         r14, [sp, #44]          @ load pTest
+    add         r4, r0, r3             @r4: pDstY2 = pDstY + nWidth
+    add         r5, r2, r3, lsl #2     @r5: pSrcRGB2 = tmpSrcRGB + nWidthx4
+    sub         r8, r3, #16                @r8: nWidthTmp = nWidth -16
+
+    @q0: temp1, R
+    @q1: temp2, GB
+    @q2: R
+    @q3: G
+    @q4: B
+    @q5: temp3, output
+
+
+    vmov.u16 q6, #66 @coefficient assignment
+    vmov.u16 q7, #129
+    vmov.u16 q8, #25
+    vmov.u16 q9,  #0x8080  @ 128<<8 + 128
+
+    vmov.u16 q10, #0x1000  @ 16<<8 + 128
+    vorr.u16 q10, #0x0080
+
+    vmov.u16 q11, #38 @#-38
+    vmov.u16 q12, #74 @#-74
+    vmov.u16 q13, #112
+    vmov.u16 q14, #94 @#-94
+    vmov.u16 q15, #18 @#-18
+
+
+
+
+LOOP_NHEIGHT2:
+    stmfd       sp!, {r12}       @ backup registers
+
+LOOP_NWIDTH16:
+    pld         [r2, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+   @-------------------------------------------YUV ------------------------------------------
+    vmov.u16 q14, #94 @#94
+    vmov.u16 q15, #18 @#18
+    vld4.8   {d0,d1,d2,d3}, [r2]! @loadRGB interleavely
+    vld4.8   {d4,d5,d6,d7}, [r2]! @loadRGB interleavely
+
+
+    vmov.u16 d8,d2
+    vmov.u16 d9,d6
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d0
+    vmov.u16 d13,d4
+
+    vand.u16 q4,#0x00FF  @R
+    vand.u16 q5,#0x00FF  @G
+    vand.u16 q6,#0x00FF  @B
+
+    vmov.u16 q8,q9   @ CalcU()
+    vmla.u16 q8,q6,q13  @112 * B[k]
+    vmls.u16 q8,q4,q11  @q0:U -(38 * R[k]) @128<<6+ 32 + u>>2
+    vmls.u16 q8,q5,q12  @-(74 * G[k])
+    vshr.u16 q8,q8, #8  @(128<<8+ 128 + u)>>8
+
+    vmov.u16 q7,q9      @CalcV()
+    vmla.u16 q7,q4,q13  @112 * R[k]
+    vmls.u16 q7,q5,q14  @q0:U -(94 * G[k])  @128<<6+ 32 + v>>2
+    vmls.u16 q7,q6,q15  @-(18 * B[k])
+    vshr.u16 q7,q7, #8  @(128<<8+ 128 + v)>>8
+
+
+    vtrn.8 q8,q7
+    vst1.8  {q8}, [r1]!    @write UV component to yuv420_buffer+linear_ylanesiez
+
+    @-------------------------------------------Y ------------------------------------------
+
+    vmov.u16 q14, #66 @#66
+    vmov.u16 q15, #129 @#129
+    vmov.u16 q8, #25 @#25
+
+    @CalcY_Y()
+
+    vmul.u16 q7,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q7,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q7,q6,q8  @q0 += 25 *B[k]
+
+    vadd.u16 q7,q7,q10
+    vshr.u16 q7,q7, #8
+
+    vmov.u16 d8,d2
+    vmov.u16 d9,d6
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d0
+    vmov.u16 d13,d4
+
+    vshr.u16 q4,q4,#8  @R
+    vshr.u16 q5,q5,#8  @G
+    vshr.u16 q6,q6,#8  @B
+
+    vmul.u16 q0,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q0,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q0,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q0,q0,q10
+    vshr.u16 q0,q0, #8
+
+    vtrn.8 q7,q0
+    vst1.8  {q7}, [r0]!@write to Y to yuv420_buffer
+
+
+
+   @-------------------------------------------Y ------------------------------------------
+
+            @---------------------------------------------Y1-------------------------------------------
+
+    pld         [r5, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld4.8   {d0,d1,d2,d3}, [r5]! @loadRGB interleavely
+    vld4.8   {d4,d5,d6,d7}, [r5]! @loadRGB interleavely
+
+    vmov.u16 d8,d2
+    vmov.u16 d9,d6
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d0
+    vmov.u16 d13,d4
+
+
+    vand.u16 q4,#0x00FF  @R
+    vand.u16 q5,#0x00FF  @G
+    vand.u16 q6,#0x00FF  @B
+
+
+
+    vmul.u16 q7,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q7,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q7,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q7,q7,q10
+    vshr.u16 q7,q7, #8
+
+    vmov.u16 d8,d2
+    vmov.u16 d9,d6
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d0
+    vmov.u16 d13,d4
+
+    vshr.u16 q4,q4,#8  @R
+    vshr.u16 q5,q5,#8  @G
+    vshr.u16 q6,q6,#8  @B
+
+    vmul.u16 q0,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q0,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q0,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q0,q0,q10
+    vshr.u16 q0,q0, #8
+
+    vtrn.8 q7,q0
+    vst1.8  {q7}, [r4]!@write to Y to yuv420_buffer
+
+    subs r8,r8,#16                       @nWidth16--
+    BPL LOOP_NWIDTH16                @if nWidth16>0
+    @-----------------------------------unaligned ---------------------------------------
+
+    adds r8,r8,#16 @ + 16 - 2
+    BEQ NO_UNALIGNED  @in case that nWidht is multiple of 16
+LOOP_NWIDTH2:
+    @----------------------------------pDstRGB1--Y------------------------------------------
+    @stmfd sp!, {r14} @backup r14
+
+
+    ldr r9,  [r2], #4 @loadRGB  int
+    ldr r12,  [r2], #4 @loadRGB  int
+
+    mov r10, r9,lsr #16    @copy to r10
+    mov r14, r12    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    add r10,r10,r14
+
+    mov r11, #66 @accumilator += R*66
+    mul r7, r10, r11
+
+    mov r10, r9,lsr #8    @copy to r10
+    mov r14, r12,lsl #8    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @G:
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @G:
+    add r10,r10,r14
+
+    mov r11, #129 @accumilator += G *129
+    mla r7, r10, r11, r7
+
+    mov r10, r9    @copy to r10
+    mov r14, r12,lsl #16    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @B
+    add r10,r10,r14
+
+    mov r11, #25 @accumilator 1 -= B *25
+    mla r7, r10, r11, r7
+
+    ldr r6, =0x10801080
+    add  r7, r6
+
+    lsr r7, #8
+    strb r7, [r0],#1
+    lsr r7,#16
+    strb r7, [r0],#1
+    @ldmfd sp!, {r14} @load r14
+
+
+    @----------------------------------pDstRGB2--UV------------------------------------------
+
+    mov r10, r9    @copy to r10
+    ldr  r7,=0x00008080
+    mov  r12,r7
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B:
+
+    mov r11, #112 @accumilator += B*112
+    mla r7, r10, r11, r7
+
+
+    mov r11, #18 @accumilator -= B*18
+    mul r11, r10, r11
+    sub r12, r12, r11
+
+
+
+
+    mov r10, r9, lsr #16    @copy to r10
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+
+    mov r11, #38 @accumilator -= R *38
+    mul r11, r10, r11
+    sub r7, r7, r11
+
+    mov r11, #112 @accumilator  = R *112
+    mla r12, r10, r11, r12
+
+    mov r10, r9,lsr #8    @copy to r10
+    ldr r6, =0x000000FF
+    and r10, r10, r6  @G: (rgbIn[k] & 0x07E0) >> 5;
+
+    mov r11, #74 @accumilator -= G*74
+    mul r11, r10, r11
+    sub r7, r7, r11
+
+    mov r11, #94 @accumilator -= G*94
+    mul r11, r10, r11
+    sub r12, r12, r11
+
+    lsr r7, #8 @ >>8
+    strb r7, [r1],#1
+    lsr r12, #8 @ >>8
+    strb r12, [r1],#1
+
+    @----------------------------------pDstRGB2--Y------------------------------------------
+    @stmfd sp!, {r14} @backup r14
+
+
+    ldr r9,  [r5], #4 @loadRGB  int
+    ldr r12,  [r5], #4 @loadRGB  int
+
+    mov r10, r9,lsr #16    @copy to r10
+    mov r14, r12    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    add r10,r10,r14
+
+    mov r11, #66 @accumilator += R*66
+    mul r7, r10, r11
+
+    mov r10, r9,lsr #8    @copy to r10
+    mov r14, r12,lsl #8    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @G:
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @G:
+    add r10,r10,r14
+
+    mov r11, #129 @accumilator += G *129
+    mla r7, r10, r11, r7
+
+    mov r10, r9    @copy to r10
+    mov r14, r12,lsl #16    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @B
+    add r10,r10,r14
+
+
+
+
+    mov r11, #25 @accumilator 1 -= B *25
+    mla r7, r10, r11, r7
+
+    ldr r6, =0x10801080
+    add  r7, r6
+    lsr r7, #8
+
+    strb r7, [r4],#1
+    lsr r7,#16
+    strb r7, [r4],#1
+    @ldmfd sp!, {r14} @load r14
+
+
+    subs r8,r8,#2                      @ nWidth2 -= 2
+    BGT LOOP_NWIDTH2                @ if nWidth2>0
+
+
+NO_UNALIGNED: @in case that nWidht is multiple of 16
+
+    @-----------------------------------------------------------------------------
+    sub         r8, r3, #16                @r8: nWidthTmp = nWidth -16
+    add r0, r0,  r3   @pDstY +  nwidth
+    add r2, r2, r3, lsl #2    @pSrcRGB +  nwidthx4
+    add r4, r4,  r3   @pDstY2 +  nwidth
+    add r5, r5, r3, lsl #2   @pSrcRGB2 +  nwidthx4
+
+    ldmfd sp!, {r12}
+    subs r12,r12,#2                       @nHeight -=2
+    BGT LOOP_NHEIGHT2                @if nHeight2>0
+
+    ldmfd       sp!, {r4-r12,pc}       @ backup registers
+    .fnend
diff --git a/libswconverter/csc_RGBA8888_to_YUV420SP_NEON.s b/libswconverter/csc_RGBA8888_to_YUV420SP_NEON.s
new file mode 100755 (executable)
index 0000000..92c2d58
--- /dev/null
@@ -0,0 +1,388 @@
+
+    .arch armv7-a
+    .text
+    .global csc_RGBA8888_to_YUV420SP_NEON
+    .type   csc_RGBA8888_to_YUV420SP_NEON, %function
+csc_RGBA8888_to_YUV420SP_NEON:
+    .fnstart
+
+    @r0     pDstY
+    @r1     pDstUV
+    @r2     pSrcRGB
+    @r3     nWidth
+    @r4     pDstY2 = pDstY + nWidth
+    @r5     pSrcRGB2 = pSrcRGB + nWidthx2
+    @r6     temp7, nWidth16m
+    @r7     temp6, accumilator
+    @r8     temp5, nWidthTemp
+    @r9     temp4, Raw RGB565
+    @r10    temp3, r,g,b
+    @r11    temp2, immediate operand
+    @r12    temp1, nHeight
+    @r14    temp0, debugging pointer
+
+    .equ CACHE_LINE_SIZE, 32
+    .equ PRE_LOAD_OFFSET, 6
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+    ldr         r12, [sp, #40]           @ load nHeight
+    @ldr         r14, [sp, #44]          @ load pTest
+    add         r4, r0, r3             @r4: pDstY2 = pDstY + nWidth
+    add         r5, r2, r3, lsl #2     @r5: pSrcRGB2 = tmpSrcRGB + nWidthx4
+    sub         r8, r3, #16                @r8: nWidthTmp = nWidth -16
+
+    @q0: temp1, R
+    @q1: temp2, GB
+    @q2: R
+    @q3: G
+    @q4: B
+    @q5: temp3, output
+
+
+    vmov.u16 q6, #66 @coefficient assignment
+    vmov.u16 q7, #129
+    vmov.u16 q8, #25
+    vmov.u16 q9,  #0x8080  @ 128<<8 + 128
+
+    vmov.u16 q10, #0x1000  @ 16<<8 + 128
+    vorr.u16 q10, #0x0080
+
+    vmov.u16 q11, #38 @#-38
+    vmov.u16 q12, #74 @#-74
+    vmov.u16 q13, #112
+    vmov.u16 q14, #94 @#-94
+    vmov.u16 q15, #18 @#-18
+
+
+
+
+LOOP_NHEIGHT2:
+    stmfd       sp!, {r12}       @ backup registers
+
+LOOP_NWIDTH16:
+    pld         [r2, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+   @-------------------------------------------YUV ------------------------------------------
+    vmov.u16 q14, #94 @#94
+    vmov.u16 q15, #18 @#18
+    vld4.8   {d0,d1,d2,d3}, [r2]! @loadRGB interleavely
+    vld4.8   {d4,d5,d6,d7}, [r2]! @loadRGB interleavely
+
+
+    @vmov.u16 d8,d2
+    @vmov.u16 d9,d6
+    @vmov.u16 d10,d1
+    @vmov.u16 d11,d5
+    @vmov.u16 d12,d0
+    @vmov.u16 d13,d4
+    vmov.u16 d8,d0
+    vmov.u16 d9,d4
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d2
+    vmov.u16 d13,d6
+
+    vand.u16 q4,#0x00FF  @R
+    vand.u16 q5,#0x00FF  @G
+    vand.u16 q6,#0x00FF  @B
+
+    vmov.u16 q8,q9   @ CalcU()
+    vmla.u16 q8,q6,q13  @112 * B[k]
+    vmls.u16 q8,q4,q11  @q0:U -(38 * R[k]) @128<<6+ 32 + u>>2
+    vmls.u16 q8,q5,q12  @-(74 * G[k])
+    vshr.u16 q8,q8, #8  @(128<<8+ 128 + u)>>8
+
+    vmov.u16 q7,q9      @CalcV()
+    vmla.u16 q7,q4,q13  @112 * R[k]
+    vmls.u16 q7,q5,q14  @q0:U -(94 * G[k])  @128<<6+ 32 + v>>2
+    vmls.u16 q7,q6,q15  @-(18 * B[k])
+    vshr.u16 q7,q7, #8  @(128<<8+ 128 + v)>>8
+
+
+    vtrn.8 q8,q7
+    vst1.8  {q8}, [r1]!    @write UV component to yuv420_buffer+linear_ylanesiez
+
+    @-------------------------------------------Y ------------------------------------------
+
+    vmov.u16 q14, #66 @#66
+    vmov.u16 q15, #129 @#129
+    vmov.u16 q8, #25 @#25
+
+    @CalcY_Y()
+
+    vmul.u16 q7,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q7,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q7,q6,q8  @q0 += 25 *B[k]
+
+    vadd.u16 q7,q7,q10
+    vshr.u16 q7,q7, #8
+
+    @vmov.u16 d8,d2
+    @vmov.u16 d9,d6
+    @vmov.u16 d10,d1
+    @vmov.u16 d11,d5
+    @vmov.u16 d12,d0
+    @vmov.u16 d13,d4
+    vmov.u16 d8,d0
+    vmov.u16 d9,d4
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d2
+    vmov.u16 d13,d6
+
+    vshr.u16 q4,q4,#8  @R
+    vshr.u16 q5,q5,#8  @G
+    vshr.u16 q6,q6,#8  @B
+
+    vmul.u16 q0,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q0,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q0,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q0,q0,q10
+    vshr.u16 q0,q0, #8
+
+    vtrn.8 q7,q0
+    vst1.8  {q7}, [r0]!@write to Y to yuv420_buffer
+
+
+
+   @-------------------------------------------Y ------------------------------------------
+
+            @---------------------------------------------Y1-------------------------------------------
+
+    pld         [r5, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld4.8   {d0,d1,d2,d3}, [r5]! @loadRGB interleavely
+    vld4.8   {d4,d5,d6,d7}, [r5]! @loadRGB interleavely
+
+    @vmov.u16 d8,d2
+    @vmov.u16 d9,d6
+    @vmov.u16 d10,d1
+    @vmov.u16 d11,d5
+    @vmov.u16 d12,d0
+    @vmov.u16 d13,d4
+    vmov.u16 d8,d0
+    vmov.u16 d9,d4
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d2
+    vmov.u16 d13,d6
+
+    vand.u16 q4,#0x00FF  @R
+    vand.u16 q5,#0x00FF  @G
+    vand.u16 q6,#0x00FF  @B
+
+
+
+    vmul.u16 q7,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q7,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q7,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q7,q7,q10
+    vshr.u16 q7,q7, #8
+
+    @vmov.u16 d8,d2
+    @vmov.u16 d9,d6
+    @vmov.u16 d10,d1
+    @vmov.u16 d11,d5
+    @vmov.u16 d12,d0
+    @vmov.u16 d13,d4
+    vmov.u16 d8,d0
+    vmov.u16 d9,d4
+    vmov.u16 d10,d1
+    vmov.u16 d11,d5
+    vmov.u16 d12,d2
+    vmov.u16 d13,d6
+
+    vshr.u16 q4,q4,#8  @R
+    vshr.u16 q5,q5,#8  @G
+    vshr.u16 q6,q6,#8  @B
+
+    vmul.u16 q0,q4,q14  @q0 = 66 *R[k]
+    vmla.u16 q0,q5,q15  @q0 += 129 *G[k]
+    vmla.u16 q0,q6,q8  @q0 += 25 *B[k]
+    vadd.u16 q0,q0,q10
+    vshr.u16 q0,q0, #8
+
+    vtrn.8 q7,q0
+    vst1.8  {q7}, [r4]!@write to Y to yuv420_buffer
+
+    subs r8,r8,#16                       @nWidth16--
+    BPL LOOP_NWIDTH16                @if nWidth16>0
+    @-----------------------------------unaligned ---------------------------------------
+
+    adds r8,r8,#16 @ + 16 - 2
+    BEQ NO_UNALIGNED  @in case that nWidht is multiple of 16
+LOOP_NWIDTH2:
+    @----------------------------------pDstRGB1--Y------------------------------------------
+    @stmfd sp!, {r14} @backup r14
+
+
+    ldr r9,  [r2], #4 @loadRGB  int
+    ldr r12,  [r2], #4 @loadRGB  int
+
+    mov r10, r9,lsr #16    @copy to r10
+    mov r14, r12    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    add r10,r10,r14
+
+    mov r11, #66 @accumilator += R*66
+    mul r7, r10, r11
+
+    mov r10, r9,lsr #8    @copy to r10
+    mov r14, r12,lsl #8    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @G:
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @G:
+    add r10,r10,r14
+
+    mov r11, #129 @accumilator += G *129
+    mla r7, r10, r11, r7
+
+    mov r10, r9    @copy to r10
+    mov r14, r12,lsl #16    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @B
+    add r10,r10,r14
+
+    mov r11, #25 @accumilator 1 -= B *25
+    mla r7, r10, r11, r7
+
+    ldr r6, =0x10801080
+    add  r7, r6
+
+    lsr r7, #8
+    strb r7, [r0],#1
+    lsr r7,#16
+    strb r7, [r0],#1
+    @ldmfd sp!, {r14} @load r14
+
+
+    @----------------------------------pDstRGB2--UV------------------------------------------
+
+    mov r10, r9    @copy to r10
+    ldr  r7,=0x00008080
+    mov  r12,r7
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B:
+
+    mov r11, #112 @accumilator += B*112
+    mla r7, r10, r11, r7
+
+
+    mov r11, #18 @accumilator -= B*18
+    mul r11, r10, r11
+    sub r12, r12, r11
+
+
+
+
+    mov r10, r9, lsr #16    @copy to r10
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+
+    mov r11, #38 @accumilator -= R *38
+    mul r11, r10, r11
+    sub r7, r7, r11
+
+    mov r11, #112 @accumilator  = R *112
+    mla r12, r10, r11, r12
+
+    mov r10, r9,lsr #8    @copy to r10
+    ldr r6, =0x000000FF
+    and r10, r10, r6  @G: (rgbIn[k] & 0x07E0) >> 5;
+
+    mov r11, #74 @accumilator -= G*74
+    mul r11, r10, r11
+    sub r7, r7, r11
+
+    mov r11, #94 @accumilator -= G*94
+    mul r11, r10, r11
+    sub r12, r12, r11
+
+    lsr r7, #8 @ >>8
+    strb r7, [r1],#1
+    lsr r12, #8 @ >>8
+    strb r12, [r1],#1
+
+    @----------------------------------pDstRGB2--Y------------------------------------------
+    @stmfd sp!, {r14} @backup r14
+
+
+    ldr r9,  [r5], #4 @loadRGB  int
+    ldr r12,  [r5], #4 @loadRGB  int
+
+    mov r10, r9,lsr #16    @copy to r10
+    mov r14, r12    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @R: (rgbIn[k] & 0xF800) >> 10;
+    add r10,r10,r14
+
+    mov r11, #66 @accumilator += R*66
+    mul r7, r10, r11
+
+    mov r10, r9,lsr #8    @copy to r10
+    mov r14, r12,lsl #8    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @G:
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @G:
+    add r10,r10,r14
+
+    mov r11, #129 @accumilator += G *129
+    mla r7, r10, r11, r7
+
+    mov r10, r9    @copy to r10
+    mov r14, r12,lsl #16    @copy to r10
+
+    ldr r6, =0x000000FF
+    and r10, r10, r6 @B
+    ldr r6, =0x00FF0000
+    and r14, r14, r6 @B
+    add r10,r10,r14
+
+
+
+
+    mov r11, #25 @accumilator 1 -= B *25
+    mla r7, r10, r11, r7
+
+    ldr r6, =0x10801080
+    add  r7, r6
+    lsr r7, #8
+
+    strb r7, [r4],#1
+    lsr r7,#16
+    strb r7, [r4],#1
+    @ldmfd sp!, {r14} @load r14
+
+
+    subs r8,r8,#2                      @ nWidth2 -= 2
+    BGT LOOP_NWIDTH2                @ if nWidth2>0
+
+
+NO_UNALIGNED: @in case that nWidht is multiple of 16
+
+    @-----------------------------------------------------------------------------
+    sub         r8, r3, #16                @r8: nWidthTmp = nWidth -16
+    add r0, r0,  r3   @pDstY +  nwidth
+    add r2, r2, r3, lsl #2    @pSrcRGB +  nwidthx4
+    add r4, r4,  r3   @pDstY2 +  nwidth
+    add r5, r5, r3, lsl #2   @pSrcRGB2 +  nwidthx4
+
+    ldmfd sp!, {r12}
+    subs r12,r12,#2                       @nHeight -=2
+    BGT LOOP_NHEIGHT2                @if nHeight2>0
+
+    ldmfd       sp!, {r4-r12,pc}       @ backup registers
+    .fnend
diff --git a/libswconverter/csc_interleave_memcpy_neon.s b/libswconverter/csc_interleave_memcpy_neon.s
new file mode 100755 (executable)
index 0000000..1ab25b6
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_linear_to_tiled_crop_neon.s
+ * @brief   SEC_OMX specific define
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Interleave src1, src2 to dst
+ *
+ * @param dest
+ *   dst address[out]
+ *
+ * @param src1
+ *   src1 address[in]
+ *
+ * @param src2
+ *   src2 address[in]
+ *
+ * @param src_size
+ *   src_size or src1
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_interleave_memcpy_neon
+    .type   csc_interleave_memcpy_neon, %function
+csc_interleave_memcpy_neon:
+    .fnstart
+
+    @r0     dest
+    @r1     src1
+    @r2     src2
+    @r3     src_size
+    @r4
+    @r5
+    @r6
+    @r7
+    @r8     temp1
+    @r9     temp2
+    @r10    dest_addr
+    @r11    src1_addr
+    @r12    src2_addr
+    @r14    i
+
+    stmfd       sp!, {r8-r12,r14}       @ backup registers
+
+    mov         r10, r0
+    mov         r11, r1
+    mov         r12, r2
+    mov         r14, r3
+
+    cmp         r14, #128
+    blt         LESS_THAN_128
+
+LOOP_128:
+    vld1.8      {q0}, [r11]!
+    vld1.8      {q2}, [r11]!
+    vld1.8      {q4}, [r11]!
+    vld1.8      {q6}, [r11]!
+    vld1.8      {q8}, [r11]!
+    vld1.8      {q10}, [r11]!
+    vld1.8      {q12}, [r11]!
+    vld1.8      {q14}, [r11]!
+    vld1.8      {q1}, [r12]!
+    vld1.8      {q3}, [r12]!
+    vld1.8      {q5}, [r12]!
+    vld1.8      {q7}, [r12]!
+    vld1.8      {q9}, [r12]!
+    vld1.8      {q11}, [r12]!
+    vld1.8      {q13}, [r12]!
+    vld1.8      {q15}, [r12]!
+
+    vst2.8      {q0, q1}, [r10]!
+    vst2.8      {q2, q3}, [r10]!
+    vst2.8      {q4, q5}, [r10]!
+    vst2.8      {q6, q7}, [r10]!
+    vst2.8      {q8, q9}, [r10]!
+    vst2.8      {q10, q11}, [r10]!
+    vst2.8      {q12, q13}, [r10]!
+    vst2.8      {q14, q15}, [r10]!
+
+    sub         r14, #128
+    cmp         r14, #128
+    bgt         LOOP_128
+
+LESS_THAN_128:
+    cmp         r14, #0
+    beq         RESTORE_REG
+
+LOOP_1:
+    ldrb        r8, [r11], #1
+    ldrb        r9, [r12], #1
+    strb        r8, [r10], #1
+    strb        r9, [r10], #1
+    subs        r14, #1
+    bne         LOOP_1
+
+RESTORE_REG:
+    ldmfd       sp!, {r8-r12,r15}       @ restore registers
+    .fnend
diff --git a/libswconverter/csc_linear_to_tiled_crop_neon.s b/libswconverter/csc_linear_to_tiled_crop_neon.s
new file mode 100755 (executable)
index 0000000..8f59826
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_linear_to_tiled_crop_neon.s
+ * @brief   SEC_OMX specific define
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts linear data to tiled
+ * Crops left, top, right, buttom
+ * 1. Y of YUV420P to Y of NV12T
+ * 2. Y of YUV420S to Y of NV12T
+ * 3. UV of YUV420S to UV of NV12T
+ *
+ * @param nv12t_dest
+ *   Y or UV plane address of NV12T[out]
+ *
+ * @param yuv420_src
+ *   Y or UV plane address of YUV420P(S)[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left. It should be even.
+ *
+ * @param top
+ *   Crop size of top. It should be even.
+ *
+ * @param right
+ *   Crop size of right. It should be even.
+ *
+ * @param buttom
+ *   Crop size of buttom. It should be even.
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_linear_to_tiled_crop_neon
+    .type   csc_linear_to_tiled_crop_neon, %function
+csc_linear_to_tiled_crop_neon:
+    .fnstart
+
+    @r0     tiled_dest
+    @r1     linear_src
+    @r2     yuv420_width
+    @r3     yuv420_height
+    @r4     j
+    @r5     i
+    @r6     nn(tiled_addr)
+    @r7     mm(linear_addr)
+    @r8     aligned_x_size
+    @r9     aligned_y_size
+    @r10    temp1
+    @r11    temp2
+    @r12    temp3
+    @r14    temp4
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+
+    ldr         r11, [sp, #44]           @ top
+    ldr         r14, [sp, #52]           @ buttom
+    ldr         r10, [sp, #40]           @ left
+    ldr         r12, [sp, #48]           @ right
+
+    sub         r9, r3, r11             @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5
+    sub         r9, r9, r14
+    bic         r9, r9, #0x1F
+
+    sub         r8, r2, r10             @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6
+    sub         r8, r8, r12
+    bic         r8, r8, #0x3F
+
+    mov         r5, #0                  @ i = 0
+LOOP_ALIGNED_Y_SIZE:
+
+    mov         r4, #0                  @ j = 0
+LOOP_ALIGNED_X_SIZE:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r10, [sp, #44]          @ r10 = top
+    ldr         r14, [sp, #40]          @ r14 = left
+    add         r10, r5, r10            @ temp1 = linear_x_size*(i+top)
+    mul         r10, r2, r10
+    add         r7, r1, r4              @ linear_addr = linear_src+j
+    add         r7, r7, r10             @ linear_addr = linear_addr+temp1
+    add         r7, r7, r14             @ linear_addr = linear_addr+left
+    sub         r10, r2, #32
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*1, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*2, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*3, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    add         r6, r0, r6              @ tiled_addr = tiled_dest+tiled_addr
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*1}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*2}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*3}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*4, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*5, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*6, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*7, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*4}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*5}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*6}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*7}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*8, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*9, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*10, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*11, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*8}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*9}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*10}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*11}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*12, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*13, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*14, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*15, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*12}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*13}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*14}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*15}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*16, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*17, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*18, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*19, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*16}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*17}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*18}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*19}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*20, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*21, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*22, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*23, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*20}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*21}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*22}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*23}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*24, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*25, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*26, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*27, 64}
+    pld         [r7, r2]
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*24}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*25}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*26}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*27}
+    vst1.8      {q14, q15}, [r6]!
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src+linear_x_size*28, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*29, 64}
+    pld         [r7, r2]
+    vld1.8      {q6, q7}, [r7], r10
+    pld         [r7, r2]
+    vld1.8      {q8, q9}, [r7]!         @ load {linear_src+linear_x_size*30, 64}
+    pld         [r7, r2]
+    vld1.8      {q10, q11}, [r7], r10
+    vld1.8      {q12, q13}, [r7]!       @ load {linear_src+linear_x_size*31, 64}
+    vld1.8      {q14, q15}, [r7], r10
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr+64*28}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*29}
+    vst1.8      {q6, q7}, [r6]!
+    vst1.8      {q8, q9}, [r6]!         @ store {tiled_addr+64*30}
+    vst1.8      {q10, q11}, [r6]!
+    vst1.8      {q12, q13}, [r6]!       @ store {tiled_addr+64*31}
+    vst1.8      {q14, q15}, [r6]!
+
+    add         r4, r4, #64             @ j = j+64
+    cmp         r4, r8                  @ j<aligned_x_size
+    blt         LOOP_ALIGNED_X_SIZE
+
+    add         r5, r5, #32             @ i = i+32
+    cmp         r5, r9                  @ i<aligned_y_size
+    blt         LOOP_ALIGNED_Y_SIZE
+
+    ldr         r10, [sp, #44]          @ r10 = top
+    ldr         r11, [sp, #52]          @ r11 = buttom
+    sub         r10, r3, r10
+    sub         r10, r10, r11
+    cmp         r5, r10                 @ i == (yuv420_height-top-buttom)
+    beq         LOOP_LINEAR_Y_SIZE_2_START
+
+LOOP_LINEAR_Y_SIZE_1:
+
+    mov         r4, #0                  @ j = 0
+LOOP_ALIGNED_X_SIZE_1:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r10, [sp, #44]          @ r10 = top
+    ldr         r14, [sp, #40]          @ r14 = left
+    add         r10, r5, r10            @ temp1 = yuv420_width*(i+top)
+    mul         r10, r2, r10
+    add         r7, r1, r4              @ linear_addr = linear_src+j
+    add         r7, r7, r10             @ linear_addr = linear_addr+temp1
+    add         r7, r7, r14             @ linear_addr = linear_addr+left
+    sub         r10, r2, #32            @ temp1 = yuv420_width-32
+
+    pld         [r7, r2]
+    vld1.8      {q0, q1}, [r7]!         @ load {linear_src, 64}
+    pld         [r7, r2]
+    vld1.8      {q2, q3}, [r7], r10
+    vld1.8      {q4, q5}, [r7]!         @ load {linear_src+linear_x_size*1, 64}
+    vld1.8      {q6, q7}, [r7]
+    add         r6, r0, r6              @ tiled_addr = tiled_dest+tiled_addr
+    and         r10, r5, #0x1F          @ temp1 = i&0x1F
+    mov         r10, r10, lsl #6        @ temp1 = 64*temp1
+    add         r6, r6, r10             @ tiled_addr = tiled_addr+temp1
+    vst1.8      {q0, q1}, [r6]!         @ store {tiled_addr}
+    vst1.8      {q2, q3}, [r6]!
+    vst1.8      {q4, q5}, [r6]!         @ store {tiled_addr+64*1}
+    vst1.8      {q6, q7}, [r6]!
+
+    add         r4, r4, #64             @ j = j+64
+    cmp         r4, r8                  @ j<aligned_x_size
+    blt         LOOP_ALIGNED_X_SIZE_1
+
+    add         r5, r5, #2              @ i = i+2
+    ldr         r10, [sp, #44]          @ r10 = top
+    ldr         r14, [sp, #52]          @ r14 = buttom
+    sub         r10, r3, r10
+    sub         r10, r10, r14
+    cmp         r5, r10                 @ i<yuv420_height-top-buttom
+    blt         LOOP_LINEAR_Y_SIZE_1
+
+LOOP_LINEAR_Y_SIZE_2_START:
+    ldr         r10, [sp, #40]          @ r10 = left
+    ldr         r11, [sp, #48]          @ r11 = right
+    sub         r10, r2, r10
+    sub         r10, r10, r11
+    cmp         r8, r10                 @ aligned_x_size == (yuv420_width-left-right)
+    beq         RESTORE_REG
+
+    mov         r5, #0                  @ i = 0
+LOOP_LINEAR_Y_SIZE_2:
+
+    mov         r4, r8                  @ j = aligned_x_size
+LOOP_LINEAR_X_SIZE_2:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r10, [sp, #44]          @ r14 = top
+    ldr         r14, [sp, #40]          @ r10 = left
+    add         r10, r5, r10
+    mul         r10, r2, r10            @ temp1 = linear_x_size*(i+top)
+    add         r7, r1, r4              @ linear_addr = linear_src+j
+    add         r7, r7, r10             @ linear_addr = linear_addr+temp1
+    add         r7, r7, r14             @ linear_addr = linear_addr+left
+
+    add         r6, r0, r6              @ tiled_addr = tiled_dest+tiled_addr
+    and         r11, r5, #0x1F          @ temp2 = i&0x1F
+    mov         r11, r11, lsl #6        @ temp2 = 64*temp2
+    add         r6, r6, r11             @ tiled_addr = tiled_addr+temp2
+    and         r11, r4, #0x3F          @ temp2 = j&0x3F
+    add         r6, r6, r11             @ tiled_addr = tiled_addr+temp2
+
+    ldrh        r10, [r7], r2
+    ldrh        r11, [r7]
+    strh        r10, [r6], #64
+    strh        r11, [r6]
+
+    ldr         r12, [sp, #40]          @ r12 = left
+    ldr         r14, [sp, #48]          @ r14 = right
+    add         r4, r4, #2              @ j = j+2
+    sub         r12, r2, r12
+    sub         r12, r12, r14
+    cmp         r4, r12                 @ j<(yuv420_width-left-right)
+    blt         LOOP_LINEAR_X_SIZE_2
+
+    ldr         r12, [sp, #44]          @ r12 = top
+    ldr         r14, [sp, #52]          @ r14 = buttom
+    add         r5, r5, #2              @ i = i+2
+    sub         r12, r3, r12
+    sub         r12, r12, r14
+    cmp         r5, r12                 @ i<(yuv420_height-top-buttom)
+    blt         LOOP_LINEAR_Y_SIZE_2
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+GET_TILED_OFFSET:
+
+    mov         r11, r5, asr #5         @ temp2 = i>>5
+    mov         r10, r4, asr #6         @ temp1 = j>>6
+
+    and         r12, r11, #0x1          @ if (temp2 & 0x1)
+    cmp         r12, #0x1
+    bne         GET_TILED_OFFSET_EVEN_FORMULA_1
+
+GET_TILED_OFFSET_ODD_FORMULA:
+    sub         r6, r11, #1             @ tiled_addr = temp2-1
+
+    ldr         r7, [sp, #40]          @ left
+    add         r12, r2, #127           @ temp3 = linear_x_size+127
+    sub         r12, r12, r7
+    ldr         r7, [sp, #48]          @ right
+    sub         r12, r12, r7
+    bic         r12, r12, #0x7F         @ temp3 = (temp3 >>7)<<7
+    mov         r12, r12, asr #6        @ temp3 = temp3>>6
+    mul         r6, r6, r12             @ tiled_addr = tiled_addr*temp3
+    add         r6, r6, r10             @ tiled_addr = tiled_addr+temp1
+    add         r6, r6, #2              @ tiled_addr = tiled_addr+2
+    bic         r12, r10, #0x3          @ temp3 = (temp1>>2)<<2
+    add         r6, r6, r12             @ tiled_addr = tiled_addr+temp3
+    mov         r6, r6, lsl #11         @ tiled_addr = tiled_addr<<11
+    b           GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_1:
+    ldr         r7, [sp, #44]          @ top
+    add         r12, r3, #31            @ temp3 = linear_y_size+31
+    sub         r12, r12, r7
+    ldr         r7, [sp, #52]          @ buttom
+    sub         r12, r12, r7
+    bic         r12, r12, #0x1F         @ temp3 = (temp3>>5)<<5
+    sub         r12, r12, #32           @ temp3 = temp3 - 32
+    cmp         r5, r12                 @ if (i<(temp3-32)) {
+    bge         GET_TILED_OFFSET_EVEN_FORMULA_2
+    add         r12, r10, #2            @ temp3 = temp1+2
+    bic         r12, r12, #3            @ temp3 = (temp3>>2)<<2
+    add         r6, r10, r12            @ tiled_addr = temp1+temp3
+    ldr         r7, [sp, #40]          @ left
+    add         r12, r2, #127           @ temp3 = linear_x_size+127
+    sub         r12, r12, r7
+    ldr         r7, [sp, #48]          @ right
+    sub         r12, r12, r7
+    bic         r12, r12, #0x7F         @ temp3 = (temp3>>7)<<7
+    mov         r12, r12, asr #6        @ temp3 = temp3>>6
+    mul         r11, r11, r12           @ tiled_y_index = tiled_y_index*temp3
+    add         r6, r6, r11             @ tiled_addr = tiled_addr+tiled_y_index
+    mov         r6, r6, lsl #11         @
+    b           GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_2:
+    ldr         r7, [sp, #40]          @ left
+    add         r12, r2, #127           @ temp3 = linear_x_size+127
+    sub         r12, r12, r7
+    ldr         r7, [sp, #48]          @ right
+    sub         r12, r12, r7
+    bic         r12, r12, #0x7F         @ temp3 = (temp3>>7)<<7
+    mov         r12, r12, asr #6        @ temp3 = temp3>>6
+    mul         r6, r11, r12            @ tiled_addr = temp2*temp3
+    add         r6, r6, r10             @ tiled_addr = tiled_addr+temp3
+    mov         r6, r6, lsl #11         @ tiled_addr = tiled_addr<<11@
+
+GET_TILED_OFFSET_RETURN:
+    mov         pc, lr
+
+    .fnend
diff --git a/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s b/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s
new file mode 100755 (executable)
index 0000000..33a31da
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_linear_to_tiled_interleave_crop_neon.s
+ * @brief   SEC_OMX specific define
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ * 3. UV of NV12T to UV of YUV420S
+ *
+ * @param yuv420_dest
+ *   Y or UV plane address of YUV420[out]
+ *
+ * @param nv12t_src
+ *   Y or UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left. It should be even.
+ *
+ * @param top
+ *   Crop size of top. It should be even.
+ *
+ * @param right
+ *   Crop size of right. It should be even.
+ *
+ * @param buttom
+ *   Crop size of buttom. It should be even.
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_linear_to_tiled_interleave_crop_neon
+    .type   csc_linear_to_tiled_interleave_crop_neon, %function
+csc_linear_to_tiled_interleave_crop_neon:
+    .fnstart
+
+    @r0     tiled_dest
+    @r1     linear_src_u
+    @r2     linear_src_v
+    @r3     yuv420_width
+    @r4     yuv420_height
+    @r5     j
+    @r6     i
+    @r7     tiled_addr
+    @r8     linear_addr
+    @r9     aligned_x_size
+    @r10    aligned_y_size
+    @r11    temp1
+    @r12    temp2
+    @r14    temp3
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+
+    ldr         r4, [sp, #40]           @ load linear_y_size to r4
+
+    ldr         r10, [sp, #48]          @ r10 = top
+    ldr         r14, [sp, #56]          @ r14 = buttom
+    ldr         r11, [sp, #44]          @ r11 = left
+    ldr         r12, [sp, #52]          @ r12 = right
+
+    sub         r10, r4, r10            @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5
+    sub         r10, r10, r14
+    bic         r10, r10, #0x1F
+    sub         r11, r3, r11            @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6
+    sub         r11, r11, r12
+    bic         r9, r11, #0x3F
+
+    mov         r6, #0                  @ i = 0
+LOOP_ALIGNED_Y_SIZE:
+
+    mov         r5, #0                  @ j = 0
+LOOP_ALIGNED_X_SIZE:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r12, [sp, #48]          @ r12 = top
+    ldr         r8, [sp, #44]           @ r8 = left
+
+    mov         r11, r3, asr #1         @ temp1 = (yuv420_width/2)*(i+top)
+    add         r12, r6, r12
+    mul         r11, r11, r12
+    add         r11, r11, r5, asr #1    @ temp1 = temp1+j/2
+    add         r11, r11, r8, asr #1    @ temp1 = temp1+left/2
+
+    mov         r12, r3, asr #1         @ temp2 = yuv420_width/2
+    sub         r12, r12, #16           @ temp2 = yuv420_width-16
+
+    add         r8, r1, r11             @ linear_addr = linear_src_u+temp1
+    add         r11, r2, r11            @ temp1 = linear_src_v+temp1
+    add         r7, r0, r7              @ tiled_addr = tiled_dest+tiled_addr
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*1, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*2, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*3, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*1, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*2, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*3, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*1}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*2}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*3}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*4, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*5, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*6, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*7, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*4, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*5, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*6, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*7, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*4}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*5}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*6}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*7}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*8, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*9, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*10, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*11, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*8, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*9, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*10, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*11, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*8}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*9}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*10}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*11}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*12, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*13, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*14, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*15, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*12, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*13, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*14, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*15, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*12}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*13}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*14}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*15}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*16, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*17, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*18, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*19, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*16, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*17, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*18, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*19, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*16}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*17}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*18}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*19}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*20, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*21, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*22, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*23, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*20, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*21, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*22, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*23, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*20}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*21}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*22}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*23}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*24, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*25, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*26, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*27, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*24, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*25, 32}
+    vld1.8      {q7}, [r11], r12
+    pld         [r8]
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*26, 32}
+    vld1.8      {q11}, [r11], r12
+    pld         [r8, r3, asr #1]
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*27, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*24}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*25}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*26}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*27}
+    vst2.8      {q14, q15}, [r7]!
+
+    pld         [r8, r3]
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*28, 32}
+    vld1.8      {q2}, [r8], r12
+    pld         [r8, r3]
+    vld1.8      {q4}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*29, 32}
+    vld1.8      {q6}, [r8], r12
+    pld         [r11]
+    vld1.8      {q8}, [r8]!             @ load {linear_src_u+(linear_x_size/2)*30, 32}
+    vld1.8      {q10}, [r8], r12
+    pld         [r11, r3, asr #1]
+    vld1.8      {q12}, [r8]!            @ load {linear_src_u+(linear_x_size/2)*31, 32}
+    vld1.8      {q14}, [r8], r12
+    pld         [r11, r3]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*28, 32}
+    vld1.8      {q3}, [r11], r12
+    pld         [r11, r3]
+    vld1.8      {q5}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*29, 32}
+    vld1.8      {q7}, [r11], r12
+    vld1.8      {q9}, [r11]!            @ load {linear_src_v+(linear_x_size/2)*30, 32}
+    vld1.8      {q11}, [r11], r12
+    vld1.8      {q13}, [r11]!           @ load {linear_src_v+(linear_x_size/2)*31, 32}
+    vld1.8      {q15}, [r11], r12
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr+64*28}
+    vst2.8      {q2, q3}, [r7]!
+    vst2.8      {q4, q5}, [r7]!         @ store {tiled_addr+64*29}
+    vst2.8      {q6, q7}, [r7]!
+    vst2.8      {q8, q9}, [r7]!         @ store {tiled_addr+64*30}
+    vst2.8      {q10, q11}, [r7]!
+    vst2.8      {q12, q13}, [r7]!       @ store {tiled_addr+64*31}
+    vst2.8      {q14, q15}, [r7]!
+
+    add         r5, r5, #64             @ j = j+64
+    cmp         r5, r9                  @ j<aligned_x_size
+    blt         LOOP_ALIGNED_X_SIZE
+
+    add         r6, r6, #32             @ i = i+32
+    cmp         r6, r10                 @ i<aligned_y_size
+    blt         LOOP_ALIGNED_Y_SIZE
+
+    cmp         r6, r4
+    beq         LOOP_LINEAR_Y_SIZE_2_START
+
+LOOP_LINEAR_Y_SIZE_1:
+
+    mov         r5, #0                  @ j = 0
+LOOP_ALIGNED_X_SIZE_1:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r12, [sp, #48]          @ r12 = top
+    ldr         r8, [sp, #44]           @ r8 = left
+
+    mov         r11, r3, asr #1         @ temp1 = (yuv420_width/2)*(i+top)
+    add         r12, r6, r12
+    mul         r11, r11, r12
+    add         r11, r11, r5, asr #1    @ temp1 = temp1+j/2
+    add         r11, r11, r8, asr #1    @ temp1 = temp1+left/2
+
+    add         r8, r1, r11             @ linear_addr = linear_src_u+temp1
+    add         r11, r2, r11            @ temp1 = linear_src_v+temp1
+    add         r7, r0, r7              @ tiled_addr = tiled_dest+tiled_addr
+    and         r14, r6, #0x1F          @ temp3 = i&0x1F@
+    mov         r14, r14, lsl #6        @ temp3 = temp3*64
+    add         r7, r7, r14             @ tiled_addr = tiled_addr+temp3
+
+    vld1.8      {q0}, [r8]!             @ load {linear_src_u, 32}
+    vld1.8      {q2}, [r8]
+    vld1.8      {q1}, [r11]!            @ load {linear_src_v, 32}
+    vld1.8      {q3}, [r11]
+    vst2.8      {q0, q1}, [r7]!         @ store {tiled_addr}
+    vst2.8      {q2, q3}, [r7]!
+
+    add         r5, r5, #64             @ j = j+64
+    cmp         r5, r9                  @ j<aligned_x_size
+    blt         LOOP_ALIGNED_X_SIZE_1
+
+    ldr         r12, [sp, #48]          @ r12 = top
+    ldr         r8, [sp, #56]           @ r8 = buttom
+    add         r6, r6, #1              @ i = i+1
+    sub         r12, r4, r12
+    sub         r12, r12, r8
+    cmp         r6, r12                 @ i<(yuv420_height-top-buttom)
+    blt         LOOP_LINEAR_Y_SIZE_1
+
+LOOP_LINEAR_Y_SIZE_2_START:
+    cmp         r5, r3
+    beq         RESTORE_REG
+
+    mov         r6, #0                  @ i = 0
+LOOP_LINEAR_Y_SIZE_2:
+
+    mov         r5, r9                  @ j = aligned_x_size
+LOOP_LINEAR_X_SIZE_2:
+
+    bl          GET_TILED_OFFSET
+
+    ldr         r12, [sp, #48]          @ r12 = top
+    ldr         r8, [sp, #44]           @ r8 = left
+
+    mov         r11, r3, asr #1         @ temp1 = (yuv420_width/2)*(i+top)
+    add         r12, r6, r12
+    mul         r11, r11, r12
+    add         r11, r11, r5, asr #1    @ temp1 = temp1+j/2
+    add         r11, r11, r8, asr #1    @ temp1 = temp1+left/2
+
+    mov         r12, r3, asr #1         @ temp2 = linear_x_size/2
+    sub         r12, r12, #1            @ temp2 = linear_x_size-1
+
+    add         r8, r1, r11             @ linear_addr = linear_src_u+temp1
+    add         r11, r2, r11            @ temp1 = linear_src_v+temp1
+    add         r7, r0, r7              @ tiled_addr = tiled_dest+tiled_addr
+    and         r14, r6, #0x1F          @ temp3 = i&0x1F@
+    mov         r14, r14, lsl #6        @ temp3 = temp3*64
+    add         r7, r7, r14             @ tiled_addr = tiled_addr+temp3
+    and         r14, r5, #0x3F          @ temp3 = j&0x3F
+    add         r7, r7, r14             @ tiled_addr = tiled_addr+temp3
+
+    ldrb        r10, [r8], #1
+    ldrb        r14, [r11], #1
+    mov         r14, r14, lsl #8
+    orr         r10, r10, r14
+    strh        r10, [r7], #2
+
+    ldr         r12, [sp, #44]          @ r12 = left
+    ldr         r8, [sp, #52]           @ r8 = right
+    add         r5, r5, #2              @ j = j+2
+    sub         r12, r3, r12
+    sub         r12, r12, r8
+    cmp         r5, r12                 @ j<(yuv420_width-left-right)
+    blt         LOOP_LINEAR_X_SIZE_2
+
+    ldr         r12, [sp, #48]          @ r12 = top
+    ldr         r8, [sp, #56]           @ r8 = buttom
+    add         r6, r6, #1              @ i = i+1
+    sub         r12, r4, r12
+    sub         r12, r12, r8
+    cmp         r6, r12                 @ i<(yuv420_height-top-buttom)
+    blt         LOOP_LINEAR_Y_SIZE_2
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+GET_TILED_OFFSET:
+    stmfd       sp!, {r14}
+
+    mov         r12, r6, asr #5         @ temp2 = i>>5
+    mov         r11, r5, asr #6         @ temp1 = j>>6
+
+    and         r14, r12, #0x1          @ if (temp2 & 0x1)
+    cmp         r14, #0x1
+    bne         GET_TILED_OFFSET_EVEN_FORMULA_1
+
+GET_TILED_OFFSET_ODD_FORMULA:
+
+    ldr         r7, [sp, #48]           @ r7 = left , (r14 was pushed to stack)
+    ldr         r8, [sp, #56]           @ r8 = right , (r14 was pushed to stack)
+    sub         r14, r3, r7
+    sub         r14, r14, r8
+    add         r14, r14, #127          @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7
+    bic         r14, r14, #0x7F         @ temp3 = (temp3 >>7)<<7
+    mov         r14, r14, asr #6        @ temp3 = temp3>>6
+    sub         r7, r12, #1             @ tiled_addr = temp2-1
+    mul         r7, r7, r14             @ tiled_addr = tiled_addr*temp3
+    add         r7, r7, r11             @ tiled_addr = tiled_addr+temp1
+    add         r7, r7, #2              @ tiled_addr = tiled_addr+2
+    bic         r14, r11, #0x3          @ temp3 = (temp1>>2)<<2
+    add         r7, r7, r14             @ tiled_addr = tiled_addr+temp3
+    mov         r7, r7, lsl #11         @ tiled_addr = tiled_addr<<11
+    b           GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_1:
+    ldr         r7, [sp, #52]           @ r7 = top, (r14 was pushed to stack)
+    ldr         r8, [sp, #60]           @ r8 = buttom, (r14 was pushed to stack)
+    sub         r14, r4, r7
+    sub         r14, r14, r8
+    add         r14, r14, #31           @ temp3 = (((yuv420_height-top-buttom)+31)>>5)<<5
+    bic         r14, r14, #0x1F         @ temp3 = (temp3>>5)<<5
+    sub         r14, r14, #32           @ temp3 = temp3 - 32
+    cmp         r6, r14                 @ if (i<(temp3-32)) {
+    bge         GET_TILED_OFFSET_EVEN_FORMULA_2
+    add         r14, r11, #2            @ temp3 = temp1+2
+    bic         r14, r14, #3            @ temp3 = (temp3>>2)<<2
+    add         r7, r11, r14            @ tiled_addr = temp1+temp3
+    ldr         r8, [sp, #48]           @ r8 = left, (r14 was pushed to stack)
+    sub         r14, r3, r8
+    ldr         r8, [sp, #56]           @ r8 = right, (r14 was pushed to stack)
+    sub         r14, r14, r8
+    add         r14, r14, #127          @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7
+    bic         r14, r14, #0x7F         @ temp3 = (temp3>>7)<<7
+    mov         r14, r14, asr #6        @ temp3 = temp3>>6
+    mul         r12, r12, r14           @ tiled_y_index = tiled_y_index*temp3
+    add         r7, r7, r12             @ tiled_addr = tiled_addr+tiled_y_index
+    mov         r7, r7, lsl #11         @
+    b           GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_2:
+    ldr         r8, [sp, #48]           @ r8 = left, (r14 was pushed to stack)
+    sub         r14, r3, r8
+    ldr         r8, [sp, #56]           @ r8 = right, (r14 was pushed to stack)
+    sub         r14, r14, r8
+    add         r14, r14, #127          @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7
+    bic         r14, r14, #0x7F         @ temp3 = (temp3>>7)<<7
+    mov         r14, r14, asr #6        @ temp3 = temp3>>6
+    mul         r7, r12, r14            @ tiled_addr = temp2*temp3
+    add         r7, r7, r11             @ tiled_addr = tiled_addr+temp3
+    mov         r7, r7, lsl #11         @ tiled_addr = tiled_addr<<11@
+
+GET_TILED_OFFSET_RETURN:
+    ldmfd       sp!, {r15}              @ restore registers
+
+    .fnend
+
diff --git a/libswconverter/csc_tiled_to_linear_crop_neon.s b/libswconverter/csc_tiled_to_linear_crop_neon.s
new file mode 100755 (executable)
index 0000000..9cb81b5
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_tiled_to_linear_crop_neon.s
+ * @brief   SEC_OMX specific define
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ * 3. UV of NV12T to UV of YUV420S
+ *
+ * @param yuv420_dest
+ *   Y or UV plane address of YUV420[out]
+ *
+ * @param nv12t_src
+ *   Y or UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left. It should be even.
+ *
+ * @param top
+ *   Crop size of top. It should be even.
+ *
+ * @param right
+ *   Crop size of right. It should be even.
+ *
+ * @param buttom
+ *   Crop size of buttom. It should be even.
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_tiled_to_linear_crop_neon
+    .type   csc_tiled_to_linear_crop_neon, %function
+csc_tiled_to_linear_crop_neon:
+    .fnstart
+
+    @r0     yuv420_dest
+    @r1     nv12t_src
+    @r2     yuv420_width
+    @r3     yuv420_height
+       @r4
+    @r5     i
+    @r6     j
+    @r7     tiled_offset
+    @r8     tiled_offset1
+    @r9     linear_offset
+    @r10    temp1
+    @r11    temp2
+    @r12    temp3
+    @r14    temp4
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+
+    ldr         r12, [sp, #48]          @ r12 = right
+    ldr         r10, [sp, #40]          @ r10 = left
+    sub         r12, r2, r12            @ temp3 = yuv420_width-right@
+    sub         r10, r12, r10           @ temp1 = temp3-left@
+    cmp         r10, #256               @ if (temp1 >= 256)
+    blt         LOOP_HEIGHT_64_START
+
+    ldr         r5, [sp, #44]           @ i = top
+LOOP_HEIGHT_256:
+    ldr         r6, [sp, #40]           @ j = left
+    mov         r14, r5, asr #5         @ temp4 = i>>5
+    bic         r12, r6, #0xFF          @ temp3 = (j>>8)<<8
+    mov         r12, r12, asr #6        @ temp3 = temp3>>6
+    and         r11, r14, #0x1          @ if (temp4 & 0x1)
+    cmp         r11, #0x1
+    bne         LOOP_HEIGHT_256_GET_TILED_EVEN
+LOOP_HEIGHT_256_GET_TILED_ODD:
+    sub         r7, r14, #1             @ tiled_offset = temp4-1
+    add         r10, r2, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = tiled_offset*(temp1>>6)
+    mul         r7, r7, r10
+    add         r7, r7, r12             @ tiled_offset = tiled_offset+temp3
+    add         r7, r7, #2              @ tiled_offset = tiled_offset+2
+    bic         r10, r12, #0x3          @ temp1 = (temp3>>2)<<2
+    add         r7, r7, r10             @ tiled_offset = tiled_offset+temp1
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #4096           @ tiled_offset1 = tiled_offset+2048*2
+    mov         r14, #8
+    b           LOOP_HEIGHT_256_GET_TILED_END
+
+LOOP_HEIGHT_256_GET_TILED_EVEN:
+    add         r11, r3, #31            @ temp2 = ((yuv420_height+31)>>5)<<5
+    bic         r11, r11, #0x1F
+    add         r10, r5, #32            @ if ((i+32)<temp2)
+    cmp         r10, r11
+    bge         LOOP_HEIGHT_256_GET_TILED_EVEN1
+    add         r10, r12, #2            @ temp1 = temp3+2
+    bic         r10, r10, #0x3          @ temp1 = (temp1>>2)<<2
+    add         r7, r12, r10            @ tiled_offset = temp3+temp1@
+    add         r10, r2, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = tiled_offset+temp4*(temp1>>6)
+    mla         r7, r14, r10, r7
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #12288          @ tiled_offset1 = tiled_offset+2048*6
+    mov         r14, #8
+    b           LOOP_HEIGHT_256_GET_TILED_END
+
+LOOP_HEIGHT_256_GET_TILED_EVEN1:
+    add         r10, r2, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = temp4*(temp1>>6)
+    mul         r7, r14, r10
+    add         r7, r7, r12             @ tiled_offset = tiled_offset+temp3
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #4096           @ tiled_offset1 = tiled_offset+2048*2
+    mov         r14, #4
+
+LOOP_HEIGHT_256_GET_TILED_END:
+
+    ldr         r12, [sp, #48]          @ right
+    ldr         r9, [sp, #44]           @ top
+    and         r10, r5, #0x1F          @ temp1 = i&0x1F
+    add         r7, r7, r10, lsl #6     @ tiled_offset = tiled_offset+64*(temp1)
+    add         r8, r8, r10, lsl #6     @ tiled_offset1 = tiled_offset1+64*(temp1)
+    sub         r11, r2, r6             @ temp2 = yuv420_width-left(==j)-right
+    sub         r11, r11, r12
+    sub         r9, r5, r9              @ linear_offset = temp2*(i-top)@
+    mul         r9, r11, r9
+    add         r12, r6, #256           @ temp3 = ((j+256)>>8)<<8@
+    bic         r12, r12, #0xFF
+    sub         r12, r12, r6            @ temp3 = temp3-j@
+    and         r10, r6, #0x3F          @ temp1 = left(==j)&0x3F
+
+    cmp         r12, #192               @ if (temp3 > 192)
+    ble         LOOP_HEIGHT_256_LEFT_192
+    add         r11, r1, r7             @ r11 = nv12t_src+tiled_offset+temp1
+    add         r11, r11, r10
+    pld         [r11]
+    add         r12, r1, r7             @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r11, #32]
+    add         r12, r12, #2048
+    pld         [r12]
+    cmp         r10, #0
+    pld         [r12, #32]
+    stmnefd     sp!, {r9-r12, r14}      @ backup registers
+    rsbne       r10, r10, #64
+    blne        MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r9-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_256_64
+    vld1.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+temp1, 64}
+    vld1.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r11]!        @ store {yuv420_dest+linear_offset, 64}
+    vst1.8      {q2, q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_256_64:
+    add         r11, r1, r8             @ r11 = nv12t_src+tiled_offset1
+    pld         [r11]
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r11, #32]
+    vld1.8      {q6, q7}, [r12]
+    add         r12, r11, #2048         @ r12 = nv12t_src+tiled_offset1+2048
+    pld         [r12]
+    vld1.8      {q8, q9}, [r11]!        @ load {nv12t_src+tiled_offset1, 64}
+    pld         [r12, #32]
+    vld1.8      {q10, q11}, [r11]
+    vld1.8      {q12, q13}, [r12]!      @ load {nv12t_src+tiled_offset1+2048, 64}
+    vld1.8      {q14, q15}, [r12]
+
+    sub         r11, r0, r10            @ r11 = yuv420_dest+linear_offset+64-temp1
+    add         r12, r9, #64
+    add         r11, r11, r12
+
+    vst1.8      {q4, q5}, [r11]!       @ store {yuv420_dest+linear_offset+64-temp1, 64}
+    vst1.8      {q6, q7}, [r11]!
+    vst1.8      {q8, q9}, [r11]!       @ store {yuv420_dest+linear_offset+128-temp1, 64}
+    vst1.8      {q10, q11}, [r11]!
+    vst1.8      {q12, q13}, [r11]!     @ store {yuv420_dest+linear_offset+192-temp1, 64}
+    vst1.8      {q14, q15}, [r11]!
+
+    add         r9, r9, #256
+    sub         r9, r9, r10
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_192:
+    cmp         r12, #128               @ if (temp3 > 128)
+    ble         LOOP_HEIGHT_256_LEFT_128
+    add         r11, r1, r7             @ r11 = nv12t_src+tiled_offset+2048+temp1
+    add         r11, r11, r10
+    add         r11, r11, #2048
+    pld         [r11]
+    add         r12, r1, r8             @ r12 = nv12t_src+tiled_offset1
+    pld         [r11, #32]
+    cmp         r10, #0
+    pld         [r12]
+    stmnefd     sp!, {r9-r12, r14}      @ backup registers
+    pld         [r12, #32]
+    rsbne       r10, r10, #64
+    blne        MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r9-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_192_64
+    vld1.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+2048+temp1, 64}
+    vld1.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r11]!        @ store {yuv420_dest+linear_offset, 64}
+    vst1.8      {q2, q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_192_64:
+    add         r11, r1, r8             @ r11 = nv12t_src+tiled_offset1+2048
+    add         r11, r11, #2048
+    pld         [r11]
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset1, 64}
+    pld         [r11, #32]
+    vld1.8      {q6, q7}, [r12]
+    vld1.8      {q8, q9}, [r11]!        @ load {nv12t_src+tiled_offset1+2048, 64}
+    vld1.8      {q10, q11}, [r11]
+
+    sub         r11, r0, r10            @ r11 = yuv420_dest+linear_offset+64-temp1
+    add         r12, r9, #64
+    add         r11, r11, r12
+
+    vst1.8      {q4, q5}, [r11]!        @ store {yuv420_dest+linear_offset+64-temp1, 64}
+    vst1.8      {q6, q7}, [r11]!
+    vst1.8      {q8, q9}, [r11]!        @ store {yuv420_dest+linear_offset+128-temp1, 64}
+    vst1.8      {q10, q11}, [r11]!
+
+    add         r9, r9, #192
+    sub         r9, r9, r10
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_128:
+    cmp         r12, #64                @ if (temp3 > 64)
+    ble         LOOP_HEIGHT_256_LEFT_64
+    add         r11, r1, r8             @ r11 = nv12t_src+tiled_offset1+temp1
+    add         r11, r11, r10
+    pld         [r11]
+    add         r12, r1, r8             @ r12 = nv12t_src+tiled_offset1
+    add         r12, r12, #2048
+    pld         [r11, #32]
+    cmp         r10, #0
+    pld         [r12]
+    stmnefd     sp!, {r9-r12, r14}      @ backup registers
+    pld         [r12, #32]
+    rsbne       r10, r10, #64
+    blne        MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r9-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_128_64
+    vld1.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset1+temp1, 64}
+    vld1.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r11]!        @ store {yuv420_dest+linear_offset, 64}
+    vst1.8      {q2, q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_128_64:
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset1, 64}
+    vld1.8      {q6, q7}, [r12]
+
+    sub         r11, r0, r10            @ r11 = yuv420_dest+linear_offset+64-temp1
+    add         r12, r9, #64
+    add         r11, r11, r12
+
+    vst1.8      {q4, q5}, [r11]!        @ store {yuv420_dest+linear_offset+64-temp1, 64}
+    vst1.8      {q6, q7}, [r11]!
+
+    add         r9, r9, #128
+    sub         r9, r9, r10
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_64:
+    add         r11, r1, r8             @ r11 = nv12t_src+tiled_offset1+2048+temp1
+    add         r11, r11, #2048
+    add         r11, r11, r10
+    cmp         r10, #0
+    pld         [r11]
+    stmnefd     sp!, {r9-r12, r14}      @ backup registers
+    pld         [r11, #32]
+    rsbne       r10, r10, #64
+    blne        MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r9-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_64_64
+    vld1.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset1+temp1, 64}
+    vld1.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r11]!        @ store {yuv420_dest+linear_offset, 64}
+    vst1.8      {q2, q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_64_64:
+    add         r9, r9, #64
+    sub         r9, r9, r10
+
+LOOP_HEIGHT_256_LEFT_END:
+
+    ldr         r12, [sp, #48]          @ right
+    add         r7, r7, r14, lsl #11    @ tiled_offset = tiled_offset+temp4*2048
+    add         r10, r1, r7             @ r10 = nv12t_src+tiled_offset
+    pld         [r10]
+    bic         r6, r6, #0xFF           @ j = (left>>8)<<8
+    pld         [r10, #32]
+    add         r6, r6, #256            @ j = j + 256
+    sub         r11, r2, r12            @ temp2 = yuv420_width-right-256
+    sub         r11, r11, #256
+    cmp         r6, r11
+    bgt         LOOP_HEIGHT_256_WIDTH_END
+
+LOOP_HEIGHT_256_WIDTH:
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r12]
+    vld1.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset, 64}
+    pld         [r12, #32]
+    vld1.8      {q2, q3}, [r10]
+
+    add         r8, r8, r14, lsl #11    @ tiled_offset1 = tiled_offset1+temp4*2048
+    add         r10, r1, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r10]
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r10, #32]
+    vld1.8      {q6, q7}, [r12]
+
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r12]
+    vld1.8      {q8, q9}, [r10]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r12, #32]
+    vld1.8      {q10, q11}, [r10]
+
+    add         r7, r7, r14, lsl #11    @ tiled_offset = tiled_offset+temp4*2048
+    add         r10, r1, r7
+    pld         [r10]
+    vld1.8      {q12, q13}, [r12]!      @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r10, #32]
+    vld1.8      {q14, q15}, [r12]
+
+    add         r12, r0, r9             @ r12 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r12]!
+    vst1.8      {q2, q3}, [r12]!
+    vst1.8      {q4, q5}, [r12]!
+    vst1.8      {q6, q7}, [r12]!
+    vst1.8      {q8, q9}, [r12]!
+    vst1.8      {q10, q11}, [r12]!
+    vst1.8      {q12, q13}, [r12]!
+    vst1.8      {q14, q15}, [r12]!
+    add         r9, r9, #256            @ linear_offset = linear_offset+256
+
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+
+    add         r6, r6, #256            @ j=j+256
+    cmp         r6, r11                 @ j<=temp2
+    ble         LOOP_HEIGHT_256_WIDTH
+
+LOOP_HEIGHT_256_WIDTH_END:
+
+    add         r8, r8, r14, lsl #11    @ tiled_offset1 = tiled_offset1+temp4*2048
+    ldr         r14, [sp, #48]          @ right
+    sub         r11, r2, r6             @ temp2 = yuv420_width-right-j
+    sub         r11, r11, r14
+    cmp         r11, #0
+    beq         LOOP_HEIGHT_256_RIGHT_END
+    cmp         r11, #192
+    ble         LOOP_HEIGHT_256_RIGHT_192
+    add         r12, r10, #2048
+    pld         [r12]
+    vld1.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r12, #32]
+    vld1.8      {q2, q3}, [r10]
+
+    add         r10, r1, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r10]
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048}
+    pld         [r10, #32]
+    vld1.8      {q6, q7}, [r12]
+
+    add         r14, r10, #2048         @ r10 = nv12t_src+tiled_offset1+2048
+    pld         [r14]
+    vld1.8      {q8, q9}, [r10]!        @ load {nv12t_src+tiled_offset1}
+    pld         [r14, #32]
+    vld1.8      {q10, q11}, [r10]
+
+    add         r12, r0, r9             @ r12 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r12]!
+    vst1.8      {q2, q3}, [r12]!
+    vst1.8      {q4, q5}, [r12]!
+    vst1.8      {q6, q7}, [r12]!
+    vst1.8      {q8, q9}, [r12]!
+    vst1.8      {q10, q11}, [r12]!
+    add         r9, r9, #192            @ linear_offset = linear_offset+192
+
+    stmfd       sp!, {r9-r12, r14}      @ backup registers
+    sub         r10, r11, #192
+    mov         r11, r14
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_192:
+    cmp         r11, #128
+    ble         LOOP_HEIGHT_256_RIGHT_128
+    add         r12, r10, #2048
+    pld         [r12]
+    vld1.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r12, #32]
+    vld1.8      {q2, q3}, [r10]
+
+    add         r14, r1, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r14]
+    vld1.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048}
+    pld         [r14, #32]
+    vld1.8      {q6, q7}, [r12]
+
+    add         r12, r0, r9             @ r12 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r12]!
+    vst1.8      {q2, q3}, [r12]!
+    vst1.8      {q4, q5}, [r12]!
+    vst1.8      {q6, q7}, [r12]!
+    add         r9, r9, #128            @ linear_offset = linear_offset+128
+
+    stmfd       sp!, {r9-r12, r14}      @ backup registers
+    sub         r10, r11, #128
+    mov         r11, r14
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_128:
+    cmp         r11, #64
+    ble         LOOP_HEIGHT_256_RIGHT_64
+    add         r14, r10, #2048
+    pld         [r14]
+    vld1.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r14, #32]
+    vld1.8      {q2, q3}, [r10]
+
+    add         r12, r0, r9             @ r12 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r12]!
+    vst1.8      {q2, q3}, [r12]!
+    add         r9, r9, #64            @ linear_offset = linear_offset+64
+
+    stmfd       sp!, {r9-r12, r14}      @ backup registers
+    sub         r10, r11, #64
+    mov         r11, r14
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_64:
+    stmfd       sp!, {r9-r12, r14}      @ backup registers
+    mov         r14, r11
+    mov         r11, r10
+    mov         r10, r14
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12, r14}      @ restore registers
+
+LOOP_HEIGHT_256_RIGHT_END:
+
+    ldr         r14, [sp, #52]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r3, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_256
+    b           RESTORE_REG
+
+LOOP_HEIGHT_64_START:
+    cmp         r10, #64               @ if (temp1 >= 64)
+    blt         LOOP_HEIGHT_2_START
+
+    ldr         r5, [sp, #44]           @ i = top
+LOOP_HEIGHT_64:
+    ldr         r6, [sp, #40]           @ j = left
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    ldr         r9, [sp, #44]           @ linear_offset = top
+    add         r11, r6, #64            @ temp2 = ((j+64)>>6)<<6
+    bic         r11, r11, #0x3F
+    sub         r11, r11, r6            @ temp2 = temp2-j
+    sub         r9, r5, r9              @ linear_offset = temp1*(i-top)
+    mul         r9, r9, r10
+    and         r14, r6, #0x3           @ temp4 = j&0x3
+    add         r7, r7, r14             @ tiled_offset = tiled_offset+temp4
+    stmfd       sp!, {r9-r12}           @ backup parameters
+    mov         r10, r11
+    add         r11, r1, r7
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12}           @ restore parameters
+    add         r9, r9, r11             @ linear_offset = linear_offset+temp2
+    add         r6, r6, r11             @ j = j+temp2@
+
+    add         r14, r6, #64
+    cmp         r14, r12
+    bgt         LOOP_HEIGHT_64_1
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    add         r7, r1, r7
+    vld1.8      {q0, q1}, [r7]!
+    vld1.8      {q2, q3}, [r7]
+    add         r7, r0, r9
+    vst1.8      {q0, q1}, [r7]!
+    vst1.8      {q2, q3}, [r7]
+    add         r9, r9, #64
+    add         r6, r6, #64
+
+LOOP_HEIGHT_64_1:
+    add         r14, r6, #64
+    cmp         r14, r12
+    bgt         LOOP_HEIGHT_64_2
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    add         r7, r1, r7
+    vld1.8      {q0, q1}, [r7]!
+    vld1.8      {q2, q3}, [r7]
+    add         r7, r0, r9
+    vst1.8      {q0, q1}, [r7]!
+    vst1.8      {q2, q3}, [r7]
+    add         r9, r9, #64
+    add         r6, r6, #64
+
+LOOP_HEIGHT_64_2:
+    cmp         r6, r12
+    bge         LOOP_HEIGHT_64_3
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    sub         r11, r12, r6
+    stmfd       sp!, {r9-r12}           @ backup parameters
+    mov         r10, r11
+    add         r11, r1, r7
+    bl          MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12}           @ restore parameters
+
+LOOP_HEIGHT_64_3:
+
+    ldr         r14, [sp, #52]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r3, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_64
+    b           RESTORE_REG
+
+LOOP_HEIGHT_2_START:
+
+    ldr         r5, [sp, #44]           @ i = top
+LOOP_HEIGHT_2:
+
+    ldr         r6, [sp, #40]           @ j = left
+    ldr         r9, [sp, #44]           @ linear_offset = top
+    add         r11, r6, #64            @ temp2 = ((j+64)>>6)<<6
+    bic         r11, r11, #0x3F
+    sub         r11, r11, r6            @ temp2 = temp2-j
+    sub         r9, r5, r9              @ linear_offset = temp1*(i-top)
+    mul         r9, r10, r9
+    add         r9, r0, r9              @ linear_offset = linear_dst+linear_offset
+LOOP_HEIGHT_2_WIDTH:
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+
+    and         r14, r6, #0x3           @ temp4 = j&0x3@
+    add         r7, r7, r14             @ tiled_offset = tiled_offset+temp4@
+    add         r7, r1, r7
+
+    ldrh        r14, [r7]
+    strh        r14, [r9], #2
+
+    ldr         r14, [sp, #48]          @ right
+    add         r6, r6, #2              @ j=j+2
+    sub         r14, r2, r14            @ j<yuv420_width-right
+    cmp         r6, r14
+    blt         LOOP_HEIGHT_2_WIDTH
+
+    ldr         r14, [sp, #52]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r3, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_2
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+MEMCOPY_UNDER_64:                       @ count=r10, src=r11
+    cmp         r10, #32
+    add         r9, r0, r9              @ r9 = yuv420_dest+linear_offset
+    blt         MEMCOPY_UNDER_32
+    vld1.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+temp1, 64}
+    sub         r10, r10, #32
+    cmp         r10, #0
+    vst1.8      {q0, q1}, [r9]!         @ load {nv12t_src+tiled_offset+temp1, 64}
+    beq         MEMCOPY_UNDER_END
+MEMCOPY_UNDER_32:
+    cmp         r10, #16
+    blt         MEMCOPY_UNDER_16
+    vld1.8      {q0}, [r11]!            @ load {nv12t_src+tiled_offset+temp1, 64}
+    sub         r10, r10, #16
+    cmp         r10, #0
+    vst1.8      {q0}, [r9]!             @ load {nv12t_src+tiled_offset+temp1, 64}
+    beq         MEMCOPY_UNDER_END
+MEMCOPY_UNDER_16:
+    ldrb        r12, [r11], #1
+    strb        r12, [r9], #1
+    subs        r10, r10, #1
+    bne         MEMCOPY_UNDER_16
+
+MEMCOPY_UNDER_END:
+    and         r10, r6, #0x3F          @ temp1 = left(==j)&0x3F
+    cmp         r10, #0
+    mov         pc, lr
+
+tile_4x2_read_asm:
+LFB0:
+    add     ip, r3, #32
+    sub     r0, r0, #1
+    cmp     r1, ip
+    cmple   r3, r1
+    mov     ip, r2, asr #2
+    mov     r0, r0, asr #7
+    stmfd   sp!, {r4, r5, lr}
+LCFI0:
+    add     r0, r0, #1
+    bge     L2
+    sub     r1, r1, #1
+    tst     r1, #32
+    bne     L2
+    tst     r3, #32
+    bne     L2
+    mov     r4, r2, asr #7
+    and     r1, r3, #31
+    eor     r4, r4, r3, asr #5
+    ubfx    r3, r3, #6, #8
+    tst     r4, #1
+    ubfx    r4, r2, #8, #6
+    and     ip, ip, #15
+    mov     r2, r2, asr #6
+    mla     r3, r0, r3, r4
+    orr     r1, ip, r1, asl #4
+    b       L9
+L2:
+    mov     r2, ip, asr #5
+    and     r4, r3, #31
+    eor     r1, r2, r3, asr #5
+    and     r5, r2, #127
+    ubfx    r3, r3, #6, #8
+    tst     r1, #1
+    and     r1, ip, #15
+    mov     r2, ip, asr #4
+    mla     r3, r0, r3, r5
+    orr     r1, r1, r4, asl #4
+L9:
+    andne   r2, r2, #1
+    andeq   r2, r2, #1
+    orrne   r2, r2, #2
+    mov     r1, r1, asl #2
+    orr     r3, r1, r3, asl #13
+    orr     r0, r3, r2, asl #11
+    ldmfd   sp!, {r4, r5, pc}
+LFE0:
+    .fnend
+
diff --git a/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s b/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s
new file mode 100755 (executable)
index 0000000..cdd101e
--- /dev/null
@@ -0,0 +1,786 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_tiled_to_linear_deinterleave_crop_neon.s
+ * @brief   SEC_OMX specific define
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts and Deinterleaves tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. UV of NV12T to UV of YUV420P
+ *
+ * @param yuv420_u_dest
+ *   U plane address of YUV420P[out]
+ *
+ * @param yuv420_v_dest
+ *   V plane address of YUV420P[out]
+ *
+ * @param nv12t_src
+ *   UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ *   Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left. It should be even.
+ *
+ * @param top
+ *   Crop size of top. It should be even.
+ *
+ * @param right
+ *   Crop size of right. It should be even.
+ *
+ * @param buttom
+ *   Crop size of buttom. It should be even.
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_tiled_to_linear_deinterleave_crop_neon
+    .type   csc_tiled_to_linear_deinterleave_crop_neon, %function
+csc_tiled_to_linear_deinterleave_crop_neon:
+    .fnstart
+
+    @r0     yuv420_u_dest
+    @r1     yuv420_v_dest
+    @r2     nv12t_src
+    @r3     yuv420_width
+    @r4     yuv420_height
+    @r5     i
+    @r6     j
+    @r7     tiled_offset
+    @r8     tiled_offset1
+    @r9     linear_offset
+    @r10    temp1
+    @r11    temp2
+    @r12    temp3
+    @r14    temp4
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+
+    ldr         r4, [sp, #40]           @ r4 = yuv420_height
+
+    ldr         r12, [sp, #52]          @ r12 = right
+    ldr         r10, [sp, #44]          @ r10 = left
+    sub         r12, r3, r12            @ temp3 = yuv420_width-right@
+    sub         r10, r12, r10           @ temp1 = temp3-left@
+    cmp         r10, #256               @ if (temp1 >= 256)
+    blt         LOOP_HEIGHT_64_START
+
+    ldr         r5, [sp, #48]           @ top
+LOOP_HEIGHT_256:
+    ldr         r6, [sp, #44]           @ j = left
+    mov         r14, r5, asr #5         @ temp4 = i>>5
+    bic         r12, r6, #0xFF          @ temp3 = (j>>8)<<8
+    mov         r12, r12, asr #6        @ temp3 = temp3>>6
+    and         r11, r14, #0x1          @ if (temp4 & 0x1)
+    cmp         r11, #0x1
+    bne         LOOP_HEIGHT_256_GET_TILED_EVEN
+LOOP_HEIGHT_256_GET_TILED_ODD:
+    sub         r7, r14, #1             @ tiled_offset = temp4-1
+    add         r10, r3, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = tiled_offset*(temp1>>6)
+    mul         r7, r7, r10
+    add         r7, r7, r12             @ tiled_offset = tiled_offset+temp3
+    add         r7, r7, #2              @ tiled_offset = tiled_offset+2
+    bic         r10, r12, #0x3          @ temp1 = (temp3>>2)<<2
+    add         r7, r7, r10             @ tiled_offset = tiled_offset+temp1
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #4096           @ tiled_offset1 = tiled_offset+2048*2
+    mov         r14, #8
+    b           LOOP_HEIGHT_256_GET_TILED_END
+
+LOOP_HEIGHT_256_GET_TILED_EVEN:
+    add         r11, r4, #31            @ temp2 = ((yuv420_height+31)>>5)<<5
+    bic         r11, r11, #0x1F
+    add         r10, r5, #32            @ if ((i+32)<temp2)
+    cmp         r10, r11
+    bge         LOOP_HEIGHT_256_GET_TILED_EVEN1
+    add         r10, r12, #2            @ temp1 = temp3+2
+    bic         r10, r10, #0x3          @ temp1 = (temp1>>2)<<2
+    add         r7, r12, r10            @ tiled_offset = temp3+temp1@
+    add         r10, r3, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = tiled_offset+temp4*(temp1>>6)
+    mla         r7, r14, r10, r7
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #12288          @ tiled_offset1 = tiled_offset+2048*6
+    mov         r14, #8
+    b           LOOP_HEIGHT_256_GET_TILED_END
+
+LOOP_HEIGHT_256_GET_TILED_EVEN1:
+    add         r10, r3, #127           @ temp1 = ((yuv420_width+127)>>7)<<7
+    bic         r10, r10, #0x7F
+    mov         r10, r10, asr #6        @ tiled_offset = temp4*(temp1>>6)
+    mul         r7, r14, r10
+    add         r7, r7, r12             @ tiled_offset = tiled_offset+temp3
+    mov         r7, r7, lsl #11         @ tiled_offset = tiled_offset<<11
+    add         r8, r7, #4096           @ tiled_offset1 = tiled_offset+2048*2
+    mov         r14, #4
+
+LOOP_HEIGHT_256_GET_TILED_END:
+
+    ldr         r12, [sp, #52]          @ right
+    ldr         r9, [sp, #48]           @ top
+    and         r10, r5, #0x1F          @ temp1 = i&0x1F
+    add         r7, r7, r10, lsl #6     @ tiled_offset = tiled_offset+64*(temp1)
+    add         r8, r8, r10, lsl #6     @ tiled_offset1 = tiled_offset1+64*(temp1)
+    sub         r11, r3, r6             @ temp2 = yuv420_width-left(==j)-right
+    sub         r11, r11, r12
+    sub         r9, r5, r9              @ linear_offset = temp2*(i-top)/2@
+    mul         r9, r11, r9
+    mov         r9, r9, asr #1
+    add         r12, r6, #256           @ temp3 = ((j+256)>>8)<<8@
+    bic         r12, r12, #0xFF
+    sub         r12, r12, r6            @ temp3 = temp3-j@
+    and         r10, r6, #0x3F          @ temp1 = left(==j)&0x3F
+
+    cmp         r12, #192               @ if (temp3 > 192)
+    ble         LOOP_HEIGHT_256_LEFT_192
+    add         r11, r2, r7             @ r11 = nv12t_src+tiled_offset+temp1
+    add         r11, r11, r10
+    pld         [r11]
+    add         r12, r2, r7             @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r11, #32]
+    add         r12, r12, #2048
+    pld         [r12]
+    cmp         r10, #0
+    pld         [r12, #32]
+    stmnefd     sp!, {r8-r12, r14}      @ backup registers
+    rsbne       r10, r10, #64
+    blne        INTERLEAVED_MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r8-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_256_64
+    vld2.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+temp1, 64}
+    vld2.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r11]!
+    vst1.8      {q2}, [r11]!
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r11]!
+    vst1.8      {q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_256_64:
+    add         r11, r2, r8             @ r11 = nv12t_src+tiled_offset1
+    pld         [r11]
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r11, #32]
+    vld2.8      {q6, q7}, [r12]
+    add         r12, r11, #2048         @ r12 = nv12t_src+tiled_offset1+2048
+    pld         [r12]
+    vld2.8      {q8, q9}, [r11]!        @ load {nv12t_src+tiled_offset1, 64}
+    pld         [r12, #32]
+    vld2.8      {q10, q11}, [r11]
+    vld2.8      {q12, q13}, [r12]!      @ load {nv12t_src+tiled_offset1+2048, 64}
+    vld2.8      {q14, q15}, [r12]
+
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q4}, [r11]!
+    vst1.8      {q6}, [r11]!
+    vst1.8      {q8}, [r11]!
+    vst1.8      {q10}, [r11]!
+    vst1.8      {q12}, [r11]!
+    vst1.8      {q14}, [r11]!
+
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q5}, [r11]!
+    vst1.8      {q7}, [r11]!
+    vst1.8      {q9}, [r11]!
+    vst1.8      {q11}, [r11]!
+    vst1.8      {q13}, [r11]!
+    vst1.8      {q15}, [r11]!
+
+    add         r9, r9, #128
+    sub         r9, r9, r10, asr #1
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_192:
+    cmp         r12, #128               @ if (temp3 > 128)
+    ble         LOOP_HEIGHT_256_LEFT_128
+    add         r11, r2, r7             @ r11 = nv12t_src+tiled_offset+2048+temp1
+    add         r11, r11, r10
+    add         r11, r11, #2048
+    pld         [r11]
+    add         r12, r2, r8             @ r12 = nv12t_src+tiled_offset1
+    pld         [r11, #32]
+    cmp         r10, #0
+    pld         [r12]
+    stmnefd     sp!, {r8-r12, r14}      @ backup registers
+    pld         [r12, #32]
+    rsbne       r10, r10, #64
+    blne        INTERLEAVED_MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r8-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_192_64
+    vld2.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+2048+temp1, 64}
+    vld2.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r11]!
+    vst1.8      {q2}, [r11]!
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r11]!
+    vst1.8      {q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_192_64:
+    add         r11, r2, r8             @ r11 = nv12t_src+tiled_offset1+2048
+    add         r11, r11, #2048
+    pld         [r11]
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset1, 64}
+    pld         [r11, #32]
+    vld2.8      {q6, q7}, [r12]
+    vld2.8      {q8, q9}, [r11]!        @ load {nv12t_src+tiled_offset1+2048, 64}
+    vld2.8      {q10, q11}, [r11]
+
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q4}, [r11]!
+    vst1.8      {q6}, [r11]!
+    vst1.8      {q8}, [r11]!
+    vst1.8      {q10}, [r11]!
+
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q5}, [r11]!
+    vst1.8      {q7}, [r11]!
+    vst1.8      {q9}, [r11]!
+    vst1.8      {q11}, [r11]!
+
+    add         r9, r9, #96
+    sub         r9, r9, r10, asr #1
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_128:
+    cmp         r12, #64                @ if (temp3 > 64)
+    ble         LOOP_HEIGHT_256_LEFT_64
+    add         r11, r2, r8             @ r11 = nv12t_src+tiled_offset1+temp1
+    add         r11, r11, r10
+    pld         [r11]
+    add         r12, r2, r8             @ r12 = nv12t_src+tiled_offset1
+    add         r12, r12, #2048
+    pld         [r11, #32]
+    cmp         r10, #0
+    pld         [r12]
+    stmnefd     sp!, {r8-r12, r14}      @ backup registers
+    pld         [r12, #32]
+    rsbne       r10, r10, #64
+    blne        INTERLEAVED_MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r8-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_128_64
+    vld2.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset1+temp1, 64}
+    vld2.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r11]!
+    vst1.8      {q2}, [r11]!
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r11]!
+    vst1.8      {q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_128_64:
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset1, 64}
+    vld2.8      {q6, q7}, [r12]
+
+    add         r11, r0, r9             @ r11 = yuv420_u_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q4}, [r11]!
+    vst1.8      {q6}, [r11]!
+
+    add         r11, r1, r9             @ r11 = yuv420_v_dest+linear_offset+32-temp1/2
+    add         r11, r11, #32
+    sub         r11, r11, r10, asr #1
+    vst1.8      {q5}, [r11]!
+    vst1.8      {q7}, [r11]!
+
+    add         r9, r9, #64
+    sub         r9, r9, r10, asr #1
+    b           LOOP_HEIGHT_256_LEFT_END
+
+LOOP_HEIGHT_256_LEFT_64:
+    add         r11, r2, r8             @ r11 = nv12t_src+tiled_offset1+2048+temp1
+    add         r11, r11, #2048
+    add         r11, r11, r10
+    cmp         r10, #0
+    pld         [r11]
+    stmnefd     sp!, {r8-r12, r14}      @ backup registers
+    pld         [r11, #32]
+    rsbne       r10, r10, #64
+    blne        INTERLEAVED_MEMCOPY_UNDER_64
+    ldmnefd     sp!, {r8-r12, r14}      @ restore registers
+    bne         LOOP_HEIGHT_256_LEFT_64_64
+    vld2.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset1+temp1, 64}
+    vld2.8      {q2, q3}, [r11]
+    add         r11, r0, r9             @ r11 = yuv420_dest+linear_offset
+    vst1.8      {q0, q1}, [r11]!        @ store {yuv420_dest+linear_offset, 64}
+    vst1.8      {q2, q3}, [r11]!
+LOOP_HEIGHT_256_LEFT_64_64:
+    add         r9, r9, #32
+    sub         r9, r9, r10, asr #1
+
+LOOP_HEIGHT_256_LEFT_END:
+
+    ldr         r12, [sp, #52]          @ right
+    add         r7, r7, r14, lsl #11    @ tiled_offset = tiled_offset+temp4*2048
+    add         r10, r2, r7             @ r10 = nv12t_src+tiled_offset
+    pld         [r10]
+    bic         r6, r6, #0xFF           @ j = (left>>8)<<8
+    pld         [r10, #32]
+    add         r6, r6, #256            @ j = j + 256
+    sub         r11, r3, r12            @ temp2 = yuv420_width-right-256
+    sub         r11, r11, #256
+    cmp         r6, r11
+    bgt         LOOP_HEIGHT_256_WIDTH_END
+
+LOOP_HEIGHT_256_WIDTH:
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r12]
+    vld2.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset, 64}
+    pld         [r12, #32]
+    vld2.8      {q2, q3}, [r10]
+
+    add         r8, r8, r14, lsl #11    @ tiled_offset1 = tiled_offset1+temp4*2048
+    add         r10, r2, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r10]
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r10, #32]
+    vld2.8      {q6, q7}, [r12]
+
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+    pld         [r12]
+    vld2.8      {q8, q9}, [r10]!        @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r12, #32]
+    vld2.8      {q10, q11}, [r10]
+
+    add         r7, r7, r14, lsl #11    @ tiled_offset = tiled_offset+temp4*2048
+    add         r10, r2, r7
+    pld         [r10]
+    vld2.8      {q12, q13}, [r12]!      @ load {nv12t_src+tiled_offset+2048, 64}
+    pld         [r10, #32]
+    vld2.8      {q14, q15}, [r12]
+
+    add         r12, r0, r9             @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r12]!
+    vst1.8      {q2}, [r12]!
+    vst1.8      {q4}, [r12]!
+    vst1.8      {q6}, [r12]!
+    vst1.8      {q8}, [r12]!
+    vst1.8      {q10}, [r12]!
+    vst1.8      {q12}, [r12]!
+    vst1.8      {q14}, [r12]!
+    add         r12, r1, r9             @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r12]!
+    vst1.8      {q3}, [r12]!
+    vst1.8      {q5}, [r12]!
+    vst1.8      {q7}, [r12]!
+    vst1.8      {q9}, [r12]!
+    vst1.8      {q11}, [r12]!
+    vst1.8      {q13}, [r12]!
+    vst1.8      {q15}, [r12]!
+    add         r9, r9, #128            @ linear_offset = linear_offset+128
+
+    add         r12, r10, #2048         @ r12 = nv12t_src+tiled_offset+2048
+
+    add         r6, r6, #256            @ j=j+256
+    cmp         r6, r11                 @ j<=temp2
+    ble         LOOP_HEIGHT_256_WIDTH
+
+LOOP_HEIGHT_256_WIDTH_END:
+
+    add         r8, r8, r14, lsl #11    @ tiled_offset1 = tiled_offset1+temp4*2048
+    ldr         r14, [sp, #52]          @ right
+    sub         r11, r3, r6             @ temp2 = yuv420_width-right-j
+    sub         r11, r11, r14
+    cmp         r11, #0
+    beq         LOOP_HEIGHT_256_RIGHT_END
+    cmp         r11, #192
+    ble         LOOP_HEIGHT_256_RIGHT_192
+    add         r12, r10, #2048
+    pld         [r12]
+    vld2.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r12, #32]
+    vld2.8      {q2, q3}, [r10]
+
+    add         r10, r2, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r10]
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048}
+    pld         [r10, #32]
+    vld2.8      {q6, q7}, [r12]
+
+    add         r14, r10, #2048         @ r10 = nv12t_src+tiled_offset1+2048
+    pld         [r14]
+    vld2.8      {q8, q9}, [r10]!        @ load {nv12t_src+tiled_offset1}
+    pld         [r14, #32]
+    vld2.8      {q10, q11}, [r10]
+
+    add         r12, r0, r9             @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r12]!
+    vst1.8      {q2}, [r12]!
+    vst1.8      {q4}, [r12]!
+    vst1.8      {q6}, [r12]!
+    vst1.8      {q8}, [r12]!
+    vst1.8      {q10}, [r12]!
+    add         r12, r1, r9             @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r12]!
+    vst1.8      {q3}, [r12]!
+    vst1.8      {q5}, [r12]!
+    vst1.8      {q7}, [r12]!
+    vst1.8      {q9}, [r12]!
+    vst1.8      {q11}, [r12]!
+    add         r9, r9, #96            @ linear_offset = linear_offset+96
+
+    stmfd       sp!, {r8-r12, r14}      @ backup registers
+    sub         r10, r11, #192
+    mov         r11, r14
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r8-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_192:
+    cmp         r11, #128
+    ble         LOOP_HEIGHT_256_RIGHT_128
+    add         r12, r10, #2048
+    pld         [r12]
+    vld2.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r12, #32]
+    vld2.8      {q2, q3}, [r10]
+
+    add         r14, r2, r8             @ r10 = nv12t_src+tiled_offset1
+    pld         [r14]
+    vld2.8      {q4, q5}, [r12]!        @ load {nv12t_src+tiled_offset+2048}
+    pld         [r14, #32]
+    vld2.8      {q6, q7}, [r12]
+
+    add         r12, r0, r9             @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r12]!
+    vst1.8      {q2}, [r12]!
+    vst1.8      {q4}, [r12]!
+    vst1.8      {q6}, [r12]!
+    add         r12, r1, r9             @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r12]!
+    vst1.8      {q3}, [r12]!
+    vst1.8      {q5}, [r12]!
+    vst1.8      {q7}, [r12]!
+    add         r9, r9, #64            @ linear_offset = linear_offset+64
+
+    stmfd       sp!, {r8-r12, r14}      @ backup registers
+    sub         r10, r11, #128
+    mov         r11, r14
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r8-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_128:
+    cmp         r11, #64
+    ble         LOOP_HEIGHT_256_RIGHT_64
+    add         r14, r10, #2048
+    pld         [r14]
+    vld2.8      {q0, q1}, [r10]!        @ load {nv12t_src+tiled_offset}
+    pld         [r14, #32]
+    vld2.8      {q2, q3}, [r10]
+
+    add         r12, r0, r9             @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r12]!
+    vst1.8      {q2}, [r12]!
+    add         r12, r1, r9             @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r12]!
+    vst1.8      {q3}, [r12]!
+    add         r9, r9, #32            @ linear_offset = linear_offset+32
+
+    stmfd       sp!, {r8-r12, r14}      @ backup registers
+    sub         r10, r11, #64
+    mov         r11, r14
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r8-r12, r14}      @ restore registers
+    b           LOOP_HEIGHT_256_RIGHT_END
+
+LOOP_HEIGHT_256_RIGHT_64:
+    stmfd       sp!, {r8-r12, r14}      @ backup registers
+    mov         r14, r11
+    mov         r11, r10
+    mov         r10, r14
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r8-r12, r14}      @ restore registers
+
+LOOP_HEIGHT_256_RIGHT_END:
+
+    ldr         r14, [sp, #56]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r4, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_256
+    b           RESTORE_REG
+
+LOOP_HEIGHT_64_START:
+    cmp         r10, #64                @ if (temp1 >= 64)
+    blt         LOOP_HEIGHT_2_START
+
+    ldr         r5, [sp, #48]           @ i = top
+LOOP_HEIGHT_64:
+    ldr         r6, [sp, #44]           @ j = left
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r3
+    mov         r1, r4
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    ldr         r9, [sp, #48]           @ linear_offset = top
+    ldr         r12, [sp, #52]          @ r12 = right
+    add         r11, r6, #64            @ temp2 = ((j+64)>>6)<<6
+    bic         r11, r11, #0x3F
+    sub         r11, r11, r6            @ temp2 = temp2-j
+    sub         r12, r3, r12            @ temp3 = yuv420_width-right
+    sub         r14, r12, r6            @ temp4 = temp3-left
+    sub         r9, r5, r9              @ linear_offset = temp4*(i-top)/2
+    mul         r9, r9, r14
+    mov         r9, r9, asr #1
+    and         r14, r6, #0x3           @ temp4 = j&0x3
+    add         r7, r7, r14             @ tiled_offset = tiled_offset+temp4
+    stmfd       sp!, {r9-r12}           @ backup parameters
+    mov         r10, r11
+    add         r11, r2, r7
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12}           @ restore parameters
+    add         r9, r9, r11, asr #1     @ linear_offset = linear_offset+temp2/2
+    add         r6, r6, r11             @ j = j+temp2@
+
+    add         r14, r6, #64
+    cmp         r14, r12
+    bgt         LOOP_HEIGHT_64_1
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r3
+    mov         r1, r4
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    add         r7, r2, r7
+    vld2.8      {q0, q1}, [r7]!
+    vld2.8      {q2, q3}, [r7]
+    add         r7, r0, r9
+    vst1.8      {q0}, [r7]!
+    vst1.8      {q2}, [r7]
+    add         r7, r1, r9
+    vst1.8      {q1}, [r7]!
+    vst1.8      {q3}, [r7]
+    add         r9, r9, #32
+    add         r6, r6, #64
+
+LOOP_HEIGHT_64_1:
+    add         r14, r6, #64
+    cmp         r14, r12
+    bgt         LOOP_HEIGHT_64_2
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r3
+    mov         r1, r4
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    add         r7, r2, r7
+    vld2.8      {q0, q1}, [r7]!
+    vld2.8      {q2, q3}, [r7]
+    add         r7, r0, r9
+    vst1.8      {q0}, [r7]!
+    vst1.8      {q2}, [r7]
+    add         r7, r1, r9
+    vst1.8      {q1}, [r7]!
+    vst1.8      {q3}, [r7]
+    add         r9, r9, #32
+    add         r6, r6, #64
+
+LOOP_HEIGHT_64_2:
+    cmp         r6, r12
+    bge         LOOP_HEIGHT_64_3
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r3
+    mov         r1, r4
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+    sub         r11, r12, r6
+    stmfd       sp!, {r9-r12}           @ backup parameters
+    mov         r10, r11
+    add         r11, r2, r7
+    bl          INTERLEAVED_MEMCOPY_UNDER_64
+    ldmfd       sp!, {r9-r12}           @ restore parameters
+
+LOOP_HEIGHT_64_3:
+
+    ldr         r14, [sp, #56]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r4, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_64
+    b           RESTORE_REG
+
+LOOP_HEIGHT_2_START:
+
+    ldr         r5, [sp, #48]           @ i = top
+LOOP_HEIGHT_2:
+
+    ldr         r12, [sp, #52]          @ linear_offset = right
+    ldr         r6, [sp, #44]           @ j = left
+    ldr         r9, [sp, #48]           @ linear_offset = top
+
+    sub         r12, r3, r12            @ temp3 = yuv420_width-right
+    sub         r14, r12, r6            @ temp4 = temp3-left@
+    sub         r9, r5, r9              @ r9 = i-top
+    mul         r9, r14, r9             @ temp4*(i-top)
+    mov         r9, r9, lsr #1          @ linear_offset = temp4*(i-top)/2
+    add         r11, r0, r9
+    add         r12, r1, r9
+LOOP_HEIGHT_2_WIDTH:
+    stmfd       sp!, {r0-r3, r12}       @ backup parameters
+    mov         r0, r2
+    mov         r1, r3
+    mov         r2, r6
+    mov         r3, r5
+    bl          tile_4x2_read_asm
+    mov         r7, r0
+    ldmfd       sp!, {r0-r3, r12}       @ restore parameters
+
+    and         r14, r6, #0x3           @ temp4 = j&0x3@
+    add         r7, r7, r14             @ tiled_offset = tiled_offset+temp4@
+    add         r7, r2, r7
+
+    ldrh        r14, [r7]
+    strb        r14, [r11], #1
+    mov         r14, r14, lsr #8
+    strb        r14, [r12], #1
+
+    ldr         r14, [sp, #52]          @ right
+    add         r6, r6, #2              @ j=j+2
+    sub         r14, r3, r14            @ j<yuv420_width-right
+    cmp         r6, r14
+    blt         LOOP_HEIGHT_2_WIDTH
+
+    ldr         r14, [sp, #56]          @ buttom
+    add         r5, r5, #1              @ i=i+1
+    sub         r14, r4, r14            @ i<yuv420_height-buttom
+    cmp         r5, r14
+    blt         LOOP_HEIGHT_2
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+INTERLEAVED_MEMCOPY_UNDER_64:           @ count=r10, src=r11
+    cmp         r10, #32
+    blt         INTERLEAVED_MEMCOPY_UNDER_32
+    vld2.8      {q0, q1}, [r11]!        @ load {nv12t_src+tiled_offset+temp1, 64}
+    sub         r10, r10, #32
+    cmp         r10, #0
+    add         r12, r0, r9              @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {q0}, [r12]             @ load {nv12t_src+tiled_offset+temp1, 64}
+    add         r12, r1, r9              @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {q1}, [r12]             @ load {nv12t_src+tiled_offset+temp1, 64}
+    add         r9, r9, #16
+    beq         INTERLEAVED_MEMCOPY_UNDER_END
+INTERLEAVED_MEMCOPY_UNDER_32:
+    cmp         r10, #16
+    blt         INTERLEAVED_MEMCOPY_UNDER_16
+    vld2.8      {q0}, [r11]!            @ load {nv12t_src+tiled_offset+temp1, 64}
+    sub         r10, r10, #16
+    cmp         r10, #0
+    add         r12, r0, r9              @ r12 = yuv420_u_dest+linear_offset
+    vst1.8      {d0}, [r12]!             @ load {nv12t_src+tiled_offset+temp1, 64}
+    add         r12, r1, r9              @ r12 = yuv420_v_dest+linear_offset
+    vst1.8      {d1}, [r12]!             @ load {nv12t_src+tiled_offset+temp1, 64}
+    add         r9, r9, #8
+    beq         INTERLEAVED_MEMCOPY_UNDER_END
+INTERLEAVED_MEMCOPY_UNDER_16:
+    ldrh        r12, [r11], #2
+    add         r8, r0, r9              @ r8 = yuv420_u_dest+linear_offset
+    strb        r12, [r8]
+    add         r8, r1, r9              @ r8 = yuv420_v_dest+linear_offset
+    mov         r12, r12, lsr #8
+    strb        r12, [r8]
+    subs        r10, r10, #2
+    add         r9, r9, #1
+    bne         INTERLEAVED_MEMCOPY_UNDER_16
+
+INTERLEAVED_MEMCOPY_UNDER_END:
+    and         r10, r6, #0x3F          @ temp1 = left(==j)&0x3F
+    cmp         r10, #0
+    mov         pc, lr
+
+tile_4x2_read_asm:
+LFB0:
+    add     ip, r3, #32
+    sub     r0, r0, #1
+    cmp     r1, ip
+    cmple   r3, r1
+    mov     ip, r2, asr #2
+    mov     r0, r0, asr #7
+    stmfd   sp!, {r4, r5, lr}
+LCFI0:
+    add     r0, r0, #1
+    bge     L2
+    sub     r1, r1, #1
+    tst     r1, #32
+    bne     L2
+    tst     r3, #32
+    bne     L2
+    mov     r4, r2, asr #7
+    and     r1, r3, #31
+    eor     r4, r4, r3, asr #5
+    ubfx    r3, r3, #6, #8
+    tst     r4, #1
+    ubfx    r4, r2, #8, #6
+    and     ip, ip, #15
+    mov     r2, r2, asr #6
+    mla     r3, r0, r3, r4
+    orr     r1, ip, r1, asl #4
+    b       L9
+L2:
+    mov     r2, ip, asr #5
+    and     r4, r3, #31
+    eor     r1, r2, r3, asr #5
+    and     r5, r2, #127
+    ubfx    r3, r3, #6, #8
+    tst     r1, #1
+    and     r1, ip, #15
+    mov     r2, ip, asr #4
+    mla     r3, r0, r3, r5
+    orr     r1, r1, r4, asl #4
+L9:
+    andne   r2, r2, #1
+    andeq   r2, r2, #1
+    orrne   r2, r2, #2
+    mov     r1, r1, asl #2
+    orr     r3, r1, r3, asl #13
+    orr     r0, r3, r2, asl #11
+    ldmfd   sp!, {r4, r5, pc}
+LFE0:
+    .fnend
+
diff --git a/libswconverter/csc_tiled_to_linear_uv_deinterleave_neon.s b/libswconverter/csc_tiled_to_linear_uv_deinterleave_neon.s
new file mode 100755 (executable)
index 0000000..b4d5084
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_tiled_to_linear_uv_deinterleave_neon.s
+ * @brief   SEC_OMX specific define. It support MFC 6.x tiled.
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts and Deinterleave tiled data to linear for mfc 6.x
+ * 1. UV of NV12T to Y of YUV420P
+ *
+ * @param u_dst
+ *   U address of YUV420[out]
+ *
+ * @param v_dst
+ *   V address of YUV420[out]
+ *
+ * @param uv_src
+ *   UV address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   real width of YUV420[in]. It should be even.
+ *
+ * @param yuv420_height
+ *   real height of YUV420[in] It should be even.
+ */
+
+    .arch armv7-a
+    .text
+    .global csc_tiled_to_linear_uv_deinterleave_neon
+    .type   csc_tiled_to_linear_uv_deinterleave_neon, %function
+csc_tiled_to_linear_uv_deinterleave_neon:
+    .fnstart
+
+    .equ CACHE_LINE_SIZE, 64
+    .equ PRE_LOAD_OFFSET, 6
+
+    @r0     u_dst
+    @r1     v_dst
+    @r2     uv_src
+    @r3     width
+    @r4     height
+    @r5     i
+    @r6     j
+    @r7     dst_offset
+    @r8     src_offset
+    @r9     aligned_height
+    @r10    aligned_width
+    @r11    tiled_width
+    @r12    temp1
+    @r14    temp2
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+    ldr         r4, [sp, #40]           @ r4 = height
+
+    bic         r9, r4, #0x7            @ aligned_height = height & (~0x7)
+    bic         r10, r3, #0xF           @ aligned_width = width & (~0xF)
+    add         r11, r3, #15            @ tiled_width = ((width + 15) >> 4) << 4
+    mov         r11, r11, asr #4
+    mov         r11, r11, lsl #4
+
+    mov         r5, #0
+LOOP_MAIN_ALIGNED_HEIGHT:
+    mul         r8, r11, r5             @ src_offset = tiled_width * i
+    mov         r6, #0
+    add         r8, r2, r8              @ src_offset = uv_src + src_offset
+LOOP_MAIN_ALIGNED_WIDTH:
+    mov         r12, r3, asr #1         @ temp1 = (width >> 1) * i + (j >> 1)
+    mul         r12, r12, r5
+
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld2.8      {q0, q1}, [r8]!
+    add         r12, r12, r6, asr #1
+    vld2.8      {q2, q3}, [r8]!
+    add         r7, r0, r12             @ dst_offset = u_dst + temp1
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld2.8      {q4, q5}, [r8]!
+    mov         r14, r3, asr #1         @ temp2 = width / 2
+    vld2.8      {q6, q7}, [r8]!
+
+    vst1.8      {d0}, [r7], r14
+    vst1.8      {d1}, [r7], r14
+    vst1.8      {d4}, [r7], r14
+    vst1.8      {d5}, [r7], r14
+    vst1.8      {d8}, [r7], r14
+    vst1.8      {d9}, [r7], r14
+    vst1.8      {d12}, [r7], r14
+    vst1.8      {d13}, [r7], r14
+
+    add         r7, r1, r12             @ dst_offset = v_dst + temp1
+
+    vst1.8      {d2}, [r7], r14
+    vst1.8      {d3}, [r7], r14
+    vst1.8      {d6}, [r7], r14
+    vst1.8      {d7}, [r7], r14
+    vst1.8      {d10}, [r7], r14
+    vst1.8      {d11}, [r7], r14
+    add         r6, r6, #16
+    vst1.8      {d14}, [r7], r14
+    cmp         r6, r10
+    vst1.8      {d15}, [r7], r14
+    blt         LOOP_MAIN_ALIGNED_WIDTH
+
+MAIN_REMAIN_WIDTH_START:
+    cmp         r10, r3                 @ if (aligned_width != width) {
+    beq         MAIN_REMAIN_WIDTH_END
+    stmfd       sp!, {r0-r2,r4}         @ backup registers
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3)
+    add         r8, r8, r6, lsl #3
+    add         r8, r2, r8              @ r8 = uv_src + src_offset
+    mov         r12, r3, asr #1         @ temp1 = (width >> 1) * i + (j >> 1)
+    mul         r12, r12, r5
+    add         r12, r12, r6, asr #1
+    add         r7, r0, r12             @ r7 = u_dst + temp1
+    add         r12, r1, r12            @ r12 = v_dst + temp1
+    sub         r14, r3, r6             @ r14 = (width - j) / 2
+    mov         r14, r14, asr #1
+
+    mov         r4, #0
+LOOP_MAIN_REMAIN_HEIGHT:
+    mov         r0, #0                  @ r0 is index in de-interleave
+LOOP_MAIN_REMAIN_WIDTH:
+    ldrb        r1, [r8], #1
+    ldrb        r2, [r8], #1
+    strb        r1, [r7], #1
+    strb        r2, [r12], #1
+    add         r0, #1
+    cmp         r0, r14
+    blt         LOOP_MAIN_REMAIN_WIDTH
+
+    sub         r8, r8, r14, lsl #1
+    sub         r7, r7, r14
+    sub         r12, r12, r14
+    add         r8, r8, #16
+    add         r7, r7, r3, asr #1
+    add         r12, r12, r3, asr #1
+
+    add         r4, #1
+    cmp         r4, #8
+    blt         LOOP_MAIN_REMAIN_HEIGHT
+    ldmfd       sp!, {r0-r2,r4}         @ restore registers
+MAIN_REMAIN_WIDTH_END:
+
+    add         r5, r5, #8
+    cmp         r5, r9
+    blt         LOOP_MAIN_ALIGNED_HEIGHT
+
+REMAIN_HEIGHT_START:
+    cmp         r9, r4                  @ if (aligned_height != height) {
+    beq         REMAIN_HEIGHT_END
+
+    mov         r6, #0
+LOOP_REMAIN_HEIGHT_WIDTH16:
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3)
+    add         r8, r8, r6, lsl #3
+    add         r8, r2, r8              @ src_offset = uv_src + src_offset
+
+    mov         r12, r3, asr #1         @ temp1 = (width >> 1) * i + (j >> 1)
+    mul         r12, r12, r5
+    add         r12, r12, r6, asr #1
+    add         r7, r0, r12             @ r7 = u_dst + temp1
+    add         r12, r1, r12            @ r12 = v_dst + temp1
+    mov         r14, r3, asr #1         @ temp2 = width / 2
+
+    stmfd       sp!, {r0-r1}            @ backup registers
+    mov         r0, #0
+    sub         r1, r4, r9
+LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1:
+    vld2.8      {d0, d1}, [r8]!
+    vst1.8      {d0}, [r7], r14
+    vst1.8      {d1}, [r12], r14
+
+    add         r0, r0, #1
+    cmp         r0, r1
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1
+    ldmfd       sp!, {r0-r1}            @ restore registers
+
+    add         r6, r6, #16
+    cmp         r6, r10
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16
+
+REMAIN_HEIGHT_REMAIN_WIDTH_START:
+    cmp         r10, r3
+    beq         REMAIN_HEIGHT_REMAIN_WIDTH_END
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3)
+    add         r8, r8, r6, lsl #3
+    add         r8, r2, r8              @ src_offset = uv_src + src_offset
+
+    mov         r12, r3, asr #1         @ temp1 = (width >> 1) * i + (j >> 1)
+    mul         r12, r12, r5
+    add         r12, r12, r6, asr #1
+    add         r7, r0, r12             @ r7 = u_dst + temp1
+    add         r12, r1, r12            @ r12 = v_dst + temp1
+    sub         r14, r3, r6             @ r14 = (width - j) /2
+    mov         r14, r14, asr #1
+
+    stmfd       sp!, {r0-r2,r4-r5}            @ backup registers
+    mov         r0, #0
+    sub         r1, r4, r9
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1:
+
+    mov         r4, #0
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx:
+    ldrb        r2, [r8], #1
+    ldrb        r5, [r8], #1
+    strb        r2, [r7], #1
+    strb        r5, [r12], #1
+    add         r4, #1
+    cmp         r4, r14
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx
+
+    sub         r8, r8, r14, lsl #1
+    sub         r7, r7, r14
+    sub         r12, r12, r14
+    add         r8, r8, #16
+    add         r7, r7, r3, asr #1
+    add         r12, r12, r3, asr #1
+
+    add         r0, r0, #1
+    cmp         r0, r1
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1
+    ldmfd       sp!, {r0-r2,r4-r5}            @ restore registers
+
+REMAIN_HEIGHT_REMAIN_WIDTH_END:
+
+REMAIN_HEIGHT_END:
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+    .fnend
diff --git a/libswconverter/csc_tiled_to_linear_uv_neon.s b/libswconverter/csc_tiled_to_linear_uv_neon.s
new file mode 100755 (executable)
index 0000000..c90d1f3
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_tiled_to_linear_uv.s
+ * @brief   SEC_OMX specific define. It support MFC 6.x tiled.
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts tiled data to linear for mfc 6.x tiled
+ * 1. uv of nv12t to y of yuv420s
+ *
+ * @param dst
+ *   uv address of yuv420s[out]
+ *
+ * @param src
+ *   uv address of nv12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420s[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420s[in]
+ *
+ */
+    .arch armv7-a
+    .text
+    .global csc_tiled_to_linear_uv_neon
+    .type   csc_tiled_to_linear_uv_neon, %function
+csc_tiled_to_linear_uv_neon:
+    .fnstart
+
+    .equ CACHE_LINE_SIZE, 64
+    .equ PRE_LOAD_OFFSET, 6
+
+    @r0     y_dst
+    @r1     y_src
+    @r2     width
+    @r3     height
+    @r4     temp3
+    @r5     i
+    @r6     j
+    @r7     dst_offset
+    @r8     src_offset
+    @r9     aligned_height
+    @r10    aligned_width
+    @r11    tiled_width
+    @r12    temp1
+    @r14    temp2
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+    ldr         r4, [sp, #40]           @ r4 = height
+
+    bic         r9, r3, #0x7            @ aligned_height = height & (~0xF)
+    bic         r10, r2, #0xF           @ aligned_width = width & (~0xF)
+    add         r11, r2, #15            @ tiled_width = ((width + 15) >> 4) << 4
+    mov         r11, r11, asr #4
+    mov         r11, r11, lsl #4
+
+    mov         r5, #0
+LOOP_MAIN_ALIGNED_HEIGHT:
+    mul         r8, r11, r5             @ src_offset = tiled_width * i
+    mov         r6, #0
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+LOOP_MAIN_ALIGNED_WIDTH:
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q0, q1}, [r8]!
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    vld1.8      {q2, q3}, [r8]!
+    add         r12, r12, r6
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q4, q5}, [r8]!
+    add         r7, r0, r12             @ dst_offset = y_dst + temp1
+    vld1.8      {q6, q7}, [r8]!
+
+    vst1.8      {q0}, [r7], r2
+    vst1.8      {q1}, [r7], r2
+    vst1.8      {q2}, [r7], r2
+    vst1.8      {q3}, [r7], r2
+    vst1.8      {q4}, [r7], r2
+    vst1.8      {q5}, [r7], r2
+    vst1.8      {q6}, [r7], r2
+    vst1.8      {q7}, [r7], r2
+    add         r6, r6, #16
+    cmp         r6, r10
+    blt         LOOP_MAIN_ALIGNED_WIDTH
+
+MAIN_REMAIN_WIDTH_START:
+    cmp         r10, r2                 @ if (aligned_width != width) {
+    beq         MAIN_REMAIN_WIDTH_END
+
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3);
+    add         r8, r8, r6, lsl #3
+    add         r8, r1, r8              @ r8 = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+    sub         r14, r2, r6             @ r14 = width - j
+
+    stmfd       sp!, {r0-r1}            @ backup registers
+    mov         r1, #0
+LOOP_MAIN_REMAIN_HEIGHT:
+    mov         r0, #0                  @ r0 is index in memcpy
+LOOP_MAIN_REMAIN_WIDTH:
+    ldrh        r4, [r8], #2
+    strh        r4, [r7], #2
+    add         r0, #2
+    cmp         r0, r14
+    blt         LOOP_MAIN_REMAIN_WIDTH
+
+    sub         r8, r8, r14
+    sub         r7, r7, r14
+    add         r8, r8, #16
+    add         r7, r7, r2
+
+    add         r1, #1
+    cmp         r1, #8
+    blt         LOOP_MAIN_REMAIN_HEIGHT
+    ldmfd       sp!, {r0-r1}            @ restore registers
+MAIN_REMAIN_WIDTH_END:
+
+    add         r5, r5, #8
+    cmp         r5, r9
+    blt         LOOP_MAIN_ALIGNED_HEIGHT
+
+REMAIN_HEIGHT_START:
+    cmp         r9, r3                  @ if (aligned_height != height) {
+    beq         REMAIN_HEIGHT_END
+
+    mov         r6, #0
+LOOP_REMAIN_HEIGHT_WIDTH16:
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3)
+    add         r8, r8, r6, lsl #3
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+
+    sub         r12, r3, r9
+    mov         r14, #0
+LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1:
+    vld1.8      {q0}, [r8]!
+    vld1.8      {q1}, [r8]!
+    vst1.8      {q0}, [r7], r2
+    vst1.8      {q1}, [r7], r2
+
+    add         r14, r14, #2
+    cmp         r14, r12
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1
+
+    add         r6, r6, #16
+    cmp         r6, r10
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16
+
+REMAIN_HEIGHT_REMAIN_WIDTH_START:
+    cmp         r10, r2
+    beq         REMAIN_HEIGHT_REMAIN_WIDTH_END
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 3)
+    add         r8, r8, r6, lsl #3
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+
+    stmfd       sp!, {r0-r1,r3}         @ backup registers
+    mov         r0, #0
+    sub         r1, r3, r9
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1:
+
+    sub         r14, r2, r6
+    mov         r4, #0
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx:
+    ldrh        r3, [r8], #2
+    strh        r3, [r7], #2
+    add         r4, #2
+    cmp         r4, r14
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx
+
+    sub         r8, r8, r14
+    sub         r7, r7, r14
+    add         r8, r8, #16
+    add         r7, r7, r2
+
+    add         r0, r0, #1
+    cmp         r0, r1
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1
+    ldmfd       sp!, {r0-r1,r3}            @ restore registers
+
+REMAIN_HEIGHT_REMAIN_WIDTH_END:
+
+REMAIN_HEIGHT_END:
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+    .fnend
diff --git a/libswconverter/csc_tiled_to_linear_y_neon.s b/libswconverter/csc_tiled_to_linear_y_neon.s
new file mode 100755 (executable)
index 0000000..3cdf092
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    csc_tiled_to_linear_y.s
+ * @brief   SEC_OMX specific define. It support MFC 6.x tiled.
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ *   2012.02.01 : Create
+ */
+
+/*
+ * Converts tiled data to linear for mfc 6.x
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ *
+ * @param dst
+ *   Y address of YUV420[out]
+ *
+ * @param src
+ *   Y address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   real width of YUV420[in]. It should be even.
+ *
+ * @param yuv420_height
+ *   real height of YUV420[in] It should be even.
+ *
+ */
+    .arch armv7-a
+    .text
+    .global csc_tiled_to_linear_y_neon
+    .type   csc_tiled_to_linear_y_neon, %function
+csc_tiled_to_linear_y_neon:
+    .fnstart
+
+    .equ CACHE_LINE_SIZE, 64
+    .equ PRE_LOAD_OFFSET, 6
+
+    @r0     y_dst
+    @r1     y_src
+    @r2     width
+    @r3     height
+    @r4     temp3
+    @r5     i
+    @r6     j
+    @r7     dst_offset
+    @r8     src_offset
+    @r9     aligned_height
+    @r10    aligned_width
+    @r11    tiled_width
+    @r12    temp1
+    @r14    temp2
+
+    stmfd       sp!, {r4-r12,r14}       @ backup registers
+    ldr         r4, [sp, #40]           @ r4 = height
+
+    bic         r9, r3, #0xF            @ aligned_height = height & (~0xF)
+    bic         r10, r2, #0xF           @ aligned_width = width & (~0xF)
+    add         r11, r2, #15            @ tiled_width = ((width + 15) >> 4) << 4
+    mov         r11, r11, asr #4
+    mov         r11, r11, lsl #4
+
+    mov         r5, #0
+LOOP_MAIN_ALIGNED_HEIGHT:
+    mul         r8, r11, r5             @ src_offset = tiled_width * i
+    mov         r6, #0
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+LOOP_MAIN_ALIGNED_WIDTH:
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q0, q1}, [r8]!
+    vld1.8      {q2, q3}, [r8]!
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q4, q5}, [r8]!
+    vld1.8      {q6, q7}, [r8]!
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q8, q9}, [r8]!
+    add         r12, r12, r6
+    vld1.8      {q10, q11}, [r8]!
+    add         r7, r0, r12             @ dst_offset = y_dst + temp1
+    pld         [r8, #(CACHE_LINE_SIZE*PRE_LOAD_OFFSET)]
+    vld1.8      {q12, q13}, [r8]!
+    vld1.8      {q14, q15}, [r8]!
+
+    vst1.8      {q0}, [r7], r2
+    vst1.8      {q1}, [r7], r2
+    vst1.8      {q2}, [r7], r2
+    vst1.8      {q3}, [r7], r2
+    vst1.8      {q4}, [r7], r2
+    vst1.8      {q5}, [r7], r2
+    vst1.8      {q6}, [r7], r2
+    vst1.8      {q7}, [r7], r2
+    vst1.8      {q8}, [r7], r2
+    vst1.8      {q9}, [r7], r2
+    vst1.8      {q10}, [r7], r2
+    vst1.8      {q11}, [r7], r2
+    vst1.8      {q12}, [r7], r2
+    vst1.8      {q13}, [r7], r2
+    add         r6, r6, #16
+    vst1.8      {q14}, [r7], r2
+    cmp         r6, r10
+    vst1.8      {q15}, [r7], r2
+    blt         LOOP_MAIN_ALIGNED_WIDTH
+
+MAIN_REMAIN_WIDTH_START:
+    cmp         r10, r2                 @ if (aligned_width != width) {
+    beq         MAIN_REMAIN_WIDTH_END
+
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 4);
+    add         r8, r8, r6, lsl #4
+    add         r8, r1, r8              @ r8 = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+    sub         r14, r2, r6             @ r14 = width - j
+
+    stmfd       sp!, {r0-r1}            @ backup registers
+    mov         r1, #0
+LOOP_MAIN_REMAIN_HEIGHT:
+    mov         r0, #0                  @ r0 is index in memcpy
+LOOP_MAIN_REMAIN_WIDTH:
+    ldrh        r4, [r8], #2
+    strh        r4, [r7], #2
+    add         r0, #2
+    cmp         r0, r14
+    blt         LOOP_MAIN_REMAIN_WIDTH
+
+    sub         r8, r8, r14
+    sub         r7, r7, r14
+    add         r8, r8, #16
+    add         r7, r7, r2
+
+    add         r1, #1
+    cmp         r1, #16
+    blt         LOOP_MAIN_REMAIN_HEIGHT
+    ldmfd       sp!, {r0-r1}            @ restore registers
+MAIN_REMAIN_WIDTH_END:
+
+    add         r5, r5, #16
+    cmp         r5, r9
+    blt         LOOP_MAIN_ALIGNED_HEIGHT
+
+REMAIN_HEIGHT_START:
+    cmp         r9, r3                  @ if (aligned_height != height) {
+    beq         REMAIN_HEIGHT_END
+
+    mov         r6, #0
+LOOP_REMAIN_HEIGHT_WIDTH16:
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 4)
+    add         r8, r8, r6, lsl #4
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+
+    sub         r12, r3, r9
+    mov         r14, #0
+LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1:
+    vld1.8      {q0}, [r8]!
+    vld1.8      {q1}, [r8]!
+    vst1.8      {q0}, [r7], r2
+    vst1.8      {q1}, [r7], r2
+
+    add         r14, r14, #2
+    cmp         r14, r12
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1
+
+    add         r6, r6, #16
+    cmp         r6, r10
+    blt         LOOP_REMAIN_HEIGHT_WIDTH16
+
+REMAIN_HEIGHT_REMAIN_WIDTH_START:
+    cmp         r10, r2
+    beq         REMAIN_HEIGHT_REMAIN_WIDTH_END
+    mul         r8, r11, r5             @ src_offset = (tiled_width * i) + (j << 4)
+    add         r8, r8, r6, lsl #4
+    add         r8, r1, r8              @ src_offset = y_src + src_offset
+
+    mul         r12, r2, r5             @ temp1 = width * i + j;
+    add         r12, r12, r6
+    add         r7, r0, r12             @ r7 = y_dst + temp1
+
+    stmfd       sp!, {r0-r1,r3}         @ backup registers
+    mov         r0, #0
+    sub         r1, r3, r9
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1:
+
+    sub         r14, r2, r6
+    mov         r4, #0
+LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx:
+    ldrh        r3, [r8], #2
+    strh        r3, [r7], #2
+    add         r4, #2
+    cmp         r4, r14
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx
+
+    sub         r8, r8, r14
+    sub         r7, r7, r14
+    add         r8, r8, #16
+    add         r7, r7, r2
+
+    add         r0, r0, #1
+    cmp         r0, r1
+    blt         LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1
+    ldmfd       sp!, {r0-r1,r3}            @ restore registers
+
+REMAIN_HEIGHT_REMAIN_WIDTH_END:
+
+REMAIN_HEIGHT_END:
+
+RESTORE_REG:
+    ldmfd       sp!, {r4-r12,r15}       @ restore registers
+
+    .fnend
diff --git a/libswconverter/swconvertor.c b/libswconverter/swconvertor.c
new file mode 100755 (executable)
index 0000000..b3330fe
--- /dev/null
@@ -0,0 +1,2214 @@
+/*
+ *
+ * Copyright 2012 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file    swconvertor.c
+ *
+ * @brief   Exynos_OMX specific define
+ *
+ * @author  ShinWon Lee (shinwon.lee@samsung.com)
+ *
+ * @version 1.0
+ *
+ * @history
+ *   2012.02.01 : Create
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "swconverter.h"
+
+#ifdef NEON_SUPPORT
+#ifdef USE_NV12T_128X64
+/* MFC 5.X */
+/*
+ * Converts tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ * 3. UV of NV12T to UV of YUV420S
+ *
+ * @param yuv420_dest
+ *   Y or UV plane address of YUV420[out]
+ *
+ * @param nv12t_src
+ *   Y or UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+ void csc_tiled_to_linear_crop_neon(
+    unsigned char *yuv420_dest,
+    unsigned char *nv12t_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom);
+
+/*
+ * Converts and Deinterleaves tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. UV of NV12T to UV of YUV420P
+ *
+ * @param yuv420_u_dest
+ *   U plane address of YUV420P[out]
+ *
+ * @param yuv420_v_dest
+ *   V plane address of YUV420P[out]
+ *
+ * @param nv12t_src
+ *   UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ *   Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+void csc_tiled_to_linear_deinterleave_crop_neon(
+    unsigned char *yuv420_u_dest,
+    unsigned char *yuv420_v_dest,
+    unsigned char *nv12t_uv_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_uv_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom);
+
+/*
+ * Converts linear data to tiled
+ * Crops left, top, right, buttom
+ * 1. Y of YUV420P to Y of NV12T
+ * 2. Y of YUV420S to Y of NV12T
+ * 3. UV of YUV420S to UV of NV12T
+ *
+ * @param nv12t_dest
+ *   Y or UV plane address of NV12T[out]
+ *
+ * @param yuv420_src
+ *   Y or UV plane address of YUV420P(S)[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+void csc_linear_to_tiled_crop_neon(
+    unsigned char *nv12t_dest,
+    unsigned char *yuv420_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom);
+
+/*
+ * Converts and Interleaves linear to tiled
+ * Crops left, top, right, buttom
+ * 1. UV of YUV420P to UV of NV12T
+ *
+ * @param nv12t_uv_dest
+ *   UV plane address of NV12T[out]
+ *
+ * @param yuv420p_u_src
+ *   U plane address of YUV420P[in]
+ *
+ * @param yuv420p_v_src
+ *   V plane address of YUV420P[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ *   Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+void csc_linear_to_tiled_interleave_crop_neon(
+    unsigned char *nv12t_uv_dest,
+    unsigned char *yuv420_u_src,
+    unsigned char *yuv420_v_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom);
+#else
+/* others */
+void csc_tiled_to_linear_y_neon(
+    unsigned char  *y_dst,
+    unsigned char  *y_src,
+    unsigned int    width,
+    unsigned int    height);
+
+void csc_tiled_to_linear_uv_neon(
+    unsigned char  *uv_dst,
+    unsigned char  *uv_src,
+    unsigned int    width,
+    unsigned int    height);
+
+void csc_tiled_to_linear_uv_deinterleave_neon(
+    unsigned char  *u_dst,
+    unsigned char  *v_dst,
+    unsigned char  *uv_src,
+    unsigned int    width,
+    unsigned int    height);
+#endif /* USE_NV12T_128X64 */
+/* common */
+void csc_interleave_memcpy_neon(
+    unsigned char  *dest,
+    unsigned char  *src1,
+    unsigned char  *src2,
+    unsigned int    src_size);
+
+void csc_BGRA8888_to_YUV420SP_NEON(
+     unsigned char *y_dst,
+     unsigned char *uv_dst,
+     unsigned char *rgb_src,
+     unsigned int   width,
+     unsigned int   height);
+
+void csc_RGBA8888_to_YUV420SP_NEON(
+    unsigned char  *y_dst,
+    unsigned char  *uv_dst,
+    unsigned char  *rgb_src,
+    unsigned int    width,
+    unsigned int    height);
+#endif /* NEON_SUPPORT */
+
+
+#ifdef USE_NV12T_128X64
+/*
+ * It support MFC 5.x tiled.
+ * Get tiled address of position(x,y)
+ *
+ * @param x_size
+ *   width of tiled[in]
+ *
+ * @param y_size
+ *   height of tiled[in]
+ *
+ * @param x_pos
+ *   x position of tield[in]
+ *
+ * @param src_size
+ *   y position of tield[in]
+ *
+ * @return
+ *   address of tiled data
+ */
+static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos)
+{
+    int pixel_x_m1, pixel_y_m1;
+    int roundup_x, roundup_y;
+    int linear_addr0, linear_addr1, bank_addr ;
+    int x_addr;
+    int trans_addr;
+
+    pixel_x_m1 = x_size -1;
+    pixel_y_m1 = y_size -1;
+
+    roundup_x = ((pixel_x_m1 >> 7) + 1);
+    roundup_y = ((pixel_x_m1 >> 6) + 1);
+
+    x_addr = x_pos >> 2;
+
+    if ((y_size <= y_pos+32) && ( y_pos < y_size) &&
+        (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
+        linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf));
+        linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
+
+        if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+            bank_addr = ((x_addr >> 4) & 0x1);
+        else
+            bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+    } else {
+        linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
+        linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
+
+        if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+            bank_addr = ((x_addr >> 4) & 0x1);
+        else
+            bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+    }
+
+    linear_addr0 = linear_addr0 << 2;
+    trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0;
+
+    return trans_addr;
+}
+
+/*
+ * It support MFC 5.x tiled.
+ * Converts tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ * 3. UV of NV12T to UV of YUV420S
+ *
+ * @param yuv420_dest
+ *   Y or UV plane address of YUV420[out]
+ *
+ * @param nv12t_src
+ *   Y or UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+static void csc_tiled_to_linear_crop(
+    unsigned char *yuv420_dest,
+    unsigned char *nv12t_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom)
+{
+    unsigned int i, j;
+    unsigned int tiled_offset = 0, tiled_offset1 = 0;
+    unsigned int linear_offset = 0;
+    unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
+
+    temp3 = yuv420_width-right;
+    temp1 = temp3-left;
+    /* real width is greater than or equal 256 */
+    if (temp1 >= 256) {
+        for (i=top; i<yuv420_height-buttom; i=i+1) {
+            j = left;
+            temp3 = (j>>8)<<8;
+            temp3 = temp3>>6;
+            temp4 = i>>5;
+            if (temp4 & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = temp4-1;
+                temp1 = ((yuv420_width+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+temp3;
+                tiled_offset = tiled_offset+2;
+                temp1 = (temp3>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+                tiled_offset1 = tiled_offset+2048*2;
+                temp4 = 8;
+            } else {
+                temp2 = ((yuv420_height+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = temp3+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = temp3+temp1;
+                    temp1 = ((yuv420_width+127)>>7)<<7;
+                    tiled_offset = tiled_offset+temp4*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                    tiled_offset1 = tiled_offset+2048*6;
+                    temp4 = 8;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = ((yuv420_width+127)>>7)<<7;
+                    tiled_offset = temp4*(temp1>>6);
+                    tiled_offset = tiled_offset+temp3;
+                    tiled_offset = tiled_offset<<11;
+                    tiled_offset1 = tiled_offset+2048*2;
+                    temp4 = 4;
+                }
+            }
+
+            temp1 = i&0x1F;
+            tiled_offset = tiled_offset+64*(temp1);
+            tiled_offset1 = tiled_offset1+64*(temp1);
+            temp2 = yuv420_width-left-right;
+            linear_offset = temp2*(i-top);
+            temp3 = ((j+256)>>8)<<8;
+            temp3 = temp3-j;
+            temp1 = left&0x3F;
+            if (temp3 > 192) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1);
+                temp2 = ((left+63)>>6)<<6;
+                temp3 = ((yuv420_width-right)>>6)<<6;
+                if (temp2 == temp3) {
+                    temp2 = yuv420_width-right-(64-temp1);
+                }
+                memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64);
+                memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64);
+                memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+256-temp1;
+            } else if (temp3 > 128) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1);
+                memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64);
+                memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+192-temp1;
+            } else if (temp3 > 64) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1);
+                memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+128-temp1;
+            } else if (temp3 > 0) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1);
+                linear_offset = linear_offset+64-temp1;
+            }
+
+            tiled_offset = tiled_offset+temp4*2048;
+            j = (left>>8)<<8;
+            j = j + 256;
+            temp2 = yuv420_width-right-256;
+            for (; j<=temp2; j=j+256) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                tiled_offset1 = tiled_offset1+temp4*2048;
+                memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
+                memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
+                tiled_offset = tiled_offset+temp4*2048;
+                memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+256;
+            }
+
+            tiled_offset1 = tiled_offset1+temp4*2048;
+            temp2 = yuv420_width-right-j;
+            if (temp2 > 192) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
+                memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
+                memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192);
+            } else if (temp2 > 128) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
+                memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128);
+            } else if (temp2 > 64) {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64);
+            } else {
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
+            }
+        }
+    } else if (temp1 >= 64) {
+        for (i=top; i<(yuv420_height-buttom); i=i+1) {
+            j = left;
+            tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
+            temp2 = ((j+64)>>6)<<6;
+            temp2 = temp2-j;
+            linear_offset = temp1*(i-top);
+            temp4 = j&0x3;
+            tiled_offset = tiled_offset+temp4;
+            memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
+            linear_offset = linear_offset+temp2;
+            j = j+temp2;
+            if ((j+64) <= temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                linear_offset = linear_offset+64;
+                j = j+64;
+            }
+            if ((j+64) <= temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
+                linear_offset = linear_offset+64;
+                j = j+64;
+            }
+            if (j < temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
+                temp2 = temp3-j;
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
+            }
+        }
+    } else {
+        for (i=top; i<(yuv420_height-buttom); i=i+1) {
+            linear_offset = temp1*(i-top);
+            for (j=left; j<(yuv420_width-right); j=j+2) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
+                temp4 = j&0x3;
+                tiled_offset = tiled_offset+temp4;
+                memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2);
+                linear_offset = linear_offset+2;
+            }
+        }
+    }
+}
+
+/*
+ * Converts and Deinterleaves tiled data to linear
+ * Crops left, top, right, buttom
+ * 1. UV of NV12T to UV of YUV420P
+ *
+ * @param yuv420_u_dest
+ *   U plane address of YUV420P[out]
+ *
+ * @param yuv420_v_dest
+ *   V plane address of YUV420P[out]
+ *
+ * @param nv12t_src
+ *   UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ *   Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+static void csc_tiled_to_linear_deinterleave_crop(
+    unsigned char *yuv420_u_dest,
+    unsigned char *yuv420_v_dest,
+    unsigned char *nv12t_uv_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_uv_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom)
+{
+    unsigned int i, j;
+    unsigned int tiled_offset = 0, tiled_offset1 = 0;
+    unsigned int linear_offset = 0;
+    unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
+
+    temp3 = yuv420_width-right;
+    temp1 = temp3-left;
+    /* real width is greater than or equal 256 */
+    if (temp1 >= 256) {
+        for (i=top; i<yuv420_uv_height-buttom; i=i+1) {
+            j = left;
+            temp3 = (j>>8)<<8;
+            temp3 = temp3>>6;
+            temp4 = i>>5;
+            if (temp4 & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = temp4-1;
+                temp1 = ((yuv420_width+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+temp3;
+                tiled_offset = tiled_offset+2;
+                temp1 = (temp3>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+                tiled_offset1 = tiled_offset+2048*2;
+                temp4 = 8;
+            } else {
+                temp2 = ((yuv420_uv_height+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = temp3+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = temp3+temp1;
+                    temp1 = ((yuv420_width+127)>>7)<<7;
+                    tiled_offset = tiled_offset+temp4*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                    tiled_offset1 = tiled_offset+2048*6;
+                    temp4 = 8;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = ((yuv420_width+127)>>7)<<7;
+                    tiled_offset = temp4*(temp1>>6);
+                    tiled_offset = tiled_offset+temp3;
+                    tiled_offset = tiled_offset<<11;
+                    tiled_offset1 = tiled_offset+2048*2;
+                    temp4 = 4;
+                }
+            }
+
+            temp1 = i&0x1F;
+            tiled_offset = tiled_offset+64*(temp1);
+            tiled_offset1 = tiled_offset1+64*(temp1);
+            temp2 = yuv420_width-left-right;
+            linear_offset = temp2*(i-top)/2;
+            temp3 = ((j+256)>>8)<<8;
+            temp3 = temp3-j;
+            temp1 = left&0x3F;
+            if (temp3 > 192) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, yuv420_v_dest+linear_offset, nv12t_uv_src+tiled_offset+temp1, 64-temp1);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
+                                        yuv420_v_dest+linear_offset+(32-temp1/2),
+                                        nv12t_uv_src+tiled_offset+2048, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2),
+                                        yuv420_v_dest+linear_offset+(64-temp1/2),
+                                        nv12t_uv_src+tiled_offset1, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(96-temp1/2),
+                                        yuv420_v_dest+linear_offset+(96-temp1/2),
+                                        nv12t_uv_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+128-temp1/2;
+            } else if (temp3 > 128) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset+2048+temp1, 64-temp1);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
+                                        yuv420_v_dest+linear_offset+(32-temp1/2),
+                                        nv12t_uv_src+tiled_offset1, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2),
+                                        yuv420_v_dest+linear_offset+(64-temp1/2),
+                                        nv12t_uv_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+96-temp1/2;
+            } else if (temp3 > 64) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset1+temp1, 64-temp1);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
+                                        yuv420_v_dest+linear_offset+(32-temp1/2),
+                                        nv12t_uv_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+64-temp1/2;
+            } else if (temp3 > 0) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset1+2048+temp1, 64-temp1);
+                linear_offset = linear_offset+32-temp1/2;
+            }
+
+            tiled_offset = tiled_offset+temp4*2048;
+            j = (left>>8)<<8;
+            j = j + 256;
+            temp2 = yuv420_width-right-256;
+            for (; j<=temp2; j=j+256) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                tiled_offset1 = tiled_offset1+temp4*2048;
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
+                                        yuv420_v_dest+linear_offset+32,
+                                        nv12t_uv_src+tiled_offset+2048, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
+                                        yuv420_v_dest+linear_offset+64,
+                                        nv12t_uv_src+tiled_offset1, 64);
+                tiled_offset = tiled_offset+temp4*2048;
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96,
+                                        yuv420_v_dest+linear_offset+96,
+                                        nv12t_uv_src+tiled_offset1+2048, 64);
+                linear_offset = linear_offset+128;
+            }
+
+            tiled_offset1 = tiled_offset1+temp4*2048;
+            temp2 = yuv420_width-right-j;
+            if (temp2 > 192) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
+                                        yuv420_v_dest+linear_offset+32,
+                                        nv12t_uv_src+tiled_offset+2048, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
+                                        yuv420_v_dest+linear_offset+64,
+                                        nv12t_uv_src+tiled_offset1, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96,
+                                        yuv420_v_dest+linear_offset+96,
+                                        nv12t_uv_src+tiled_offset1+2048, temp2-192);
+            } else if (temp2 > 128) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
+                                        yuv420_v_dest+linear_offset+32,
+                                        nv12t_uv_src+tiled_offset+2048, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
+                                        yuv420_v_dest+linear_offset+64,
+                                        nv12t_uv_src+tiled_offset1, temp2-128);
+            } else if (temp2 > 64) {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
+                                        yuv420_v_dest+linear_offset+32,
+                                        nv12t_uv_src+tiled_offset+2048, temp2-64);
+            } else {
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, temp2);
+            }
+        }
+    } else if (temp1 >= 64) {
+        for (i=top; i<(yuv420_uv_height-buttom); i=i+1) {
+            j = left;
+            tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
+            temp2 = ((j+64)>>6)<<6;
+            temp2 = temp2-j;
+            temp3 = yuv420_width-right;
+            temp4 = temp3-left;
+            linear_offset = temp4*(i-top)/2;
+            temp4 = j&0x3;
+            tiled_offset = tiled_offset+temp4;
+            csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                    yuv420_v_dest+linear_offset,
+                                    nv12t_uv_src+tiled_offset, temp2);
+            linear_offset = linear_offset+temp2/2;
+            j = j+temp2;
+            if ((j+64) <= temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                linear_offset = linear_offset+32;
+                j = j+64;
+            }
+            if ((j+64) <= temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 64);
+                linear_offset = linear_offset+32;
+                j = j+64;
+            }
+            if (j < temp3) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
+                temp1 = temp3-j;
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, temp1);
+            }
+        }
+    } else {
+        for (i=top; i<(yuv420_uv_height-buttom); i=i+1) {
+            temp3 = yuv420_width-right;
+            temp4 = temp3-left;
+            linear_offset = temp4*(i-top)/2;
+            for (j=left; j<(yuv420_width-right); j=j+2) {
+                tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
+                temp3 = j&0x3;
+                tiled_offset = tiled_offset+temp3;
+                csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
+                                        yuv420_v_dest+linear_offset,
+                                        nv12t_uv_src+tiled_offset, 2);
+                linear_offset = linear_offset+1;
+            }
+        }
+    }
+}
+
+/*
+ * Converts linear data to tiled
+ * Crops left, top, right, buttom
+ * 1. Y of YUV420P to Y of NV12T
+ * 2. Y of YUV420S to Y of NV12T
+ * 3. UV of YUV420S to UV of NV12T
+ *
+ * @param nv12t_dest
+ *   Y or UV plane address of NV12T[out]
+ *
+ * @param yuv420_src
+ *   Y or UV plane address of YUV420P(S)[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_height
+ *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+static void csc_linear_to_tiled_crop(
+    unsigned char *nv12t_dest,
+    unsigned char *yuv420_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom)
+{
+    unsigned int i, j;
+    unsigned int tiled_x_index = 0, tiled_y_index = 0;
+    unsigned int aligned_x_size = 0, aligned_y_size = 0;
+    unsigned int tiled_offset = 0;
+    unsigned int temp1 = 0, temp2 = 0;
+
+    aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5;
+    aligned_x_size = ((yuv420_width-left-right)>>6)<<6;
+
+    for (i=0; i<aligned_y_size; i=i+32) {
+        for (j=0; j<aligned_x_size; j=j+64) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+
+            memcpy(nv12t_dest+tiled_offset, yuv420_src+left+j+yuv420_width*(i+top), 64);
+            memcpy(nv12t_dest+tiled_offset+64*1, yuv420_src+left+j+yuv420_width*(i+top+1), 64);
+            memcpy(nv12t_dest+tiled_offset+64*2, yuv420_src+left+j+yuv420_width*(i+top+2), 64);
+            memcpy(nv12t_dest+tiled_offset+64*3, yuv420_src+left+j+yuv420_width*(i+top+3), 64);
+            memcpy(nv12t_dest+tiled_offset+64*4, yuv420_src+left+j+yuv420_width*(i+top+4), 64);
+            memcpy(nv12t_dest+tiled_offset+64*5, yuv420_src+left+j+yuv420_width*(i+top+5), 64);
+            memcpy(nv12t_dest+tiled_offset+64*6, yuv420_src+left+j+yuv420_width*(i+top+6), 64);
+            memcpy(nv12t_dest+tiled_offset+64*7, yuv420_src+left+j+yuv420_width*(i+top+7), 64);
+            memcpy(nv12t_dest+tiled_offset+64*8, yuv420_src+left+j+yuv420_width*(i+top+8), 64);
+            memcpy(nv12t_dest+tiled_offset+64*9, yuv420_src+left+j+yuv420_width*(i+top+9), 64);
+            memcpy(nv12t_dest+tiled_offset+64*10, yuv420_src+left+j+yuv420_width*(i+top+10), 64);
+            memcpy(nv12t_dest+tiled_offset+64*11, yuv420_src+left+j+yuv420_width*(i+top+11), 64);
+            memcpy(nv12t_dest+tiled_offset+64*12, yuv420_src+left+j+yuv420_width*(i+top+12), 64);
+            memcpy(nv12t_dest+tiled_offset+64*13, yuv420_src+left+j+yuv420_width*(i+top+13), 64);
+            memcpy(nv12t_dest+tiled_offset+64*14, yuv420_src+left+j+yuv420_width*(i+top+14), 64);
+            memcpy(nv12t_dest+tiled_offset+64*15, yuv420_src+left+j+yuv420_width*(i+top+15), 64);
+            memcpy(nv12t_dest+tiled_offset+64*16, yuv420_src+left+j+yuv420_width*(i+top+16), 64);
+            memcpy(nv12t_dest+tiled_offset+64*17, yuv420_src+left+j+yuv420_width*(i+top+17), 64);
+            memcpy(nv12t_dest+tiled_offset+64*18, yuv420_src+left+j+yuv420_width*(i+top+18), 64);
+            memcpy(nv12t_dest+tiled_offset+64*19, yuv420_src+left+j+yuv420_width*(i+top+19), 64);
+            memcpy(nv12t_dest+tiled_offset+64*20, yuv420_src+left+j+yuv420_width*(i+top+20), 64);
+            memcpy(nv12t_dest+tiled_offset+64*21, yuv420_src+left+j+yuv420_width*(i+top+21), 64);
+            memcpy(nv12t_dest+tiled_offset+64*22, yuv420_src+left+j+yuv420_width*(i+top+22), 64);
+            memcpy(nv12t_dest+tiled_offset+64*23, yuv420_src+left+j+yuv420_width*(i+top+23), 64);
+            memcpy(nv12t_dest+tiled_offset+64*24, yuv420_src+left+j+yuv420_width*(i+top+24), 64);
+            memcpy(nv12t_dest+tiled_offset+64*25, yuv420_src+left+j+yuv420_width*(i+top+25), 64);
+            memcpy(nv12t_dest+tiled_offset+64*26, yuv420_src+left+j+yuv420_width*(i+top+26), 64);
+            memcpy(nv12t_dest+tiled_offset+64*27, yuv420_src+left+j+yuv420_width*(i+top+27), 64);
+            memcpy(nv12t_dest+tiled_offset+64*28, yuv420_src+left+j+yuv420_width*(i+top+28), 64);
+            memcpy(nv12t_dest+tiled_offset+64*29, yuv420_src+left+j+yuv420_width*(i+top+29), 64);
+            memcpy(nv12t_dest+tiled_offset+64*30, yuv420_src+left+j+yuv420_width*(i+top+30), 64);
+            memcpy(nv12t_dest+tiled_offset+64*31, yuv420_src+left+j+yuv420_width*(i+top+31), 64);
+        }
+    }
+
+    for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+2) {
+        for (j=0; j<aligned_x_size; j=j+64) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+
+            temp1 = i&0x1F;
+            memcpy(nv12t_dest+tiled_offset+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 64);
+            memcpy(nv12t_dest+tiled_offset+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 64);
+        }
+    }
+
+    for (i=0; i<(yuv420_height-top-buttom); i=i+2) {
+        for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+
+            temp1 = i&0x1F;
+            temp2 = j&0x3F;
+            memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 2);
+            memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 2);
+        }
+    }
+}
+
+/*
+ * Converts and Interleaves linear to tiled
+ * Crops left, top, right, buttom
+ * 1. UV of YUV420P to UV of NV12T
+ *
+ * @param nv12t_uv_dest
+ *   UV plane address of NV12T[out]
+ *
+ * @param yuv420p_u_src
+ *   U plane address of YUV420P[in]
+ *
+ * @param yuv420p_v_src
+ *   V plane address of YUV420P[in]
+ *
+ * @param yuv420_width
+ *   Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ *   Height/2 of YUV420[in]
+ *
+ * @param left
+ *   Crop size of left
+ *
+ * @param top
+ *   Crop size of top
+ *
+ * @param right
+ *   Crop size of right
+ *
+ * @param buttom
+ *   Crop size of buttom
+ */
+static void csc_linear_to_tiled_interleave_crop(
+    unsigned char *nv12t_uv_dest,
+    unsigned char *yuv420_u_src,
+    unsigned char *yuv420_v_src,
+    unsigned int yuv420_width,
+    unsigned int yuv420_height,
+    unsigned int left,
+    unsigned int top,
+    unsigned int right,
+    unsigned int buttom)
+{
+    unsigned int i, j;
+    unsigned int tiled_x_index = 0, tiled_y_index = 0;
+    unsigned int aligned_x_size = 0, aligned_y_size = 0;
+    unsigned int tiled_offset = 0;
+    unsigned int temp1 = 0, temp2 = 0;
+
+    aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5;
+    aligned_x_size = ((yuv420_width-left-right)>>6)<<6;
+
+    for (i=0; i<aligned_y_size; i=i+32) {
+        for (j=0; j<aligned_x_size; j=j+64) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*1,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+1),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+1), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*2,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+2),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+2), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*3,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+3),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+3), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*4,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+4),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+4), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*5,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+5),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+5), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*6,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+6),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+6), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*7,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+7),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+7), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*8,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+8),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+8), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*9,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+9),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+9), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*10,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+10),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+10), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*11,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+11),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+11), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*12,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+12),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+12), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*13,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+13),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+13), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*14,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+14),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+14), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*15,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+15),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+15), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*16,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+16),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+16), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*17,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+17),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+17), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*18,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+18),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+18), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*19,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+19),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+19), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*20,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+20),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+20), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*21,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+21),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+21), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*22,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+22),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+22), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*23,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+23),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+23), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*24,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+24),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+24), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*25,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+25),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+25), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*26,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+26),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+26), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*27,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+27),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+27), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*28,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+28),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+28), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*29,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+29),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+29), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*30,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+30),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+30), 32);
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*31,
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+31),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+31), 32);
+
+        }
+    }
+
+    for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+1) {
+        for (j=0; j<aligned_x_size; j=j+64) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+            temp1 = i&0x1F;
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1),
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32);
+       }
+    }
+
+    for (i=0; i<(yuv420_height-top-buttom); i=i+1) {
+        for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) {
+            tiled_offset = 0;
+            tiled_x_index = j>>6;
+            tiled_y_index = i>>5;
+            if (tiled_y_index & 0x1) {
+                /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+                tiled_offset = tiled_y_index-1;
+                temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                tiled_offset = tiled_offset*(temp1>>6);
+                tiled_offset = tiled_offset+tiled_x_index;
+                tiled_offset = tiled_offset+2;
+                temp1 = (tiled_x_index>>2)<<2;
+                tiled_offset = tiled_offset+temp1;
+                tiled_offset = tiled_offset<<11;
+            } else {
+                temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
+                if ((i+32)<temp2) {
+                    /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
+                    temp1 = tiled_x_index+2;
+                    temp1 = (temp1>>2)<<2;
+                    tiled_offset = tiled_x_index+temp1;
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset<<11;
+                } else {
+                    /* even2 fomula: x+x_block_num*y */
+                    temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
+                    tiled_offset = tiled_y_index*(temp1>>6);
+                    tiled_offset = tiled_offset+tiled_x_index;
+                    tiled_offset = tiled_offset<<11;
+                }
+            }
+            temp1 = i&0x1F;
+            temp2 = j&0x3F;
+            csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1),
+                                    yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
+                                    yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 1);
+       }
+    }
+}
+#else
+/* 2D Configurable tiled memory access (TM)
+ * Return the linear address from tiled position (x, y) */
+static unsigned int Tile2D_To_Linear(
+    unsigned int width,
+    unsigned int height,
+    unsigned int xpos,
+    unsigned int ypos,
+    int crFlag)
+{
+    int  tileNumX;
+    int  tileX, tileY;
+    int  tileAddr;
+    int  offset;
+    int  addr;
+
+    width = ((width + 15) / 16) * 16;
+    height = ((height + 15) / 16) * 16;
+    tileNumX = width / 16;
+
+    /* crFlag - 0: Y plane, 1: CbCr plane */
+    if (crFlag == 0) {
+        tileX = xpos / 16;
+        tileY = ypos / 16;
+        tileAddr = tileY * tileNumX + tileX;
+        offset = (ypos & 15) * 16 + (xpos & 15);
+        addr = (tileAddr << 8) | offset;
+    } else {
+        tileX = xpos / 16;
+        tileY = ypos / 8;
+        tileAddr = tileY * tileNumX + tileX;
+        offset = (ypos & 7) * 16 + (xpos & 15);
+        addr = (tileAddr << 7) | offset;
+    }
+
+    return addr;
+}
+
+static void Tile2D_To_YUV420(unsigned char *Y_plane, unsigned char *Cb_plane, unsigned char *Cr_plane,
+                        unsigned int y_addr, unsigned int c_addr, unsigned int width, unsigned int height)
+{
+    unsigned int x, y, j, k, l;
+    unsigned int out_of_width, actual_width, data;
+    unsigned long base_addr;
+
+    // y: 0, 16, 32, ...
+    for (y = 0; y < height; y += 16) {
+        // x: 0, 16, 32, ...
+        for (x = 0; x < width; x += 16) {
+            out_of_width = (x + 16) > width ? 1 : 0;
+            base_addr = y_addr + Tile2D_To_Linear(width, height, x, y, 0);
+
+            for (k = 0; (k < 16) && ((y + k) < height); k++) {
+                actual_width = out_of_width ? ((width%4)?((width%16) / 4 + 1) : ((width%16) / 4)) : 4;
+                for (l = 0; l < actual_width; l++) {
+                    data = *((unsigned int *)(base_addr + 16*k + l*4));
+                    for (j = 0; (j < 4) && (x + l*4 + j) < width; j++) {
+                        Y_plane[(y+k)*width + x + l*4 +j] = (data>>(8*j))&0xff;
+                    }
+                }
+            }
+        }
+    }
+
+    for (y = 0; y < height/2; y += 8) {
+        for (x = 0; x < width; x += 16) {
+            out_of_width = (x + 16) > width ? 1 : 0;
+            base_addr = c_addr + Tile2D_To_Linear(width, height/2, x, y, 1);
+            for (k = 0; (k < 8) && ((y+k) < height/2); k++) {
+                actual_width = out_of_width ? ((width%4) ? ((width%16) / 4 + 1) : ((width%16) / 4)) : 4;
+                for (l = 0; l < actual_width; l++) {
+                    data = *((unsigned int *)(base_addr + 16*k + l*4));
+                    for (j = 0; (j < 2) && (x/2 + l*2 +j) < width/2; j++) {
+                        Cb_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>> (8*2*j))&0xff;
+                        Cr_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>>(8*2*j+8))&0xff;
+                    }
+                }
+            }
+        }
+    }
+}
+#endif /* USE_NV12T_128X64 */
+
+/*
+ * De-interleaves src to dest1, dest2
+ *
+ * @param dest1
+ *   Address of de-interleaved data[out]
+ *
+ * @param dest2
+ *   Address of de-interleaved data[out]
+ *
+ * @param src
+ *   Address of interleaved data[in]
+ *
+ * @param src_size
+ *   Size of interleaved data[in]
+ */
+void csc_deinterleave_memcpy(
+    unsigned char *dest1,
+    unsigned char *dest2,
+    unsigned char *src,
+    unsigned int src_size)
+{
+    unsigned int i = 0;
+    for(i=0; i<src_size/2; i++) {
+        dest1[i] = src[i*2];
+        dest2[i] = src[i*2+1];
+    }
+}
+
+/*
+ * Interleaves src1, src2 to dest
+ *
+ * @param dest
+ *   Address of interleaved data[out]
+ *
+ * @param src1
+ *   Address of de-interleaved data[in]
+ *
+ * @param src2
+ *   Address of de-interleaved data[in]
+ *
+ * @param src_size
+ *   Size of de-interleaved data[in]
+ */
+void csc_interleave_memcpy(
+    unsigned char *dest,
+    unsigned char *src1,
+    unsigned char *src2,
+    unsigned int src_size)
+{
+#ifdef NEON_SUPPORT
+    csc_interleave_memcpy_neon(dest, src1, src2, src_size);
+#else
+/* not neon */
+    unsigned int i = 0;
+    for(i=0; i<src_size; i++) {
+        dest[i*2] = src1[i];
+        dest[i*2+1] = src2[i];
+    }
+#endif /* NEON_SUPPORT */
+}
+
+/*
+ * Converts tiled data to linear.
+ * 1. y of nv12t to y of yuv420p
+ * 2. y of nv12t to y of yuv420s
+ *
+ * @param dst
+ *   y address of yuv420[out]
+ *
+ * @param src
+ *   y address of nv12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *   it should be even
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *   it should be even.
+ *
+ */
+void csc_tiled_to_linear_y(
+    unsigned char *y_dst,
+    unsigned char *y_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef NEON_SUPPORT
+#ifdef USE_NV12T_128X64
+    csc_tiled_to_linear_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0);
+#else
+    csc_tiled_to_linear_y_neon(y_dst, y_src, width, height);
+#endif /* USE_NV12T_128X64 */
+
+#else
+/* not neon */
+#ifdef USE_NV12T_128X64
+    csc_tiled_to_linear_crop(y_dst, y_src, width, height, 0, 0, 0, 0);
+#else
+    unsigned int i, j, k;
+    unsigned int aligned_width, aligned_height;
+    unsigned int tiled_width;
+    unsigned int src_offset, dst_offset;
+
+    aligned_height = height & (~0xF);
+    aligned_width = width & (~0xF);
+    tiled_width = ((width + 15) >> 4) << 4;
+
+    for (i = 0; i < aligned_height; i = i + 16) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 4);
+            dst_offset = width * i + j;
+            for (k = 0; k < 8; k++) {
+                memcpy(y_dst + dst_offset, y_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(y_dst + dst_offset, y_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 4);
+            dst_offset = width * i + j;
+            for (k = 0; k < 8; k++) {
+                memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+    }
+
+    if (aligned_height != height) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 4);
+            dst_offset = width * i + j;
+            for (k = 0; k < height - aligned_height; k = k + 2) {
+                memcpy(y_dst + dst_offset, y_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(y_dst + dst_offset, y_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 4);
+            dst_offset = width * i + j;
+            for (k = 0; k < height - aligned_height; k = k + 2) {
+                memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+    }
+#endif /* USE_NV12T_128X64 */
+#endif /* NEON_SUPPORT */
+}
+
+/*
+ * Converts tiled data to linear
+ * 1. uv of nv12t to y of yuv420s
+ *
+ * @param dst
+ *   uv address of yuv420s[out]
+ *
+ * @param src
+ *   uv address of nv12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420s[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420s[in]
+ *
+ */
+void csc_tiled_to_linear_uv(
+    unsigned char *uv_dst,
+    unsigned char *uv_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef NEON_SUPPORT
+#ifdef USE_NV12T_128X64
+    csc_tiled_to_linear_crop_neon(uv_dst, uv_src, width, height, 0, 0, 0, 0);
+#else
+    csc_tiled_to_linear_uv_neon(uv_dst, uv_src, width, height);
+#endif /* USE_NV12T_128X64 */
+
+#else
+/* not neon */
+#ifdef USE_NV12T_128X64
+    csc_tiled_to_linear_crop(uv_dst, uv_src, width, height, 0, 0, 0, 0);
+#else
+    unsigned int i, j, k;
+    unsigned int aligned_width, aligned_height;
+    unsigned int tiled_width;
+    unsigned int src_offset, dst_offset;
+
+    aligned_height = height & (~0x7);
+    aligned_width = width & (~0xF);
+    tiled_width = ((width + 15) >> 4) << 4;
+
+    for (i = 0; i < aligned_height; i = i + 8) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = width * i + j;
+            for (k = 0; k < 4; k++) {
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = width * i + j;
+            for (k = 0; k < 4; k++) {
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+    }
+
+    if (aligned_height != height) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = width * i + j;
+            for (k = 0; k < height - aligned_height; k = k + 1) {
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = width * i + j;
+            for (k = 0; k < height - aligned_height; k = k + 1) {
+                memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width;
+            }
+        }
+    }
+#endif /* USE_NV12T_128X64 */
+#endif /* NEON_SUPPORT */
+}
+
+/*
+ * Converts tiled data to linear
+ * 1. uv of nt12t to uv of yuv420p
+ *
+ * @param u_dst
+ *   u address of yuv420p[out]
+ *
+ * @param v_dst
+ *   v address of yuv420p[out]
+ *
+ * @param uv_src
+ *   uv address of nt12t[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420p[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420p[in]
+ */
+void csc_tiled_to_linear_uv_deinterleave(
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *uv_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef NEON_SUPPORT
+#ifdef USE_NV12T_128X64
+    csc_tiled_to_linear_deinterleave_crop_neon(u_dst, v_dst, uv_src, width, height, 0, 0, 0, 0);
+#else
+    csc_tiled_to_linear_uv_deinterleave_neon(u_dst, v_dst, uv_src, width, height);
+#endif /* USE_NV12T_128X64 */
+
+#else
+/*not neon */
+#ifdef USE_NV12_128X64
+    csc_tiled_to_linear_deinterleave_crop(u_dst, v_dst, uv_src, width, height,
+                                          0, 0, 0, 0);
+#else
+    unsigned int i, j, k;
+    unsigned int aligned_width, aligned_height;
+    unsigned int tiled_width;
+    unsigned int src_offset, dst_offset;
+
+    aligned_height = height & (~0x7);
+    aligned_width = width & (~0xF);
+    tiled_width = ((width + 15) >> 4) << 4;
+
+    for (i = 0; i < aligned_height; i = i + 8) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = (width >> 1) * i + (j >> 1);
+            for (k = 0; k < 4; k++) {
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width >> 1;
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width >> 1;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = (width >> 1) * i + (j >> 1);
+            for (k = 0; k < 4; k++) {
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width >> 1;
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width >> 1;
+            }
+        }
+    }
+    if (aligned_height != height) {
+        for (j = 0; j<aligned_width; j = j + 16) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = (width >> 1) * i + (j >> 1);
+            for (k = 0; k < height - aligned_height; k = k + 1) {
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, 16);
+                src_offset += 16;
+                dst_offset += width >> 1;
+            }
+        }
+        if (aligned_width != width) {
+            src_offset = (tiled_width * i) + (j << 3);
+            dst_offset = (width >> 1) * i + (j >> 1);
+            for (k = 0; k < height - aligned_height; k = k + 1) {
+                csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
+                                        uv_src + src_offset, width - j);
+                src_offset += 16;
+                dst_offset += width >> 1;
+            }
+        }
+    }
+#endif /* USE_NV12T_128X64 */
+#endif /* NEON_SUPPORT */
+}
+
+/*
+ * Converts linear data to tiled
+ * 1. y of yuv420 to y of nv12t
+ *
+ * @param dst
+ *   y address of nv12t[out]
+ *
+ * @param src
+ *   y address of yuv420[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *   it should be even
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *   it should be even.
+ *
+ */
+void csc_linear_to_tiled_y(
+    unsigned char *y_dst,
+    unsigned char *y_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef USE_NV12T_128X64
+#ifdef NEON_SUPPORT
+    csc_linear_to_tiled_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0);
+#else
+    csc_linear_to_tiled_crop(y_dst, y_src, width, height, 0, 0, 0, 0);
+#endif /* NEON_SUPPORT */
+#else
+    unsigned char *dst = y_dst;
+    unsigned char *src = y_src;
+    unsigned int w = width;
+    unsigned int h = height;
+#endif /* USE_NV12T_128X64 */
+}
+
+/*
+ * Converts and interleaves linear data to tiled
+ * 1. uv of nv12t to uv of yuv420
+ *
+ * @param dst
+ *   uv address of nv12t[out]
+ *
+ * @param src
+ *   u address of yuv420[in]
+ *
+ * @param src
+ *   v address of yuv420[in]
+ *
+ * @param yuv420_width
+ *   real width of yuv420[in]
+ *
+ * @param yuv420_height
+ *   real height of yuv420[in]
+ *
+ */
+void csc_linear_to_tiled_uv(
+    unsigned char *uv_dst,
+    unsigned char *u_src,
+    unsigned char *v_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef USE_NV12T_128X64
+#ifdef NEON_SUPPORT
+    csc_linear_to_tiled_interleave_crop_neon(uv_dst, u_src, v_src, width, height, 0, 0, 0, 0);
+#else
+    csc_linear_to_tiled_interleave_crop(uv_dst, u_src, v_src, width, height, 0, 0, 0, 0);
+#endif /* NEON_SUPPORT */
+#else
+    unsigned char *uv = uv_dst;
+    unsigned char *u = u_src;
+    unsigned char *v = v_src;
+    unsigned int w = width;
+    unsigned int h = height;
+#endif /* USE_NV12T_128X64 */
+}
+
+/*
+ * Converts RGB565 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of RGB565[in]
+ *
+ * @param width
+ *   Width of RGB565[in]
+ *
+ * @param height
+ *   Height of RGB565[in]
+ */
+void csc_RGB565_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    int width,
+    int height)
+{
+    int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset1 = width * height;
+    unsigned int offset2 = width/2 * height/2;
+
+    unsigned short int *pSrc = (unsigned short int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstU = (unsigned char *)u_dst;
+    unsigned char *pDstV = (unsigned char *)v_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uIndex = 0;
+    unsigned int vIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            R = (tmp & 0x0000F800) >> 8;
+            G = (tmp & 0x000007E0) >> 3;
+            B = (tmp & 0x0000001F);
+            B = B << 3;
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstU[uIndex++] = (unsigned char)U;
+                pDstV[vIndex++] = (unsigned char)V;
+            }
+        }
+    }
+}
+
+/*
+ * Converts RGB565 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of RGB565[in]
+ *
+ * @param width
+ *   Width of RGB565[in]
+ *
+ * @param height
+ *   Height of RGB565[in]
+ */
+void csc_RGB565_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    int width,
+    int height)
+{
+    int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset = width * height;
+
+    unsigned short int *pSrc = (unsigned short int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstUV = (unsigned char *)uv_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uvIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            R = (tmp & 0x0000F800) >> 11;
+            R = R * 8;
+            G = (tmp & 0x000007E0) >> 5;
+            G = G * 4;
+            B = (tmp & 0x0000001F);
+            B = B * 8;
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstUV[uvIndex++] = (unsigned char)U;
+                pDstUV[uvIndex++] = (unsigned char)V;
+            }
+        }
+    }
+}
+
+/*
+ * Converts BGRA8888 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of BGRA8888[in]
+ *
+ * @param width
+ *   Width of BGRA8888[in]
+ *
+ * @param height
+ *   Height of BGRA8888[in]
+ */
+void csc_BGRA8888_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height)
+{
+    unsigned int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset1 = width * height;
+    unsigned int offset2 = width/2 * height/2;
+
+    unsigned int *pSrc = (unsigned int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstU = (unsigned char *)u_dst;
+    unsigned char *pDstV = (unsigned char *)v_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uIndex = 0;
+    unsigned int vIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            R = (tmp & 0x00FF0000) >> 16;
+            G = (tmp & 0x0000FF00) >> 8;
+            B = (tmp & 0x000000FF);
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstU[uIndex++] = (unsigned char)U;
+                pDstV[vIndex++] = (unsigned char)V;
+            }
+        }
+    }
+}
+
+/*
+ * Converts RGBA8888 to YUV420P
+ *
+ * @param y_dst
+ *   Y plane address of YUV420P[out]
+ *
+ * @param u_dst
+ *   U plane address of YUV420P[out]
+ *
+ * @param v_dst
+ *   V plane address of YUV420P[out]
+ *
+ * @param rgb_src
+ *   Address of RGBA8888[in]
+ *
+ * @param width
+ *   Width of RGBA8888[in]
+ *
+ * @param height
+ *   Height of RGBA8888[in]
+ */
+void csc_RGBA8888_to_YUV420P(
+    unsigned char *y_dst,
+    unsigned char *u_dst,
+    unsigned char *v_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height)
+{
+    unsigned int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset1 = width * height;
+    unsigned int offset2 = width/2 * height/2;
+
+    unsigned int *pSrc = (unsigned int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstU = (unsigned char *)u_dst;
+    unsigned char *pDstV = (unsigned char *)v_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uIndex = 0;
+    unsigned int vIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            B = (tmp & 0x00FF0000) >> 16;
+            G = (tmp & 0x0000FF00) >> 8;
+            R = (tmp & 0x000000FF);
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstU[uIndex++] = (unsigned char)U;
+                pDstV[vIndex++] = (unsigned char)V;
+            }
+        }
+    }
+}
+
+/*
+ * Converts BGRA8888 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of BGRA8888[in]
+ *
+ * @param width
+ *   Width of BGRA8888[in]
+ *
+ * @param height
+ *   Height of BGRA8888[in]
+ */
+void csc_BGRA8888_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef NEON_SUPPORT
+    csc_BGRA8888_to_YUV420SP_NEON(y_dst, uv_dst, rgb_src, width, height);
+#else
+    unsigned int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset = width * height;
+
+    unsigned int *pSrc = (unsigned int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstUV = (unsigned char *)uv_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uvIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            R = (tmp & 0x00FF0000) >> 16;
+            G = (tmp & 0x0000FF00) >> 8;
+            B = (tmp & 0x000000FF);
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstUV[uvIndex++] = (unsigned char)U;
+                pDstUV[uvIndex++] = (unsigned char)V;
+            }
+        }
+    }
+#endif /* NEON_SUPPORT */
+}
+
+/*
+ * Converts RGBA8888 to YUV420SP
+ *
+ * @param y_dst
+ *   Y plane address of YUV420SP[out]
+ *
+ * @param uv_dst
+ *   UV plane address of YUV420SP[out]
+ *
+ * @param rgb_src
+ *   Address of RGBA8888[in]
+ *
+ * @param width
+ *   Width of RGBA8888[in]
+ *
+ * @param height
+ *   Height of RGBA8888[in]
+ */
+void csc_RGBA8888_to_YUV420SP(
+    unsigned char *y_dst,
+    unsigned char *uv_dst,
+    unsigned char *rgb_src,
+    unsigned int width,
+    unsigned int height)
+{
+#ifdef NEON_SUPPORT
+    csc_RGBA8888_to_YUV420SP_NEON(y_dst, uv_dst, rgb_src, width, height);
+#else
+    unsigned int i, j;
+    unsigned int tmp;
+
+    unsigned int R, G, B;
+    unsigned int Y, U, V;
+
+    unsigned int offset = width * height;
+
+    unsigned int *pSrc = (unsigned int *)rgb_src;
+
+    unsigned char *pDstY = (unsigned char *)y_dst;
+    unsigned char *pDstUV = (unsigned char *)uv_dst;
+
+    unsigned int yIndex = 0;
+    unsigned int uvIndex = 0;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            tmp = pSrc[j * width + i];
+
+            B = (tmp & 0x00FF0000) >> 16;
+            G = (tmp & 0x0000FF00) >> 8;
+            R = (tmp & 0x000000FF);
+
+            Y = ((66 * R) + (129 * G) + (25 * B) + 128);
+            Y = Y >> 8;
+            Y += 16;
+
+            pDstY[yIndex++] = (unsigned char)Y;
+
+            if ((j % 2) == 0 && (i % 2) == 0) {
+                U = ((-38 * R) - (74 * G) + (112 * B) + 128);
+                U = U >> 8;
+                U += 128;
+                V = ((112 * R) - (94 * G) - (18 * B) + 128);
+                V = V >> 8;
+                V += 128;
+
+                pDstUV[uvIndex++] = (unsigned char)U;
+                pDstUV[uvIndex++] = (unsigned char)V;
+            }
+        }
+    }
+#endif /* NEON_SUPPORT */
+}
diff --git a/libv4l2/Makefile.am b/libv4l2/Makefile.am
new file mode 100755 (executable)
index 0000000..0994321
--- /dev/null
@@ -0,0 +1,11 @@
+lib_LTLIBRARIES = libexynosv4l2.la
+
+libexynosv4l2_la_SOURCES = exynos_v4l2.c exynos_subdev.c exynos_mc.c
+libexynosv4l2_la_CFLAGS = -I$(top_srcdir)/include -I/usr/include
+libexynosv4l2_la_CFLAGS += -Wno-unused-variable -Wno-unused-value
+libexynosv4l2_la_CFLAGS += -DLOG_TAG=\"LIBEXYNOSV4L2\"
+if USE_DLOG
+libexynosv4l2_la_CFLAGS += $(DLOG_CFLAGS) -DUSE_DLOG
+endif
+
+libexynosv4l2_la_LIBADD = $(DLOG_LIBS)
diff --git a/libv4l2/exynos_mc.c b/libv4l2/exynos_mc.c
new file mode 100755 (executable)
index 0000000..142c0aa
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_mc.c
+ * \brief     source file for libexynosv4l2
+ * \author    Jinsung Yang (jsgood.yang@samsung.com)
+ * \author    Sangwoo Park (sw5771.park@samsung.com)
+ * \date      2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ *   Initial version
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+
+#include <exynos_v4l2.h>
+
+#include <exynos_log.h>
+
+static inline unsigned int __media_entity_type(struct media_entity *entity)
+{
+    return entity->info.type & MEDIA_ENT_TYPE_MASK;
+}
+
+static void __media_debug_default(void *ptr, ...)
+{
+    va_list argptr;
+    va_start(argptr, ptr);
+    vprintf((const char*)ptr, argptr);
+    va_end(argptr);
+}
+
+static void __media_debug_set_handler(
+                struct media_device *media,
+                void (*debug_handler)(void *, ...),
+                void *debug_priv)
+{
+    if (debug_handler) {
+        media->debug_handler = debug_handler;
+        media->debug_priv = debug_priv;
+    } else {
+        media->debug_handler = __media_debug_default;
+        media->debug_priv = NULL;
+    }
+}
+
+static struct media_link *__media_entity_add_link(struct media_entity *entity)
+{
+    if (entity->num_links >= entity->max_links) {
+        struct media_link *links = entity->links;
+        unsigned int max_links = entity->max_links * 2;
+        unsigned int i;
+
+        links = (struct media_link*)realloc(links, max_links * sizeof *links);
+        if (links == NULL)
+            return NULL;
+
+        for (i = 0; i < entity->num_links; ++i)
+            links[i].twin->twin = &links[i];
+
+        entity->max_links = max_links;
+        entity->links = links;
+    }
+
+    return &entity->links[entity->num_links++];
+}
+
+
+static int __media_enum_links(struct media_device *media)
+{
+    ALOGD("%s: start", __func__);
+    __u32 id;
+    int ret = 0;
+
+    for (id = 1; id <= media->entities_count; id++) {
+        struct media_entity *entity = &media->entities[id - 1];
+        struct media_links_enum links;
+        unsigned int i;
+
+        links.entity = entity->info.id;
+        links.pads = (struct media_pad_desc*)malloc(entity->info.pads * sizeof(struct media_pad_desc));
+        links.links = (struct media_link_desc*)malloc(entity->info.links * sizeof(struct media_link_desc));
+
+        if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
+            ALOGE("Unable to enumerate pads and links (%s)", strerror(errno));
+            free(links.pads);
+            free(links.links);
+            return -errno;
+        }
+
+        for (i = 0; i < entity->info.pads; ++i) {
+            entity->pads[i].entity = entity;
+            entity->pads[i].index = links.pads[i].index;
+            entity->pads[i].flags = links.pads[i].flags;
+        }
+
+        for (i = 0; i < entity->info.links; ++i) {
+            struct media_link_desc *link = &links.links[i];
+            struct media_link *fwdlink;
+            struct media_link *backlink;
+            struct media_entity *source;
+            struct media_entity *sink;
+
+            source = exynos_media_get_entity_by_id(media, link->source.entity);
+            sink = exynos_media_get_entity_by_id(media, link->sink.entity);
+            if (source == NULL || sink == NULL) {
+                ALOGE("WARNING entity %u link %u from %u/%u to %u/%u is invalid!",
+                      id, i, link->source.entity,
+                      link->source.index,
+                      link->sink.entity,
+                      link->sink.index);
+                ret = -EINVAL;
+            } else {
+                fwdlink = __media_entity_add_link(source);
+                fwdlink->source = &source->pads[link->source.index];
+                fwdlink->sink = &sink->pads[link->sink.index];
+                fwdlink->flags = link->flags;
+
+                backlink = __media_entity_add_link(sink);
+                backlink->source = &source->pads[link->source.index];
+                backlink->sink = &sink->pads[link->sink.index];
+                backlink->flags = link->flags;
+
+                fwdlink->twin = backlink;
+                backlink->twin = fwdlink;
+            }
+        }
+
+        free(links.pads);
+        free(links.links);
+    }
+    return ret;
+}
+
+static int __media_get_devname_sysfs(struct media_entity *entity)
+{
+    //struct stat devstat;
+    char devname[32];
+    char sysname[32];
+    char target[1024];
+    char *p;
+    int ret;
+
+    snprintf(sysname, sizeof(sysname), "/sys/dev/char/%u:%u", entity->info.v4l.major,
+        entity->info.v4l.minor);
+
+    ret = readlink(sysname, target, sizeof(target));
+    if (ret < 0 || ret >= (int)sizeof(target))
+        return -errno;
+
+    target[ret] = '\0';
+    p = strrchr(target, '/');
+    if (p == NULL)
+        return -EINVAL;
+
+    snprintf(devname, sizeof(devname), "/tmp/%s", p + 1);
+
+    ret = mknod(devname, 0666 | S_IFCHR, MKDEV(81, entity->info.v4l.minor));
+    strncpy(entity->devname, devname, sizeof(devname) - 1);
+
+    return 0;
+}
+
+static int __media_get_media_fd(const char *filename, struct media_device *media)
+{
+    ssize_t num;
+    int media_node;
+    char *ptr;
+
+    ALOGD("%s: %s", __func__, filename);
+
+    media->fd = open(filename, O_RDWR, 0);
+    if (media->fd < 0) {
+        ALOGE("Open sysfs media device failed, media->fd: %d", media->fd);
+        return -1;
+    }
+
+    ALOGD("%s: media->fd: %d", __func__, media->fd);
+
+    return media->fd;
+
+}
+
+static int __media_enum_entities(struct media_device *media)
+{
+    struct media_entity *entity, *temp_entity;
+    unsigned int size;
+    __u32 id;
+    int ret;
+
+    temp_entity = entity = (struct media_entity*)calloc(1,  sizeof(struct media_entity));
+    for (id = 0, ret = 0; ; id = entity->info.id) {
+        size = (media->entities_count + 1) * sizeof(*media->entities);
+        media->entities = (struct media_entity*)realloc(media->entities, size);
+
+        entity = &media->entities[media->entities_count];
+        memset(entity, 0, sizeof(*entity));
+        entity->fd = -1;
+        entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+        entity->media = media;
+
+        ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
+
+        if (ret < 0) {
+            ret = errno != EINVAL ? -errno : 0;
+            break;
+        }
+
+        /* Number of links (for outbound links) plus number of pads (for
+         * inbound links) is a good safe initial estimate of the total
+         * number of links.
+         */
+        entity->max_links = entity->info.pads + entity->info.links;
+
+        entity->pads = (struct media_pad*)malloc(entity->info.pads * sizeof(*entity->pads));
+        entity->links = (struct media_link*)malloc(entity->max_links * sizeof(*entity->links));
+        if (entity->pads == NULL || entity->links == NULL) {
+            ret = -ENOMEM;
+            break;
+        }
+
+        media->entities_count++;
+
+        /* Find the corresponding device name. */
+        if (__media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
+            __media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+            continue;
+
+        /* Fall back to get the device name via sysfs */
+        __media_get_devname_sysfs(entity);
+        if (ret < 0)
+            ALOGE("media_get_devname failed");
+    }
+    free(temp_entity);
+
+    return ret;
+}
+
+static struct media_device *__media_open_debug(
+        const char *filename,
+        void (*debug_handler)(void *, ...),
+        void *debug_priv)
+{
+    struct media_device *media;
+    int ret;
+
+    media = (struct media_device *)calloc(1, sizeof(struct media_device));
+    if (media == NULL) {
+        ALOGE("media: %p", media);
+        return NULL;
+    }
+
+    __media_debug_set_handler(media, debug_handler, debug_priv);
+
+    ALOGD("%s: Opening media device %s", __func__, filename);
+    ALOGD("%s: media: %p", __func__, media);
+
+    media->fd = __media_get_media_fd(filename, media);
+    if (media->fd < 0) {
+        exynos_media_close(media);
+        ALOGE("failed __media_get_media_fd %s", filename);
+        return NULL;
+    }
+
+    ALOGD("%s: media->fd: %d", __func__, media->fd);
+    ret = __media_enum_entities(media);
+
+    if (ret < 0) {
+        ALOGE("Unable to enumerate entities for device %s (%s)", filename, strerror(-ret));
+        exynos_media_close(media);
+        return NULL;
+    }
+
+    ALOGD("%s: Found %u entities", __func__, media->entities_count);
+    ALOGD("%s: Enumerating pads and links", __func__);
+
+    ret = __media_enum_links(media);
+    if (ret < 0) {
+        ALOGE("Unable to enumerate pads and links for device %s", filename);
+        exynos_media_close(media);
+        return NULL;
+    }
+
+    return media;
+}
+
+/**
+ * @brief Open a media device.
+ * @param filename - name (including path) of the device node.
+ *
+ * Open the media device referenced by @a filename and enumerate entities, pads and
+ * links.
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * exynos_media_close when the device isn't needed anymore.
+ */
+struct media_device *exynos_media_open(const char *filename)
+{
+    return __media_open_debug(filename, (void (*)(void *, ...))fprintf, stdout);
+}
+
+/**
+ * @brief Close a media device.
+ * @param media - device instance.
+ *
+ * Close the @a media device instance and free allocated resources. Access to the
+ * device instance is forbidden after this function returns.
+ */
+void exynos_media_close(struct media_device *media)
+{
+    unsigned int i;
+
+    if (media->fd != -1)
+        close(media->fd);
+
+    for (i = 0; i < media->entities_count; ++i) {
+        struct media_entity *entity = &media->entities[i];
+
+        free(entity->pads);
+        free(entity->links);
+        if (entity->fd != -1)
+            close(entity->fd);
+    }
+
+    free(media->entities);
+    free(media);
+}
+
+/**
+ * @brief Locate the pad at the other end of a link.
+ * @param pad - sink pad at one end of the link.
+ *
+ * Locate the source pad connected to @a pad through an enabled link. As only one
+ * link connected to a sink pad can be enabled at a time, the connected source
+ * pad is guaranteed to be unique.
+ *
+ * @return A pointer to the connected source pad, or NULL if all links connected
+ * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
+ */
+struct media_pad *exynos_media_entity_remote_source(struct media_pad *pad)
+{
+    unsigned int i;
+
+    if (!(pad->flags & MEDIA_PAD_FL_SINK))
+        return NULL;
+
+    for (i = 0; i < pad->entity->num_links; ++i) {
+        struct media_link *link = &pad->entity->links[i];
+
+        if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+            continue;
+
+        if (link->sink == pad)
+            return link->source;
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Find an entity by its name.
+ * @param media - media device.
+ * @param name - entity name.
+ * @param length - size of @a name.
+ *
+ * Search for an entity with a name equal to @a name.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *exynos_media_get_entity_by_name(struct media_device *media,
+                          const char *name, size_t length)
+{
+    unsigned int i;
+    struct media_entity *entity;
+
+    for (i = 0; i < media->entities_count; ++i) {
+        entity = &media->entities[i];
+
+        if (strncmp(entity->info.name, name, length) == 0)
+            return entity;
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Find an entity by its ID.
+ * @param media - media device.
+ * @param id - entity ID.
+ *
+ * Search for an entity with an ID equal to @a id.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *exynos_media_get_entity_by_id(struct media_device *media,
+                        __u32 id)
+{
+    unsigned int i;
+
+    for (i = 0; i < media->entities_count; ++i) {
+        struct media_entity *entity = &media->entities[i];
+
+        if (entity->info.id == id)
+            return entity;
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Configure a link.
+ * @param media - media device.
+ * @param source - source pad at the link origin.
+ * @param sink - sink pad at the link target.
+ * @param flags - configuration flags.
+ *
+ * Locate the link between @a source and @a sink, and configure it by applying
+ * the new @a flags.
+ *
+ * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
+ *
+ * @return 0 on success, -1 on failure:
+ *       -ENOENT: link not found
+ *       - other error codes returned by MEDIA_IOC_SETUP_LINK
+ */
+int exynos_media_setup_link(struct media_device *media,
+             struct media_pad *source,
+             struct media_pad *sink,
+             __u32 flags)
+{
+    struct media_link *link;
+    struct media_link_desc ulink;
+    unsigned int i;
+    int ret;
+
+    for (i = 0; i < source->entity->num_links; i++) {
+        link = &source->entity->links[i];
+
+        if (link->source->entity == source->entity &&
+            link->source->index == source->index &&
+            link->sink->entity == sink->entity &&
+            link->sink->index == sink->index)
+            break;
+    }
+
+    if (i == source->entity->num_links) {
+        ALOGE("Link not found");
+        return -ENOENT;
+    }
+
+    /* source pad */
+    ulink.source.entity = source->entity->info.id;
+    ulink.source.index = source->index;
+    ulink.source.flags = MEDIA_PAD_FL_SOURCE;
+
+    /* sink pad */
+    ulink.sink.entity = sink->entity->info.id;
+    ulink.sink.index = sink->index;
+    ulink.sink.flags = MEDIA_PAD_FL_SINK;
+
+    ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
+
+    ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
+    if (ret == -1) {
+        ALOGE("Unable to setup link (%s)", strerror(errno));
+        return -errno;
+    }
+
+    link->flags = ulink.flags;
+    link->twin->flags = ulink.flags;
+    return 0;
+}
+
+/**
+ * @brief Reset all links to the disabled state.
+ * @param media - media device.
+ *
+ * Disable all links in the media device. This function is usually used after
+ * opening a media device to reset all links to a known state.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_reset_links(struct media_device *media)
+{
+    unsigned int i, j;
+    int ret;
+
+    for (i = 0; i < media->entities_count; ++i) {
+        struct media_entity *entity = &media->entities[i];
+
+        for (j = 0; j < entity->num_links; j++) {
+            struct media_link *link = &entity->links[j];
+
+            if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
+                link->source->entity != entity)
+                continue;
+
+            ret = exynos_media_setup_link(media, link->source, link->sink,
+                           link->flags & ~MEDIA_LNK_FL_ENABLED);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
+    return 0;
+}
+
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int __media_udev_open(struct udev **udev)
+{
+    *udev = udev_new();
+    if (*udev == NULL)
+        return -ENOMEM;
+    return 0;
+}
+
+static inline void __media_udev_close(struct udev *udev)
+{
+    if (udev != NULL)
+        udev_unref(udev);
+}
+
+static int __media_get_devname_udev(struct udev *udev,
+        struct media_entity *entity)
+{
+    struct udev_device *device;
+    dev_t devnum;
+    const char *p;
+    int ret = -ENODEV;
+
+    if (udev == NULL)
+        return -EINVAL;
+
+    devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+    ALOGE("looking up device: %u:%u",
+          major(devnum), minor(devnum));
+    device = udev_device_new_from_devnum(udev, 'c', devnum);
+    if (device) {
+        p = udev_device_get_devnode(device);
+        if (p) {
+            strncpy(entity->devname, p, sizeof(entity->devname));
+            entity->devname[sizeof(entity->devname) - 1] = '\0';
+        }
+        ret = 0;
+    }
+
+    udev_device_unref(device);
+
+    return ret;
+}
+
+#else    /* HAVE_LIBUDEV */
+
+struct udev;
+
+static inline int __media_udev_open(struct udev **udev) { return 0; }
+
+static inline void __media_udev_close(struct udev *udev) { }
+
+static inline int __media_get_devname_udev(struct udev *udev,
+        struct media_entity *entity)
+{
+    return -ENOTSUP;
+}
+
+#endif    /* HAVE_LIBUDEV */
+
+/**
+ * @brief Parse string to a pad on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string where parsing ended
+ *
+ * Parse NULL terminated string describing a pad and return its struct
+ * media_pad instance.
+ *
+ * @return Pointer to struct media_pad on success, NULL on failure.
+ */
+struct media_pad *exynos_media_parse_pad(struct media_device *media,
+                  const char *p, char **endp)
+{
+    unsigned int entity_id, pad;
+    struct media_entity *entity;
+    char *end;
+
+    for (; isspace(*p); ++p);
+
+    if (*p == '"') {
+        for (end = (char *)p + 1; *end && *end != '"'; ++end);
+        if (*end != '"')
+            return NULL;
+
+        entity = exynos_media_get_entity_by_name(media, p + 1, end - p - 1);
+        if (entity == NULL)
+            return NULL;
+
+        ++end;
+    } else {
+        entity_id = strtoul(p, &end, 10);
+        entity = exynos_media_get_entity_by_id(media, entity_id);
+        if (entity == NULL)
+            return NULL;
+    }
+    for (; isspace(*end); ++end);
+
+    if (*end != ':')
+        return NULL;
+    for (p = end + 1; isspace(*p); ++p);
+
+    pad = strtoul(p, &end, 10);
+    for (p = end; isspace(*p); ++p);
+
+    if (pad >= entity->info.pads)
+        return NULL;
+
+    for (p = end; isspace(*p); ++p);
+    if (endp)
+        *endp = (char *)p;
+
+    return &entity->pads[pad];
+}
+
+/**
+ * @brief Parse string to a link on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to p where parsing ended
+ *
+ * Parse NULL terminated string p describing a link and return its struct
+ * media_link instance.
+ *
+ * @return Pointer to struct media_link on success, NULL on failure.
+ */
+struct media_link *exynos_media_parse_link(
+        struct media_device *media,
+        const char *p,
+        char **endp)
+{
+    struct media_link *link;
+    struct media_pad *source;
+    struct media_pad *sink;
+    unsigned int i;
+    char *end;
+
+    source = exynos_media_parse_pad(media, p, &end);
+    if (source == NULL)
+        return NULL;
+
+    if (end[0] != '-' || end[1] != '>')
+        return NULL;
+    p = end + 2;
+
+    sink = exynos_media_parse_pad(media, p, &end);
+    if (sink == NULL)
+        return NULL;
+
+    *endp = end;
+
+    for (i = 0; i < source->entity->num_links; i++) {
+        link = &source->entity->links[i];
+
+        if (link->source == source && link->sink == sink)
+            return link;
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Parse string to a link on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing a link and its configuration
+ * and configure the link.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_parse_setup_link(
+        struct media_device *media,
+        const char *p,
+        char **endp)
+{
+    struct media_link *link;
+    __u32 flags;
+    char *end;
+
+    link = exynos_media_parse_link(media, p, &end);
+    if (link == NULL) {
+        ALOGE("Unable to parse link");
+        return -EINVAL;
+    }
+
+    p = end;
+    if (*p++ != '[') {
+        ALOGE("Unable to parse link flags");
+        return -EINVAL;
+    }
+
+    flags = strtoul(p, &end, 10);
+    for (p = end; isspace(*p); p++);
+    if (*p++ != ']') {
+        ALOGE("Unable to parse link flags");
+        return -EINVAL;
+    }
+
+    for (; isspace(*p); p++);
+    *endp = (char *)p;
+
+    ALOGD("%s: Setting up link %u:%u -> %u:%u [%u]", __func__,
+          link->source->entity->info.id, link->source->index,
+          link->sink->entity->info.id, link->sink->index,
+          flags);
+
+    return exynos_media_setup_link(media, link->source, link->sink, flags);
+}
+
+/**
+ * @brief Parse string to link(s) on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing link(s) separated by
+ * commas (,) and configure the link(s).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_parse_setup_links(struct media_device *media, const char *p)
+{
+    char *end;
+    int ret;
+
+    do {
+        ret = exynos_media_parse_setup_link(media, p, &end);
+        if (ret < 0)
+            return ret;
+
+        p = end + 1;
+    } while (*end == ',');
+
+    return *end ? -EINVAL : 0;
+}
diff --git a/libv4l2/exynos_subdev.c b/libv4l2/exynos_subdev.c
new file mode 100755 (executable)
index 0000000..cca0357
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_subdev.c
+ * \brief     source file for libv4l2
+ * \author    Jinsung Yang (jsgood.yang@samsung.com)
+ * \author    Sangwoo Park (sw5771.park@samsung.com)
+ * \date      2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ *   Initial version
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <exynos_v4l2.h>
+
+#include <exynos_log.h>
+#include <string.h>
+
+#define SUBDEV_MAX 191
+
+static int __subdev_open(const char *filename, int oflag, va_list ap)
+{
+    mode_t mode = 0;
+    int fd;
+
+    if (oflag & O_CREAT)
+        mode = va_arg(ap, int);
+
+    fd = open(filename, oflag, mode);
+
+    return fd;
+}
+
+int exynos_subdev_open(const char *filename, int oflag, ...)
+{
+    va_list ap;
+    int fd;
+
+    va_start(ap, oflag);
+    fd = __subdev_open(filename, oflag, ap);
+    va_end(ap);
+
+    return fd;
+}
+
+int exynos_subdev_get_node_num(const char *devname, int oflag, ...)
+{
+    bool found = false;
+    int ret = -1;
+    struct stat s;
+    va_list ap;
+    FILE *stream_fd;
+    char filename[64], name[64];
+    int i = 0;
+
+    do {
+        if (i > (SUBDEV_MAX - 128))
+            break;
+
+        /* video device node */
+        snprintf(filename, sizeof(filename), "/dev/v4l-subdev%d", i);
+
+        /* if the node is video device */
+        if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
+                ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
+            ALOGD("try node: %s", filename);
+            /* open sysfs entry */
+            snprintf(filename, sizeof(filename), "/sys/class/video4linux/v4l-subdev%d/name", i);
+            if (S_ISLNK(s.st_mode)) {
+                ALOGE("symbolic link detected");
+                return -1;
+            }
+            stream_fd = fopen(filename, "r");
+            if (stream_fd == NULL) {
+                ALOGE("failed to open sysfs entry for subdev");
+                continue;   /* try next */
+            }
+
+            /* read sysfs entry for device name */
+           char *p = fgets(name, sizeof(name), stream_fd);
+            fclose(stream_fd);
+
+            /* check read size */
+            if (p == NULL) {
+                ALOGE("failed to read sysfs entry for subdev");
+            } else {
+                /* matched */
+                if (strncmp(name, devname, strlen(devname)) == 0) {
+                    ALOGI("node found for device %s: /dev/v4l-subdev%d", devname, i);
+                    found = true;
+                    break;
+                }
+            }
+        }
+        i++;
+    } while (found == false);
+
+    if (found)
+        ret = i;
+    else
+        ALOGE("no subdev device found");
+
+    return ret;
+}
+
+int exynos_subdev_open_devname(const char *devname, int oflag, ...)
+{
+    bool found = false;
+    int fd = -1;
+    struct stat s;
+    va_list ap;
+    FILE *stream_fd;
+    char filename[64], name[64];
+    long size;
+    int i = 0;
+
+    do {
+        if (i > (SUBDEV_MAX - 128))
+            break;
+
+        /* video device node */
+        snprintf(filename, sizeof(filename), "/dev/v4l-subdev%d", i);
+
+        /* if the node is video device */
+        if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
+                ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
+            ALOGD("try node: %s", filename);
+            /* open sysfs entry */
+            snprintf(filename, sizeof(filename), "/sys/class/video4linux/v4l-subdev%d/name", i);
+            if (S_ISLNK(s.st_mode)) {
+                ALOGE("symbolic link detected");
+                return -1;
+            }
+            stream_fd = fopen(filename, "r");
+            if (stream_fd == NULL) {
+                ALOGE("failed to open sysfs entry for subdev");
+                continue;   /* try next */
+            }
+
+            /* read sysfs entry for device name */
+            char *p = fgets(name, sizeof(name), stream_fd);
+            fclose(stream_fd);
+
+            /* check read size */
+            if (p == NULL) {
+                ALOGE("failed to read sysfs entry for subdev");
+            } else {
+                /* matched */
+                if (strncmp(name, devname, strlen(devname)) == 0) {
+                    ALOGI("node found for device %s: /dev/v4l-subdev%d", devname, i);
+                    found = true;
+                    break;
+                }
+            }
+        }
+       i++;
+    } while (found == false);
+
+    if (found) {
+        snprintf(filename, sizeof(filename), "/dev/v4l-subdev%d", i);
+        va_start(ap, oflag);
+        fd = __subdev_open(filename, oflag, ap);
+        va_end(ap);
+
+        if (fd > 0)
+            ALOGI("open subdev device %s", filename);
+        else
+            ALOGE("failed to open subdev device %s", filename);
+    } else {
+        ALOGE("no subdev device found");
+    }
+
+    return fd;
+}
+
+int exynos_subdev_close(int fd)
+{
+    int ret = -1;
+
+    if (fd < 0)
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+    else
+        ret = close(fd);
+
+    return ret;
+}
+
+/**
+ * @brief enum frame size on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_frame_size(int fd, struct v4l2_subdev_frame_size_enum *frame_size_enum)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!frame_size_enum) {
+        ALOGE("%s: frame_size_enum is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, frame_size_enum);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Retrieve the format on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_fmt(int fd, struct v4l2_subdev_format *fmt)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!fmt) {
+        ALOGE("%s: fmt is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FMT");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Set the format on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_fmt(int fd, struct v4l2_subdev_format *fmt)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!fmt) {
+        ALOGE("%s: fmt is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_S_FMT, fmt);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FMT");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Retrieve the crop rectangle on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_crop(int fd, struct v4l2_subdev_crop *crop)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!crop) {
+        ALOGE("%s: crop is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_G_CROP, crop);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_CROP");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Set the crop rectangle on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_crop(int fd, struct v4l2_subdev_crop *crop)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!crop) {
+        ALOGE("%s: crop is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_S_CROP, crop);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_CROP");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_frame_interval(int fd, struct v4l2_subdev_frame_interval_enum *frame_internval_enum)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!frame_internval_enum) {
+        ALOGE("%s: frame_internval_enum is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, frame_internval_enum);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!frame_internval) {
+        ALOGE("%s: frame_internval is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, frame_internval);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Set the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!frame_internval) {
+        ALOGE("%s: frame_internval is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, frame_internval);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL");
+        return ret;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief enum mbus code
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_mbus_code(int fd, struct v4l2_subdev_mbus_code_enum *mbus_code_enum)
+{
+    int ret = -1;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!mbus_code_enum) {
+        ALOGE("%s: mbus_code_enum is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, mbus_code_enum);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE");
+        return ret;
+    }
+
+    return ret;
+}
diff --git a/libv4l2/exynos_v4l2.c b/libv4l2/exynos_v4l2.c
new file mode 100755 (executable)
index 0000000..3286e8d
--- /dev/null
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      exynos_v4l2.c
+ * \brief     source file for libv4l2
+ * \author    Jinsung Yang (jsgood.yang@samsung.com)
+ * \author    Sangwoo Park (sw5771.park@samsung.com)
+ * \date      2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ *   Initial version
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <exynos_v4l2.h>
+
+#include <exynos_log.h>
+
+#include <linux/videodev2.h>
+
+#define VIDEODEV_MAX 255
+
+//#define EXYNOS_V4L2_TRACE 0
+#ifdef EXYNOS_V4L2_TRACE
+#define Exynos_v4l2_In() ALOGV("%s In , Line: %d", __FUNCTION__, __LINE__)
+#define Exynos_v4l2_Out() ALOGV("%s Out , Line: %d", __FUNCTION__, __LINE__)
+#else
+#define Exynos_v4l2_In() ((void *)0)
+#define Exynos_v4l2_Out() ((void *)0)
+#endif
+
+static bool __v4l2_check_buf_type(enum v4l2_buf_type type)
+{
+    bool supported;
+
+    switch (type) {
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+    case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+        supported = true;
+        break;
+
+    default:
+        supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false;
+        break;
+    }
+
+    return supported;
+}
+
+static int __v4l2_open(const char *filename, int oflag, va_list ap)
+{
+    mode_t mode = 0;
+    int fd;
+
+    if (oflag & O_CREAT)
+        mode = va_arg(ap, int);
+
+    fd = open(filename, oflag, mode);
+
+    return fd;
+}
+
+int exynos_v4l2_open(const char *filename, int oflag, ...)
+{
+    va_list ap;
+    int fd;
+
+    Exynos_v4l2_In();
+
+    va_start(ap, oflag);
+    fd = __v4l2_open(filename, oflag, ap);
+    va_end(ap);
+
+    Exynos_v4l2_Out();
+
+    return fd;
+}
+
+int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
+{
+    bool found = false;
+    int fd = -1;
+    struct stat s;
+    va_list ap;
+    FILE *stream_fd;
+    char filename[64], name[64];
+    int i = 0;
+
+    Exynos_v4l2_In();
+
+    do {
+        if (i > VIDEODEV_MAX)
+            break;
+
+        /* video device node */
+        snprintf(filename, sizeof(filename), "/dev/video%d", i);
+
+        /* if the node is video device */
+        if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
+                ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
+            ALOGD("try node: %s", filename);
+            /* open sysfs entry */
+            snprintf(filename, sizeof(filename), "/sys/class/video4linux/video%d/name", i);
+            if (S_ISLNK(s.st_mode)) {
+                ALOGE("symbolic link detected");
+                return -1;
+            }
+            stream_fd = fopen(filename, "r");
+            if (stream_fd == NULL) {
+                ALOGE("failed to open sysfs entry for videodev");
+                continue;   /* try next */
+            }
+
+            /* read sysfs entry for device name */
+            char *p = fgets(name, sizeof(name), stream_fd);
+            fclose(stream_fd);
+
+            /* check read size */
+            if (p == NULL) {
+                ALOGE("failed to read sysfs entry for videodev");
+            } else {
+                /* matched */
+                if (strncmp(name, devname, strlen(devname)) == 0) {
+                    ALOGI("node found for device %s: /dev/video%d", devname, i);
+                    found = true;
+                    break;
+                }
+            }
+        }
+        i++;
+    } while (found == false);
+
+    if (found) {
+        snprintf(filename, sizeof(filename), "/dev/video%d", i);
+        va_start(ap, oflag);
+        fd = __v4l2_open(filename, oflag, ap);
+        va_end(ap);
+
+        if (fd > 0)
+            ALOGI("open video device %s", filename);
+        else
+            ALOGE("failed to open video device %s", filename);
+    } else {
+        ALOGE("no video device found");
+    }
+
+    Exynos_v4l2_Out();
+
+    return fd;
+}
+
+int exynos_v4l2_close(int fd)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0)
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+    else
+        ret = close(fd);
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf)
+{
+    int ret = -1;
+    struct v4l2_input input;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return NULL;
+    }
+
+    input.index = index;
+    ret = ioctl(fd, VIDIOC_ENUMINPUT, &input, 32);
+    if (ret) {
+        ALOGE("%s: no matching index founds", __func__);
+        return false;
+    }
+
+    ALOGI("Name of input channel[%d] is %s", input.index, input.name);
+
+    strncpy(input_name_buf, (const char *)input.name, 32);
+
+    Exynos_v4l2_Out();
+
+    return true;
+}
+
+int exynos_v4l2_s_input(int fd, int index)
+{
+    int ret = -1;
+    struct v4l2_input input;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    input.index = index;
+
+    ret = ioctl(fd, VIDIOC_S_INPUT, &input);
+    if (ret){
+        ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+bool exynos_v4l2_querycap(int fd, unsigned int need_caps)
+{
+    struct v4l2_capability cap;
+    int ret;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return false;
+    }
+
+    if (!(need_caps & V4L2_CAP_VIDEO_CAPTURE) &&
+            !(need_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) &&
+            !(need_caps & V4L2_CAP_VIDEO_OUTPUT) &&
+            !(need_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) &&
+            !(need_caps & V4L2_CAP_VIDEO_OVERLAY)) {
+        ALOGE("%s: unsupported capabilities", __func__);
+        return false;
+    }
+
+    memset(&cap, 0, sizeof(cap));
+
+    ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno));
+        return false;
+    }
+
+    if ((need_caps & cap.capabilities) != need_caps) {
+        ALOGE("%s: unsupported capabilities", __func__);
+        return false;
+    }
+
+    Exynos_v4l2_Out();
+
+    return true;
+}
+
+bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt)
+{
+    struct v4l2_fmtdesc fmtdesc;
+    int found = 0;
+
+    Exynos_v4l2_In();
+
+    fmtdesc.type = type;
+    fmtdesc.index = 0;
+
+    while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+        if (fmtdesc.pixelformat == fmt) {
+            ALOGE("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
+            found = 1;
+            break;
+        }
+
+        fmtdesc.index++;
+    }
+
+    if (!found) {
+        ALOGE("%s: unsupported pixel format", __func__);
+        return false;
+    }
+
+    Exynos_v4l2_Out();
+
+    return true;
+}
+
+int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!fmt) {
+        ALOGE("%s: fmt is NULL", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(fmt->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_G_FMT, fmt);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!fmt) {
+        ALOGE("%s: fmt is NULL", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(fmt->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    } else {
+        ret = ioctl(fd, request, fmt);
+        if (ret) {
+            if (request == VIDIOC_TRY_FMT)
+                ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno));
+            else
+                ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno));
+
+            return ret;
+        }
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt)
+{
+    return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt);
+}
+
+int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt)
+{
+    return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt);
+}
+
+int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req)
+{
+    int ret = -1;
+    unsigned int count;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!req) {
+        ALOGE("%s: req is NULL", __func__);
+        return ret;
+    }
+
+    if ((req->memory != V4L2_MEMORY_MMAP) &&
+       (req->memory != V4L2_MEMORY_USERPTR) &&
+       (req->memory != V4L2_MEMORY_DMABUF)) {
+        ALOGE("%s: unsupported memory type", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(req->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    count = req->count;
+
+    ret = ioctl(fd, VIDIOC_REQBUFS, req);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno));
+        return ret;
+    }
+
+    if (count != req->count) {
+        ALOGW("number of buffers had been changed: %d => %d", count, req->count);
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!buf) {
+        ALOGE("%s: buf is NULL", __func__);
+        return ret;
+    }
+
+    if ((buf->memory != V4L2_MEMORY_MMAP) &&
+       (buf->memory != V4L2_MEMORY_DMABUF)) {
+        ALOGE("%s: unsupported memory type", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(buf->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_QUERYBUF, buf);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!buf) {
+        ALOGE("%s: buf is NULL", __func__);
+        return ret;
+    }
+
+    if ((buf->memory != V4L2_MEMORY_MMAP) &&
+       (buf->memory != V4L2_MEMORY_USERPTR) &&
+       (buf->memory != V4L2_MEMORY_DMABUF)) {
+        ALOGE("%s: unsupported memory type", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(buf->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_QBUF, buf);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!buf) {
+        ALOGE("%s: buf is NULL", __func__);
+        return ret;
+    }
+
+    if ((buf->memory != V4L2_MEMORY_MMAP) &&
+       (buf->memory != V4L2_MEMORY_USERPTR) &&
+       (buf->memory != V4L2_MEMORY_DMABUF)) {
+        ALOGE("%s: unsupported memory type", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(buf->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_DQBUF, buf);
+    if (ret) {
+        if (errno == EAGAIN)
+            return -errno;
+
+        ALOGW("failed to ioctl: VIDIOC_DQBUF (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_STREAMON, &type);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!crop) {
+        ALOGE("%s: crop is NULL", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(crop->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_CROPCAP, crop);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!crop) {
+        ALOGE("%s: crop is NULL", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(crop->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_G_CROP, crop);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (!crop) {
+        ALOGE("%s: crop is NULL", __func__);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(crop->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_S_CROP, crop);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value)
+{
+    int ret = -1;
+    struct v4l2_control ctrl;
+
+    Exynos_v4l2_In();
+
+    ctrl.id = id;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_G_CTRL (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    *value = ctrl.value;
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value)
+{
+    int ret = -1;
+    struct v4l2_control ctrl;
+
+    Exynos_v4l2_In();
+
+    ctrl.id = id;
+    ctrl.value = value;
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_S_CTRL (%d)", errno);
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_prepare(int fd, struct v4l2_buffer *arg)
+{
+    int ret = -1;
+    struct v4l2_control ctrl;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_PREPARE_BUF, arg);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_PREPARE_BUF (%d)", errno);
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(streamparm->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_G_PARM, streamparm);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (__v4l2_check_buf_type(streamparm->type) == false) {
+        ALOGE("%s: unsupported buffer type", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_S_PARM, streamparm);
+    if (ret) {
+        ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno));
+        return ret;
+    }
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (ctrl == NULL) {
+        ALOGE("%s: ctrl is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl);
+    if (ret)
+        ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno));
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
+
+int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
+{
+    int ret = -1;
+
+    Exynos_v4l2_In();
+
+    if (fd < 0) {
+        ALOGE("%s: invalid fd: %d", __func__, fd);
+        return ret;
+    }
+
+    if (ctrl == NULL) {
+        ALOGE("%s: ctrl is NULL", __func__);
+        return ret;
+    }
+
+    ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl);
+    if (ret)
+        ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno));
+
+    Exynos_v4l2_Out();
+
+    return ret;
+}
diff --git a/packaging/libexynos-common.spec b/packaging/libexynos-common.spec
new file mode 100755 (executable)
index 0000000..493f7b4
--- /dev/null
@@ -0,0 +1,96 @@
+Name: libexynos-common
+Summary: HAL support library
+Version: 0.0.1
+License: TO BE FILLED IN
+Group: Development/Libraries
+Release: 0
+ExclusiveArch: %arm
+Source: %{name}-%{version}.tar.gz
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+#!BuildIgnore: kernel-headers
+BuildRequires:  kernel-headers-exynos7270-tw2
+BuildRequires:  pkgconfig(dlog)
+BuildConflicts: linux-glibc-devel
+
+%description
+implementation of libexynos common
+
+
+%package devel
+Summary: HAL support library (Developement)
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+development package for libexynos-common
+
+%prep
+%setup -q
+
+%build
+./autogen.sh
+
+export CFLAGS+=" -mfpu=neon\
+ -DUSE_DLOG\
+  -DGST_EXT_TIME_ANALYSIS"
+
+LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--hash-style=both -Wl,--as-needed"; export LDFLAGS
+%configure --prefix=%{_prefix} --disable-static --enable-dlog
+
+
+#make %{?jobs:-j%jobs}
+make
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp COPYING %{buildroot}/usr/share/license/%{name}
+mkdir -p %{buildroot}%{_includedir}
+mkdir -p %{buildroot}%{_includedir}/linux
+mkdir -p %{buildroot}%{_includedir}/system
+mkdir -p %{buildroot}%{_libdir}/pkgconfig
+mkdir -p %{buildroot}/usr/libion/include/ion/
+mkdir -p %{buildroot}/usr/libion/kernel-headers/linux
+install -m0644 include/content_protect.h %{buildroot}%{_includedir}
+install -m0644 include/csc.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_format.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_gscaler.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_ion.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_log.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_scaler.h %{buildroot}%{_includedir}
+install -m0644 include/exynos_v4l2.h %{buildroot}%{_includedir}
+install -m0644 include/ion.h %{buildroot}%{_includedir}
+install -m0644 include/media.h %{buildroot}%{_includedir}
+install -m0644 include/swconverter.h %{buildroot}%{_includedir}
+install -m0644 include/linux/compiler.h %{buildroot}%{_includedir}/linux
+install -m0644 include/system/graphics.h %{buildroot}%{_includedir}/system
+install -m0644 libion/include/ion/ion.h %{buildroot}/usr/libion/include/ion/
+install -m0644 libion/kernel-headers/linux/ion.h %{buildroot}/usr/libion/kernel-headers/linux
+install exynos-common.pc %{buildroot}%{_libdir}/pkgconfig/
+%make_install
+
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%manifest libexynos-common.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libcsc.so*
+%{_libdir}/libexynosgscaler.so*
+%{_libdir}/libion.so*
+%{_libdir}/libswconverter.so*
+%{_libdir}/libexynosv4l2.so*
+/usr/share/license/%{name}
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/*
+/usr/libion/include/ion/*
+/usr/libion/kernel-headers/linux/*
+%{_libdir}/pkgconfig/*
+
+