summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSejun Park <sejun79.park@samsung.com>2017-03-15 13:50:44 +0900
committerSejun Park <sejun79.park@samsung.com>2017-03-16 13:24:12 +0900
commit825a2ef5c5394cda5191f38118238d7b74c2b1cc (patch)
tree3e85c28a14e963c47ab07b5c51f396928f166e30
parent8c640ad377e054ceed527bf29397b982b054155b (diff)
downloadlibexynos-common-825a2ef5c5394cda5191f38118238d7b74c2b1cc.tar.gz
libexynos-common-825a2ef5c5394cda5191f38118238d7b74c2b1cc.tar.bz2
libexynos-common-825a2ef5c5394cda5191f38118238d7b74c2b1cc.zip
Change-Id: Iee46e0c7bb5146ef516d9652c4c5634022cd4310
-rwxr-xr-xCOPYING203
-rwxr-xr-xMakefile.am4
-rwxr-xr-xREADME15
-rwxr-xr-xautogen.sh6
-rwxr-xr-xconfigure.ac70
-rwxr-xr-xexynos-common.pc11
-rwxr-xr-xinclude/content_protect.h59
-rwxr-xr-xinclude/csc.h562
-rwxr-xr-xinclude/exynos_format.h224
-rwxr-xr-xinclude/exynos_gscaler.h519
-rwxr-xr-xinclude/exynos_ion.h53
-rwxr-xr-xinclude/exynos_log.h56
-rwxr-xr-xinclude/exynos_scaler.h451
-rwxr-xr-xinclude/exynos_v4l2.h208
-rwxr-xr-xinclude/ion.h188
-rwxr-xr-xinclude/linux/compiler.h95
-rwxr-xr-xinclude/media.h125
-rwxr-xr-xinclude/swconverter.h405
-rwxr-xr-xinclude/system/graphics.h763
-rwxr-xr-xlibcsc/Makefile.am11
-rwxr-xr-xlibcsc/csc.c1309
-rwxr-xr-xlibexynos-common.manifest5
-rwxr-xr-xlibgscaler/Makefile.am7
-rwxr-xr-xlibgscaler/libgscaler.cpp646
-rwxr-xr-xlibgscaler/libgscaler_obj.cpp2074
-rwxr-xr-xlibgscaler/libgscaler_obj.h265
-rwxr-xr-xlibion/Makefile.am12
-rwxr-xr-xlibion/include/ion/ion.h47
-rwxr-xr-xlibion/ion.c190
-rwxr-xr-xlibion/kernel-headers/linux/ion.h106
-rwxr-xr-xlibswconverter/Makefile.am24
-rwxr-xr-xlibswconverter/csc_BGRA8888_to_RGBA8888_NEON.s112
-rwxr-xr-xlibswconverter/csc_BGRA8888_to_YUV420SP_NEON.s365
-rwxr-xr-xlibswconverter/csc_RGBA8888_to_YUV420SP_NEON.s388
-rwxr-xr-xlibswconverter/csc_interleave_memcpy_neon.s120
-rwxr-xr-xlibswconverter/csc_linear_to_tiled_crop_neon.s492
-rwxr-xr-xlibswconverter/csc_linear_to_tiled_interleave_crop_neon.s563
-rwxr-xr-xlibswconverter/csc_tiled_to_linear_crop_neon.s701
-rwxr-xr-xlibswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s786
-rwxr-xr-xlibswconverter/csc_tiled_to_linear_uv_deinterleave_neon.s250
-rwxr-xr-xlibswconverter/csc_tiled_to_linear_uv_neon.s217
-rwxr-xr-xlibswconverter/csc_tiled_to_linear_y_neon.s232
-rwxr-xr-xlibswconverter/swconvertor.c2214
-rwxr-xr-xlibv4l2/Makefile.am11
-rwxr-xr-xlibv4l2/exynos_mc.c774
-rwxr-xr-xlibv4l2/exynos_subdev.c453
-rwxr-xr-xlibv4l2/exynos_v4l2.c889
-rwxr-xr-xpackaging/libexynos-common.spec96
48 files changed, 17376 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100755
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
index 0000000..2bef805
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = libion libv4l2 libswconverter libcsc libgscaler
+
+pcfiles = exynoes-common.pc
+
diff --git a/README b/README
new file mode 100755
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
index 0000000..30d679f
--- /dev/null
+++ b/autogen.sh
@@ -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
index 0000000..6adadc5
--- /dev/null
+++ b/configure.ac
@@ -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
index 0000000..d3e44ea
--- /dev/null
+++ b/exynos-common.pc
@@ -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
index 0000000..3cbf31f
--- /dev/null
+++ b/include/content_protect.h
@@ -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
index 0000000..7f277d6
--- /dev/null
+++ b/include/csc.h
@@ -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
index 0000000..23a0d0c
--- /dev/null
+++ b/include/exynos_format.h
@@ -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
index 0000000..38b57a4
--- /dev/null
+++ b/include/exynos_gscaler.h
@@ -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
index 0000000..ed79198
--- /dev/null
+++ b/include/exynos_ion.h
@@ -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
index 0000000..1b1faee
--- /dev/null
+++ b/include/exynos_log.h
@@ -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
index 0000000..1eea919
--- /dev/null
+++ b/include/exynos_scaler.h
@@ -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
index 0000000..6320529
--- /dev/null
+++ b/include/exynos_v4l2.h
@@ -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
index 0000000..67161ca
--- /dev/null
+++ b/include/ion.h
@@ -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
index 0000000..9dd0d8a
--- /dev/null
+++ b/include/linux/compiler.h
@@ -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
index 0000000..d627bef
--- /dev/null
+++ b/include/media.h
@@ -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
index 0000000..877e4ba
--- /dev/null
+++ b/include/swconverter.h
@@ -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
index 0000000..afd9f7b
--- /dev/null
+++ b/include/system/graphics.h
@@ -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
index 0000000..3293e20
--- /dev/null
+++ b/libcsc/Makefile.am
@@ -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
index 0000000..d90968e
--- /dev/null
+++ b/libcsc/csc.c
@@ -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
index 0000000..a76fdba
--- /dev/null
+++ b/libexynos-common.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
diff --git a/libgscaler/Makefile.am b/libgscaler/Makefile.am
new file mode 100755
index 0000000..afe91ef
--- /dev/null
+++ b/libgscaler/Makefile.am
@@ -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
index 0000000..8073e80
--- /dev/null
+++ b/libgscaler/libgscaler.cpp
@@ -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
index 0000000..58b88e0
--- /dev/null
+++ b/libgscaler/libgscaler_obj.cpp
@@ -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
index 0000000..e36e397
--- /dev/null
+++ b/libgscaler/libgscaler_obj.h
@@ -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
index 0000000..80234e9
--- /dev/null
+++ b/libion/Makefile.am
@@ -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
index 0000000..6b847e0
--- /dev/null
+++ b/libion/include/ion/ion.h
@@ -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
index 0000000..403a585
--- /dev/null
+++ b/libion/ion.c
@@ -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
index 0000000..bb145d1
--- /dev/null
+++ b/libion/kernel-headers/linux/ion.h
@@ -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
index 0000000..2a98d0e
--- /dev/null
+++ b/libswconverter/Makefile.am
@@ -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
index 0000000..0f4b45b
--- /dev/null
+++ b/libswconverter/csc_BGRA8888_to_RGBA8888_NEON.s
@@ -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
index 0000000..956f553
--- /dev/null
+++ b/libswconverter/csc_BGRA8888_to_YUV420SP_NEON.s
@@ -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
index 0000000..92c2d58
--- /dev/null
+++ b/libswconverter/csc_RGBA8888_to_YUV420SP_NEON.s
@@ -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
index 0000000..1ab25b6
--- /dev/null
+++ b/libswconverter/csc_interleave_memcpy_neon.s
@@ -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
index 0000000..8f59826
--- /dev/null
+++ b/libswconverter/csc_linear_to_tiled_crop_neon.s
@@ -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
index 0000000..33a31da
--- /dev/null
+++ b/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s
@@ -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
index 0000000..9cb81b5
--- /dev/null
+++ b/libswconverter/csc_tiled_to_linear_crop_neon.s
@@ -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
index 0000000..cdd101e
--- /dev/null
+++ b/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s
@@ -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
index 0000000..b4d5084
--- /dev/null
+++ b/libswconverter/csc_tiled_to_linear_uv_deinterleave_neon.s
@@ -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
index 0000000..c90d1f3
--- /dev/null
+++ b/libswconverter/csc_tiled_to_linear_uv_neon.s
@@ -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
index 0000000..3cdf092
--- /dev/null
+++ b/libswconverter/csc_tiled_to_linear_y_neon.s
@@ -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
index 0000000..b3330fe
--- /dev/null
+++ b/libswconverter/swconvertor.c
@@ -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
index 0000000..0994321
--- /dev/null
+++ b/libv4l2/Makefile.am
@@ -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
index 0000000..142c0aa
--- /dev/null
+++ b/libv4l2/exynos_mc.c
@@ -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
index 0000000..cca0357
--- /dev/null
+++ b/libv4l2/exynos_subdev.c
@@ -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
index 0000000..3286e8d
--- /dev/null
+++ b/libv4l2/exynos_v4l2.c
@@ -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
index 0000000..493f7b4
--- /dev/null
+++ b/packaging/libexynos-common.spec
@@ -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/*
+
+