qcom/display: Update HALs

- Update the display HAL from Code Aurora Forum
- Add updated overlay library
- Enable HWC with basic video going through overlay
- Cleanup some files

Change-Id: I65c687c51be458cee71213c79e03eeda962d9086
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
new file mode 100644
index 0000000..24663b7
--- /dev/null
+++ b/libcopybit/Android.mk
@@ -0,0 +1,59 @@
+# Copyright (C) 2008 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.
+
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+
+ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
+    include $(CLEAR_VARS)
+    LOCAL_PRELINK_MODULE := false
+    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+    LOCAL_SHARED_LIBRARIES := liblog libdl libcutils libmemalloc libutils
+    LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
+    LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+    LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+    LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
+    LOCAL_MODULE_TAGS := optional
+    include $(BUILD_SHARED_LIBRARY)
+else
+    ifneq ($(call is-chipset-in-board-platform,msm7630),true)
+        ifeq ($(call is-board-platform-in-list,$(MSM7K_BOARD_PLATFORMS)),true)
+            include $(CLEAR_VARS)
+            ifeq ($(ARCH_ARM_HAVE_NEON),true)
+                LOCAL_CFLAGS += -D__ARM_HAVE_NEON
+            endif
+            ifeq ($(call is-board-platform,msm7627a),true)
+                LOCAL_CFLAGS += -DTARGET_7x27A
+            endif
+            ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
+                LOCAL_CFLAGS += -DUSE_ASHMEM
+                ifeq ($(call is-chipset-prefix-in-board-platform,msm7627),true)
+                   LOCAL_CFLAGS += -DTARGET_7x27
+                endif
+            endif
+
+            LOCAL_PRELINK_MODULE := false
+            LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+            LOCAL_SHARED_LIBRARIES := liblog libmemalloc
+            LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+            LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+            LOCAL_MODULE_TAGS := optional
+            LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qcom/display/libgralloc
+            LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+    endif
+endif
diff --git a/libcopybit/MODULE_LICENSE_APACHE2 b/libcopybit/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libcopybit/MODULE_LICENSE_APACHE2
diff --git a/libcopybit/NOTICE b/libcopybit/NOTICE
new file mode 100644
index 0000000..9c1e63a
--- /dev/null
+++ b/libcopybit/NOTICE
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2008, 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.
+
+   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.
+
+
+                                 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
diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h
new file mode 100644
index 0000000..8c7d05b
--- /dev/null
+++ b/libcopybit/c2d2.h
@@ -0,0 +1,618 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __c2d2_h_
+#define __c2d2_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef C2D_API
+#define C2D_API /* define API export as needed */
+#endif
+#if !defined(int32) && !defined(_INT32_DEFINED)
+typedef int                     int32;
+#define _INT32_DEFINED
+#endif
+#if !defined(uint32) && !defined(_UINT32_DEFINED)
+typedef unsigned int            uint32;
+#define _UINT32_DEFINED
+#endif
+
+/*****************************************************************************/
+/*********************** Blit definitions *****************************/
+/*****************************************************************************/
+
+/* Status codes, returned by any blit function */
+typedef enum {
+    C2D_STATUS_OK              = 0,
+    C2D_STATUS_NOT_SUPPORTED   = 1,
+    C2D_STATUS_OUT_OF_MEMORY   = 2,
+    C2D_STATUS_INVALID_PARAM   = 3,
+    C2D_STATUS_SURFACE_IN_USE  = 4,
+} C2D_STATUS;
+
+
+/* Definitions of color format modes, used together with color formats */
+typedef enum {
+    C2D_FORMAT_PACK_INTO_32BIT   = (1 <<  8), /* pack into dword if set */
+    C2D_FORMAT_SWAP_ENDIANNESS   = (1 <<  9), /* swaps the order */
+    C2D_FORMAT_LINEAR_SPACE      = (1 << 10), /* linear color space */
+    C2D_FORMAT_PREMULTIPLIED     = (1 << 11), /* alpha premultiplied */
+    C2D_FORMAT_INVERT_ALPHA      = (1 << 12), /* inverts alpha */
+    C2D_FORMAT_DISABLE_ALPHA     = (1 << 13), /* disables alpha */
+    C2D_FORMAT_INTERLACED        = (1 << 14), /* YUV line-interlaced */
+    C2D_FORMAT_TRANSPARENT       = (1 << 15), /* YUV 1-bit alpha in Y */
+    C2D_FORMAT_MACROTILED        = (1 << 16), /* tiled in macro level */
+    C2D_FORMAT_TILED_4x4         = (1 << 17), /* 4x4 tiled format */
+    C2D_FORMAT_SWAP_RB           = (1 << 18), /* Swap R & B color components */
+} C2D_FORMAT_MODE;
+
+/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
+ * The bits of each color channel are packed into a machine word
+ * representing a single pixel from left to right (MSB to LSB) in the
+ * order indicated by format name. For the sub-byte formats the pixels
+ * are packed into bytes from left to right (MSbit to LSBit).
+ * If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal
+ * machine word used for pixel storage is 32-bit and the whole word
+ * is reversed if endianness is swapped.
+ * If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a
+ * minimal machine word representing a pixel
+ * is reversed for both sub-byte and multi-byte formats.
+ * If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of
+ * the formats below is considered linear, if applicable.
+ * If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels
+ * are premultiplied with the alpha, if applicable.
+ * If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation
+ * is inverted: 0 - opaque, 1 - transparent, if applicable.
+ * If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves
+ * as a placeholder and is ignored during blit, if applicable.
+ * If the C2D_FORMAT_MACROTILED bit is set, the surface is in the
+ * tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats  */
+typedef enum {
+    C2D_COLOR_FORMAT_1            = 0,   /* 1-bit alpha/color expansion */
+
+    C2D_COLOR_FORMAT_2_PALETTE    = 1,   /* 2-bit indices for palette */
+    C2D_COLOR_FORMAT_4_PALETTE    = 2,   /* 4-bit indices for palette */
+    C2D_COLOR_FORMAT_8_PALETTE    = 3,   /* 8-bit indices for palette */
+
+    C2D_COLOR_FORMAT_2_L          = 4,   /* 2-bit grayscale */
+    C2D_COLOR_FORMAT_4_L          = 5,   /* 4-bit grayscale */
+    C2D_COLOR_FORMAT_8_L          = 6,   /* 8-bit grayscale */
+
+    C2D_COLOR_FORMAT_2_A          = 7,   /* 2-bit alpha only */
+    C2D_COLOR_FORMAT_4_A          = 8,   /* 4-bit alpha only */
+    C2D_COLOR_FORMAT_8_A          = 9,   /* 8-bit alpha only */
+
+    C2D_COLOR_FORMAT_444_RGB      = 10,  /* 12-bit colors */
+    C2D_COLOR_FORMAT_565_RGB      = 11,  /* 16-bit colors */
+    C2D_COLOR_FORMAT_888_RGB      = 12,  /* 24-bit colors */
+
+    C2D_COLOR_FORMAT_1555_ARGB    = 13,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_ARGB    = 14,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_8565_ARGB    = 15,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_ARGB    = 16,  /* 32-bit colors (8-bit alpha) */
+
+    C2D_COLOR_FORMAT_5551_RGBA    = 17,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_RGBA    = 18,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_5658_RGBA    = 19,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_RGBA    = 20,  /* 32-bit colors (8-bit alpha) */
+
+    /* derived RGB color formats (base format + mode bits) */
+
+} C2D_RGB_FORMAT;
+
+/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF.
+ * Each of Y,U,V channels usually takes 1 byte and therefore is
+ * individually addressable. The definitions below show how Y,U,V
+ * channels are packed into macropixels for each particular format.
+ * The order is from left (smaller byte addresses) to right (larger
+ * byte addresses). The first three digits (4xx) denote the chroma
+ * subsampling in standard YUV notation. The digits in the macropixel
+ * denote that the whole block (from the previous digit or from the
+ * beginning) has to be repeated the number of times. Underscores
+ * between Y,U,V channels are used to describe separate planes for
+ * planar YUV formats. Formats are mapped to numbers so that future
+ * versions with various YUV permutations are easy to add.
+ * If the C2D_FORMAT_INTERLACED bit is set, the line order is
+ * interlaced: 0,2,4,...1,3,5... if applicable.
+ * If the C2D_FORMAT_TRANSPARENT bit is set, the least significant
+ * bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */
+typedef enum {
+    C2D_COLOR_FORMAT_411_YYUYYV   = 110, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_YUYYVY   = 111, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYYVYY   = 112, /* packed, 12-bit, "Y411" */
+    C2D_COLOR_FORMAT_411_YUYV2Y4  = 116, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYVY2Y4  = 117, /* packed, 12-bit, "Y41P" */
+
+    C2D_COLOR_FORMAT_422_YUYV     = 120, /* packed, 16-bit, "YUY2" */
+    C2D_COLOR_FORMAT_422_UYVY     = 121, /* packed, 16-bit, "UYVY" */
+    C2D_COLOR_FORMAT_422_YVYU     = 122, /* packed, 16-bit, "YVYU" */
+    C2D_COLOR_FORMAT_422_VYUY     = 123, /* packed, 16-bit         */
+
+    C2D_COLOR_FORMAT_444_YUV      = 130, /* packed, 24-bit         */
+    C2D_COLOR_FORMAT_444_UYV      = 131, /* packed, 24-bit, "IYU2" */
+    C2D_COLOR_FORMAT_444_AYUV     = 136, /* packed, 24-bit, "AYUV" */
+
+    C2D_COLOR_FORMAT_410_Y_UV     = 150, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_411_Y_UV     = 151, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_420_Y_UV     = 152, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_422_Y_UV     = 153, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_444_Y_UV     = 154, /* planar, Y + interleaved UV */
+
+    C2D_COLOR_FORMAT_410_Y_VU     = 160, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_411_Y_VU     = 161, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_420_Y_VU     = 162, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_422_Y_VU     = 163, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_444_Y_VU     = 164, /* planar, Y + interleaved VU */
+
+    C2D_COLOR_FORMAT_410_Y_U_V    = 170, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_411_Y_U_V    = 171, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_420_Y_V_U    = 172, /* planar, Y + V + U separate */
+    C2D_COLOR_FORMAT_420_Y_U_V    = 173, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_422_Y_U_V    = 174, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_444_Y_U_V    = 175, /* planar, Y + U + V separate */
+
+    C2D_COLOR_FORMAT_800_Y        = 190, /* planar, Y only, grayscale */
+
+    /* derived YUV color formats (base format + mode bits), FOURCC */
+
+    C2D_COLOR_FORMAT_411_Y411     = 112,
+    C2D_COLOR_FORMAT_411_Y41P     = 117,
+    C2D_COLOR_FORMAT_411_IY41     = 117 | (1 << 14),
+    C2D_COLOR_FORMAT_411_Y41T     = 117 | (1 << 15),
+
+    C2D_COLOR_FORMAT_422_YUY2     = 120,
+    C2D_COLOR_FORMAT_422_IUYV     = 121 | (1 << 14),
+    C2D_COLOR_FORMAT_422_Y42T     = 121 | (1 << 15),
+    C2D_COLOR_FORMAT_444_IYU2     = 131,
+
+    C2D_COLOR_FORMAT_420_NV12     = 152,
+    C2D_COLOR_FORMAT_420_NV21     = 162,
+
+    C2D_COLOR_FORMAT_410_YUV9     = 170,
+    C2D_COLOR_FORMAT_410_YVU9     = 170,
+    C2D_COLOR_FORMAT_411_Y41B     = 171,
+    C2D_COLOR_FORMAT_420_YV12     = 172,
+    C2D_COLOR_FORMAT_420_IYUV     = 173,
+    C2D_COLOR_FORMAT_420_I420     = 173,
+    C2D_COLOR_FORMAT_422_YV16     = 174,
+    C2D_COLOR_FORMAT_422_Y42B     = 174,
+
+    C2D_COLOR_FORMAT_800_Y800     = 190,
+
+} C2D_YUV_FORMAT;
+
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_SOURCE_RECT_BIT      = (1 <<  0), /* enables source_rect field */
+    C2D_MIRROR_H_BIT         = (1 <<  1), /* enables horizontal flipping */
+    C2D_MIRROR_V_BIT         = (1 <<  2), /* enables vertical flipping */
+    C2D_SOURCE_TILE_BIT      = (1 <<  3), /* enables source surface tiling */
+    C2D_TARGET_RECT_BIT      = (1 <<  4), /* enables target_rect field */
+    C2D_ROTATE_BIT           = (1 <<  5), /* enables all rotation fields */
+    C2D_SCISSOR_RECT_BIT     = (1 <<  6), /* enables scissor_rect field */
+    C2D_MASK_SURFACE_BIT     = (1 <<  7), /* enables mask_surface_id field */
+    C2D_MASK_ALIGN_BIT       = (1 <<  8), /* aligns mask to source_rect */
+    C2D_MASK_SCALE_BIT       = (1 <<  9), /* enables mask surface scaling */
+    C2D_MASK_TILE_BIT        = (1 << 10), /* enables mask surface tiling */
+    C2D_GLOBAL_ALPHA_BIT     = (1 << 11), /* enables global_alpha field */
+    C2D_COLOR_KEY_BIT        = (1 << 12), /* enables color_key field */
+    C2D_NO_PIXEL_ALPHA_BIT   = (1 << 13), /* disables source alpha channel */
+    C2D_NO_BILINEAR_BIT      = (1 << 14), /* disables bilinear on scaling */
+    C2D_NO_ANTIALIASING_BIT  = (1 << 15), /* disables antialiasing on edges */
+    C2D_DRAW_LINE_BIT        = (1 << 16), /* enables line drawing with source rectangle */
+    C2D_DRAW_LINE_NOLAST     = (1 << 17), /* disable last pixel draw for line */
+} C2D_SOURCE_CONFIG;
+
+/* Target configuration bits, defines rotation + mirroring.
+ * Mirror is applied prior to rotation if enabled. */
+typedef enum {
+    C2D_TARGET_MIRROR_H        = (1 << 0), /* horizontal flip */
+    C2D_TARGET_MIRROR_V        = (1 << 1), /* vertical flip */
+    C2D_TARGET_ROTATE_0        = (0 << 2), /* no rotation */
+    C2D_TARGET_ROTATE_90       = (1 << 2), /* 90 degree rotation */
+    C2D_TARGET_ROTATE_180      = (2 << 2), /* 180 degree rotation */
+    C2D_TARGET_ROTATE_270      = (3 << 2), /* 270 degree rotation, 90 + 180 */
+    C2D_TARGET_MASK_ALIGN      = (1 << 4), /* aligns mask to target scissor */
+    C2D_TARGET_MASK_SCALE      = (1 << 5), /* enables mask scaling */
+    C2D_TARGET_MASK_TILE       = (1 << 6), /* enables mask tiling */
+    C2D_TARGET_COLOR_KEY       = (1 << 7), /* enables target_color_key */
+    C2D_TARGET_NO_PIXEL_ALPHA  = (1 << 8), /* disables target alpha channel */
+} C2D_TARGET_CONFIG;
+
+#define C2D_TARGET_ROTATION_MASK  (C2D_TARGET_ROTATE_90*3)
+
+/* Additional blend modes, can be used with both source and target configs.
+   If none of the below is set, the default "SRC over DST" is applied. */
+typedef enum {
+    C2D_ALPHA_BLEND_SRC_OVER   = (0  << 20), /* Default, Porter-Duff "SRC over DST" */
+    C2D_ALPHA_BLEND_SRC        = (1  << 20), /* Porter-Duff "SRC" */
+    C2D_ALPHA_BLEND_SRC_IN     = (2  << 20), /* Porter-Duff "SRC in DST" */
+    C2D_ALPHA_BLEND_DST_IN     = (3  << 20), /* Porter-Duff "DST in SRC" */
+    C2D_ALPHA_BLEND_SRC_OUT    = (4  << 20), /* Porter-Duff "SRC out DST" */
+    C2D_ALPHA_BLEND_DST_OUT    = (5  << 20), /* Porter-Duff "DST out SRC" */
+    C2D_ALPHA_BLEND_DST_OVER   = (6  << 20), /* Porter-Duff "DST over SRC" */
+    C2D_ALPHA_BLEND_SRC_ATOP   = (7  << 20), /* Porter-Duff "SRC ATOP" */
+    C2D_ALPHA_BLEND_DST_ATOP   = (8  << 20), /* Porter-Duff "DST ATOP" */
+    C2D_ALPHA_BLEND_XOR        = (9  << 20), /* Xor */
+    C2D_ALPHA_BLEND_MULTIPLY   = (10 << 20), /* OpenVG "MULTIPLY" */
+    C2D_ALPHA_BLEND_SCREEN     = (11 << 20), /* OpenVG "SCREEN" */
+    C2D_ALPHA_BLEND_DARKEN     = (12 << 20), /* OpenVG "DARKEN" */
+    C2D_ALPHA_BLEND_LIGHTEN    = (13 << 20), /* OpenVG "LIGHTEN" */
+    C2D_ALPHA_BLEND_ADDITIVE   = (14 << 20), /* OpenVG "ADDITIVE" */
+    C2D_ALPHA_BLEND_DIRECT     = (15 << 20), /* Direct alpha blitting */
+    C2D_ALPHA_BLEND_INVERTC    = (16 << 20), /* Invert color */
+    C2D_ALPHA_BLEND_NONE       = (1  << 25), /* disables alpha blending */
+} C2D_ALPHA_BLEND_MODE;
+
+
+/* Surface caps enumeration */
+typedef enum {
+    C2D_SOURCE          = (1 << 0), /* allows to use as a source */
+    C2D_TARGET          = (1 << 1), /* allows to use as a target */
+    C2D_MASK            = (1 << 2), /* allows to use as a mask */
+    C2D_PALETTE         = (1 << 3), /* allows to use as a palette */
+} C2D_SURFACE_BITS;
+
+/* Surface type enumeration */
+typedef enum {
+    C2D_SURFACE_RGB_HOST        = 1, /* Host memory RGB surface */
+    C2D_SURFACE_RGB_EXT         = 2, /* External memory RGB surface */
+    C2D_SURFACE_YUV_HOST        = 3, /* Host memory YUV surface */
+    C2D_SURFACE_YUV_EXT         = 4, /* External memory YUV surface */
+    C2D_SURFACE_WITH_PHYS       = (1<<3), /* physical address already mapped */
+                                        /* this bit is valid with HOST types */
+    C2D_SURFACE_WITH_PHYS_DUMMY = (1<<4), /* physical address already mapped */
+                                        /* this bit is valid with HOST types */
+} C2D_SURFACE_TYPE;
+
+/* Structure for registering a RGB buffer as a blit surface */
+typedef struct {
+    uint32 format;   /* RGB color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *buffer;   /* pointer to the RGB buffer */
+    void  *phys;     /* physical address */
+    int32  stride;   /* defines stride in bytes, negative stride is allowed */
+} C2D_RGB_SURFACE_DEF;
+
+/* Structure for registering a YUV plane(s) as a blit surface */
+typedef struct {
+    uint32 format;   /* YUV color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *plane0;  /* holds the whole buffer if YUV format is not planar */
+    void  *phys0;   /* physical address */
+    int32  stride0; /* stride in bytes if YUV format is not planar */
+    void  *plane1;  /* holds UV or VU plane for planar interleaved */
+    void  *phys1;   /* physical address */
+    int32  stride1; /* stride for UV or VU plane for planar interleaved */
+    void  *plane2;  /* holds the 3. plane, ignored if YUV format is not planar */
+    void  *phys2;    /* physical address */
+    int32  stride2; /* stride for the 3. plane, ignored if YUV format is not planar */
+} C2D_YUV_SURFACE_DEF;
+
+
+/* Rectangle definition */
+typedef struct {
+    int32 x;        /* upper-left x */
+    int32 y;        /* upper-left y */
+    int32 width;    /* width */
+    int32 height;   /* height */
+} C2D_RECT;
+
+/* C2D_OBJECT encapsulates the blit parameters for a source surface.
+ * The fg_color defines color in target format for bits equal to 1
+ * in the source C2D_COLOR_FORMAT_1 format. It also defines rendering
+ * color for all alpha-only source formats. If the surface_id is 0
+ * the fg_color defines a constant fill color used instead of the surface.
+ * The bg_color defines color in target format for bits equal to 0
+ * in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored.
+ * The palette_id is used for all palette source formats, otherwise ignored.
+
+ * The source_rect first defines the content of the source surface,
+ * it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set,
+ * then scaled with bilinear interpolation to exactly fit target_rect
+ * or repeated across target_rect if C2D_SOURCE_TILE_BIT is set,
+ * target_rect is then rotated clockwise by an arbitrary angle in degrees
+ * around the rot_orig_x/y, defined relative to target_rect's top left point,
+ * and then clipped to scissor_rect defined in target coordinate system.
+
+ * Finally alpha blending is applied before pixels get written into the target.
+ * Surface's pixel alpha is combined with mask alpha and with global alpha.
+ * Mask surface follows all transformations applied to the source surface.
+ * Source color key defines transparent color, applied together with alpha. */
+typedef struct C2D_OBJECT_STR {
+    uint32 surface_id;      /* source surface */
+
+    uint32 fg_color;        /* foreground color */
+    uint32 bg_color;        /* background color */
+    uint32 palette_id;      /* one-dimensional horizontal palette surface */
+
+    uint32 config_mask;     /* defines which fields below are enabled */
+
+    C2D_RECT source_rect;  /* region of the source surface,   16.16 fp */
+    C2D_RECT target_rect;  /* position and scaling in target, 16.16 fp */
+
+    int32 rot_orig_x;       /* rotation origin relative to target_rect's... */
+    int32 rot_orig_y;       /* ...top left point,     both are 16.16 fp */
+    int32 rotation;         /* clock-wise rotation in degrees, 16.16 fp */
+
+    C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */
+
+    uint32 mask_surface_id; /* source alpha-mask surface */
+    uint32 global_alpha;    /* 0 = fully transparent, 255 = fully opaque */
+    uint32 color_key;       /* transparent color for the source surface */
+
+    struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
+} C2D_OBJECT;
+
+
+/*****************************************************************************/
+/**************************** C2D API 2.0 ********************************/
+/*****************************************************************************/
+
+/******************************************************************************
+ * Functions to create/destroy surfaces */
+
+/* Creates a generic blit surface according to its type.
+ * Pass a combination of desired surface bits according to planned usage.
+ * Accepted values for surface_bits may include bits from C2D_SURFACE_BITS,
+ * and also from C2D_DISPLAY for compatibility with HW display controller.
+ * For host memory types the memory is preallocated outside the API
+ * and should remain valid until surface is destroyed.
+ * For external memory types the memory is allocated within API.
+ * On success, the non-zero surface identifier is returned.
+ * All numbers greater that 0 are valid surface identifiers, 0 is invalid.
+
+ * Host memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_HOST
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * all fields in definition structure should be set
+
+ * External memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_EXT
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * buffer field in definition structure is ignored
+
+ * Host memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_HOST
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * one or all plane and stride fields in definition structure
+ * should be set depending on whether the format is planar or not
+
+ * External memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_EXT
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * all plane and stride fields in definition structure are ignored */
+C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/* Requests properties of the specified surface. */
+C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id,
+                         uint32 *surface_bits,
+                         C2D_SURFACE_TYPE *surface_type,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Destroys a generic blit surface.
+ * For external memory surfaces also deallocates the memory.
+ * It is safe to free any external resources associated with a given
+ * surface on c2dCreateSurface call after this function returns. */
+C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id );
+
+
+/******************************************************************************
+ * Functions to modify/exchange surface data */
+
+/* The format of fill_color is the same as color format being used
+ * for specified surface. If fill_rect is NULL the whole surface is filled.
+ * Alpha-blending is not performed while filling.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id,
+                         uint32 fill_color,
+                         C2D_RECT *fill_rect );
+
+/* Writes data located in host memory into the specified surface.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the host memory buffer should be loaded, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in target surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while writing.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Reads data from the specified surface into the host memory.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the surface should be read, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in source surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while reading.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Notifies c2d imlementation that surface has been updated from outside the API,
+ * if updated_rect is NULL then the whole surface has been updated. */
+C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id,
+                         C2D_RECT *updated_rect );
+
+/* Updates surface information.
+ * Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS".
+ * Count for surface planes have to be same than for already allocated surface */
+C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/******************************************************************************
+ * Functions to do actual blit */
+
+/* Draw a list of blit objects into the given target.
+ * The target_config is a bitwise OR of values from C2D_TARGET_CONFIG.
+ * The target transformation creates the effect that target surface
+ * is transformed before the blit and then transformed back
+ * after blit, however no physical target transform is performed.
+ * The objects_list is a linked list of blit objects, no more
+ * than num_objects is drawn from the given list.
+ * If num_objects is 0, the whole list is drawn.
+ * The blit is not guaranteed to complete after function returns. */
+C2D_API C2D_STATUS c2dDraw( uint32 target_id,
+                         uint32 target_config, C2D_RECT *target_scissor,
+                         uint32 target_mask_id, uint32 target_color_key,
+                         C2D_OBJECT *objects_list, uint32 num_objects );
+
+
+/* timstamp set in the blit commands flush */
+typedef void*                   c2d_ts_handle;
+
+/* Forces any pending blit to complete for a given target.
+ * Non-blocking. All input surfaces for this target except those
+ * which are shared with other targets are expected to be immediately
+ * writable after client has been waiting returned timestamp with
+ * c2dWaitTimestamp funtion or c2dFinish has been called for same target */
+C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp);
+
+
+/* Waits the pending timestamp */
+C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp );
+
+
+/* Forces any pending blit to complete for a given target.
+ * Blocking version, returns when blit is done.
+ * All input surfaces for this target except those which are shared with
+ * other targets are expected to be immediately
+ * writable after this function returns. */
+C2D_API C2D_STATUS c2dFinish( uint32 target_id );
+
+
+/*****************************************************************************/
+/****************************** Display API **********************************/
+/*****************************************************************************/
+
+
+/* Display input enumeration */
+typedef enum {
+    C2D_DISPLAY_INPUT_0      = 0,       /*!< default input */
+    C2D_DISPLAY_INPUT_1      = (1<<16), /*!< Overlay 1     */
+    C2D_DISPLAY_INPUT_2      = (1<<17), /*!< Overlay 2...    */
+} C2D_DISPLAY_INPUT;
+
+
+/******************************************************************************
+ * Functions for display output. */
+
+/* Functionality described in this section is optional and is
+ * provided only for the cases when blit HW
+ * is tightly bound to the display controller. */
+
+/* Display enumeration, may also be used in surface caps */
+typedef enum {
+    C2D_DISPLAY_MAIN         = (1 << 10), /* main display */
+    C2D_DISPLAY_SECONDARY    = (1 << 11), /* secondary display */
+    C2D_DISPLAY_TV_OUT       = (1 << 12), /* tv-out */
+} C2D_DISPLAY;
+
+/* Display window enumeration */
+typedef enum {
+    C2D_DISPLAY_OVERLAY      = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input.
+                                                When defined the surface is set on the overlay window
+                                                otherwise the surface is set on the background window. */
+} C2D_DISPLAY_WINDOW;                    /*!< Window bit set with display parameter */
+
+
+/* Display update modes */
+typedef enum {
+    C2D_DISPLAY_MODE_TEAR_SYNC   = (1 << 0), /* enables tearing sync */
+    C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */
+} C2D_DISPLAY_MODE;
+
+
+/* Sets the given surface as a current display front buffer.
+ * Several displays can be specified as an output if supported.
+ * Still only one input can be specified at a time fro display/displays.
+ * The surface remains shown until it gets replaced with another one. */
+C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display,
+                         uint32 surface_id, uint32 mode );
+
+/* Returns the current surface for a particular display.
+ * Only one display can be specified at a time.
+ * The latest surface set with compDisplaySetSurface or
+ * the default pre-allocated surface is returned. */
+C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display,
+                         uint32 *surface_id );
+
+/* Returns the properties for a particular display.
+ * Only one display can be specified at a time. */
+C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Sets the properties for a particular display input.
+ * Only one display + input can be specified at a time.
+ * C2D_OBJECT used to set input rect(target rect),
+ * blending operations, rotation...etc for display source */
+C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display,
+                         uint32 target_config, uint32 target_color_key,
+                         C2D_OBJECT * c2dObject, uint32 mode);
+
+/* allows user to map a memory region to the gpu. only supported on linux
+ * mem_fd is the fd of the memory region, hostptr is the host pointer to the region,
+ * len and offset are the size and offset of the memory.
+ * flags is one of the memory types supported by gsl
+ * gpaddr is passed by refernce back to the user
+ */
+C2D_API C2D_STATUS c2dMapAddr ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+/* allows user to unmap memory region mapped by c2dMapAddr.
+ * gpaddr is the gpuaddr to unmap */
+C2D_API C2D_STATUS c2dUnMapAddr (void * gpuaddr);
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __c2d2_h_ */
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
new file mode 100644
index 0000000..886d12b
--- /dev/null
+++ b/libcopybit/copybit.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010 - 2011, Code Aurora Forum. All rights reserved.
+ *
+ * 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.
+ */
+
+
+#define LOG_TAG "copybit"
+
+#include <cutils/log.h>
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <copybit.h>
+
+#include "gralloc_priv.h"
+#include "software_converter.h"
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#if defined(COPYBIT_MSM7K)
+#define MAX_SCALE_FACTOR    (4)
+#define MAX_DIMENSION       (4096)
+#elif defined(COPYBIT_QSD8K)
+#define MAX_SCALE_FACTOR    (8)
+#define MAX_DIMENSION       (2048)
+#else
+#error "Unsupported MDP version"
+#endif
+
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    int     mFD;
+    uint8_t mAlpha;
+    int     mFlags;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+open:  open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+common: {
+tag: HARDWARE_MODULE_TAG,
+     version_major: 1,
+     version_minor: 0,
+     id: COPYBIT_HARDWARE_MODULE_ID,
+     name: "QCT MSM7K COPYBIT Module",
+     author: "Google, Inc.",
+     methods: &copybit_module_methods
+        }
+};
+
+/******************************************************************************/
+
+/** min of int a, b */
+static inline int min(int a, int b) {
+    return (a<b) ? a : b;
+}
+
+/** max of int a, b */
+static inline int max(int a, int b) {
+    return (a>b) ? a : b;
+}
+
+/** scale each parameter by mul/div. Assume div isn't 0 */
+static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
+    if (mul != div) {
+        *a = (mul * *a) / div;
+        *b = (mul * *b) / div;
+    }
+}
+
+/** Determine the intersection of lhs & rhs store in out */
+static void intersect(struct copybit_rect_t *out,
+                      const struct copybit_rect_t *lhs,
+                      const struct copybit_rect_t *rhs) {
+    out->l = max(lhs->l, rhs->l);
+    out->t = max(lhs->t, rhs->t);
+    out->r = min(lhs->r, rhs->r);
+    out->b = min(lhs->b, rhs->b);
+}
+
+/** convert COPYBIT_FORMAT to MDP format */
+static int get_format(int format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGB_565:       return MDP_RGB_565;
+        case HAL_PIXEL_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
+        case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
+        case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
+        case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CBCR_H2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
+    }
+    return -1;
+}
+
+/** convert from copybit image to mdp image structure */
+static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)
+{
+    private_handle_t* hnd = (private_handle_t*)rhs->handle;
+    if(hnd == NULL){
+        ALOGE("copybit: Invalid handle");
+        return;
+    }
+    img->width      = rhs->w;
+    img->height     = rhs->h;
+    img->format     = get_format(rhs->format);
+    img->offset     = hnd->offset;
+    img->memory_id  = hnd->fd;
+}
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *dev,
+                      struct mdp_blit_req *e,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor,
+                      uint32_t horiz_padding,
+                      uint32_t vert_padding) {
+    struct copybit_rect_t clip;
+    intersect(&clip, scissor, dst);
+
+    e->dst_rect.x  = clip.l;
+    e->dst_rect.y  = clip.t;
+    e->dst_rect.w  = clip.r - clip.l;
+    e->dst_rect.h  = clip.b - clip.t;
+
+    uint32_t W, H, delta_x, delta_y;
+    if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+        delta_x = (clip.t - dst->t);
+        delta_y = (dst->r - clip.r);
+        e->src_rect.w = (clip.b - clip.t);
+        e->src_rect.h = (clip.r - clip.l);
+        W = dst->b - dst->t;
+        H = dst->r - dst->l;
+    } else {
+        delta_x  = (clip.l - dst->l);
+        delta_y  = (clip.t - dst->t);
+        e->src_rect.w  = (clip.r - clip.l);
+        e->src_rect.h  = (clip.b - clip.t);
+        W = dst->r - dst->l;
+        H = dst->b - dst->t;
+    }
+
+    MULDIV(&delta_x, &e->src_rect.w, src->r - src->l, W);
+    MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H);
+
+    e->src_rect.x = delta_x + src->l;
+    e->src_rect.y = delta_y + src->t;
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }else{
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }
+    }
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }else{
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }
+    }
+}
+
+/** setup mdp request */
+static void set_infos(struct copybit_context_t *dev,
+                      struct mdp_blit_req *req, int flags)
+{
+    req->alpha = dev->mAlpha;
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = dev->mFlags | flags;
+#if defined(COPYBIT_QSD8K)
+    req->flags |= MDP_BLEND_FG_PREMULT;
+#endif
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, void const *list)
+{
+    int err = ioctl(dev->mFD, MSMFB_BLIT,
+                    (struct mdp_blit_req_list const*)list);
+    ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
+    if (err == 0) {
+        return 0;
+    } else {
+#if DEBUG_MDP_ERRORS
+        struct mdp_blit_req_list const* l =
+            (struct mdp_blit_req_list const*)list;
+        for (int i=0 ; i<l->count ; i++) {
+            ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                  "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                  "    flags=%08lx"
+                  ,
+                  i,
+                  l->req[i].src.width,
+                  l->req[i].src.height,
+                  l->req[i].src.format,
+                  l->req[i].src_rect.x,
+                  l->req[i].src_rect.y,
+                  l->req[i].src_rect.w,
+                  l->req[i].src_rect.h,
+                  l->req[i].dst.width,
+                  l->req[i].dst.height,
+                  l->req[i].dst.format,
+                  l->req[i].dst_rect.x,
+                  l->req[i].dst_rect.y,
+                  l->req[i].dst_rect.w,
+                  l->req[i].dst_rect.h,
+                  l->req[i].flags
+                 );
+        }
+#endif
+        return -errno;
+    }
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+    struct copybit_device_t *dev,
+    int name,
+    int value)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = 0;
+    if (ctx) {
+        switch(name) {
+            case COPYBIT_ROTATION_DEG:
+                switch (value) {
+                    case 0:
+                        ctx->mFlags &= ~0x7;
+                        break;
+                    case 90:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_90;
+                        break;
+                    case 180:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_180;
+                        break;
+                    case 270:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_270;
+                        break;
+                    default:
+                        ALOGE("Invalid value for COPYBIT_ROTATION_DEG");
+                        status = -EINVAL;
+                        break;
+                }
+                break;
+            case COPYBIT_PLANE_ALPHA:
+                if (value < 0)      value = MDP_ALPHA_NOP;
+                if (value >= 256)   value = 255;
+                ctx->mAlpha = value;
+                break;
+            case COPYBIT_DITHER:
+                if (value == COPYBIT_ENABLE) {
+                    ctx->mFlags |= MDP_DITHER;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_DITHER;
+                }
+                break;
+            case COPYBIT_BLUR:
+                if (value == COPYBIT_ENABLE) {
+                    ctx->mFlags |= MDP_BLUR;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_BLUR;
+                }
+                break;
+            case COPYBIT_PREMULTIPLIED_ALPHA:
+                if(value == COPYBIT_ENABLE) {
+                    ctx->mFlags |= MDP_BLEND_FG_PREMULT;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
+                }
+                break;
+            case COPYBIT_TRANSFORM:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= value & 0x7;
+                break;
+            default:
+                status = -EINVAL;
+                break;
+        }
+    } else {
+        status = -EINVAL;
+    }
+    return status;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+    if (ctx) {
+        switch(name) {
+            case COPYBIT_MINIFICATION_LIMIT:
+                value = MAX_SCALE_FACTOR;
+                break;
+            case COPYBIT_MAGNIFICATION_LIMIT:
+                value = MAX_SCALE_FACTOR;
+                break;
+            case COPYBIT_SCALING_FRAC_BITS:
+                value = 32;
+                break;
+            case COPYBIT_ROTATION_STEP_DEG:
+                value = 90;
+                break;
+            default:
+                value = -EINVAL;
+        }
+    } else {
+        value = -EINVAL;
+    }
+    return value;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = 0;
+    private_handle_t *yv12_handle = NULL;
+    if (ctx) {
+        struct {
+            uint32_t count;
+            struct mdp_blit_req req[12];
+        } list;
+
+        if (ctx->mAlpha < 255) {
+            switch (src->format) {
+                // we don't support plane alpha with RGBA formats
+                case HAL_PIXEL_FORMAT_RGBA_8888:
+                case HAL_PIXEL_FORMAT_BGRA_8888:
+                case HAL_PIXEL_FORMAT_RGBA_5551:
+                case HAL_PIXEL_FORMAT_RGBA_4444:
+                    ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
+                           src->format);
+                    return -EINVAL;
+            }
+        }
+
+        if (src_rect->l < 0 || src_rect->r > src->w ||
+            src_rect->t < 0 || src_rect->b > src->h) {
+            // this is always invalid
+            ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
+                   __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
+
+            return -EINVAL;
+        }
+
+        if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h);
+            return -EINVAL;
+        }
+
+        if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h);
+            return -EINVAL;
+        }
+
+        if(src->format ==  HAL_PIXEL_FORMAT_YV12) {
+            int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+                GRALLOC_USAGE_PRIVATE_MM_HEAP;
+            if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
+                                  src->format, usage)){
+                if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
+                    (const_cast<copybit_image_t *>(src))->format =
+                        HAL_PIXEL_FORMAT_YCrCb_420_SP;
+                    (const_cast<copybit_image_t *>(src))->handle =
+                        yv12_handle;
+                    (const_cast<copybit_image_t *>(src))->base =
+                        (void *)yv12_handle->base;
+                }
+                else{
+                    ALOGE("Error copybit conversion from yv12 failed");
+                    if(yv12_handle)
+                        free_buffer(yv12_handle);
+                    return -EINVAL;
+                }
+            }
+            else{
+                ALOGE("Error:unable to allocate memeory for yv12 software conversion");
+                return -EINVAL;
+            }
+        }
+        const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
+        const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
+        struct copybit_rect_t clip;
+        list.count = 0;
+        status = 0;
+        while ((status == 0) && region->next(region, &clip)) {
+            intersect(&clip, &bounds, &clip);
+            mdp_blit_req* req = &list.req[list.count];
+            int flags = 0;
+
+            private_handle_t* src_hnd = (private_handle_t*)src->handle;
+            if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
+                flags |=  MDP_BLIT_NON_CACHED;
+            }
+
+            set_infos(ctx, req, flags);
+            set_image(&req->dst, dst);
+            set_image(&req->src, src);
+            set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
+
+            if (req->src_rect.w<=0 || req->src_rect.h<=0)
+                continue;
+
+            if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
+                continue;
+
+            if (++list.count == maxCount) {
+                status = msm_copybit(ctx, &list);
+                list.count = 0;
+            }
+        }
+        if ((status == 0) && list.count) {
+            status = msm_copybit(ctx, &list);
+        }
+    } else {
+        ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
+        status = -EINVAL;
+    }
+    if(yv12_handle)
+        free_buffer(yv12_handle);
+    return status;
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_region_t const *region)
+{
+    struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+    struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+    return stretch_copybit(dev, dst, src, &dr, &sr, region);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        close(ctx->mFD);
+        free(ctx);
+    }
+    return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device)
+{
+    int status = -EINVAL;
+    copybit_context_t *ctx;
+    ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
+    memset(ctx, 0, sizeof(*ctx));
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = const_cast<hw_module_t*>(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->mAlpha = MDP_ALPHA_NOP;
+    ctx->mFlags = 0;
+    ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
+    if (ctx->mFD < 0) {
+        status = errno;
+        ALOGE("Error opening frame buffer errno=%d (%s)",
+              status, strerror(status));
+        status = -status;
+    } else {
+        struct fb_fix_screeninfo finfo;
+        if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
+            if (strncmp(finfo.id, "msmfb", 5) == 0) {
+                /* Success */
+                status = 0;
+            } else {
+                ALOGE("Error not msm frame buffer");
+                status = -EINVAL;
+            }
+        } else {
+            ALOGE("Error executing ioctl for screen info");
+            status = -errno;
+        }
+    }
+
+    if (status == 0) {
+        *device = &ctx->device.common;
+    } else {
+        close_copybit(&ctx->device.common);
+    }
+    return status;
+}
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
new file mode 100644
index 0000000..6384dfe
--- /dev/null
+++ b/libcopybit/copybit.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2008 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 ANDROID_COPYBIT_INTERFACE_H
+#define ANDROID_COPYBIT_INTERFACE_H
+
+#include <hardware/hardware.h>
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/**
+ * The id of this module
+ */
+#define COPYBIT_HARDWARE_MODULE_ID "copybit"
+
+/**
+ * Name of the graphics device to open
+ */
+#define COPYBIT_HARDWARE_COPYBIT0 "copybit0"
+
+/* supported pixel-formats. these must be compatible with
+ * graphics/PixelFormat.java, ui/PixelFormat.h, pixelflinger/format.h
+ */
+enum {
+    COPYBIT_FORMAT_RGBA_8888    = HAL_PIXEL_FORMAT_RGBA_8888,
+    COPYBIT_FORMAT_RGBX_8888    = HAL_PIXEL_FORMAT_RGBX_8888,
+    COPYBIT_FORMAT_RGB_888      = HAL_PIXEL_FORMAT_RGB_888,
+    COPYBIT_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,
+    COPYBIT_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,
+    COPYBIT_FORMAT_RGBA_5551    = HAL_PIXEL_FORMAT_RGBA_5551,
+    COPYBIT_FORMAT_RGBA_4444    = HAL_PIXEL_FORMAT_RGBA_4444,
+    COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
+    COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
+};
+
+/* name for copybit_set_parameter */
+enum {
+    /* rotation of the source image in degrees (0 to 359) */
+    COPYBIT_ROTATION_DEG    = 1,
+    /* plane alpha value */
+    COPYBIT_PLANE_ALPHA     = 2,
+    /* enable or disable dithering */
+    COPYBIT_DITHER          = 3,
+    /* transformation applied (this is a superset of COPYBIT_ROTATION_DEG) */
+    COPYBIT_TRANSFORM       = 4,
+    /* blurs the copied bitmap. The amount of blurring cannot be changed
+     * at this time. */
+    COPYBIT_BLUR            = 5,
+    /* Informs the copybit that the source and destination contains
+       premultiplied alpha */
+    COPYBIT_PREMULTIPLIED_ALPHA  = 6,
+    /* FB width */
+    COPYBIT_FRAMEBUFFER_WIDTH = 7,
+    /* FB height */
+    COPYBIT_FRAMEBUFFER_HEIGHT = 8,
+};
+
+/* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
+enum {
+    /* flip source image horizontally */
+    COPYBIT_TRANSFORM_FLIP_H    = HAL_TRANSFORM_FLIP_H,
+    /* flip source image vertically */
+    COPYBIT_TRANSFORM_FLIP_V    = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 90 degres */
+    COPYBIT_TRANSFORM_ROT_90    = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 180 degres */
+    COPYBIT_TRANSFORM_ROT_180   = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 270 degres */
+    COPYBIT_TRANSFORM_ROT_270   = HAL_TRANSFORM_ROT_270,
+};
+
+/* enable/disable value copybit_set_parameter */
+enum {
+    COPYBIT_DISABLE = 0,
+    COPYBIT_ENABLE  = 1
+};
+
+/* use get_static_info() to query static informations about the hardware */
+enum {
+    /* Maximum amount of minification supported by the hardware*/
+    COPYBIT_MINIFICATION_LIMIT  = 1,
+    /* Maximum amount of magnification supported by the hardware */
+    COPYBIT_MAGNIFICATION_LIMIT = 2,
+    /* Number of fractional bits support by the scaling engine */
+    COPYBIT_SCALING_FRAC_BITS   = 3,
+    /* Supported rotation step in degres. */
+    COPYBIT_ROTATION_STEP_DEG   = 4,
+};
+
+/* Image structure */
+struct copybit_image_t {
+    /* width */
+    uint32_t    w;
+    /* height */
+    uint32_t    h;
+    /* format COPYBIT_FORMAT_xxx */
+    int32_t     format;
+    /* base of buffer with image */
+    void        *base;
+    /* handle to the image */
+    native_handle_t* handle;
+    /* number of pixels added for the stride */
+    uint32_t    horiz_padding;
+    /* number of pixels added for the vertical stride */
+    uint32_t    vert_padding;
+};
+
+/* Rectangle */
+struct copybit_rect_t {
+    /* left */
+    int l;
+    /* top */
+    int t;
+    /* right */
+    int r;
+    /* bottom */
+    int b;
+};
+
+/* Region */
+struct copybit_region_t {
+    int (*next)(struct copybit_region_t const *region, struct copybit_rect_t *rect);
+};
+
+/**
+ * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
+ * and the fields of this data structure must begin with hw_module_t
+ * followed by module specific information.
+ */
+struct copybit_module_t {
+    struct hw_module_t common;
+};
+
+/**
+ * Every device data structure must begin with hw_device_t
+ * followed by module specific public methods and attributes.
+ */
+struct copybit_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set a copybit parameter.
+     *
+     * @param dev from open
+     * @param name one for the COPYBIT_NAME_xxx
+     * @param value one of the COPYBIT_VALUE_xxx
+     *
+     * @return 0 if successful
+     */
+    int (*set_parameter)(struct copybit_device_t *dev, int name, int value);
+
+    /**
+     * Get a static copybit information.
+     *
+     * @param dev from open
+     * @param name one of the COPYBIT_STATIC_xxx
+     *
+     * @return value or -EINVAL if error
+     */
+    int (*get)(struct copybit_device_t *dev, int name);
+
+    /**
+     * Execute the bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*blit)(struct copybit_device_t *dev,
+                struct copybit_image_t const *dst,
+                struct copybit_image_t const *src,
+                struct copybit_region_t const *region);
+
+    /**
+     * Execute the stretch bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param dst_rect is the destination rectangle
+     * @param src_rect is the source rectangle
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*stretch)(struct copybit_device_t *dev,
+                   struct copybit_image_t const *dst,
+                   struct copybit_image_t const *src,
+                   struct copybit_rect_t const *dst_rect,
+                   struct copybit_rect_t const *src_rect,
+                   struct copybit_region_t const *region);
+};
+
+
+/** convenience API for opening and closing a device */
+
+static inline int copybit_open(const struct hw_module_t* module,
+                               struct copybit_device_t** device) {
+    return module->methods->open(module,
+                                 COPYBIT_HARDWARE_COPYBIT0, (struct hw_device_t**)device);
+}
+
+static inline int copybit_close(struct copybit_device_t* device) {
+    return device->common.close(&device->common);
+}
+
+
+__END_DECLS
+
+#endif  // ANDROID_COPYBIT_INTERFACE_H
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
new file mode 100644
index 0000000..72aa279
--- /dev/null
+++ b/libcopybit/copybit_c2d.cpp
@@ -0,0 +1,1477 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * 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.
+ */
+
+#define LOG_TAG "copybit_c2d"
+
+#include <cutils/log.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <linux/msm_kgsl.h>
+
+#include <EGL/eglplatform.h>
+#include <cutils/native_handle.h>
+#include <cutils/ashmem.h>
+#include <linux/ashmem.h>
+#include <gralloc_priv.h>
+
+#include <copybit.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "c2d2.h"
+#include "software_converter.h"
+
+#include <dlfcn.h>
+
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+using android::sp;
+
+C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
+                                   C2D_SURFACE_TYPE surface_type,
+                                   void *surface_definition,
+                                   int32 x, int32 y );
+
+C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
+                            uint32 target_config, C2D_RECT *target_scissor,
+                            uint32 target_mask_id, uint32 target_color_key,
+                            C2D_OBJECT *objects_list, uint32 num_objects );
+
+C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
+
+C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
+
+C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
+
+C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
+
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
+
+/******************************************************************************/
+
+#if defined(COPYBIT_Z180)
+#define MAX_SCALE_FACTOR    (4096)
+#define MAX_DIMENSION       (4096)
+#else
+#error "Unsupported HW version"
+#endif
+
+#define NUM_SURFACES 3
+
+enum {
+    RGB_SURFACE,
+    YUV_SURFACE_2_PLANES,
+    YUV_SURFACE_3_PLANES
+};
+
+enum eConversionType {
+    CONVERT_TO_ANDROID_FORMAT,
+    CONVERT_TO_C2D_FORMAT
+};
+
+enum eC2DFlags {
+    FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
+    FLAGS_YUV_DESTINATION     = 1<<1
+};
+
+static android::sp<gralloc::IAllocController> sAlloc = 0;
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    unsigned int src[NUM_SURFACES];  /* src surfaces */
+    unsigned int dst[NUM_SURFACES];  /* dst surfaces */
+    unsigned int trg_transform;      /* target transform */
+    C2D_OBJECT blitState;
+    void *libc2d2;
+    alloc_data temp_src_buffer;
+    alloc_data temp_dst_buffer;
+    int fb_width;
+    int fb_height;
+    bool isPremultipliedAlpha;
+};
+
+struct blitlist{
+    uint32_t count;
+    C2D_OBJECT blitObjects[12];
+};
+
+struct bufferInfo {
+    int width;
+    int height;
+    int format;
+};
+
+struct yuvPlaneInfo {
+    int yStride;       //luma stride
+    int plane1_stride;
+    int plane2_stride;
+    int plane1_offset;
+    int plane2_offset;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+open:  open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+common: {
+tag: HARDWARE_MODULE_TAG,
+     version_major: 1,
+     version_minor: 0,
+     id: COPYBIT_HARDWARE_MODULE_ID,
+     name: "QCT COPYBIT C2D 2.0 Module",
+     author: "Qualcomm",
+     methods: &copybit_module_methods
+        }
+};
+
+
+/* convert COPYBIT_FORMAT to C2D format */
+static int get_format(int format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
+        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_SWAP_RB |
+                                                  C2D_FORMAT_DISABLE_ALPHA;
+        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_SWAP_RB;
+        case HAL_PIXEL_FORMAT_BGRA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+        case HAL_PIXEL_FORMAT_RGBA_5551:      return C2D_COLOR_FORMAT_5551_RGBA;
+        case HAL_PIXEL_FORMAT_RGBA_4444:      return C2D_COLOR_FORMAT_4444_RGBA;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
+                                                  C2D_FORMAT_MACROTILED;
+        default:                              ALOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL;
+    }
+    return -EINVAL;
+}
+
+/* Get the C2D formats needed for conversion to YUV */
+static int get_c2d_format_for_yuv_destination(int halFormat) {
+    switch (halFormat) {
+        // We do not swap the RB when the target is YUV
+        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_DISABLE_ALPHA;
+        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+                                              // The U and V need to be interchanged when the target is YUV
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        default:                              return get_format(halFormat);
+    }
+    return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- *//*!
+ * \internal
+ * \brief Get the bpp for a particular color format
+ * \param color format
+ * \return bits per pixel
+ *//* ------------------------------------------------------------------- */
+int c2diGetBpp(int32 colorformat)
+{
+
+    int c2dBpp = 0;
+
+    switch(colorformat&0xFF)
+    {
+        case C2D_COLOR_FORMAT_4444_RGBA:
+        case C2D_COLOR_FORMAT_4444_ARGB:
+        case C2D_COLOR_FORMAT_1555_ARGB:
+        case C2D_COLOR_FORMAT_565_RGB:
+        case C2D_COLOR_FORMAT_5551_RGBA:
+            c2dBpp = 16;
+            break;
+        case C2D_COLOR_FORMAT_8888_RGBA:
+        case C2D_COLOR_FORMAT_8888_ARGB:
+            c2dBpp = 32;
+            break;
+        case C2D_COLOR_FORMAT_8_L:
+        case C2D_COLOR_FORMAT_8_A:
+            c2dBpp = 8;
+            break;
+        case C2D_COLOR_FORMAT_4_A:
+            c2dBpp = 4;
+            break;
+        case C2D_COLOR_FORMAT_1:
+            c2dBpp = 1;
+            break;
+        default:
+            ALOGE("%s ERROR", __func__);
+            break;
+    }
+    return c2dBpp;
+}
+
+static uint32 c2d_get_gpuaddr( struct private_handle_t *handle)
+{
+    uint32 memtype, *gpuaddr;
+    C2D_STATUS rc;
+
+    if(!handle)
+        return 0;
+
+    if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+                         private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
+        memtype = KGSL_USER_MEM_TYPE_PMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
+        memtype = KGSL_USER_MEM_TYPE_ASHMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+        memtype = KGSL_USER_MEM_TYPE_ION;
+    else {
+        ALOGE("Invalid handle flags: 0x%x", handle->flags);
+        return 0;
+    }
+
+    rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, handle->offset, memtype, (void**)&gpuaddr);
+    if (rc == C2D_STATUS_OK) {
+        return (uint32) gpuaddr;
+    }
+    return 0;
+}
+
+static int is_supported_rgb_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int get_num_planes(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return 2;
+        }
+        case HAL_PIXEL_FORMAT_YV12: {
+            return 3;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_supported_yuv_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_valid_destination_format(int format)
+{
+    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+        // C2D does not support NV12Tile as a destination format.
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
+
+static int calculate_yuv_offset_and_stride(const bufferInfo& info,
+                                           yuvPlaneInfo& yuvInfo)
+{
+    int width  = info.width;
+    int height = info.height;
+    int format = info.format;
+
+    int aligned_height = 0;
+    int aligned_width = 0, size = 0;
+
+    switch (format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            /* NV12 Tile buffers have their luma height aligned to 32bytes and width
+             * aligned to 128 bytes. The chroma offset starts at an 8K boundary
+             */
+            aligned_height = ALIGN(height, 32);
+            aligned_width  = ALIGN(width, 128);
+            size = aligned_width * aligned_height;
+            yuvInfo.plane1_offset = ALIGN(size,8192);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            break;
+        }
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            aligned_width = ALIGN(width, 32);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
+                // The encoder requires a 2K aligned chroma offset
+                yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
+            } else
+                yuvInfo.plane1_offset = aligned_width * height;
+
+            break;
+        }
+        default: {
+            return COPYBIT_FAILURE;
+        }
+    }
+    return COPYBIT_SUCCESS;
+}
+
+/** create C2D surface from copybit image */
+static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs,
+                      int *cformat, uint32_t *mapped, const eC2DFlags flags)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    C2D_SURFACE_TYPE surfaceType;
+    int status = COPYBIT_SUCCESS;
+
+    if (flags & FLAGS_YUV_DESTINATION) {
+        *cformat = get_c2d_format_for_yuv_destination(rhs->format);
+    } else {
+        *cformat = get_format(rhs->format);
+    }
+
+    if(*cformat == -EINVAL) {
+        ALOGE("%s: invalid format", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if(handle == NULL) {
+        ALOGE("%s: invalid handle", __func__);
+        return -EINVAL;
+    }
+
+    if (handle->gpuaddr == 0) {
+        handle->gpuaddr = c2d_get_gpuaddr(handle);
+        if(!handle->gpuaddr) {
+            ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
+            return COPYBIT_FAILURE;
+        }
+        *mapped = 1;
+    }
+
+    /* create C2D surface */
+    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+
+        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
+
+        surfaceDef.phys = (void*) handle->gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+
+        surfaceDef.format = *cformat |
+            ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        int aligned_width = ALIGN(surfaceDef.width,32);
+        surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
+            ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            goto error;
+            status = COPYBIT_FAILURE;
+        }
+    } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+        surfaceDef.format = *cformat;
+
+        bufferInfo info;
+        info.width = rhs->w;
+        info.height = rhs->h;
+        info.format = rhs->format;
+
+        yuvPlaneInfo yuvInfo;
+        status = calculate_yuv_offset_and_stride(info, yuvInfo);
+        if(status != COPYBIT_SUCCESS) {
+            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+            goto error;
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) (handle->gpuaddr);
+        surfaceDef.stride0 = yuvInfo.yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+        surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
+        surfaceDef.stride1 = yuvInfo.plane1_stride;
+        if (3 == get_num_planes(rhs->format)) {
+            surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
+            surfaceDef.phys2 = (void*) (handle->gpuaddr + yuvInfo.plane2_offset);
+            surfaceDef.stride2 = yuvInfo.plane2_stride;
+        }
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
+            ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            goto error;
+            status = COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+        goto error;
+        status = COPYBIT_FAILURE;
+    }
+
+    return status;
+
+error:
+    if(*mapped == 1) {
+        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+        handle->gpuaddr = 0;
+        *mapped = 0;
+    }
+    return status;
+}
+
+static int set_src_image( uint32 *surfaceId, const struct copybit_image_t *rhs,
+                          int *cformat, uint32 *mapped)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    *cformat  = get_format(rhs->format);
+    C2D_SURFACE_TYPE surfaceType;
+    uint32 gpuaddr = (uint32)handle->gpuaddr;
+    int status = COPYBIT_SUCCESS;
+
+    if (handle->gpuaddr == 0)
+    {
+        handle->gpuaddr = c2d_get_gpuaddr( handle);
+        if(!handle->gpuaddr)
+            return COPYBIT_FAILURE;
+
+        *mapped = 1;
+    }
+
+    /* create C2D surface */
+    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
+
+        surfaceDef.phys = (void*) handle->gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+        surfaceDef.buffer = (void*) (handle->base + handle->offset);
+
+        surfaceDef.format = get_format(rhs->format);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) {
+            ALOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__);
+            status = COPYBIT_FAILURE;
+            goto error;
+        }
+    } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* YUV */
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        int offset = 0;
+        int yStride = 0;
+        int uvStride = 0;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
+        surfaceDef.format = get_format(rhs->format);
+        bufferInfo info;
+        info.width = rhs->w;
+        info.height = rhs->h;
+        info.format = rhs->format;
+
+        yuvPlaneInfo yuvInfo;
+        status = calculate_yuv_offset_and_stride(info, yuvInfo);
+        if(status != COPYBIT_SUCCESS) {
+            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+            goto error;
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) handle->gpuaddr;
+        surfaceDef.stride0 = yuvInfo.yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+        surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
+        surfaceDef.stride1 = yuvInfo.plane1_stride;
+
+        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  (void*)&surfaceDef)) {
+            ALOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__);
+            status = COPYBIT_FAILURE;
+            goto error;
+        }
+    } else {
+        ALOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format);
+        status = COPYBIT_FAILURE;
+    }
+
+    return COPYBIT_SUCCESS;
+
+error:
+    if(*mapped == 1) {
+        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+        handle->gpuaddr = 0;
+        *mapped = 0;
+    }
+    return status;
+}
+
+void unset_image( uint32 surfaceId, const struct copybit_image_t *rhs,
+                  uint32 mmapped)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+
+    if (mmapped && handle->gpuaddr) {
+        // Unmap this gpuaddr
+        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+        handle->gpuaddr = 0;
+    }
+}
+
+static int blit_to_target( uint32 surfaceId, const struct copybit_image_t *rhs)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    uint32 cformat  = get_format(rhs->format);
+    C2D_SURFACE_TYPE surfaceType;
+    uint32 memoryMapped = 0;
+    int status = COPYBIT_SUCCESS;
+
+    if (!handle->gpuaddr) {
+        handle->gpuaddr = c2d_get_gpuaddr(handle);
+        if(!handle->gpuaddr)
+            return COPYBIT_FAILURE;
+
+        memoryMapped = 1;
+    }
+
+    /* create C2D surface */
+
+    if(cformat) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+        surfaceDef.buffer = (void*) handle->base;
+        surfaceDef.phys = (void*) handle->gpuaddr;
+
+        surfaceType = C2D_SURFACE_RGB_HOST;
+        surfaceDef.format = get_format(rhs->format);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+        if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) {
+            ALOGE("%s: LINK_c2dReadSurface ERROR", __func__);
+            status = COPYBIT_FAILURE;
+            goto done;
+        }
+    }
+    else {
+        /* YUV */
+        /* TODO */
+    }
+
+done:
+    if (memoryMapped) {
+        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
+        handle->gpuaddr = 0;
+    }
+    return status;
+}
+
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *ctx,
+                      C2D_OBJECT *c2dObject,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor)
+{
+    // Set the target rect.
+    if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
+       (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
+        /* target rotation is 270 */
+        c2dObject->target_rect.x        = (dst->t)<<16;
+        c2dObject->target_rect.y        = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
+        c2dObject->target_rect.x        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
+        c2dObject->target_rect.y        = (dst->l)<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
+        c2dObject->target_rect.y        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
+        c2dObject->target_rect.x        = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    } else {
+        c2dObject->target_rect.x        = (dst->l)<<16;
+        c2dObject->target_rect.y        = (dst->t)<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    }
+    c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
+
+    // Set the source rect
+    c2dObject->source_rect.x        = (src->l)<<16;
+    c2dObject->source_rect.y        = (src->t)<<16;
+    c2dObject->source_rect.height   = ((src->b) - (src->t))<<16;
+    c2dObject->source_rect.width    = ((src->r) - (src->l))<<16;
+    c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
+
+    // Set the scissor rect
+    c2dObject->scissor_rect.x       = scissor->l;
+    c2dObject->scissor_rect.y       = scissor->t;
+    c2dObject->scissor_rect.height  = (scissor->b) - (scissor->t);
+    c2dObject->scissor_rect.width   = (scissor->r) - (scissor->l);
+    c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target)
+{
+    int objects;
+
+    for(objects = 0; objects < list->count; objects++) {
+        list->blitObjects[objects].next = &(list->blitObjects[objects+1]);
+    }
+
+    if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects,
+                    list->count)) {
+        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    return COPYBIT_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+    struct copybit_device_t *dev,
+    int name,
+    int value)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx) {
+        ALOGE("%s: null context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    switch(name) {
+        case COPYBIT_ROTATION_DEG:
+            ctx->blitState.rotation = value<<16;
+            /* SRC rotation */
+            if(!value)
+                ctx->blitState.config_mask &=~C2D_ROTATE_BIT;;
+            break;
+        case COPYBIT_PLANE_ALPHA:
+            if (value < 0)      value = 0;
+            if (value >= 256)   value = 255;
+
+            ctx->blitState.global_alpha = value;
+
+            if(ctx->blitState.global_alpha<255)
+                ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT;
+            else
+                ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT;
+            break;
+        case COPYBIT_DITHER:
+            /* TODO */
+            break;
+        case COPYBIT_BLUR:
+            /* TODO */
+            break;
+        case COPYBIT_TRANSFORM:
+            ctx->blitState.config_mask &=~C2D_ROTATE_BIT;
+            ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT;
+            ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT;
+            ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+            if((value&0x7) == COPYBIT_TRANSFORM_ROT_180)
+                ctx->trg_transform = C2D_TARGET_ROTATE_180;
+            else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270)
+                ctx->trg_transform = C2D_TARGET_ROTATE_90;
+            else {
+                if(value&COPYBIT_TRANSFORM_FLIP_H)
+                    ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
+                if(value&COPYBIT_TRANSFORM_FLIP_V)
+                    ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
+                if(value&COPYBIT_TRANSFORM_ROT_90)
+                    ctx->trg_transform = C2D_TARGET_ROTATE_270;
+            }
+            break;
+        case COPYBIT_PREMULTIPLIED_ALPHA:
+            (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true :
+                ctx->isPremultipliedAlpha = false;
+            break;
+        case COPYBIT_FRAMEBUFFER_WIDTH:
+            ctx->fb_width = value;
+            break;
+        case COPYBIT_FRAMEBUFFER_HEIGHT:
+            ctx->fb_height = value;
+            break;
+        default:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            return -EINVAL;
+            break;
+    }
+
+    return COPYBIT_SUCCESS;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+
+    if (!ctx) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    switch(name) {
+        case COPYBIT_MINIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_MAGNIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_SCALING_FRAC_BITS:
+            value = 32;
+            break;
+        case COPYBIT_ROTATION_STEP_DEG:
+            value = 1;
+            break;
+        default:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            value = -EINVAL;
+    }
+    return value;
+}
+
+static int is_alpha(int cformat)
+{
+    int alpha = 0;
+    switch (cformat & 0xFF) {
+        case C2D_COLOR_FORMAT_8888_ARGB:
+        case C2D_COLOR_FORMAT_8888_RGBA:
+        case C2D_COLOR_FORMAT_5551_RGBA:
+        case C2D_COLOR_FORMAT_4444_ARGB:
+            alpha = 1;
+            break;
+        default:
+            alpha = 0;
+            break;
+    }
+
+    if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
+        alpha = 0;
+
+    return alpha;
+}
+
+/* Function to check if we need a temporary buffer for the blit.
+ * This would happen if the requested destination stride and the
+ * C2D stride do not match. We ignore RGB buffers, since their
+ * stride is always aligned to 32.
+ */
+static bool need_temp_buffer(struct copybit_image_t const *img)
+{
+    if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
+        return false;
+
+    struct private_handle_t* handle = (struct private_handle_t*)img->handle;
+
+    // The width parameter in the handle contains the aligned_w. We check if we
+    // need to convert based on this param. YUV formats have bpp=1, so checking
+    // if the requested stride is aligned should suffice.
+    if (0 == (handle->width)%32) {
+        return false;
+    }
+
+    return true;
+}
+
+/* Function to extract the information from the copybit image and set the corresponding
+ * values in the bufferInfo struct.
+ */
+static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
+{
+    info.width = img->w;
+    info.height = img->h;
+    info.format = img->format;
+}
+
+/* Function to get the required size for a particular format, inorder for C2D to perform
+ * the blit operation.
+ */
+static size_t get_size(const bufferInfo& info)
+{
+    size_t size = 0;
+    int w = info.width;
+    int h = info.height;
+    int aligned_w = ALIGN(w, 32);
+    switch(info.format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            {
+                // Chroma for this format is aligned to 2K.
+                size = ALIGN((aligned_w*h), 2048) +
+                    ALIGN(w/2, 32) * h/2 *2;
+                size = ALIGN(size, 4096);
+            } break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                size = aligned_w*h +
+                    ALIGN(w/2, 32) * h/2 *2;
+                size = ALIGN(size, 4096);
+            } break;
+        default: break;
+    }
+    return size;
+}
+
+/* Function to allocate memory for the temporary buffer. This memory is
+ * allocated from Ashmem. It is the caller's responsibility to free this
+ * memory.
+ */
+static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
+{
+    ALOGD("%s E", __FUNCTION__);
+    // Alloc memory from system heap
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = get_size(info);
+    data.align = getpagesize();
+    data.uncached = true;
+    int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+
+    if (sAlloc == 0) {
+        sAlloc = gralloc::IAllocController::getInstance(false);
+    }
+
+    if (sAlloc == 0) {
+        ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    int err = sAlloc->allocate(data, allocFlags, 0);
+    if (0 != err) {
+        ALOGE("%s: allocate failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    ALOGD("%s X", __FUNCTION__);
+    return err;
+}
+
+/* Function to free the temporary allocated memory.*/
+static void free_temp_buffer(alloc_data &data)
+{
+    if (-1 != data.fd) {
+        sp<IMemAlloc> memalloc = sAlloc->getAllocator(data.allocType);
+        memalloc->free_buffer(data.base, data.size, 0, data.fd);
+    }
+}
+
+/* Function to perform the software color conversion. Convert the
+ * C2D compatible format to the Android compatible format
+ */
+static int copy_image(private_handle_t *src_handle,
+                      struct copybit_image_t const *rhs,
+                      eConversionType conversionType)
+{
+    if (src_handle->fd == -1) {
+        ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    // Copy the info.
+    int ret = COPYBIT_SUCCESS;
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
+                    return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
+                } else {
+                    return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
+                }
+
+            } break;
+        default: {
+            ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+            ret = COPYBIT_FAILURE;
+        } break;
+    }
+    return ret;
+}
+
+static void delete_handle(private_handle_t *handle)
+{
+    if (handle) {
+        delete handle;
+        handle = 0;
+    }
+}
+/** do a stretch blit type operation */
+static int stretch_copybit_internal(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region,
+    bool enableBlend)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
+    uint32 maxCount;
+    uint32 src_mapped = 0, trg_mapped = 0;
+    blitlist list;
+    C2D_OBJECT *req;
+    memset(&list, 0, sizeof(list));
+    int cformat;
+    c2d_ts_handle timestamp;
+    uint32 src_surface_index = 0, dst_surface_index = 0;
+
+    if (!ctx) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+        ALOGE("%s: src dimension error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w, dst->h);
+        return -EINVAL;
+    }
+
+    maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
+
+    struct copybit_rect_t clip;
+    list.count = 0;
+
+    if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
+        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    bool isYUVDestination = false;
+    if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
+        dst_surface_index = RGB_SURFACE;
+    } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
+        isYUVDestination = true;
+        int num_planes = get_num_planes(dst->format);
+        if (num_planes == 2) {
+            dst_surface_index = YUV_SURFACE_2_PLANES;
+        } else if (num_planes == 3) {
+            dst_surface_index = YUV_SURFACE_3_PLANES;
+        } else {
+            ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
+                  __FUNCTION__, dst->format);
+            return COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    copybit_image_t dst_image;
+    dst_image.w = dst->w;
+    dst_image.h = dst->h;
+    dst_image.format = dst->format;
+    dst_image.handle = dst->handle;
+    // Check if we need a temp. copy for the destination. We'd need this the destination
+    // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
+    // aligned to 32.
+    bool needTempDestination = need_temp_buffer(dst);
+    bufferInfo dst_info;
+    populate_buffer_info(dst, dst_info);
+    private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
+                                                     dst_info.width, dst_info.height);
+    if (dst_hnd == NULL) {
+        ALOGE("%s: dst_hnd is null", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    if (needTempDestination) {
+        if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
+            free_temp_buffer(ctx->temp_dst_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
+                ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                return COPYBIT_FAILURE;
+            }
+        }
+        dst_hnd->fd = ctx->temp_dst_buffer.fd;
+        dst_hnd->size = ctx->temp_dst_buffer.size;
+        dst_hnd->flags = ctx->temp_dst_buffer.allocType;
+        dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
+        dst_hnd->offset = ctx->temp_dst_buffer.offset;
+        dst_hnd->gpuaddr = 0;
+        dst_image.handle = dst_hnd;
+    }
+
+    int flags = 0;
+    flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
+    flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0;
+
+    status = set_image( ctx->dst[dst_surface_index], &dst_image,
+                        &cformat, &trg_mapped, (eC2DFlags)flags);
+    if(status) {
+        ALOGE("%s: dst: set_image error", __FUNCTION__);
+        delete_handle(dst_hnd);
+        return COPYBIT_FAILURE;
+    }
+
+    if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
+        src_surface_index = RGB_SURFACE;
+    } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
+        int num_planes = get_num_planes(src->format);
+        if (num_planes == 2) {
+            src_surface_index = YUV_SURFACE_2_PLANES;
+        } else if (num_planes == 3) {
+            src_surface_index = YUV_SURFACE_3_PLANES;
+        } else {
+            ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
+                  __FUNCTION__, src->format);
+            delete_handle(dst_hnd);
+            return -EINVAL;
+        }
+    } else {
+        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format);
+        delete_handle(dst_hnd);
+        return -EINVAL;
+    }
+
+    copybit_image_t src_image;
+    src_image.w = src->w;
+    src_image.h = src->h;
+    src_image.format = src->format;
+    src_image.handle = src->handle;
+
+    bool needTempSource = need_temp_buffer(src);
+    bufferInfo src_info;
+    populate_buffer_info(src, src_info);
+    private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
+                                                     src_info.width, src_info.height);
+    if (NULL == src_hnd) {
+        ALOGE("%s: src_hnd is null", __FUNCTION__);
+        delete_handle(dst_hnd);
+        return COPYBIT_FAILURE;
+    }
+    if (needTempSource) {
+        if (get_size(src_info) != ctx->temp_src_buffer.size) {
+            free_temp_buffer(ctx->temp_src_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) {
+                ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                return COPYBIT_FAILURE;
+            }
+        }
+        src_hnd->fd = ctx->temp_src_buffer.fd;
+        src_hnd->size = ctx->temp_src_buffer.size;
+        src_hnd->flags = ctx->temp_src_buffer.allocType;
+        src_hnd->base = (int)(ctx->temp_src_buffer.base);
+        src_hnd->offset = ctx->temp_src_buffer.offset;
+        src_hnd->gpuaddr = 0;
+        src_image.handle = src_hnd;
+
+        // Copy the source.
+        copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT);
+
+        // Flush the cache
+        sp<IMemAlloc> memalloc = sAlloc->getAllocator(src_hnd->flags);
+        if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
+                                   src_hnd->offset, src_hnd->fd)) {
+            ALOGE("%s: clean_buffer failed", __FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            return COPYBIT_FAILURE;
+        }
+    }
+
+    status = set_image( ctx->src[src_surface_index], &src_image,
+                        &cformat, &src_mapped, (eC2DFlags)flags);
+    if(status) {
+        ALOGE("%s: set_src_image error", __FUNCTION__);
+        delete_handle(dst_hnd);
+        delete_handle(src_hnd);
+        return COPYBIT_FAILURE;
+    }
+
+    if (enableBlend) {
+        if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+            ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            if(!(ctx->blitState.global_alpha)) {
+                // src alpha is zero
+                unset_image( ctx->src[src_surface_index],
+                             &src_image, src_mapped);
+                unset_image( ctx->dst[dst_surface_index],
+                             &dst_image, trg_mapped);
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                return status;
+            }
+        } else {
+            if(is_alpha(cformat))
+                ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            else
+                ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+        }
+    } else {
+        ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+    }
+
+    ctx->blitState.surface_id = ctx->src[src_surface_index];
+
+    while ((status == 0) && region->next(region, &clip)) {
+        req = &(list.blitObjects[list.count]);
+        memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
+
+        set_rects(ctx, req, dst_rect, src_rect, &clip);
+
+        if (++list.count == maxCount) {
+            status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
+            list.count = 0;
+        }
+    }
+    if ((status == 0) && list.count) {
+        status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
+    }
+
+    if(LINK_c2dFinish(ctx->dst[dst_surface_index])) {
+        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+    }
+
+    unset_image( ctx->src[src_surface_index], &src_image,
+                 src_mapped);
+    unset_image( ctx->dst[dst_surface_index], &dst_image,
+                 trg_mapped);
+    if (needTempDestination) {
+        // copy the temp. destination without the alignment to the actual destination.
+        copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+        // Invalidate the cache.
+        sp<IMemAlloc> memalloc = sAlloc->getAllocator(dst_hnd->flags);
+        memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
+                               dst_hnd->offset, dst_hnd->fd);
+    }
+    delete_handle(dst_hnd);
+    delete_handle(src_hnd);
+    ctx->isPremultipliedAlpha = false;
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+    return status;
+}
+
+static int stretch_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    bool needsBlending = (ctx->blitState.global_alpha != 0);
+    return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
+                                    region, needsBlending);
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_region_t const *region)
+{
+    struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+    struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+    return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        for(int i = 0; i <NUM_SURFACES; i++) {
+            LINK_c2dDestroySurface(ctx->dst[i]);
+            LINK_c2dDestroySurface(ctx->src[i]);
+        }
+
+        if (ctx->libc2d2) {
+            ::dlclose(ctx->libc2d2);
+            ALOGV("dlclose(libc2d2)");
+        }
+
+        free_temp_buffer(ctx->temp_src_buffer);
+        free_temp_buffer(ctx->temp_dst_buffer);
+        free(ctx);
+    }
+
+    return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device)
+{
+    int status = COPYBIT_SUCCESS;
+    C2D_RGB_SURFACE_DEF surfDefinition = {0};
+    C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
+    struct copybit_context_t *ctx;
+    char fbName[64];
+
+    ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
+    if(!ctx) {
+        ALOGE("%s: malloc failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    /* initialize drawstate */
+    memset(ctx, 0, sizeof(*ctx));
+
+    for (int i=0; i< NUM_SURFACES; i++) {
+        ctx->dst[i] = -1;
+        ctx->src[i] = -1;
+    }
+
+    ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
+    if (!ctx->libc2d2) {
+        ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
+        goto error;
+    }
+    *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dCreateSurface");
+    *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dUpdateSurface");
+    *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
+                                             "c2dReadSurface");
+    *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
+    *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
+    *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
+    *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
+                                               "c2dWaitTimestamp");
+    *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
+                                                "c2dDestroySurface");
+    *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
+                                         "c2dMapAddr");
+    *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
+                                           "c2dUnMapAddr");
+
+    if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
+        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
+        || !LINK_c2dDestroySurface) {
+        ALOGE("%s: dlsym ERROR", __FUNCTION__);
+        goto error;
+    }
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = (hw_module_t*)(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
+    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+    /* Create RGB Surface */
+    surfDefinition.buffer = (void*)0xdddddddd;
+    surfDefinition.phys = (void*)0xdddddddd;
+    surfDefinition.stride = 1 * 4;
+    surfDefinition.width = 1;
+    surfDefinition.height = 1;
+    surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
+    if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) {
+        ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__);
+        ctx->dst[RGB_SURFACE] = -1;
+        goto error;
+    }
+
+
+    if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) {
+        ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__);
+        ctx->src[RGB_SURFACE] = -1;
+        goto error;
+    }
+
+    /* Create YUV source surface */
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
+
+    yuvSurfaceDef.width = 4;
+    yuvSurfaceDef.height = 4;
+    yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride0 = 4;
+
+    yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride1 = 4;
+
+    if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+        ctx->src[YUV_SURFACE_2_PLANES] = -1;
+        goto error;
+    }
+
+    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_2_PLANES] = -1;
+        goto error;
+    }
+
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
+    yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride2 = 4;
+
+    if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+        ctx->src[YUV_SURFACE_3_PLANES] = -1;
+        goto error;
+    }
+
+    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_3_PLANES] = -1;
+        goto error;
+    }
+
+    ctx->temp_src_buffer.fd = -1;
+    ctx->temp_src_buffer.base = 0;
+    ctx->temp_src_buffer.size = 0;
+
+    ctx->temp_dst_buffer.fd = -1;
+    ctx->temp_dst_buffer.base = 0;
+    ctx->temp_dst_buffer.size = 0;
+
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+    ctx->isPremultipliedAlpha = false;
+
+    *device = &ctx->device.common;
+    return status;
+
+error:
+    for (int i = 0; i<NUM_SURFACES; i++) {
+        if (-1 != (ctx->src[i])) {
+            LINK_c2dDestroySurface(ctx->src[i]);
+            ctx->src[i] = -1;
+        }
+        if (-1 != (ctx->dst[i])) {
+            LINK_c2dDestroySurface(ctx->dst[i]);
+            ctx->dst[i] = -1;
+        }
+    }
+    if (ctx->libc2d2)
+        ::dlclose(ctx->libc2d2);
+    if (ctx)
+        free(ctx);
+    status = COPYBIT_FAILURE;
+    *device = NULL;
+
+    return status;
+}
diff --git a/libcopybit/copybit_priv.h b/libcopybit/copybit_priv.h
new file mode 100644
index 0000000..fd1b27e
--- /dev/null
+++ b/libcopybit/copybit_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <copybit.h>
+struct copybit_iterator : public copybit_region_t {
+    copybit_iterator(const copybit_rect_t& rect) {
+        mRect = rect;
+        mCount = 1;
+        this->next = iterate;
+    }
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        if (!self || !rect) {
+            return 0;
+        }
+
+        copybit_iterator const* me = static_cast<copybit_iterator const*>(self);
+        if (me->mCount) {
+            rect->l = me->mRect.l;
+            rect->t = me->mRect.t;
+            rect->r = me->mRect.r;
+            rect->b = me->mRect.b;
+            me->mCount--;
+            return 1;
+        }
+        return 0;
+    }
+    copybit_rect_t mRect;
+    mutable int mCount;
+};
diff --git a/libcopybit/software_converter.cpp b/libcopybit/software_converter.cpp
new file mode 100644
index 0000000..c9bb674
--- /dev/null
+++ b/libcopybit/software_converter.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "copybit"
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "software_converter.h"
+
+/** Convert YV12 to YCrCb_420_SP */
+int convertYV12toYCrCb420SP(const copybit_image_t *src, private_handle_t *yv12_handle)
+{
+    private_handle_t* hnd = (private_handle_t*)src->handle;
+
+    if(hnd == NULL || yv12_handle == NULL){
+        ALOGE("Invalid handle");
+        return -1;
+    }
+
+    // Please refer to the description of YV12 in hardware.h
+    // for the formulae used to calculate buffer sizes and offsets
+
+    // In a copybit_image_t, w is the stride and
+    // stride - horiz_padding is the actual width
+    // vertical stride is the same as height, so not considered
+    unsigned int   stride  = src->w;
+    unsigned int   width   = src->w - src->horiz_padding;
+    unsigned int   height  = src->h;
+    unsigned int   y_size  = stride * src->h;
+    unsigned int   c_width = ALIGN(stride/2, 16);
+    unsigned int   c_size  = c_width * src->h/2;
+    unsigned int   chromaPadding = c_width - width/2;
+    unsigned int   chromaSize = c_size * 2;
+    unsigned char* newChroma = (unsigned char *)(yv12_handle->base + y_size);
+    unsigned char* oldChroma = (unsigned char*)(hnd->base + y_size);
+    memcpy((char *)yv12_handle->base,(char *)hnd->base,y_size);
+
+#ifdef __ARM_HAVE_NEON
+   /* interleave */
+    if(!chromaPadding) {
+        unsigned char * t1 = newChroma;
+        unsigned char * t2 = oldChroma;
+        unsigned char * t3 = t2 + chromaSize/2;
+        for(unsigned int i=0; i < (chromaSize/2)>>3; i++) {
+            __asm__ __volatile__ (
+                                    "vld1.u8 d0, [%0]! \n"
+                                    "vld1.u8 d1, [%1]! \n"
+                                    "vst2.u8 {d0, d1}, [%2]! \n"
+                                    :"+r"(t2), "+r"(t3), "+r"(t1)
+                                    :
+                                    :"memory","d0","d1"
+                                 );
+
+        }
+    }
+#else  //__ARM_HAVE_NEON
+    if(!chromaPadding) {
+        for(unsigned int i = 0; i< chromaSize/2; i++) {
+            newChroma[i*2]   = oldChroma[i];
+            newChroma[i*2+1] = oldChroma[i+chromaSize/2];
+        }
+
+    }
+#endif
+    // If the image is not aligned to 16 pixels,
+    // convert using the C routine below
+    // r1 tracks the row of the source buffer
+    // r2 tracks the row of the destination buffer
+    // The width/2 checks are to avoid copying
+    // from the padding
+
+    if(chromaPadding) {
+        unsigned int r1 = 0, r2 = 0, i = 0, j = 0;
+        while(r1 < height/2) {
+            if(j == width) {
+                j = 0;
+                r2++;
+                continue;
+            }
+            if (j+1 == width) {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                r2++;
+                newChroma[r2*width] = oldChroma[r1*c_width+i+c_size];
+                j = 1;
+            } else {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                newChroma[r2*width + j + 1] = oldChroma[r1*c_width+i+c_size];
+                j+=2;
+            }
+            i++;
+            if (i == width/2 ) {
+                i = 0;
+                r1++;
+            }
+        }
+    }
+
+  return 0;
+}
+
+struct copyInfo{
+    int width;
+    int height;
+    int src_stride;
+    int dst_stride;
+    int src_plane1_offset;
+    int src_plane2_offset;
+    int dst_plane1_offset;
+    int dst_plane2_offset;
+};
+
+/* Internal function to do the actual copy of source to destination */
+static int copy_source_to_destination(const int src_base, const int dst_base,
+                                      copyInfo& info)
+{
+    if (!src_base || !dst_base) {
+        ALOGE("%s: invalid memory src_base = 0x%x dst_base=0x%x",
+             __FUNCTION__, src_base, dst_base);
+         return COPYBIT_FAILURE;
+    }
+
+    int width = info.width;
+    int height = info.height;
+    unsigned char *src = (unsigned char*)src_base;
+    unsigned char *dst = (unsigned char*)dst_base;
+
+    // Copy the luma
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, width);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+
+    // Copy plane 1
+    src = (unsigned char*)(src_base + info.src_plane1_offset);
+    dst = (unsigned char*)(dst_base + info.dst_plane1_offset);
+    width = width/2;
+    height = height/2;
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, info.src_stride);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+    return 0;
+}
+
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    ALOGD("Enter %s", __FUNCTION__);
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(info.width, 32);
+    info.dst_stride = ALIGN(info.width, 16);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return COPYBIT_FAILURE;
+    }
+
+    ret = copy_source_to_destination(hnd->base, dst_hnd->base, info);
+    return ret;
+}
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(hnd->width, 16);
+    info.dst_stride = ALIGN(info.width, 32);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return -1;
+    }
+
+    ret = copy_source_to_destination(hnd->base, dst_hnd->base, info);
+    return ret;
+}
diff --git a/libcopybit/software_converter.h b/libcopybit/software_converter.h
new file mode 100644
index 0000000..54b503d
--- /dev/null
+++ b/libcopybit/software_converter.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include <copybit.h>
+#include "gralloc_priv.h"
+#include "gr.h"
+
+#define COPYBIT_SUCCESS 0
+#define COPYBIT_FAILURE -1
+
+int convertYV12toYCrCb420SP(const copybit_image_t *src,private_handle_t *yv12_handle);
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);
+
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);