exynos: reorganized and updated from insignal

Changes needed on exynos4210 devices:

libcsc -> libseccscapi
libswconverter -> remove

TARGET_HAL_PATH := hardware/samsung/exynos4/hal
TARGET_OMX_PATH := hardware/samsung/exynos/multimedia/openmax
$(call inherit-product, hardware/samsung/exynos4210.mk)

Change-Id: Ic59ef95b85ef37b3f38fb36cf6a364a5414685ee
diff --git a/exynos5/hal/libhdmi/Android.mk b/exynos5/hal/libhdmi/Android.mk
new file mode 100644
index 0000000..9acbc52
--- /dev/null
+++ b/exynos5/hal/libhdmi/Android.mk
@@ -0,0 +1,17 @@
+# 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.
+
+ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),)
+include $(all-subdir-makefiles)
+endif
diff --git a/exynos5/hal/libhdmi/SecHdmi/Android.mk b/exynos5/hal/libhdmi/SecHdmi/Android.mk
new file mode 100644
index 0000000..61bd1a9
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/Android.mk
@@ -0,0 +1,76 @@
+# 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.
+
+ifeq ($(BOARD_USES_HDMI),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_PRELINK_MODULE := false
+#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := libutils liblog libedid libcec
+
+LOCAL_SRC_FILES := \
+	SecHdmiV4L2Utils.cpp \
+	SecHdmi.cpp \
+	SecGscaler.cpp \
+	fimd_api.c
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
+
+ifeq ($(TARGET_SOC),exynos5250)
+	LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250
+endif
+
+LOCAL_CFLAGS  += \
+	-DSCREEN_WIDTH=$(SCREEN_WIDTH) \
+	-DSCREEN_HEIGHT=$(SCREEN_HEIGHT) \
+	-DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM)
+
+LOCAL_SHARED_LIBRARIES += libion
+
+ifeq ($(BOARD_USES_HDMI_SUBTITLES),true)
+	LOCAL_CFLAGS  += -DBOARD_USES_HDMI_SUBTITLES
+endif
+
+ifeq ($(BOARD_USES_HDMI_FIMGAPI),true)
+	LOCAL_CFLAGS += -DBOARD_USES_HDMI_FIMGAPI
+	LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/libfimg4x
+	LOCAL_C_INCLUDES += external/skia/include/core
+	LOCAL_SHARED_LIBRARIES += libfimg
+endif
+
+ifeq ($(BOARD_HDMI_STD), STD_NTSC_M)
+	LOCAL_CFLAGS  += -DSTD_NTSC_M
+endif
+
+ifeq ($(BOARD_HDMI_STD),STD_480P)
+	LOCAL_CFLAGS  += -DSTD_480P
+endif
+
+ifeq ($(BOARD_HDMI_STD),STD_720P)
+	LOCAL_CFLAGS  += -DSTD_720P
+endif
+
+ifeq ($(BOARD_HDMI_STD),STD_1080P)
+	LOCAL_CFLAGS  += -DSTD_1080P
+endif
+
+LOCAL_MODULE := libhdmi
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp
new file mode 100644
index 0000000..0a84d11
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp
@@ -0,0 +1,1524 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define DEBUG_LIB_FIMC
+#define LOG_TAG "libgscaler"
+//#define USE_GSC_USERPTR
+#include <cutils/log.h>
+#include "../libhdmi/SecHdmi/SecGscaler.h"
+
+#ifdef USE_GSC_USERPTR
+#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR
+#else
+#define V4L2_MEMORY_TYPE V4L2_MEMORY_MMAP
+#endif
+
+struct yuv_fmt_list yuv_list[] = {
+    { "V4L2_PIX_FMT_NV12",      "YUV420/2P/LSB_CBCR",   V4L2_PIX_FMT_NV12,      12, 1 },
+    { "V4L2_PIX_FMT_NV12M",     "YUV420/2P/LSB_CBCR",   V4L2_PIX_FMT_NV12M,     12, 2 },
+    { "V4L2_PIX_FMT_NV12MT",    "YUV420/2P/LSB_CBCR",   V4L2_PIX_FMT_NV12MT,    12, 2 },
+    { "V4L2_PIX_FMT_NV21",      "YUV420/2P/LSB_CRCB",   V4L2_PIX_FMT_NV21,      12, 1 },
+    { "V4L2_PIX_FMT_NV21X",     "YUV420/2P/MSB_CBCR",   V4L2_PIX_FMT_NV21X,     12, 2 },
+    { "V4L2_PIX_FMT_NV12X",     "YUV420/2P/MSB_CRCB",   V4L2_PIX_FMT_NV12X,     12, 2 },
+    { "V4L2_PIX_FMT_YUV420",    "YUV420/3P",            V4L2_PIX_FMT_YUV420,    12, 3 },
+    { "V4L2_PIX_FMT_YUV420M",   "YUV420/3P",            V4L2_PIX_FMT_YUV420M,   12, 3 },
+    { "V4L2_PIX_FMT_YUYV",      "YUV422/1P/YCBYCR",     V4L2_PIX_FMT_YUYV,      16, 1 },
+    { "V4L2_PIX_FMT_YVYU",      "YUV422/1P/YCRYCB",     V4L2_PIX_FMT_YVYU,      16, 1 },
+    { "V4L2_PIX_FMT_UYVY",      "YUV422/1P/CBYCRY",     V4L2_PIX_FMT_UYVY,      16, 1 },
+    { "V4L2_PIX_FMT_VYUY",      "YUV422/1P/CRYCBY",     V4L2_PIX_FMT_VYUY,      16, 1 },
+    { "V4L2_PIX_FMT_UV12",      "YUV422/2P/LSB_CBCR",   V4L2_PIX_FMT_NV16,      16, 2 },
+    { "V4L2_PIX_FMT_UV21",      "YUV422/2P/LSB_CRCB",   V4L2_PIX_FMT_NV61,      16, 2 },
+    { "V4L2_PIX_FMT_UV12X",     "YUV422/2P/MSB_CBCR",   V4L2_PIX_FMT_NV16X,     16, 2 },
+    { "V4L2_PIX_FMT_UV21X",     "YUV422/2P/MSB_CRCB",   V4L2_PIX_FMT_NV61X,     16, 2 },
+    { "V4L2_PIX_FMT_YUV422P",   "YUV422/3P",            V4L2_PIX_FMT_YUV422P,   16, 3 },
+};
+
+void dump_pixfmt_mp(struct v4l2_pix_format_mplane *pix_mp)
+{
+    LOGI("w: %d", pix_mp->width);
+    LOGI("h: %d", pix_mp->height);
+    LOGI("color: %x", pix_mp->colorspace);
+
+    switch (pix_mp->pixelformat) {
+    case V4L2_PIX_FMT_YUYV:
+        LOGI ("YUYV");
+        break;
+    case V4L2_PIX_FMT_UYVY:
+        LOGI ("UYVY");
+        break;
+    case V4L2_PIX_FMT_RGB565:
+        LOGI ("RGB565");
+        break;
+    case V4L2_PIX_FMT_RGB565X:
+        LOGI ("RGB565X");
+        break;
+    default:
+        LOGI("not supported");
+    }
+}
+
+void dump_crop(struct v4l2_rect *rect)
+{
+    LOGI("crop l: %d", rect->left);
+    LOGI("crop t: %d", rect->top);
+    LOGI("crop w: %d", rect->width);
+    LOGI("crop h: %d", rect->height);
+}
+
+void gsc_v4l2_dump_state(int fd)
+{
+    struct v4l2_format format;
+    struct v4l2_crop   crop;
+    struct v4l2_subdev_crop sCrop;
+
+    format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    if (ioctl(fd, VIDIOC_G_FMT, &format) < 0)
+        return;
+
+    LOGI("dumping driver state:");
+    dump_pixfmt_mp(&format.fmt.pix_mp);
+
+    crop.type = format.type;
+    if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
+        return;
+
+    LOGI("input image crop:");
+    dump_crop(&(crop.c));
+
+    sCrop.pad   = GSC_SUBDEV_PAD_SOURCE;
+    sCrop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    if (ioctl(fd, VIDIOC_SUBDEV_G_CROP, &sCrop) < 0)
+        return;
+
+    LOGI("output image crop:");
+    dump_crop(&(sCrop.rect));
+
+}
+
+int gsc_v4l2_querycap(int fd, char *node)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_capability v4l2cap;
+
+    if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) {
+        LOGE("%s::VIDIOC_QUERYCAP failed", __func__);
+        return -1;
+    }
+
+    if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) {
+        LOGE("%s::%s is not support streaming", __func__, node);
+        return -1;
+    }
+
+    if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
+        LOGE("%s::%s is not support video output mplane", __func__, node);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_query_buf(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, int num_plane)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_GSCALER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_GSCALER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    if (MAX_BUFFERS_GSCALER <= buf_index || MAX_PLANES_GSCALER < num_plane) {
+        LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane);
+        return -1;
+    }
+
+    buf.type     = type;
+    buf.memory   = V4L2_MEMORY_MMAP;
+    buf.index    = buf_index;
+    buf.length   = num_plane;
+    buf.m.planes = planes;
+
+    if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
+        return -1;
+    }
+
+    for (int i = 0; i < num_plane; i++) {
+        if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length,
+                 PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) {
+            LOGE("%s::mmap failed", __func__);
+            LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset);
+            LOGE("%s::Legnth = %d"  , __func__, buf.m.planes[i].length);
+            LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
+            return -1;
+        }
+        secBuf->size.extS[i] = buf.m.planes[i].length;
+
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::vaddr[bufindex=%d][planeindex=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
+    LOGD("%s::Legnth = %d"  , __func__, buf.m.planes[i].length);
+#endif
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_req_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_requestbuffers reqbuf;
+
+    reqbuf.type   = type;
+    reqbuf.memory = memory;
+    reqbuf.count  = num_bufs;
+
+#ifdef DEBUG_LIB_FIMC
+    LOGI("%d buffers needed", reqbuf.count);
+#endif
+
+    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
+        LOGE("%s::VIDIOC_REQBUFS failed, reqbuf.count=%d", __func__, reqbuf.count);
+        return -1;
+    }
+
+#ifdef DEBUG_LIB_FIMC
+    LOGI("%d buffers allocated", reqbuf.count);
+#endif
+
+    if (reqbuf.count < num_bufs) {
+        LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
+            __func__, reqbuf.count, num_bufs);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_s_ctrl(int fd, int id, int value)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_control vc;
+
+    vc.id    = id;
+    vc.value = value;
+
+    if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+        LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_set_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, s5p_fimc_img_info *img_info)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_format  fmt;
+    struct v4l2_crop    crop;
+
+    fmt.type = type;
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::fmt.type=%d", __func__, fmt.type);
+#endif
+    if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_G_FMT failed", __func__);
+        return -1;
+    }
+
+    switch (fmt.type) {
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        fmt.fmt.pix.width       = img_info->full_width;
+        fmt.fmt.pix.height      = img_info->full_height;
+        fmt.fmt.pix.pixelformat = img_info->color_space;
+        fmt.fmt.pix.field       = field;
+        break;
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+        fmt.fmt.pix_mp.width       = img_info->full_width;
+        fmt.fmt.pix_mp.height      = img_info->full_height;
+        fmt.fmt.pix_mp.pixelformat = img_info->color_space;
+        fmt.fmt.pix_mp.field       = field;
+        fmt.fmt.pix_mp.num_planes  = img_info->planes;
+        break;
+    default:
+        LOGE("%s::invalid buffer type", __func__);
+        return -1;
+        break;
+    }
+
+#ifdef DEBUG_LIB_FIMC
+for (int i = 0; i < 3; i++) {
+    LOGD("%s::fmt.fmt.pix_mp. w=%d, h=%d, pixelformat=0x%08x, filed=%d, num_planes=%d",
+               __func__,
+               fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
+               fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.field,
+               fmt.fmt.pix_mp.num_planes);
+}
+#endif
+
+    if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_S_FMT failed", __func__);
+        return -1;
+    }
+
+#ifdef DEBUG_LIB_FIMC
+for (int i = 0; i < 3; i++) {
+    LOGD("%s::pix_mp.pix_mp.plane_fmt[%d].sizeimage   =0x%08x", __func__, i, fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+    LOGD("%s::pix_mp.pix_mp.plane_fmt[%d].bytesperline=0x%08x", __func__, i, fmt.fmt.pix_mp.plane_fmt[i].bytesperline);
+}
+#endif
+
+    crop.type     = type;
+    crop.c.left   = img_info->start_x;
+    crop.c.top    = img_info->start_y;
+    crop.c.width  = img_info->width;
+    crop.c.height = img_info->height;
+
+    if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
+            __func__,
+            img_info->start_x,
+            img_info->start_y,
+            img_info->width,
+            img_info->height);
+        return -1;
+    }
+
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::pix_mp pixelformat=0x%08x", __func__, fmt.fmt.pix_mp.pixelformat);
+    LOGD("%s::pix_mp w=%d, h=%d, planes=%d", __func__, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.num_planes);
+    LOGD("%s::crop   x=%d, y=%d, w=%d, h=%d", __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+#endif
+
+    return 0;
+}
+
+int gsc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
+        LOGE("%s::VIDIOC_STREAMON failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_queue(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int index, int num_plane)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+    LOGD("%s::num_plane=%d", __func__, num_plane);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_GSCALER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_GSCALER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    buf.type     = type;
+    buf.memory   = memory;
+    buf.length   = num_plane;
+    buf.index    = index;
+    buf.m.planes = planes;
+
+    for (unsigned int i = 0; i < buf.length; i++) {
+        buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i];
+        buf.m.planes[i].length    = secBuf->size.extS[i];
+        buf.m.planes[i].bytesused = buf.m.planes[i].length;
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::buf.index=%d", __func__, buf.index);
+    LOGD("%s::buf.m.planes[%d].m.userptr=0x%08x", __func__, i, (unsigned int)buf.m.planes[i].m.userptr);
+    LOGD("%s::buf.m.planes[%d].length   =0x%08x", __func__, i, buf.m.planes[i].length);
+    LOGD("%s::buf.m.planes[%d].bytesused=0x%08x", __func__, i, buf.m.planes[i].bytesused);
+#endif
+    }
+
+    if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_QBUF failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_dequeue(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int *index, int num_plane)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_GSCALER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_GSCALER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+
+    buf.type     = type;
+    buf.memory   = memory;
+    buf.length   = num_plane;
+    buf.m.planes = planes;
+
+    if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_DQBUF failed", __func__);
+        return -1;
+    }
+
+    *index = buf.index;
+
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::buf.index=%d", __func__, buf.index);
+#endif
+
+    return 0;
+}
+
+int gsc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
+        LOGE("%s::VIDIOC_STREAMOFF failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_v4l2_clr_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_requestbuffers req;
+
+    req.count   = 0;
+    req.type    = type;
+    req.memory  = memory;
+
+    if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
+        LOGE("%s::VIDIOC_REQBUFS failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int gsc_subdev_set_fmt(int fd, unsigned int pad, enum v4l2_mbus_pixelcode code, s5p_fimc_img_info *img_info)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_subdev_format fmt;
+    struct v4l2_subdev_crop   crop;
+
+    fmt.pad   = pad;
+    fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    fmt.format.width  = img_info->full_width;
+    fmt.format.height = img_info->full_height;
+    fmt.format.code   = code;
+
+    if (ioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_FMT failed", __func__);
+        return -1;
+    }
+
+    crop.pad   = pad;
+    crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    crop.rect.left   = img_info->start_x;
+    crop.rect.top    = img_info->start_y;
+    crop.rect.width  = img_info->width;
+    crop.rect.height = img_info->height;
+
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::pix_mp w=%d, h=%d", __func__, fmt.format.width, fmt.format.height);
+    LOGD("%s::crop   x=%d, y=%d, w=%d, h=%d", __func__, crop.rect.left, crop.rect.top, crop.rect.width, crop.rect.height);
+#endif
+
+    if (ioctl(fd, VIDIOC_SUBDEV_S_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_CROP failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+static inline int multipleOfN(int number, int N)
+{
+    int result = number;
+    switch (N) {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+    case 16:
+    case 32:
+    case 64:
+    case 128:
+    case 256:
+        result = (number - (number & (N-1)));
+        break;
+    default:
+        result = number - (number % N);
+        break;
+    }
+    return result;
+}
+
+SecGscaler::SecGscaler()
+:   mFlagCreate(false)
+{
+}
+
+SecGscaler::~SecGscaler()
+{
+    if (mFlagCreate == true) {
+        LOGE("%s::this is not Destroyed fail", __func__);
+
+        if (destroy() == false)
+            LOGE("%s::destroy failed", __func__);
+    }
+}
+
+bool SecGscaler::create(enum DEV dev, enum MODE mode, unsigned int numOfBuf)
+{
+    create(dev, numOfBuf);
+    return true;
+}
+
+bool SecGscaler::create(enum DEV dev, unsigned int numOfBuf)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+    if (mFlagCreate == true) {
+        LOGE("%s::Already Created", __func__);
+        return true;
+    }
+
+    char node[20];
+    char subdevname[32];
+    char videodevname[32];
+
+    struct v4l2_capability   v4l2cap;
+    struct media_entity_desc entity_desc;
+
+    mDev = dev;
+    mVideoNodeNum = dev;
+    mNumOfBuf = numOfBuf;
+
+    mVideodevFd = 0;
+    mMediadevFd = 0;
+    mSubdevFd = 0;
+
+    mSrcIndex = 0;
+    mRotVal = 0;
+    mFlagGlobalAlpha = false;
+    mGlobalAlpha = 0x0;
+    mFlagLocalAlpha = false;
+    mFlagColorKey = false;
+    mColorKey = 0x0;
+    mFlagSetSrcParam = false;
+    mFlagSetDstParam = false;
+    mFlagStreamOn = false;
+
+    memset(&mS5pFimc, 0, sizeof(s5p_fimc_t));
+
+    switch(mDev) {
+    case DEV_0:
+        mVideoNodeNum = 24;
+        mSubdevNodeNum = 4;
+        break;
+    case DEV_1:
+        mVideoNodeNum = 27;
+        mSubdevNodeNum = 5;
+        break;
+    case DEV_2:
+        mVideoNodeNum = 30;
+        mSubdevNodeNum = 6;
+        break;
+    case DEV_3:
+        mVideoNodeNum = 33;
+        mSubdevNodeNum = 3; // need to modify //carrotsm
+        break;
+    default:
+        LOGE("%s::invalid mDev(%d)", __func__, mDev);
+        goto err;
+        break;
+    }
+
+    sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
+    mMediadevFd = open(node, O_RDONLY);
+
+    if (mMediadevFd < 0) {
+        LOGE("%s::open(%s) failed : O_RDONLY", __func__, node);
+        goto err;
+    }
+
+    sprintf(subdevname,   PFX_ENTITY_SUBDEV_GSC, mDev);
+    sprintf(videodevname, PFX_ENTITY_OUTPUTDEV_GSC, mDev);
+
+    for (__u32 id = 0; ; id = entity_desc.id) {
+        entity_desc.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+
+        if (ioctl(mMediadevFd, MEDIA_IOC_ENUM_ENTITIES, &entity_desc) < 0) {
+            if (errno == EINVAL) {
+                LOGD("%s::MEDIA_IOC_ENUM_ENTITIES ended", __func__);
+                break;
+            }
+            LOGE("%s::MEDIA_IOC_ENUM_ENTITIES failed", __func__);
+            goto err;
+        }
+
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s::entity_desc.id=%d, .minor=%d .name=%s", __func__, entity_desc.id, entity_desc.v4l.minor, entity_desc.name);
+#endif
+
+        if (strncmp(entity_desc.name, subdevname, strlen(subdevname)) == 0)
+            mSubdevEntity = entity_desc.id;
+
+        if (strncmp(entity_desc.name, videodevname, strlen(videodevname)) == 0)
+            mVideodevEntity = entity_desc.id;
+    }
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+    mMediadevFd = -1;
+
+    sprintf(node, "%s%d", PFX_NODE_SUBDEV, mSubdevNodeNum);
+    mSubdevFd = open(node, O_RDWR);
+    if (mSubdevFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto err;
+    }
+
+    sprintf(node, "%s%d", PFX_NODE_VIDEODEV, mVideoNodeNum);
+    mVideodevFd = open(node, O_RDWR);
+    if (mVideodevFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto err;
+    }
+
+    /* check capability */
+    if (gsc_v4l2_querycap(mVideodevFd, node) < 0 ) {
+        LOGE("%s::tvout_std_v4l2_querycap failed", __func__);
+        goto err;
+    }
+
+    mFlagCreate = true;
+
+    return true;
+
+err :
+    if (0 < mVideodevFd)
+        close(mVideodevFd);
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+
+    if (0 < mSubdevFd)
+        close(mSubdevFd);
+
+    mVideodevFd = -1;
+    mMediadevFd = -1;
+    mSubdevFd = -1;
+
+    return false;
+}
+
+bool SecGscaler::destroy()
+{
+    s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Already Destroyed", __func__);
+        return true;
+    }
+
+    if (mFlagStreamOn == true) {
+        if (streamOff() == false) {
+            LOGE("%s::streamOff() failed", __func__);
+            return false;
+        }
+
+        if (closeVideodevFd() == false) {
+            LOGE("%s::closeVideodevFd() failed", __func__);
+            return false;
+        }
+
+        mFlagStreamOn = false;
+    }
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+
+    if (0 < mSubdevFd)
+        close(mSubdevFd);
+
+    mVideodevFd = -1;
+    mMediadevFd = -1;
+    mSubdevFd = -1;
+
+    mFlagCreate = false;
+
+    return true;
+}
+
+bool SecGscaler::flagCreate(void)
+{
+    return mFlagCreate;
+}
+
+int SecGscaler::getFd(void)
+{
+    return getVideodevFd();
+}
+
+int SecGscaler::getVideodevFd(void)
+{
+    return mVideodevFd;
+}
+
+bool SecGscaler::openVideodevFd(void)
+{
+    char node[32];
+
+    sprintf(node, "%s%d", PFX_NODE_VIDEODEV, mVideoNodeNum);
+    mVideodevFd = open(node, O_RDWR);
+    if (mVideodevFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        return false;
+    }
+
+    return true;
+}
+
+bool SecGscaler::closeVideodevFd(void)
+{
+    if (mFlagSetSrcParam == true) {
+        if (gsc_v4l2_clr_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE) < 0) {
+            LOGE("%s::gsc_v4l2_clr_buf() failed", __func__);
+            return false;
+        }
+    }
+
+    if (0 < mVideodevFd) {
+        if (close(mVideodevFd) < 0) {
+            LOGE("%s::close Videodev failed", __func__);
+            return false;
+        }
+    }
+    mVideodevFd = -1;
+
+    return true;
+}
+
+int SecGscaler::getSubdevFd(void)
+{
+    return mSubdevFd;
+}
+
+__u32 SecGscaler::getSubdevEntity(void)
+{
+    return mSubdevEntity;
+}
+
+__u32 SecGscaler::getVideodevEntity(void)
+{
+    return mVideodevEntity;
+}
+
+bool  SecGscaler::getFlagSteamOn(void)
+{
+    return mFlagStreamOn;
+}
+
+SecBuffer * SecGscaler::getSrcBufferAddr(int index)
+{
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    return &mSrcBuffer[index];
+}
+
+bool SecGscaler::setSrcParams(unsigned int width, unsigned int height,
+                              unsigned int cropX, unsigned int cropY,
+                              unsigned int *cropWidth, unsigned int *cropHeight,
+                              int colorFormat,
+                              bool forceChange)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
+    if (v4l2ColorFormat < 0) {
+        LOGE("%s::not supported color format", __func__);
+        return false;
+    }
+
+    s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+    unsigned int fimcWidth  = *cropWidth;
+    unsigned int fimcHeight = *cropHeight;
+    int src_planes = m_getYuvPlanes(v4l2ColorFormat);
+    int src_bpp    = m_getYuvBpp(v4l2ColorFormat);
+    unsigned int frame_size  = width * height;
+    unsigned int frame_ratio = 8;
+
+    if (m_checkSrcSize(width, height, cropX, cropY,
+                   &fimcWidth, &fimcHeight, v4l2ColorFormat, false) == false) {
+        LOGE("%s::::size align error!", __func__);
+        return false;
+    }
+
+    if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
+        if (forceChange == true) {
+#ifdef DEBUG_LIB_FIMC
+            LOGD("size is changed from [w=%d, h=%d] to [w=%d, h=%d]",
+                    *cropWidth, *cropHeight, fimcWidth, fimcHeight);
+#endif
+        } else {
+            LOGE("%s::invalid source params", __func__);
+            return false;
+        }
+    }
+
+    if (   (params->src.full_width == width)
+        && (params->src.full_height == height)
+        && (params->src.start_x == cropX)
+        && (params->src.start_y == cropY)
+        && (params->src.width == fimcWidth)
+        && (params->src.height == fimcHeight)
+        && (params->src.color_space == (unsigned int)v4l2ColorFormat))
+        return true;
+
+    params->src.full_width  = width;
+    params->src.full_height = height;
+    params->src.start_x     = cropX;
+    params->src.start_y     = cropY;
+    params->src.width       = fimcWidth;
+    params->src.height      = fimcHeight;
+    params->src.color_space = v4l2ColorFormat;
+    src_planes = (src_planes == -1) ? 1 : src_planes;
+    params->src.planes = src_planes;
+
+    mSrcBuffer[mSrcIndex].size.extS[0] = 0;
+    mSrcBuffer[mSrcIndex].size.extS[1] = 0;
+    mSrcBuffer[mSrcIndex].size.extS[2] = 0;
+
+    frame_ratio = frame_ratio * (src_planes -1) / (src_bpp - 8);
+#ifdef USE_GSC_USERPTR
+    for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) {
+        switch (src_planes) {
+        case 1:
+            switch (v4l2ColorFormat) {
+            case V4L2_PIX_FMT_BGR32:
+                params->src.color_space = V4L2_PIX_FMT_RGB32;
+            case V4L2_PIX_FMT_RGB32:
+                mSrcBuffer[buf_index].size.extS[0] = frame_size << 2;
+                break;
+            case V4L2_PIX_FMT_RGB565X:
+            case V4L2_PIX_FMT_NV16:
+            case V4L2_PIX_FMT_NV61:
+            case V4L2_PIX_FMT_YUYV:
+            case V4L2_PIX_FMT_UYVY:
+            case V4L2_PIX_FMT_VYUY:
+            case V4L2_PIX_FMT_YVYU:
+                mSrcBuffer[buf_index].size.extS[0] = frame_size << 1;
+                break;
+            case V4L2_PIX_FMT_YUV420:
+            case V4L2_PIX_FMT_NV12:
+            case V4L2_PIX_FMT_NV21:
+                mSrcBuffer[buf_index].size.extS[0] = (frame_size * 3) >> 1;
+                break;
+            default:
+                LOGE("%s::invalid color type", __func__);
+                return false;
+                break;
+            }
+            mSrcBuffer[buf_index].size.extS[1] = 0;
+            mSrcBuffer[buf_index].size.extS[2] = 0;
+            break;
+        case 2:
+        case 3:
+            mSrcBuffer[buf_index].size.extS[0] = frame_size;
+            mSrcBuffer[buf_index].size.extS[1] = frame_size / frame_ratio;
+            mSrcBuffer[buf_index].size.extS[2] = frame_size / frame_ratio;
+            break;
+        default:
+            LOGE("%s::invalid color foarmt", __func__);
+            return false;
+            break;
+        }
+    }
+#else
+    if (v4l2ColorFormat == V4L2_PIX_FMT_BGR32)
+        params->src.color_space = V4L2_PIX_FMT_RGB32;
+#endif
+
+    if (mFlagSetSrcParam == true) {
+        if (gsc_v4l2_clr_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE) < 0) {
+            LOGE("%s::gsc_v4l2_clr_buf() failed", __func__);
+            return false;
+        }
+    }
+
+    if (gsc_v4l2_set_fmt(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_NONE, &(params->src)) < 0) {
+        LOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__);
+        return false;
+    }
+
+    if (gsc_v4l2_req_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mNumOfBuf) < 0) {
+        LOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__);
+        return false;
+    }
+#ifdef USE_GSC_USERPTR
+#else
+    for (unsigned int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) {
+        if (gsc_v4l2_query_buf(mVideodevFd, &mSrcBuffer[buf_index], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP, buf_index, params->src.planes) < 0) {
+            LOGE("%s::gsc_v4l2_query_buf() failed", __func__);
+            return false;
+        }
+    }
+#endif
+
+    *cropWidth  = fimcWidth;
+    *cropHeight = fimcHeight;
+
+    mFlagSetSrcParam = true;
+
+    return true;
+}
+
+bool SecGscaler::getSrcParams(unsigned int *width, unsigned int *height,
+                              unsigned int *cropX, unsigned int *cropY,
+                              unsigned int *cropWidth, unsigned int *cropHeight,
+                              int *v4l2colorFormat)
+{
+    struct v4l2_format fmt;
+    struct v4l2_crop   crop;
+
+    fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    if (ioctl(mVideodevFd, VIDIOC_G_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
+        return false;
+    }
+
+    switch (fmt.type) {
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+    case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+        *width       = fmt.fmt.pix.width;
+        *height      = fmt.fmt.pix.height;
+        *v4l2colorFormat = fmt.fmt.pix.pixelformat;
+        break;
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+        *width       = fmt.fmt.pix_mp.width;
+        *height      = fmt.fmt.pix_mp.height;
+        *v4l2colorFormat = fmt.fmt.pix_mp.pixelformat;
+        break;
+    default:
+        LOGE("%s::Invalid buffer type", __func__);
+        return false;
+        break;
+    }
+
+    crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    if (ioctl(mVideodevFd, VIDIOC_G_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_G_CROP failed", __func__);
+        return false;
+    }
+
+    *cropX      = crop.c.left;
+    *cropY      = crop.c.top;
+    *cropWidth  = crop.c.width;
+    *cropHeight = crop.c.height;
+
+    return true;
+}
+
+bool SecGscaler::setSrcAddr(unsigned int YAddr,
+                            unsigned int CbAddr,
+                            unsigned int CrAddr,
+                            int colorFormat)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagSetSrcParam == false) {
+        LOGE("%s::mFlagSetSrcParam == false", __func__);
+        return false;
+    }
+
+#ifdef USE_GSC_USERPTR
+    mSrcBuffer[mSrcIndex].virt.extP[0] = (char *)YAddr;
+    mSrcBuffer[mSrcIndex].virt.extP[1] = (char *)CbAddr;
+    mSrcBuffer[mSrcIndex].virt.extP[2] = (char *)CrAddr;
+#else
+    unsigned int srcAddr[MAX_PLANES_GSCALER];
+
+    srcAddr[0] = YAddr;
+    srcAddr[1] = CbAddr;
+    srcAddr[2] = CrAddr;
+
+    for (int plane_index = 0; plane_index < mS5pFimc.params.src.planes; plane_index++) {
+        memcpy((void *)mSrcBuffer[mSrcIndex].virt.extP[plane_index], (void *)srcAddr[plane_index], mSrcBuffer[mSrcIndex].size.extS[plane_index]);
+    }
+#endif
+
+    return true;
+}
+
+bool SecGscaler::setDstParams(unsigned int width, unsigned int height,
+                              unsigned int cropX, unsigned int cropY,
+                              unsigned int *cropWidth, unsigned int *cropHeight,
+                              int colorFormat,
+                              bool forceChange)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    int mbusFormat = V4L2_MBUS_FMT_YUV8_1X24;
+
+    s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+    unsigned int fimcWidth  = *cropWidth;
+    unsigned int fimcHeight = *cropHeight;
+
+    if( m_checkDstSize(width, height, cropX, cropY,
+                   &fimcWidth, &fimcHeight, V4L2_PIX_FMT_YUV444,
+                   mRotVal, true) == false) {
+        LOGE("%s::size align error!", __func__);
+        return false;
+    }
+
+
+    if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
+        if (forceChange == true) {
+#ifdef DEBUG_LIB_FIMC
+            LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
+                    *cropWidth, *cropHeight, fimcWidth, fimcHeight);
+#endif
+        } else {
+            LOGE("%s::Invalid destination params", __func__);
+            return false;
+        }
+    }
+
+    if (90 == mRotVal || 270 == mRotVal) {
+        params->dst.full_width  = height;
+        params->dst.full_height = width;
+
+        if (90 == mRotVal) {
+            params->dst.start_x     = cropY;
+            params->dst.start_y     = width - (cropX + fimcWidth);
+        } else {
+            params->dst.start_x = height - (cropY + fimcHeight);
+            params->dst.start_y = cropX;
+        }
+
+        params->dst.width       = fimcHeight;
+        params->dst.height      = fimcWidth;
+
+        params->dst.start_y     += (fimcWidth - params->dst.height);
+
+    } else {
+        params->dst.full_width  = width;
+        params->dst.full_height = height;
+
+        if (180 == mRotVal) {
+            params->dst.start_x = width - (cropX + fimcWidth);
+            params->dst.start_y = height - (cropY + fimcHeight);
+        } else {
+            params->dst.start_x     = cropX;
+            params->dst.start_y     = cropY;
+        }
+
+        params->dst.width       = fimcWidth;
+        params->dst.height      = fimcHeight;
+    }
+
+    if (gsc_subdev_set_fmt(mSubdevFd, GSC_SUBDEV_PAD_SOURCE, V4L2_MBUS_FMT_YUV8_1X24, &(params->dst)) < 0) {
+        LOGE("%s::gsc_subdev_set_fmt()[dst] failed", __func__);
+        return false;
+    }
+
+    mFlagSetDstParam = true;
+
+    return true;
+}
+
+bool SecGscaler::getDstParams(unsigned int *width, unsigned int *height,
+                              unsigned int *cropX, unsigned int *cropY,
+                              unsigned int *cropWidth, unsigned int *cropHeight,
+                              int *mbusColorFormat)
+{
+    struct v4l2_subdev_format fmt;
+    struct v4l2_subdev_crop   crop;
+
+    fmt.pad   = GSC_SUBDEV_PAD_SOURCE;
+    fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+    if (ioctl(mSubdevFd, VIDIOC_SUBDEV_G_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_FMT", __func__);
+        return -1;
+    }
+
+    *width  = fmt.format.width;
+    *height = fmt.format.height;
+    *mbusColorFormat = fmt.format.code;
+
+    crop.pad   = GSC_SUBDEV_PAD_SOURCE;
+    crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+    if (ioctl(mSubdevFd, VIDIOC_SUBDEV_G_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_CROP", __func__);
+        return -1;
+    }
+
+    *cropX      = crop.rect.left;
+    *cropY      = crop.rect.top;
+    *cropWidth  = crop.rect.width;
+    *cropHeight = crop.rect.height;
+
+    return true;
+}
+
+bool SecGscaler::setDstAddr(unsigned int YAddr, unsigned int CbAddr, unsigned int CrAddr, int buf_index)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    return true;
+}
+
+bool SecGscaler::setRotVal(unsigned int rotVal)
+{
+    struct v4l2_control vc;
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (gsc_v4l2_s_ctrl(mVideodevFd, V4L2_CID_ROTATE, rotVal) < 0) {
+        LOGE("%s::fimc_v4l2_s_ctrl(V4L2_CID_ROTATE) failed", __func__);
+        return false;
+    }
+
+    mRotVal = rotVal;
+    return true;
+}
+
+bool SecGscaler::setGlobalAlpha(bool enable, int alpha)
+{
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagStreamOn == true) {
+        LOGE("%s::mFlagStreamOn == true", __func__);
+        return false;
+    }
+
+    mFlagGlobalAlpha = enable;
+    mGlobalAlpha     = alpha;
+
+    return true;
+
+}
+
+bool SecGscaler::setLocalAlpha(bool enable)
+{
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagStreamOn == true) {
+        LOGE("%s::mFlagStreamOn == true", __func__);
+        return false;
+    }
+
+    if (mFlagLocalAlpha == enable)
+        return true;
+
+    return true;
+}
+
+bool SecGscaler::setColorKey(bool enable, int colorKey)
+{
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagStreamOn == true) {
+        LOGE("%s::mFlagStreamOn == true", __func__);
+        return false;
+    }
+
+    mFlagColorKey = enable;
+    mColorKey = colorKey;
+
+    return true;
+}
+
+bool SecGscaler::run()
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagSetSrcParam == false) {
+        LOGE("%s::faild : Need to set source parameters of Gscaler", __func__);
+        return false;
+    }
+
+    if (mFlagSetDstParam == false) {
+        LOGE("%s::faild : Need to set destination parameters of Gscaler", __func__);
+        return false;
+    }
+
+    s5p_fimc_params_t *params = &(mS5pFimc.params);
+    int src_planes = m_getYuvPlanes(params->src.color_space);
+    unsigned int dqIndex = 0;
+    src_planes     = (src_planes == -1) ? 1 : src_planes;
+
+    if (gsc_v4l2_queue(mVideodevFd, &(mSrcBuffer[mSrcIndex]), V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mSrcIndex, src_planes) < 0) {
+        LOGE("%s::fimc_v4l2_queue[src](mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, mNumOfBuf, mSrcIndex);
+        return false;
+    }
+
+    mSrcIndex++;
+    if (mSrcIndex >= MAX_BUFFERS_GSCALER) {
+        mSrcIndex = 0;
+    }
+
+    if (gsc_v4l2_dequeue(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, &dqIndex, src_planes) < 0) {
+        LOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d, dqIndex=%d) failed", __func__, mNumOfBuf, dqIndex);
+        return false;
+    }
+
+    return true;
+}
+
+bool SecGscaler::streamOn(void)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagStreamOn == true) {
+        LOGE("%s::already streamon", __func__);
+        return true;
+    }
+
+    s5p_fimc_params_t *params = &(mS5pFimc.params);
+    int src_planes = m_getYuvPlanes(params->src.color_space);
+    src_planes     = (src_planes == -1) ? 1 : src_planes;
+
+    if (gsc_v4l2_queue(mVideodevFd, &(mSrcBuffer[mSrcIndex]), V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mSrcIndex, src_planes) < 0) {
+        LOGE("%s::fimc_v4l2_queue[src](mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, mNumOfBuf, mSrcIndex);
+        return false;
+    }
+
+    mSrcIndex++;
+    if (mSrcIndex == MAX_BUFFERS_GSCALER - 1) {
+        if (gsc_v4l2_stream_on(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+            LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
+            return false;
+        }
+        mFlagStreamOn = true;
+    }
+
+    if (mSrcIndex >= MAX_BUFFERS_GSCALER) {
+        mSrcIndex = 0;
+    }
+
+    return true;
+}
+
+bool SecGscaler::streamOff(void)
+{
+#ifdef DEBUG_LIB_FIMC
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagStreamOn == false) {
+        LOGE("%s::already streamoff", __func__);
+        return true;
+    }
+
+    if (gsc_v4l2_stream_off(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+        LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
+        return false;
+    }
+
+    mSrcIndex = 0;
+#ifdef USE_GSC_USERPTR
+    SecBuffer zeroBuf;
+    for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++)
+        mSrcBuffer[buf_index] = zeroBuf;
+#else
+    for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) {
+        for (int plane_index = 0; plane_index < MAX_PLANES_GSCALER; plane_index++) {
+            munmap((void *)mSrcBuffer[buf_index].virt.extP[plane_index], mSrcBuffer[buf_index].size.extS[plane_index]);
+        }
+    }
+#endif
+
+    mFlagStreamOn = false;
+
+    return true;
+}
+
+bool SecGscaler::m_checkSrcSize(unsigned int width, unsigned int height,
+                             unsigned int cropX, unsigned int cropY,
+                             unsigned int *cropWidth, unsigned int *cropHeight,
+                             int colorFormat,
+                             bool forceChange)
+{
+    bool ret = true;
+
+    if (8 <= height && *cropHeight < 8) {
+        if (forceChange)
+            *cropHeight = 8;
+        ret = false;
+    }
+
+    if (16 <= width && *cropWidth < 16) {
+        if (forceChange)
+            *cropWidth = 16;
+        ret = false;
+    }
+
+    if (height < 8)
+        return false;
+
+    if (width % 16 != 0)
+        return false;
+
+    if (*cropWidth % 16 != 0) {
+        if (forceChange)
+            *cropWidth = multipleOfN(*cropWidth, 16);
+        ret = false;
+    }
+
+    return ret;
+}
+
+bool SecGscaler::m_checkDstSize(unsigned int width, unsigned int height,
+                             unsigned int cropX, unsigned int cropY,
+                             unsigned int *cropWidth, unsigned int *cropHeight,
+                             int colorFormat, int rotVal,  bool forceChange)
+{
+    bool ret = true;
+    unsigned int rotWidth;
+    unsigned int rotHeight;
+    unsigned int *rotCropWidth;
+    unsigned int *rotCropHeight;
+
+    if (rotVal == 90 || rotVal == 270) {
+        rotWidth = height;
+        rotHeight = width;
+        rotCropWidth = cropHeight;
+        rotCropHeight = cropWidth;
+    } else {
+        rotWidth = width;
+        rotHeight = height;
+        rotCropWidth = cropWidth;
+        rotCropHeight = cropHeight;
+    }
+
+    if (rotHeight < 8)
+        return false;
+
+    if (rotWidth % 8 != 0)
+        return false;
+
+    switch (colorFormat) {
+    case V4L2_PIX_FMT_NV21:
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV12T:
+    case V4L2_PIX_FMT_NV12M:
+    case V4L2_PIX_FMT_NV12MT:
+    case V4L2_PIX_FMT_YUV420M:
+    case V4L2_PIX_FMT_YUV420:
+        if (*rotCropHeight % 2 != 0) {
+            if (forceChange)
+                *rotCropHeight = multipleOfN(*rotCropHeight, 2);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+int SecGscaler::m_widthOfFimc(int v4l2ColorFormat, int width)
+{
+    int newWidth = width;
+
+    switch (v4l2ColorFormat) {
+    case V4L2_PIX_FMT_RGB565:
+        newWidth = multipleOfN(width, 8);
+        break;
+    case V4L2_PIX_FMT_RGB32:
+        newWidth = multipleOfN(width, 4);
+        break;
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_UYVY:
+        newWidth = multipleOfN(width, 4);
+        break;
+    case V4L2_PIX_FMT_NV61:
+    case V4L2_PIX_FMT_NV16:
+        newWidth = multipleOfN(width, 8);
+        break;
+    case V4L2_PIX_FMT_YUV422P:
+        newWidth = multipleOfN(width, 16);
+        break;
+    case V4L2_PIX_FMT_NV21:
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV12MT:
+        newWidth = multipleOfN(width, 8);
+        break;
+    case V4L2_PIX_FMT_YUV420:
+    case V4L2_PIX_FMT_YUV420M:
+        newWidth = multipleOfN(width, 16);
+        break;
+    default :
+        break;
+    }
+
+    return newWidth;
+}
+
+int SecGscaler::m_heightOfFimc(int v4l2ColorFormat, int height)
+{
+    int newHeight = height;
+
+    switch (v4l2ColorFormat) {
+    case V4L2_PIX_FMT_NV21:
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV12T:
+    case V4L2_PIX_FMT_NV12MT:
+    case V4L2_PIX_FMT_YUV420:
+    case V4L2_PIX_FMT_YUV420M:
+        newHeight = multipleOfN(height, 2);
+        break;
+    default :
+        break;
+    }
+    return newHeight;
+}
+
+int SecGscaler::m_getYuvBpp(unsigned int fmt)
+{
+    int i, sel = -1;
+
+    for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+        if (yuv_list[i].fmt == fmt) {
+            sel = i;
+            break;
+        }
+    }
+
+    if (sel == -1)
+        return sel;
+    else
+        return yuv_list[sel].bpp;
+}
+
+int SecGscaler::m_getYuvPlanes(unsigned int fmt)
+{
+    int i, sel = -1;
+
+    for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+        if (yuv_list[i].fmt == fmt) {
+            sel = i;
+            break;
+        }
+    }
+
+    if (sel == -1)
+        return sel;
+    else
+        return yuv_list[sel].planes;
+}
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h
new file mode 100644
index 0000000..e9867ed
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SEC_GSC_OUT_H__
+#define __SEC_GSC_OUT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/fb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <asm/sizes.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <hardware/hardware.h>
+
+#include "utils/Timers.h"
+
+#include "s5p_fimc_v4l2.h"
+#include "sec_utils_v4l2.h"
+#include "media.h"
+#include "v4l2-subdev.h"
+
+#include "sec_format.h"
+
+#include "SecBuffer.h"
+
+#define PFX_NODE_MEDIADEV          "/dev/media"
+#define PFX_NODE_SUBDEV            "/dev/v4l-subdev"
+#define PFX_NODE_VIDEODEV          "/dev/video"
+#define PFX_ENTITY_SUBDEV_GSC      "exynos-gsc-sd.%d"
+#define PFX_ENTITY_OUTPUTDEV_GSC   "exynos-gsc.%d.output"
+
+#define GSC_SUBDEV_PAD_SINK      (0)
+#define GSC_SUBDEV_PAD_SOURCE    (1)
+#define GSC_VIDEODEV_PAD_SOURCE  (0)
+#define MAX_BUFFERS_GSCALER      (2)
+#define MAX_PLANES_GSCALER       (3)
+
+#ifdef __cplusplus
+}
+
+class SecGscaler
+{
+public:
+    enum DEV {
+        DEV_0 = 0,
+        DEV_1,
+        DEV_2,
+        DEV_3,
+        DEV_MAX,
+    };
+
+    enum MODE {
+        MODE_NONE = 0,
+        MODE_SINGLE_BUF,
+        MODE_MULTI_BUF,
+        MODE_DMA_AUTO,
+        MODE_MAX,
+    };
+
+private:
+    bool                        mFlagCreate;
+    int                         mDev;
+    int                         mVideoNodeNum;
+    int                         mSubdevNodeNum;
+    int                         mVideodevFd;
+    int                         mMediadevFd;
+    int                         mSubdevFd;
+    unsigned int                mNumOfBuf;
+    unsigned int                mSrcIndex;
+    int                         mRotVal;
+    bool                        mFlagGlobalAlpha;
+    int                         mGlobalAlpha;
+    bool                        mFlagLocalAlpha;
+    bool                        mFlagColorKey;
+    int                         mColorKey;
+    bool                        mFlagSetSrcParam;
+    bool                        mFlagSetDstParam;
+    bool                        mFlagStreamOn;
+
+    s5p_fimc_t                  mS5pFimc;
+    SecBuffer                   mSrcBuffer[MAX_BUFFERS_GSCALER];
+
+    __u32                       mSubdevEntity;
+    __u32                       mVideodevEntity;
+    //struct media_link_desc      mlink_desc;
+
+public:
+    SecGscaler();
+    virtual ~SecGscaler();
+
+    bool create(enum DEV dev, enum MODE mode, unsigned int numOfBuf);
+    bool create(enum DEV dev, unsigned int numOfBuf);
+
+    bool destroy(void);
+    bool flagCreate(void);
+
+    int   getFd(void);
+    int   getVideodevFd(void);
+    bool  openVideodevFd(void);
+    bool  closeVideodevFd(void);
+
+    int   getSubdevFd(void);
+    __u32 getSubdevEntity(void);
+    __u32 getVideodevEntity(void);
+    bool  getFlagSteamOn(void);
+
+    SecBuffer * getSrcBufferAddr(int index);
+
+    bool setSrcParams(unsigned int width, unsigned int height,
+                      unsigned int cropX, unsigned int cropY,
+                      unsigned int *cropWidth, unsigned int *cropHeight,
+                      int colorFormat,
+                      bool forceChange = true);
+
+    bool getSrcParams(unsigned int *width, unsigned int *height,
+                      unsigned int *cropX, unsigned int *cropY,
+                      unsigned int *cropWidth, unsigned int *cropHeight,
+                      int *v4l2colorFormat);
+
+    bool setSrcAddr(unsigned int YAddr,
+                    unsigned int CbAddr = 0,
+                    unsigned int CrAddr = 0,
+                    int colorFormat = 0);
+
+    bool setDstParams(unsigned int width, unsigned int height,
+                      unsigned int cropX, unsigned int cropY,
+                      unsigned int *cropWidth, unsigned int *cropHeight,
+                      int colorFormat,
+                      bool forceChange = true);
+
+    bool getDstParams(unsigned int *width, unsigned int *height,
+                      unsigned int *cropX, unsigned int *cropY,
+                      unsigned int *cropWidth, unsigned int *cropHeight,
+                      int *mbusColorFormat);
+
+    bool setDstAddr(unsigned int YAddr,
+                    unsigned int CbAddr = 0,
+                    unsigned int CrAddr = 0,
+                    int buf_index = 0);
+
+    bool setRotVal(unsigned int rotVal);
+    bool setGlobalAlpha(bool enable = true, int alpha = 0xff);
+    bool setLocalAlpha(bool enable);
+    bool setColorKey(bool enable = true, int colorKey = 0xff);
+
+    bool run(void);
+    bool streamOn(void);
+    bool streamOff(void);
+
+private:
+    bool m_checkSrcSize(unsigned int width, unsigned int height,
+                        unsigned int cropX, unsigned int cropY,
+                        unsigned int *cropWidth, unsigned int *cropHeight,
+                        int colorFormat,
+                        bool forceChange = false);
+
+    bool m_checkDstSize(unsigned int width, unsigned int height,
+                        unsigned int cropX, unsigned int cropY,
+                        unsigned int *cropWidth, unsigned int *cropHeight,
+                        int colorFormat,
+                        int rotVal,
+                        bool forceChange = false);
+    int  m_widthOfFimc(int v4l2ColorFormat, int width);
+    int  m_heightOfFimc(int v4l2ColorFormat, int height);
+    int  m_getYuvBpp(unsigned int fmt);
+    int  m_getYuvPlanes(unsigned int fmt);
+};
+#endif
+
+#endif //__SEC_GSC_OUT_H__
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp b/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp
new file mode 100644
index 0000000..8f0f80b
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp
@@ -0,0 +1,1985 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define DEBUG_MSG_ENABLE
+//#define LOG_NDEBUG 0
+//#define LOG_TAG "libhdmi"
+#include <cutils/log.h>
+#include "ion.h"
+#include "SecHdmi.h"
+#include "SecHdmiV4L2Utils.h"
+
+#define CHECK_GRAPHIC_LAYER_TIME (0)
+
+namespace android {
+
+extern unsigned int output_type;
+extern v4l2_std_id t_std_id;
+extern int g_hpd_state;
+extern unsigned int g_hdcp_en;
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+extern unsigned int g2d_reserved_memory0;
+extern unsigned int g2d_reserved_memory1;
+extern unsigned int g2d_reserved_memory_size;
+extern unsigned int cur_g2d_address;
+#endif
+
+#if defined(BOARD_USES_CEC)
+SecHdmi::CECThread::~CECThread()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    mFlagRunning = false;
+}
+
+bool SecHdmi::CECThread::threadLoop()
+{
+    unsigned char buffer[CEC_MAX_FRAME_SIZE];
+    int size;
+    unsigned char lsrc, ldst, opcode;
+
+    {
+        Mutex::Autolock lock(mThreadLoopLock);
+        mFlagRunning = true;
+
+        size = CECReceiveMessage(buffer, CEC_MAX_FRAME_SIZE, 100000);
+
+        if (!size) // no data available or ctrl-c
+            return true;
+
+        if (size == 1)
+            return true; // "Polling Message"
+
+        lsrc = buffer[0] >> 4;
+
+        /* ignore messages with src address == mLaddr*/
+        if (lsrc == mLaddr)
+            return true;
+
+        opcode = buffer[1];
+
+        if (CECIgnoreMessage(opcode, lsrc)) {
+            LOGE("### ignore message coming from address 15 (unregistered)\n");
+            return true;
+        }
+
+        if (!CECCheckMessageSize(opcode, size)) {
+            LOGE("### invalid message size: %d(opcode: 0x%x) ###\n", size, opcode);
+            return true;
+        }
+
+        /* check if message broadcasted/directly addressed */
+        if (!CECCheckMessageMode(opcode, (buffer[0] & 0x0F) == CEC_MSG_BROADCAST ? 1 : 0)) {
+            LOGE("### invalid message mode (directly addressed/broadcast) ###\n");
+            return true;
+        }
+
+        ldst = lsrc;
+
+        //TODO: macroses to extract src and dst logical addresses
+        //TODO: macros to extract opcode
+
+        switch (opcode) {
+        case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+            /* responce with "Report Physical Address" */
+            buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST;
+            buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
+            buffer[2] = (mPaddr >> 8) & 0xFF;
+            buffer[3] = mPaddr & 0xFF;
+            buffer[4] = mDevtype;
+            size = 5;
+            break;
+
+        case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+            LOGD("[CEC_OPCODE_REQUEST_ACTIVE_SOURCE]\n");
+            /* responce with "Active Source" */
+            buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST;
+            buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
+            buffer[2] = (mPaddr >> 8) & 0xFF;
+            buffer[3] = mPaddr & 0xFF;
+            size = 4;
+            LOGD("Tx : [CEC_OPCODE_ACTIVE_SOURCE]\n");
+            break;
+
+        case CEC_OPCODE_ABORT:
+        case CEC_OPCODE_FEATURE_ABORT:
+        default:
+            /* send "Feature Abort" */
+            buffer[0] = (mLaddr << 4) | ldst;
+            buffer[1] = CEC_OPCODE_FEATURE_ABORT;
+            buffer[2] = CEC_OPCODE_ABORT;
+            buffer[3] = 0x04; // "refused"
+            size = 4;
+            break;
+        }
+
+        if (CECSendMessage(buffer, size) != size)
+            LOGE("CECSendMessage() failed!!!\n");
+
+    }
+    return true;
+}
+
+bool SecHdmi::CECThread::start()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mThreadControlLock);
+    if (exitPending()) {
+        if (requestExitAndWait() == WOULD_BLOCK) {
+            LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK");
+            return false;
+        }
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("EDIDGetCECPhysicalAddress");
+#endif
+    /* set to not valid physical address */
+    mPaddr = CEC_NOT_VALID_PHYSICAL_ADDRESS;
+
+    if (!EDIDGetCECPhysicalAddress(&mPaddr)) {
+        LOGE("Error: EDIDGetCECPhysicalAddress() failed.\n");
+        return false;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("CECOpen");
+#endif
+    if (!CECOpen()) {
+        LOGE("CECOpen() failed!!!\n");
+        return false;
+    }
+
+    /* a logical address should only be allocated when a device \
+       has a valid physical address, at all other times a device \
+       should take the 'Unregistered' logical address (15)
+       */
+
+    /* if physical address is not valid device should take \
+       the 'Unregistered' logical address (15)
+       */
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("CECAllocLogicalAddress");
+#endif
+    mLaddr = CECAllocLogicalAddress(mPaddr, mDevtype);
+
+    if (!mLaddr) {
+        LOGE("CECAllocLogicalAddress() failed!!!\n");
+        if (!CECClose())
+            LOGE("CECClose() failed!\n");
+        return false;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("request to run CECThread");
+#endif
+
+    status_t ret = run("SecHdmi::CECThread", PRIORITY_DISPLAY);
+    if (ret != NO_ERROR) {
+        LOGE("%s fail to run thread", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool SecHdmi::CECThread::stop()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s request Exit", __func__);
+#endif
+    Mutex::Autolock lock(mThreadControlLock);
+    if (requestExitAndWait() == WOULD_BLOCK) {
+        LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK");
+        return false;
+    }
+
+    if (!CECClose())
+        LOGE("CECClose() failed!\n");
+
+    mFlagRunning = false;
+    return true;
+}
+#endif
+
+SecHdmi::SecHdmi():
+#if defined(BOARD_USES_CEC)
+    mCECThread(NULL),
+#endif
+    mFlagCreate(false),
+    mFlagConnected(false),
+    mPreviousHdmiPresetId(V4L2_DV_1080P60),
+    mHdmiDstWidth(0),
+    mHdmiDstHeight(0),
+    mHdmiSrcYAddr(0),
+    mHdmiSrcCbCrAddr(0),
+    mFBaddr(0),
+    mFBsize(0),
+    mFBionfd(-1),
+    mFBoffset(0),
+    mHdmiOutputMode(DEFAULT_OUPUT_MODE),
+    mHdmiResolutionValue(DEFAULT_HDMI_RESOLUTION_VALUE), // V4L2_STD_480P_60_4_3
+    mHdmiStdId(DEFAULT_HDMI_STD_ID), // V4L2_STD_480P_60_4_3
+    mCompositeStd(DEFAULT_COMPOSITE_STD),
+    mHdcpMode(false),
+    mAudioMode(2),
+    mUIRotVal(0),
+    mG2DUIRotVal(0),
+    mCurrentHdmiOutputMode(-1),
+    mCurrentHdmiResolutionValue(0), // 1080960
+    mCurrentHdcpMode(false),
+    mCurrentAudioMode(-1),
+    mHdmiInfoChange(true),
+    mFlagGscalerStart(false),
+    mGscalerDstColorFormat(0),
+    mDefaultFBFd(-1),
+    mCurrentsrcW(0),
+    mCurrentsrcH(0),
+    mCurrentsrcColorFormat(0),
+    mCurrentsrcYAddr(0),
+    mCurrentsrcCbAddr(0),
+    mCurrentdstX(0),
+    mCurrentdstY(0),
+    mCurrenthdmiLayer(0),
+    mCurrentNumOfHWCLayer(0),
+    mDisplayWidth(DEFALULT_DISPLAY_WIDTH),
+    mDisplayHeight(DEFALULT_DISPLAY_HEIGHT)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    for (int i = 0; i < HDMI_LAYER_MAX; i++) {
+        mFlagLayerEnable[i] = false;
+        mFlagHdmiStart[i] = false;
+
+        mSrcWidth      [i] = 0;
+        mSrcHeight     [i] = 0;
+        mSrcColorFormat[i] = 0;
+        mHdmiResolutionWidth  [i] = 0;
+        mHdmiResolutionHeight [i] = 0;
+        mPreviousNumofHwLayer [i] = 0;
+        mSrcIndex[i] = 0;
+    }
+
+    //All layer is on
+    mFlagLayerEnable[HDMI_LAYER_VIDEO] = true;
+    mFlagLayerEnable[HDMI_LAYER_GRAPHIC_0] = true;
+    mFlagLayerEnable[HDMI_LAYER_GRAPHIC_1] = true;
+
+    mHdmiSizeOfResolutionValueList = 14;
+
+    mHdmiResolutionValueList[0]  = 1080960;
+    mHdmiResolutionValueList[1]  = 1080950;
+    mHdmiResolutionValueList[2]  = 1080930;
+    mHdmiResolutionValueList[3]  = 1080924;
+    mHdmiResolutionValueList[4]  = 1080160;
+    mHdmiResolutionValueList[5]  = 1080150;
+    mHdmiResolutionValueList[6]  = 720960;
+    mHdmiResolutionValueList[7]  = 7209601;
+    mHdmiResolutionValueList[8]  = 720950;
+    mHdmiResolutionValueList[9]  = 7209501;
+    mHdmiResolutionValueList[10] = 5769501;
+    mHdmiResolutionValueList[11] = 5769502;
+    mHdmiResolutionValueList[12] = 4809601;
+    mHdmiResolutionValueList[13] = 4809602;
+
+#if defined(BOARD_USES_CEC)
+    mCECThread = new CECThread(this);
+#endif
+
+    mGscalerForceUpdate = false;
+}
+
+SecHdmi::~SecHdmi()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (mFlagCreate == true)
+        LOGE("%s::this is not Destroyed fail", __func__);
+    else
+        disconnect();
+}
+
+bool SecHdmi::create(int width, int height)
+{
+    Mutex::Autolock lock(mLock);
+    unsigned int fimc_buf_size = 0;
+    int stride;
+    int vstride;
+
+    int ionfd_G2D = 0;
+    void * ion_base_addr = NULL;
+
+    struct s3c_fb_user_ion_client ion_handle;
+    unsigned int FB_size = ALIGN(width, 16) * ALIGN(height, 16) * HDMI_G2D_BUFFER_BPP_SIZE * 2;
+    int ionfd_FB = 0;
+
+/*
+ * Video plaback (I420): output buffer size of FIMC3 is (1920 x 1088 x 1.5)
+ * Video plaback (NV12): FIMC3 is not used.
+ * Camera preview (YV12): output buffer size of FIMC3 is (640 x 480 x 1.5)
+ * UI mode (ARGB8888) : output buffer size of FIMC3 is (480 x 800 x 1.5)
+ */
+#ifndef SUPPORT_1080P_FIMC_OUT
+    setDisplaySize(width, height);
+#endif
+
+    stride  = ALIGN(HDMI_MAX_WIDTH, 16);
+    vstride = ALIGN(HDMI_MAX_HEIGHT, 16);
+
+    fimc_buf_size = stride * vstride * HDMI_FIMC_BUFFER_BPP_SIZE;
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+    g2d_reserved_memory_size = stride * vstride * HDMI_G2D_BUFFER_BPP_SIZE;
+#endif
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    if (mFlagCreate == true) {
+        LOGE("%s::Already Created", __func__);
+        return true;
+    }
+
+    if (mDefaultFBFd <= 0) {
+        if ((mDefaultFBFd = fb_open(DEFAULT_FB)) < 0) {
+            LOGE("%s:Failed to open default FB", __func__);
+            return false;
+        }
+    }
+
+    if (mSecGscaler.create(SecGscaler::DEV_3, MAX_BUFFERS_GSCALER) == false) {
+        LOGE("%s::SecGscaler create() failed", __func__);
+        goto CREATE_FAIL;
+    }
+
+    mIonClient = ion_client_create();
+    if (mIonClient < 0) {
+        mIonClient = -1;
+        LOGE("%s::ion_client_create() failed", __func__);
+        goto CREATE_FAIL;
+    }
+
+    // get framebuffer virtual address for LCD
+    if (ioctl(mDefaultFBFd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) == -1) {
+        LOGE("%s:ioctl(S3CFB_GET_ION_USER_HANDLE) failed", __func__);
+        return false;
+    }
+
+    mFBaddr  = (unsigned int)ion_map(ion_handle.fd, ALIGN(FB_size, PAGE_SIZE), 0);
+    mFBsize  = FB_size;
+    mFBionfd = ion_handle.fd;
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+    ionfd_G2D = ion_alloc(mIonClient, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0, ION_HEAP_EXYNOS_MASK);
+
+    if (ionfd_G2D < 0) {
+        LOGE("%s::ION memory allocation failed", __func__);
+    } else {
+        ion_base_addr = ion_map(ionfd_G2D, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0);
+        if (ion_base_addr == MAP_FAILED)
+            LOGE("%s::ION mmap failed", __func__);
+    }
+
+    g2d_reserved_memory0 = (unsigned int)ion_base_addr;
+    g2d_reserved_memory1 = g2d_reserved_memory0 + g2d_reserved_memory_size;
+#endif
+
+    v4l2_std_id std_id;
+    __u32 preset_id;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::mHdmiOutputMode(%d) \n", __func__, mHdmiOutputMode);
+#endif
+    if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) {
+        std_id = composite_std_2_v4l2_std_id(mCompositeStd);
+        if ((int)std_id < 0) {
+            LOGE("%s::composite_std_2_v4l2_std_id(%d) fail\n", __func__, mCompositeStd);
+            goto CREATE_FAIL;
+        }
+        if (m_setCompositeResolution(mCompositeStd) == false) {
+            LOGE("%s::m_setCompositeResolution(%d) fail\n", __func__, mCompositeStd);
+            goto CREATE_FAIL;
+        }
+    } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+            mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+        if (hdmi_resolution_2_std_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &std_id, &preset_id) < 0) {
+            LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, mHdmiResolutionValue);
+            goto CREATE_FAIL;
+        }
+    }
+
+    if (m_setupLink() == false) {
+        LOGE("%s:Enable the link failed", __func__);
+        return false;
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+        if (m_openLayer(layer) == false)
+            LOGE("%s::hdmi_init_layer(%d) failed", __func__, layer);
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 2; layer < HDMI_LAYER_MAX; layer++) {
+        if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
+            LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer);
+            return false;
+        }
+
+        if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
+            LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer);
+            return false;
+        }
+
+        if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
+            LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, layer);
+            return false;
+        }
+    }
+
+    mFlagCreate = true;
+
+    return true;
+
+CREATE_FAIL :
+
+    if (mSecGscaler.flagCreate() == true &&
+        mSecGscaler.destroy()    == false)
+        LOGE("%s::Gscaler destory failed", __func__);
+
+    return false;
+}
+
+bool SecHdmi::destroy(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    char node[32];
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Already Destroyed fail \n", __func__);
+        goto DESTROY_FAIL;
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+        if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
+            LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, layer);
+            goto DESTROY_FAIL;
+        }
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+        if (m_closeLayer(layer) == false)
+            LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer);
+    }
+
+    if (mSecGscaler.flagCreate() == true && mSecGscaler.destroy() == false) {
+        LOGE("%s::fimc destory fail \n", __func__);
+        goto DESTROY_FAIL;
+    }
+
+#ifdef USE_LCD_ADDR_IN_HERE
+    {
+        if (0 < mDefaultFBFd) {
+            close(mDefaultFBFd);
+            mDefaultFBFd = -1;
+        }
+    }
+#endif //USE_LCD_ADDR_IN_HERE
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+    ion_unmap((void *)g2d_reserved_memory0, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE));
+#endif
+
+    if (0 < mFBaddr)
+        ion_unmap((void *)mFBaddr, ALIGN(mFBsize, PAGE_SIZE));
+
+    if (0 < mFBionfd)
+        ion_free(mFBionfd);
+
+    sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
+    mMediadevFd = open(node, O_RDONLY);
+
+    if (mMediadevFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto DESTROY_FAIL;
+    }
+
+    mlink_desc.flags = 0;
+    if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) {
+        LOGE("%s::MEDIA_IOC_SETUP_UNLINK failed", __func__);
+        goto DESTROY_FAIL;
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+        if (m_closeLayer(layer) == false)
+            LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer);
+    }
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+
+    if (0 < mSubdevMixerFd)
+        close(mSubdevMixerFd);
+
+    mMediadevFd = -1;
+    mSubdevMixerFd = -1;
+
+    mFlagCreate = false;
+
+    return true;
+
+DESTROY_FAIL :
+
+    return false;
+}
+
+bool SecHdmi::connect(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    {
+        Mutex::Autolock lock(mLock);
+
+        if (mFlagCreate == false) {
+            LOGE("%s::Not Yet Created \n", __func__);
+            return false;
+        }
+
+        if (mFlagConnected == true) {
+            LOGD("%s::Already Connected.. \n", __func__);
+            return true;
+        }
+
+        if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+                mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+            if (m_flagHWConnected() == false) {
+                LOGD("%s::m_flagHWConnected() fail \n", __func__);
+                return false;
+            }
+
+#if defined(BOARD_USES_EDID)
+            if (!EDIDOpen())
+                LOGE("EDIDInit() failed!\n");
+
+            if (!EDIDRead()) {
+                LOGE("EDIDRead() failed!\n");
+                if (!EDIDClose())
+                    LOGE("EDIDClose() failed!\n");
+            }
+#endif
+
+#if defined(BOARD_USES_CEC)
+            if (!(mCECThread->mFlagRunning))
+                mCECThread->start();
+#endif
+        }
+    }
+
+    if (this->setHdmiOutputMode(mHdmiOutputMode, true) == false)
+        LOGE("%s::setHdmiOutputMode(%d) fail \n", __func__, mHdmiOutputMode);
+
+    if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+            mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+        if (this->setHdmiResolution(mHdmiResolutionValue, true) == false)
+            LOGE("%s::setHdmiResolution(%d) fail \n", __func__, mHdmiResolutionValue);
+
+        if (this->setHdcpMode(mHdcpMode, false) == false)
+            LOGE("%s::setHdcpMode(%d) fail \n", __func__, mHdcpMode);
+
+/*        if (this->m_setAudioMode(mAudioMode) == false)
+            LOGE("%s::m_setAudioMode(%d) fail \n", __func__, mAudioMode);
+*/
+        mHdmiInfoChange = true;
+        mFlagConnected = true;
+
+#if defined(BOARD_USES_EDID)
+        display_menu();
+#endif
+    }
+
+    return true;
+}
+
+bool SecHdmi::disconnect(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    if (mFlagConnected == false) {
+        LOGE("%s::Already Disconnected.. \n", __func__);
+        return true;
+    }
+
+    if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+        mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+#if defined(BOARD_USES_CEC)
+        if (mCECThread->mFlagRunning)
+            mCECThread->stop();
+#endif
+
+#if defined(BOARD_USES_EDID)
+        if (!EDIDClose()) {
+            LOGE("EDIDClose() failed!\n");
+            return false;
+        }
+#endif
+    }
+
+    for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+        if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
+            LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, layer);
+            return false;
+        }
+    }
+
+    mFlagConnected = false;
+    mPreviousHdmiPresetId = V4L2_DV_1080P60;
+
+    mHdmiOutputMode = DEFAULT_OUPUT_MODE;
+    mHdmiResolutionValue = DEFAULT_HDMI_RESOLUTION_VALUE;
+    mHdmiStdId = DEFAULT_HDMI_STD_ID;
+    mCompositeStd = DEFAULT_COMPOSITE_STD;
+    mAudioMode = 2;
+    mCurrentHdmiOutputMode = -1;
+    mCurrentHdmiResolutionValue = 0;
+    mCurrentAudioMode = -1;
+
+    return true;
+}
+
+bool SecHdmi::startHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+    if (mFlagHdmiStart[hdmiLayer] == false &&
+            m_startHdmi(hdmiLayer) == false) {
+        LOGE("%s::hdmiLayer(%d) fail \n", __func__, hdmiLayer);
+        return false;
+    }
+    return true;
+}
+
+bool SecHdmi::stopHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+    if (mFlagHdmiStart[hdmiLayer] == true &&
+            m_stopHdmi(hdmiLayer) == false) {
+        LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, hdmiLayer);
+        return false;
+    }
+    tvout_deinit();
+    return true;
+}
+
+bool SecHdmi::flagConnected(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    return mFlagConnected;
+}
+
+bool SecHdmi::flush(int srcW, int srcH, int srcColorFormat,
+        unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr,
+        int dstX, int dstY,
+        int hdmiLayer,
+        int num_of_hwc_layer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer=%d", __func__, hdmiLayer);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, srcCrAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d, num_of_hwc_layer=%d",
+         __func__, srcW, srcH, srcColorFormat,
+                   srcYAddr, srcCbAddr, srcCrAddr,
+                   dstX, dstY, hdmiLayer, num_of_hwc_layer);
+    LOGD("saved param(%d, %d, %d)",
+            mSrcWidth[hdmiLayer], mSrcHeight[hdmiLayer], mSrcColorFormat[hdmiLayer]);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created", __func__);
+        return false;
+    }
+
+    if (srcW != mSrcWidth[hdmiLayer] ||
+        srcH != mSrcHeight[hdmiLayer] ||
+        srcColorFormat != mSrcColorFormat[hdmiLayer] ||
+        mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
+        mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
+        num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] ||
+        mHdmiInfoChange == true) {
+#ifdef DEBUG_MSG_ENABLE
+        LOGD("m_reset param(%d, %d, %d, %d, %d, %d, %d)",
+            srcW, mSrcWidth[hdmiLayer],
+            srcH, mSrcHeight[hdmiLayer],
+            srcColorFormat, mSrcColorFormat[hdmiLayer],
+            hdmiLayer);
+#endif
+        if (m_reset(srcW, srcH, dstX, dstY, srcColorFormat, hdmiLayer, num_of_hwc_layer) == false) {
+            LOGE("%s::m_reset(%d, %d, %d, %d) failed", __func__, srcW, srcH, srcColorFormat, hdmiLayer);
+            return false;
+        }
+    }
+
+    if (srcYAddr == 0) {
+        unsigned int FB_size = ALIGN(srcW, 16) * ALIGN(srcH, 16) * HDMI_G2D_BUFFER_BPP_SIZE;
+
+        srcYAddr = (unsigned int)mFBaddr + mFBoffset;
+        srcCbAddr = srcYAddr;
+
+        mFBoffset += FB_size;
+        if (FB_size < mFBoffset)
+            mFBoffset = 0;
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::mFBaddr=0x%08x, srcYAddr=0x%08x, mFBoffset=0x%08x", __func__, mFBaddr, srcYAddr, mFBoffset);
+#endif
+    }
+
+    if (hdmiLayer == HDMI_LAYER_VIDEO) {
+        if (mSecGscaler.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) {
+            LOGE("%s::setSrcAddr(0x%08x, 0x%08x, 0x%08x)", __func__, srcYAddr, srcCbAddr, srcCrAddr);
+            return false;
+        }
+    } else {
+#if CHECK_GRAPHIC_LAYER_TIME
+        nsecs_t start, end;
+        start = systemTime();
+#endif
+
+        if (num_of_hwc_layer == 0) { /* UI only mode */
+            struct v4l2_rect rect;
+
+            if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) {
+                hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
+            } else {
+                hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect);
+            }
+
+            rect.left = ALIGN(rect.left, 16);
+
+            if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
+                            srcColorFormat,
+                            srcW, srcH,
+                            srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]],
+                            rect.left, rect.top,
+                            rect.width, rect.height,
+                            mG2DUIRotVal) < 0)
+            return false;
+
+        } else { // Video Playback + UI Mode
+            if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
+                            srcColorFormat,
+                            srcW, srcH,
+                            srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]],
+                            dstX, dstY,
+                            mHdmiDstWidth, mHdmiDstHeight,
+                            mG2DUIRotVal) < 0)
+            return false;
+        }
+
+#if CHECK_GRAPHIC_LAYER_TIME
+        end = systemTime();
+        LOGD("[UI] hdmi_gl_set_param[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
+#endif
+    }
+
+    if (mFlagConnected) {
+        if (mFlagHdmiStart[hdmiLayer] == true) {
+            if (m_run(hdmiLayer) == false) {
+                LOGE("%s::m_run(%d) failed", __func__, hdmiLayer);
+                return false;
+            }
+        }
+
+        if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer) == false) {
+            LOGE("%s::start hdmiLayer(%d) failed", __func__, hdmiLayer);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SecHdmi::clear(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+    if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) {
+        LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer);
+        return false;
+    }
+    return true;
+}
+
+void SecHdmi::clearGraphicLayer(int hdmiLayer)
+{
+    mSrcWidth[hdmiLayer] = 0;
+    mSrcHeight[hdmiLayer] = 0;
+    mSrcColorFormat[hdmiLayer] = 0;
+}
+
+bool SecHdmi::enableGraphicLayer(int hdmiLayer)
+{
+    Mutex::Autolock lock(mLock);
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer);
+#endif
+    switch (hdmiLayer) {
+    case HDMI_LAYER_VIDEO:
+    case HDMI_LAYER_GRAPHIC_0:
+    case HDMI_LAYER_GRAPHIC_1:
+        mFlagLayerEnable[hdmiLayer] = true;
+        if (mFlagConnected == true)
+            m_startHdmi(hdmiLayer);
+        break;
+    default:
+        return false;
+    }
+    return true;
+}
+
+bool SecHdmi::disableGraphicLayer(int hdmiLayer)
+{
+    Mutex::Autolock lock(mLock);
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer);
+#endif
+    switch (hdmiLayer) {
+    case HDMI_LAYER_VIDEO:
+    case HDMI_LAYER_GRAPHIC_0:
+    case HDMI_LAYER_GRAPHIC_1:
+        if (mFlagConnected == true && mFlagLayerEnable[hdmiLayer])
+            if (m_stopHdmi(hdmiLayer) == false )
+                LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer);
+
+        mFlagLayerEnable[hdmiLayer] = false;
+        break;
+    default:
+        return false;
+    }
+    return true;
+}
+
+bool SecHdmi::setHdmiOutputMode(int hdmiOutputMode, bool forceRun)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::hdmiOutputMode = %d, forceRun = %d", __func__, hdmiOutputMode, forceRun);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    if (forceRun == false && mHdmiOutputMode == hdmiOutputMode) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode);
+#endif
+        return true;
+    }
+
+    int newHdmiOutputMode = hdmiOutputMode;
+
+    int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode);
+    if (v4l2OutputType < 0) {
+        LOGD("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode);
+        return false;
+    }
+
+#if defined(BOARD_USES_EDID)
+    int newV4l2OutputType = hdmi_check_output_mode(v4l2OutputType);
+    if (newV4l2OutputType != v4l2OutputType) {
+        newHdmiOutputMode = hdmi_v4l2_output_type_2_outputmode(newV4l2OutputType);
+        if (newHdmiOutputMode < 0) {
+            LOGD("%s::hdmi_v4l2_output_type_2_outputmode(%d) fail\n", __func__, newV4l2OutputType);
+            return false;
+        }
+
+        LOGD("%s::calibration mode(%d -> %d)... \n", __func__, hdmiOutputMode, newHdmiOutputMode);
+        mHdmiInfoChange = true;
+    }
+#endif
+
+    if (mHdmiOutputMode != newHdmiOutputMode) {
+        mHdmiOutputMode = newHdmiOutputMode;
+        mHdmiInfoChange = true;
+    }
+
+    return true;
+}
+
+bool SecHdmi::setHdmiResolution(unsigned int hdmiResolutionValue, bool forceRun)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiResolutionValue = %d, forceRun = %d", __func__, hdmiResolutionValue, forceRun);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    if (forceRun == false && mHdmiResolutionValue == hdmiResolutionValue) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue);
+#endif
+        return true;
+    }
+
+    unsigned int newHdmiResolutionValue = hdmiResolutionValue;
+    int w = 0;
+    int h = 0;
+    v4l2_std_id std_id;
+    __u32 preset_id;
+
+#if defined(BOARD_USES_EDID)
+    // find perfect resolutions..
+    if (hdmi_resolution_2_std_id(newHdmiResolutionValue, &w, &h, &std_id, &preset_id) < 0 ||
+        hdmi_check_resolution(std_id) < 0) {
+        bool flagFoundIndex = false;
+        int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue);
+
+        for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) {
+            if (hdmi_resolution_2_std_id(mHdmiResolutionValueList[i], &w, &h, &std_id, &preset_id) == 0 &&
+                hdmi_check_resolution(std_id) == 0) {
+                newHdmiResolutionValue = mHdmiResolutionValueList[i];
+                flagFoundIndex = true;
+                break;
+            }
+        }
+
+        if (flagFoundIndex == false) {
+            LOGE("%s::hdmi cannot control this resolution(%d) fail \n", __func__, hdmiResolutionValue);
+            // Set resolution to 480P
+            newHdmiResolutionValue = mHdmiResolutionValueList[mHdmiSizeOfResolutionValueList-2];
+        } else {
+            LOGD("%s::HDMI resolutions size is calibrated(%d -> %d)..\n", __func__, hdmiResolutionValue, newHdmiResolutionValue);
+        }
+    } else {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::find resolutions(%d) at once\n", __func__, hdmiResolutionValue);
+#endif
+    }
+#endif
+
+    if (mHdmiResolutionValue != newHdmiResolutionValue) {
+        mHdmiResolutionValue = newHdmiResolutionValue;
+        mHdmiInfoChange = true;
+    }
+
+    return true;
+}
+
+bool SecHdmi::setHdcpMode(bool hdcpMode, bool forceRun)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    if (forceRun == false && mHdcpMode == hdcpMode) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode);
+#endif
+        return true;
+    }
+
+    mHdcpMode = hdcpMode;
+    mHdmiInfoChange = true;
+
+    return true;
+}
+
+bool SecHdmi::setUIRotation(unsigned int rotVal, unsigned int hwcLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    Mutex::Autolock lock(mLock);
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not Yet Created \n", __func__);
+        return false;
+    }
+
+    if (rotVal % 90 != 0) {
+        LOGE("%s::Invalid rotation value(%d)", __func__, rotVal);
+        return false;
+    }
+
+    /* G2D rotation */
+    if (rotVal != mG2DUIRotVal) {
+        mG2DUIRotVal = rotVal;
+        mHdmiInfoChange = true;
+    }
+
+    /* FIMC rotation */
+    if (hwcLayer == 0) { /* Rotate in UI only mode */
+        if (rotVal != mUIRotVal) {
+            mSecGscaler.setRotVal(rotVal);
+            mUIRotVal = rotVal;
+            mHdmiInfoChange = true;
+        }
+    } else { /* Don't rotate video layer when video is played. */
+        rotVal = 0;
+        if (rotVal != mUIRotVal) {
+            mSecGscaler.setRotVal(rotVal);
+            mUIRotVal = rotVal;
+            mHdmiInfoChange = true;
+        }
+    }
+
+    return true;
+}
+
+bool SecHdmi::setDisplaySize(int width, int height)
+{
+    mDisplayWidth = width;
+    mDisplayHeight = height;
+
+    return true;
+}
+
+void SecHdmi::setDisplayInfo(int srcW, int srcH, int srcColorFormat,
+        unsigned int srcYAddr, unsigned int srcCbAddr,
+        int dstX, int dstY,
+        int hdmiLayer,
+        int num_of_hwc_layer)
+{
+#ifdef DEBUG_MSG_ENABLE
+LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d",
+            __func__, srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, dstX, dstY, hdmiLayer);
+#endif
+
+    mCurrentsrcW = srcW;
+    mCurrentsrcH = srcH;
+    mCurrentsrcColorFormat = srcColorFormat;
+    mCurrentsrcYAddr = srcYAddr;
+    mCurrentsrcCbAddr = srcCbAddr,
+    mCurrentdstX = dstX;
+    mCurrentdstY = dstY;
+    mCurrenthdmiLayer = hdmiLayer;
+    mCurrentNumOfHWCLayer = num_of_hwc_layer;
+
+    return;
+}
+
+bool SecHdmi::m_setupLink(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+    int  ret;
+    char node[32];
+    char subdevname[32];
+    char videodevname[32];
+
+    struct v4l2_capability   v4l2cap;
+    struct media_entity_desc entity_desc;
+
+    sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
+    mMediadevFd = open(node, O_RDWR);
+    if (mMediadevFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto err;
+    }
+
+    /* open subdev fd */
+    sprintf(subdevname, PFX_ENTITY_SUBDEV_MIXER, 0);
+    for (__u32 id = 0; ; id = entity_desc.id) {
+        entity_desc.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+
+        if (ioctl(mMediadevFd, MEDIA_IOC_ENUM_ENTITIES, &entity_desc) < 0) {
+            if (errno == EINVAL) {
+                LOGD("%s::MEDIA_IOC_ENUM_ENTITIES ended", __func__);
+                break;
+            }
+            LOGE("%s::MEDIA_IOC_ENUM_ENTITIES failed", __func__);
+            goto err;
+        }
+        LOGD("%s::entity_desc.id=%d, .minor=%d .name=%s", __func__, entity_desc.id, entity_desc.v4l.minor, entity_desc.name);
+
+        if (strncmp(entity_desc.name, subdevname, strlen(subdevname)) == 0)
+            mMixerSubdevEntity = entity_desc.id;
+    }
+
+    mlink_desc.source.entity = mSecGscaler.getSubdevEntity();
+    mlink_desc.source.index  = GSCALER_SUBDEV_PAD_SOURCE;
+    mlink_desc.source.flags  = MEDIA_PAD_FL_SOURCE;
+
+    mlink_desc.sink.entity   = mMixerSubdevEntity;
+    mlink_desc.sink.index    = MIXER_V_SUBDEV_PAD_SINK;
+    mlink_desc.sink.flags    = MEDIA_PAD_FL_SINK;
+    mlink_desc.flags         = MEDIA_LNK_FL_ENABLED;
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::mlink_desc.source.entity=%02d, .pad=%d", __func__, mlink_desc.source.entity, mlink_desc.source.index);
+    LOGD("%s::mlink_desc.sink.entity  =%02d, .pad=%d", __func__, mlink_desc.sink.entity, mlink_desc.sink.index);
+#endif
+
+    if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) {
+        LOGE("%s::MEDIA_IOC_SETUP_LINK [src.entity=%d->sink.entity=%d] failed", __func__, mlink_desc.source.entity, mlink_desc.sink.entity);
+        goto err;
+    }
+
+    sprintf(node, "%s%d", PFX_NODE_SUBDEV, 4); // Mixer0 minor=132 /dev/v4l-subdev4 // need to modify //carrotsm
+    mSubdevMixerFd = open(node, O_RDWR, 0);
+    if (mSubdevMixerFd < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto err;
+    }
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+    mMediadevFd = -1;
+
+   return true;
+
+err :
+
+    if (0 < mMediadevFd)
+        close(mMediadevFd);
+
+    if (0 < mSubdevMixerFd)
+        close(mSubdevMixerFd);
+
+    mMediadevFd = -1;
+    mSubdevMixerFd = -1;
+
+    return false;
+}
+
+bool SecHdmi::m_openLayer(int layer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::layer=%d", __func__, layer);
+#endif
+    char node[32];
+
+    switch (layer) {
+    case HDMI_LAYER_VIDEO:
+        mVideodevFd[layer] = mSecGscaler.getVideodevFd();
+
+        if (0 < mVideodevFd[layer]) {
+            LOGD("%s::Layer[%d] device already opened", __func__, layer);
+            return true;
+        }
+
+        if (mSecGscaler.openVideodevFd() == false)
+            LOGE("%s::open(%s) failed", __func__, node);
+        else
+            mVideodevFd[layer] = mSecGscaler.getVideodevFd();
+
+        goto open_success;
+        break;
+    case HDMI_LAYER_GRAPHIC_0:
+        sprintf(node, "%s", TVOUT0_DEV_G0);
+        break;
+    case HDMI_LAYER_GRAPHIC_1:
+        sprintf(node, "%s", TVOUT0_DEV_G1);
+        break;
+    default:
+        LOGE("%s::unmatched layer[%d]", __func__, layer);
+        return false;
+        break;
+    }
+
+    mVideodevFd[layer] = open(node, O_RDWR);
+    if (mVideodevFd[layer] < 0) {
+        LOGE("%s::open(%s) failed", __func__, node);
+        goto err;
+    }
+
+open_success :
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("layer=%d, mVideodevFd=%d", layer, mVideodevFd[layer]);
+#endif
+
+    if (tvout_std_v4l2_querycap(mVideodevFd[layer], node) < 0 ) {
+        LOGE("%s::tvout_std_v4l2_querycap failed", __func__);
+        goto err;
+    }
+
+    return true;
+
+err :
+
+    if (0 < mVideodevFd[layer])
+        close(mVideodevFd[layer]);
+
+    mVideodevFd[layer] = -1;
+
+    return false;
+
+}
+
+bool SecHdmi::m_closeLayer(int layer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::layer=%d", __func__, layer);
+#endif
+    switch (layer) {
+    case HDMI_LAYER_VIDEO:
+        mVideodevFd[layer] = mSecGscaler.getVideodevFd();
+
+        if (mVideodevFd[layer] < 0) {
+            LOGD("%s::Layer[%d] device already closed", __func__, layer);
+            return true;
+        } else {
+            mSecGscaler.closeVideodevFd();
+            mVideodevFd[layer] = mSecGscaler.getVideodevFd();
+        }
+        goto close_success;
+        break;
+    case HDMI_LAYER_GRAPHIC_0:
+    case HDMI_LAYER_GRAPHIC_1:
+        /* clear buffer */
+        if (0 < mVideodevFd[layer]) {
+            if (tvout_std_v4l2_reqbuf(mVideodevFd[layer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 0) < 0) {
+                LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 0);
+                return -1;
+            }
+        }
+        break;
+    default:
+        LOGE("%s::unmatched layer[%d]", __func__, layer);
+        return false;
+        break;
+    }
+
+    if (0 < mVideodevFd[layer]) {
+        if (close(mVideodevFd[layer]) < 0) {
+            LOGE("%s::close %d layer failed", __func__, layer);
+            return false;
+        }
+    }
+
+    mVideodevFd[layer] = -1;
+
+close_success :
+
+    return true;
+}
+
+bool SecHdmi::m_reset(int w, int h, int dstX, int dstY, int colorFormat, int hdmiLayer, int num_of_hwc_layer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::w=%d, h=%d, dstX=%d, dstY=%d, colorFormat=%d, hdmiLayer=%d, num_of_hwc_layer=%d",
+        __func__, w, h, dstX, dstY, colorFormat, hdmiLayer, num_of_hwc_layer);
+#endif
+
+    v4l2_std_id std_id = 0;
+
+    int srcW = w;
+    int srcH = h;
+    int dstW = 0;
+    int dstH = 0;
+
+    if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) {
+        LOGE("%s::m_stopHdmi: layer[%d] failed", __func__, hdmiLayer);
+        return false;
+    }
+
+    if (m_closeLayer(hdmiLayer) == false) {
+        LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer);
+        return false;
+    }
+
+    if (m_openLayer(hdmiLayer) == false) {
+        LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer);
+        return false;
+    }
+
+    if (w != mSrcWidth[hdmiLayer] ||
+        h != mSrcHeight[hdmiLayer] ||
+        mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
+        mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
+        num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] ||
+        colorFormat != mSrcColorFormat[hdmiLayer] ||
+        mHdmiInfoChange == true) {
+        int preVideoSrcColorFormat = mSrcColorFormat[hdmiLayer];
+        int videoSrcColorFormat = colorFormat;
+
+        if (preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP &&
+            preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
+            preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP &&
+            preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP &&
+            preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) {
+                LOGI("%s: Unsupported preVideoSrcColorFormat = 0x%x", __func__, preVideoSrcColorFormat);
+                preVideoSrcColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
+        }
+
+        if (hdmiLayer == HDMI_LAYER_VIDEO) {
+            unsigned int full_wdith  = ALIGN(w, 16);
+            unsigned int full_height = ALIGN(h, 16);
+
+            if (mSecGscaler.setSrcParams(full_wdith, full_height, 0, 0,
+                        (unsigned int*)&w, (unsigned int*)&h, colorFormat, true) == false) {
+                LOGE("%s::mSecGscaler.setSrcParams(w=%d, h=%d, color=%d) failed",
+                        __func__, w, h, colorFormat);
+                return false;
+            }
+            mGscalerDstColorFormat = V4L2_MBUS_FMT_YUV8_1X24;
+
+            /* calculate destination buffer width and height */
+            struct v4l2_rect rect;
+
+            if (mUIRotVal == 0 || mUIRotVal == 180) {
+                hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
+            } else {
+                hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect);
+            }
+
+            rect.width = ALIGN(rect.width, 16);
+
+            if (mSecGscaler.setDstParams((unsigned int)rect.width, (unsigned int)rect.height, 0, 0,
+                        (unsigned int*)&rect.width, (unsigned int*)&rect.height, mGscalerDstColorFormat, true) == false) {
+                LOGE("%s::mSecGscaler.setDstParams(w=%d, h=%d, V4L2_MBUS_FMT_YUV8_1X24) failed",
+                        __func__, rect.width, rect.height);
+                return false;
+            }
+
+            hdmi_set_videolayer(mSubdevMixerFd, mHdmiDstWidth, mHdmiDstHeight, &rect);
+        } else {
+            if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
+                LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer);
+                return false;
+            }
+
+            if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
+                LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer);
+                return false;
+            }
+
+            if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
+                LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, hdmiLayer);
+                return false;
+            }
+
+            struct v4l2_rect rect;
+            int tempSrcW, tempSrcH;
+            int gr_frame_size = 0;
+
+            if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) {
+                tempSrcW = srcW;
+                tempSrcH = srcH;
+            } else {
+                tempSrcW = srcH;
+                tempSrcH = srcW;
+            }
+
+            hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
+            rect.left = ALIGN(rect.left, 16);
+
+            if (num_of_hwc_layer == 0) { /* UI only mode */
+                hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
+                                  colorFormat, srcW, srcH,
+                                  rect.left, rect.top, rect.width, rect.height);
+                dstW = rect.width;
+                dstH = rect.height;
+            } else { /* Video Playback + UI Mode */
+                hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
+                                  colorFormat, srcW, srcH,
+                                  dstX, dstY, mHdmiDstWidth, mHdmiDstHeight);
+                dstW = mHdmiDstWidth;
+                dstH = mHdmiDstHeight;
+            }
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+            gr_frame_size = dstW * dstH;
+#else
+            gr_frame_size = srcW * srcH;
+#endif
+            for (int buf_index = 0; buf_index < MAX_BUFFERS_MIXER; buf_index++) {
+                int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
+                switch (v4l2ColorFormat) {
+                case V4L2_PIX_FMT_BGR32:
+                case V4L2_PIX_FMT_RGB32:
+                    mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 2;
+                    break;
+                case V4L2_PIX_FMT_RGB565X:
+                    mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 1;
+                    break;
+                default:
+                    LOGE("%s::invalid color type", __func__);
+                    return false;
+                    break;
+                }
+            }
+
+        }
+
+        if (preVideoSrcColorFormat != videoSrcColorFormat)
+            mHdmiInfoChange = true;
+
+        mSrcWidth[hdmiLayer] = srcW;
+        mSrcHeight[hdmiLayer] = srcH;
+        mSrcColorFormat[hdmiLayer] = colorFormat;
+
+        mHdmiResolutionWidth[hdmiLayer] = mHdmiDstWidth;
+        mHdmiResolutionHeight[hdmiLayer] = mHdmiDstHeight;
+        mPreviousNumofHwLayer[hdmiLayer] = num_of_hwc_layer;
+
+#ifdef DEBUG_MSG_ENABLE
+        LOGD("m_reset saved param(%d, %d, %d, %d, %d, %d, %d)",
+            srcW, mSrcWidth[hdmiLayer], \
+            srcH, mSrcHeight[hdmiLayer], \
+            colorFormat,mSrcColorFormat[hdmiLayer], \
+            hdmiLayer);
+#endif
+    }
+
+    if (mHdmiInfoChange == true) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("mHdmiInfoChange: %d", mHdmiInfoChange);
+#endif
+
+#if defined(BOARD_USES_CEC)
+        if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+            mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+            if (mCECThread->mFlagRunning)
+                mCECThread->stop();
+        }
+#endif
+
+        if (m_setHdmiOutputMode(mHdmiOutputMode) == false) {
+            LOGE("%s::m_setHdmiOutputMode() failed", __func__);
+            return false;
+        }
+        if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) {
+            std_id = composite_std_2_v4l2_std_id(mCompositeStd);
+            if ((int)std_id < 0) {
+                LOGE("%s::composite_std_2_v4l2_std_id(%d) failed", __func__, mCompositeStd);
+                return false;
+            }
+            if (m_setCompositeResolution(mCompositeStd) == false) {
+                LOGE("%s::m_setCompositeRsolution() failed", __func__);
+                return false;
+            }
+        } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+                   mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+            if (m_setHdmiResolution(mHdmiResolutionValue) == false) {
+                LOGE("%s::m_setHdmiResolution() failed", __func__);
+                return false;
+            }
+
+            if (m_setHdcpMode(mHdcpMode) == false) {
+                LOGE("%s::m_setHdcpMode() failed", __func__);
+                return false;
+            }
+            std_id = mHdmiStdId;
+        }
+
+        if (mPreviousHdmiPresetId != mHdmiPresetId) {
+            for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+                if (m_stopHdmi(layer) == false) {
+                    LOGE("%s::m_stopHdmi(%d) failed", __func__, layer);
+                    return false;
+                }
+            }
+
+            if (tvout_init(mVideodevFd[HDMI_LAYER_GRAPHIC_0], mHdmiPresetId) < 0) {
+                LOGE("%s::tvout_init(mHdmiPresetId=%d) failed", __func__, mHdmiPresetId);
+                return false;
+            }
+            mPreviousHdmiPresetId = mHdmiPresetId;
+        }
+
+        if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+            mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+#if defined(BOARD_USES_CEC)
+            if (!(mCECThread->mFlagRunning))
+                mCECThread->start();
+#endif
+
+/*            if (m_setAudioMode(mAudioMode) == false)
+                LOGE("%s::m_setAudioMode() failed", __func__);
+*/
+        }
+
+        mHdmiInfoChange = false;
+
+    }
+
+    return true;
+}
+
+bool SecHdmi::m_streamOn(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
+#endif
+
+    if (mFlagCreate == false) {
+        LOGE("%s::Not yet created", __func__);
+        return false;
+    }
+
+    if (mFlagHdmiStart[hdmiLayer] == true) {
+        LOGE("%s::[layer=%d] already streamon", __func__, hdmiLayer);
+        return true;
+    }
+
+    switch(hdmiLayer) {
+    case HDMI_LAYER_GRAPHIC_0:
+        break;
+    case HDMI_LAYER_GRAPHIC_1:
+        break;
+    default :
+        LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
+        return false;
+        break;
+    }
+
+    if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
+                            mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][0]) < 0) {
+        LOGE("%s::gsc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, mSrcIndex[hdmiLayer], 1);
+        return false;
+    }
+
+    mSrcIndex[hdmiLayer]++;
+    if (mSrcIndex[hdmiLayer] == MAX_BUFFERS_MIXER) {
+        if (tvout_std_v4l2_streamon(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+            LOGE("%s::gsc_v4l2_stream_on() failed", __func__);
+            return false;
+        }
+        mFlagHdmiStart[hdmiLayer] = true;
+    }
+
+    if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) {
+        mSrcIndex[hdmiLayer] = 0;
+    }
+
+    return true;
+}
+
+bool SecHdmi::m_run(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
+#endif
+
+    int buf_index = 0;
+
+    if (mFlagHdmiStart[hdmiLayer] == false || mFlagLayerEnable[hdmiLayer] == false) {
+        LOGD("%s::HDMI(%d layer) started not yet", __func__, hdmiLayer);
+        return true;
+    }
+
+    switch (hdmiLayer) {
+    case HDMI_LAYER_VIDEO:
+        if (mSecGscaler.run() == false) {
+            LOGE("%s::mSecGscaler.draw() failed", __func__);
+            return false;
+        }
+        break;
+    case HDMI_LAYER_GRAPHIC_0 :
+    case HDMI_LAYER_GRAPHIC_1 :
+        if (tvout_std_v4l2_dqbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, &buf_index, 1) < 0) {
+            LOGE("%s::tvout_std_v4l2_dqbuf(mNumOfBuf : %d, dqIndex=%d) failed", __func__, 1, buf_index);
+            return false;
+        }
+
+        if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
+                                mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]]) < 0) {
+            LOGE("%s::tvout_std_v4l2_qbuf(mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, 1, mSrcIndex[hdmiLayer]);
+            return false;
+        }
+
+        mSrcIndex[hdmiLayer]++;
+        if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) {
+            mSrcIndex[hdmiLayer] = 0;
+        }
+
+        break;
+    default :
+        LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
+        return false;
+        break;
+    }
+
+    return true;
+}
+
+bool SecHdmi::m_startHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
+#endif
+
+    int buf_index = 0;
+
+    if (mFlagHdmiStart[hdmiLayer] == true) {
+        LOGD("%s::already HDMI(%d layer) started..", __func__, hdmiLayer);
+        return true;
+    }
+
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("### %s: hdmiLayer(%d) called", __func__, hdmiLayer);
+#endif
+    switch (hdmiLayer) {
+    case HDMI_LAYER_VIDEO:
+        if (mSecGscaler.streamOn() == false) {
+            LOGE("%s::mSecGscaler.streamOn() failed", __func__);
+            return false;
+        }
+        if (mSecGscaler.getFlagSteamOn() == true)
+            mFlagHdmiStart[hdmiLayer] = true;
+        break;
+    case HDMI_LAYER_GRAPHIC_0 :
+    case HDMI_LAYER_GRAPHIC_1 :
+        if (m_streamOn(hdmiLayer) == false) {
+            LOGE("%s::m_streamOn layer(%d) failed", __func__, hdmiLayer);
+            return false;
+        }
+        break;
+    default :
+        LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
+        return false;
+        break;
+    }
+    return true;
+}
+
+bool SecHdmi::m_stopHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
+#endif
+
+    if (mFlagHdmiStart[hdmiLayer] == false) {
+        LOGD("%s::already HDMI(%d layer) stopped..", __func__, hdmiLayer);
+        return true;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s : layer[%d] called", __func__, hdmiLayer);
+#endif
+
+    switch (hdmiLayer) {
+     case HDMI_LAYER_VIDEO:
+        if (mSecGscaler.streamOff() == false) {
+            LOGE("%s::mSecGscaler.streamOff() failed", __func__);
+            return false;
+        }
+        mFlagHdmiStart[hdmiLayer] = false;
+        break;
+    case HDMI_LAYER_GRAPHIC_1 :
+    case HDMI_LAYER_GRAPHIC_0 :
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+        cur_g2d_address = 0;
+#endif
+        if (tvout_std_v4l2_streamoff(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+            LOGE("%s::tvout_std_v4l2_streamon layer(%d) failed", __func__, hdmiLayer);
+            return false;
+        }
+
+        mSrcIndex[hdmiLayer] = 0;
+        mFlagHdmiStart[hdmiLayer] = false;
+        break;
+    default :
+        LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
+        return false;
+        break;
+    }
+
+    return true;
+}
+
+bool SecHdmi::m_setHdmiOutputMode(int hdmiOutputMode)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    if (hdmiOutputMode == mCurrentHdmiOutputMode) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode);
+#endif
+        return true;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode);
+    if (v4l2OutputType < 0) {
+        LOGE("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode);
+        return false;
+    }
+
+    output_type = v4l2OutputType;
+
+    mCurrentHdmiOutputMode = hdmiOutputMode;
+
+    return true;
+}
+
+bool SecHdmi::m_setCompositeResolution(unsigned int compositeStdId)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    int w = 0;
+    int h = 0;
+
+    if (mHdmiOutputMode != COMPOSITE_OUTPUT_MODE) {
+        LOGE("%s::not supported output type \n", __func__);
+        return false;
+    }
+
+    switch (compositeStdId) {
+    case COMPOSITE_STD_NTSC_M:
+    case COMPOSITE_STD_NTSC_443:
+        w = 704;
+        h = 480;
+        break;
+    case COMPOSITE_STD_PAL_BDGHI:
+    case COMPOSITE_STD_PAL_M:
+    case COMPOSITE_STD_PAL_N:
+    case COMPOSITE_STD_PAL_Nc:
+    case COMPOSITE_STD_PAL_60:
+        w = 704;
+        h = 576;
+        break;
+    default:
+        LOGE("%s::unmathced composite_std(%d)", __func__, compositeStdId);
+        return false;
+    }
+
+    t_std_id      = composite_std_2_v4l2_std_id(mCompositeStd);
+
+    mHdmiDstWidth  = w;
+    mHdmiDstHeight = h;
+
+    mCurrentHdmiResolutionValue = -1;
+    return true;
+}
+
+bool SecHdmi::m_setHdmiResolution(unsigned int hdmiResolutionValue)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    if (hdmiResolutionValue == mCurrentHdmiResolutionValue) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue);
+#endif
+        return true;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    int w = 0;
+    int h = 0;
+
+    v4l2_std_id std_id;
+    if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+        mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+        if (hdmi_resolution_2_std_id(hdmiResolutionValue, &w, &h, &std_id, &mHdmiPresetId) < 0) {
+            LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue);
+            return false;
+        }
+        mHdmiStdId    = std_id;
+    } else {
+        LOGE("%s::not supported output type \n", __func__);
+        return false;
+    }
+
+    t_std_id      = std_id;
+
+    mHdmiDstWidth  = w;
+    mHdmiDstHeight = h;
+
+    mCurrentHdmiResolutionValue = hdmiResolutionValue;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiStdId = 0x%x, hdmiResolutionValue = 0x%x\n",
+                __func__,
+                mHdmiDstWidth,
+                mHdmiDstHeight,
+                mHdmiStdId,
+                hdmiResolutionValue);
+#endif
+
+    return true;
+}
+
+bool SecHdmi::m_setHdcpMode(bool hdcpMode)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    if (hdcpMode == mCurrentHdcpMode) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode);
+#endif
+
+        return true;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    if (hdcpMode == true)
+        g_hdcp_en = 1;
+    else
+        g_hdcp_en = 0;
+
+    mCurrentHdcpMode = hdcpMode;
+
+    return true;
+}
+
+bool SecHdmi::m_setAudioMode(int audioMode)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    if (audioMode == mCurrentAudioMode) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::same audioMode(%d) \n", __func__, audioMode);
+#endif
+        return true;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    if (hdmi_check_audio(mVideodevFd[HDMI_LAYER_GRAPHIC_0]) < 0) {
+        LOGE("%s::hdmi_check_audio() fail \n", __func__);
+        return false;
+    }
+
+    mCurrentAudioMode = audioMode;
+
+    return true;
+}
+
+int SecHdmi::m_resolutionValueIndex(unsigned int ResolutionValue)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+    int index = -1;
+
+    for (int i = 0; i < mHdmiSizeOfResolutionValueList; i++) {
+        if (mHdmiResolutionValueList[i] == ResolutionValue) {
+            index = i;
+            break;
+        }
+    }
+    return index;
+}
+
+bool SecHdmi::m_flagHWConnected(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+    LOGD("%s", __func__);
+#endif
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("### %s called\n", __func__);
+#endif
+
+    bool ret = true;
+    int hdmiStatus = hdmi_cable_status();
+
+    if (hdmiStatus <= 0) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+            LOGD("%s::hdmi_cable_status() fail \n", __func__);
+#endif
+        ret = false;
+    } else {
+        ret = true;
+    }
+
+    return ret;
+}
+
+}; // namespace android
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h b/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h
new file mode 100644
index 0000000..5ca9e4e
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+**
+** @author Sangwoo, Park(sw5771.park@samsung.com)
+** @date   2010-09-10
+**
+*/
+
+//#define LOG_NDEBUG 0
+//#define LOG_TAG "libhdmi"
+#include <cutils/log.h>
+
+#include "../libhdmi/SecHdmi/fimd_api.h"
+
+//#define DEBUG_MSG_ENABLE
+//#define DEBUG_HDMI_HW_LEVEL
+//#define BOARD_USES_EDID
+//#define BOARD_USES_CEC
+//#define SUPPORT_G2D_UI_MODE
+
+#define DEFAULT_FB      (0)
+#define MAX_MIXER_NUM               (1)
+#define MAX_BUFFERS_MIXER           (2)
+#define MAX_PLANES_MIXER            (3)
+
+#define HDMI_GSCALER_BUF_NUM        (3)
+#define HDMI_FIMC_BUFFER_BPP_SIZE   (1.5)   //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4, Default is NV12 Tiled
+#define HDMI_G2D_BUFFER_BPP_SIZE    (4)     //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4
+#define SUPPORT_1080P_FIMC_OUT
+#define HDMI_MAX_WIDTH              (1920)
+#define HDMI_MAX_HEIGHT             (1080)
+
+#define ALIGN(x, a)    (((x) + (a) - 1) & ~((a) - 1))
+
+#if defined(STD_NTSC_M)
+    #define DEFAULT_OUPUT_MODE            (COMPOSITE_OUTPUT_MODE)
+    #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60
+    #define DEFAULT_HDMI_STD_ID           (V4L2_STD_1080P_60)
+    #define DEFALULT_DISPLAY_WIDTH            (720)
+    #define DEFALULT_DISPLAY_HEIGHT            (480)
+    #define DEFAULT_COMPOSITE_STD         (COMPOSITE_STD_NTSC_M)
+#elif (STD_1080P)
+    #define DEFAULT_OUPUT_MODE            (HDMI_OUTPUT_MODE_RGB)
+    #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60
+    #define DEFAULT_HDMI_STD_ID           (V4L2_STD_1080P_60)
+    #define DEFALULT_DISPLAY_WIDTH            (1920)
+    #define DEFALULT_DISPLAY_HEIGHT            (1080)
+    #define DEFAULT_COMPOSITE_STD      (COMPOSITE_STD_NTSC_M)
+#elif defined(STD_720P)
+    #define DEFAULT_OUPUT_MODE            (HDMI_OUTPUT_MODE_YCBCR)
+    #define DEFAULT_HDMI_RESOLUTION_VALUE (720960) // 720P_60
+    #define DEFAULT_HDMI_STD_ID           (V4L2_STD_720P_60)
+    #define DEFALULT_DISPLAY_WIDTH            (1280)
+    #define DEFALULT_DISPLAY_HEIGHT            (720)
+    #define DEFAULT_COMPOSITE_STD      (COMPOSITE_STD_NTSC_M)
+#elif defined(STD_480P)
+    #define DEFAULT_OUPUT_MODE            (HDMI_OUTPUT_MODE_YCBCR)
+    #define DEFAULT_HDMI_RESOLUTION_VALUE (4809601) // 480P_60_4_3
+    #define DEFAULT_HDMI_STD_ID           (V4L2_STD_480P_60_16_9)
+    #define DEFALULT_DISPLAY_WIDTH            (720)
+    #define DEFALULT_DISPLAY_HEIGHT            (480)
+    #define DEFAULT_COMPOSITE_STD      (COMPOSITE_STD_NTSC_M)
+#else
+    #define DEFAULT_OUPUT_MODE            (HDMI_OUTPUT_MODE_YCBCR)
+    #define DEFAULT_HDMI_RESOLUTION_VALUE (4809602) // 480P_60_4_3
+    #define DEFAULT_HDMI_STD_ID           (V4L2_STD_480P_60_4_3)
+    #define DEFALULT_DISPLAY_WIDTH            (720)
+    #define DEFALULT_DISPLAY_HEIGHT            (480)
+    #define DEFAULT_COMPOSITE_STD      (COMPOSITE_STD_NTSC_M)
+#endif
+
+enum hdp_cable_status {
+    HPD_CABLE_OUT = 0, // HPD_CABLE_OUT indicates HDMI cable out.
+    HPD_CABLE_IN       // HPD_CABLE_IN indicates HDMI cable in.
+};
+
+enum state {
+    OFF = 0,
+    ON = 1,
+    NOT_SUPPORT = 2,
+};
+
+enum tv_mode {
+    HDMI_OUTPUT_MODE_YCBCR = 0,
+    HDMI_OUTPUT_MODE_RGB = 1,
+    HDMI_OUTPUT_MODE_DVI = 2,
+    COMPOSITE_OUTPUT_MODE = 3
+};
+
+enum composite_std {
+    COMPOSITE_STD_NTSC_M = 0,
+    COMPOSITE_STD_PAL_BDGHI = 1,
+    COMPOSITE_STD_PAL_M = 2,
+    COMPOSITE_STD_PAL_N = 3,
+    COMPOSITE_STD_PAL_Nc = 4,
+    COMPOSITE_STD_PAL_60 = 5,
+    COMPOSITE_STD_NTSC_443 = 6
+};
+
+enum hdmi_layer {
+    HDMI_LAYER_BASE   = 0,
+    HDMI_LAYER_VIDEO,
+    HDMI_LAYER_GRAPHIC_0,
+    HDMI_LAYER_GRAPHIC_1,
+    HDMI_LAYER_MAX,
+};
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp
new file mode 100644
index 0000000..ac4717b
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp
@@ -0,0 +1,1350 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+//#define LOG_TAG "libhdmi"
+//#define DEBUG_HDMI_HW_LEVEL
+#include <cutils/log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "sec_utils_v4l2.h"
+#include "s5p_tvout_v4l2.h"
+
+#include "videodev2.h"
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+#include "sec_g2d_4x.h"
+#include "FimgApi.h"
+#endif
+
+#include "audio.h"
+#include "video.h"
+#include "../libhdmi/libsForhdmi/libedid/libedid.h"
+#include "../libhdmi/libsForhdmi/libcec/libcec.h"
+
+#include "SecGscaler.h"
+#include "SecHdmiCommon.h"
+#include "SecHdmiV4L2Utils.h"
+
+namespace android {
+
+unsigned int output_type  = V4L2_OUTPUT_TYPE_DIGITAL;
+v4l2_std_id  t_std_id     = V4L2_STD_1080P_30;
+int          g_hpd_state  = HPD_CABLE_OUT;
+unsigned int g_hdcp_en    = 0;
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+unsigned int g2d_reserved_memory0     = 0;
+unsigned int g2d_reserved_memory1     = 0;
+unsigned int g2d_reserved_memory_size = 0;
+unsigned int cur_g2d_address          = 0;
+#endif
+
+void display_menu(void)
+{
+    struct HDMIVideoParameter video;
+    struct HDMIAudioParameter audio;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+
+    audio.formatCode = LPCM_FORMAT;
+    audio.outPacket  = HDMI_ASP;
+    audio.channelNum = CH_2;
+    audio.sampleFreq = SF_44KHZ;
+
+    LOGI("=============== HDMI Audio  =============\n");
+
+    if (EDIDAudioModeSupport(&audio))
+        LOGI("=  2CH_PCM 44100Hz audio supported      =\n");
+
+    LOGI("========= HDMI Mode & Color Space =======\n");
+
+    video.mode = HDMI;
+    if (EDIDHDMIModeSupport(&video)) {
+        video.colorSpace = HDMI_CS_YCBCR444;
+        if (EDIDColorSpaceSupport(&video))
+            LOGI("=  1. HDMI(YCbCr)                       =\n");
+
+        video.colorSpace = HDMI_CS_RGB;
+        if (EDIDColorSpaceSupport(&video))
+            LOGI("=  2. HDMI(RGB)                         =\n");
+    } else {
+        video.mode = DVI;
+        if (EDIDHDMIModeSupport(&video))
+            LOGI("=  3. DVI                               =\n");
+    }
+
+    LOGI("===========    HDMI Rseolution   ========\n");
+
+    /* 480P */
+    video.resolution = v720x480p_60Hz;
+    video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  4. 480P_60_16_9    (0x04000000)    =\n");
+
+    video.resolution = v640x480p_60Hz;
+    video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  5. 480P_60_4_3 (0x05000000)    =\n");
+
+    /* 576P */
+    video.resolution = v720x576p_50Hz;
+    video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  6. 576P_50_16_9    (0x06000000)    =\n");
+
+    video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  7. 576P_50_4_3 (0x07000000)    =\n");
+
+    /* 720P 60 */
+    video.resolution = v1280x720p_60Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  8. 720P_60         (0x08000000)    =\n");
+
+    /* 720P_50 */
+    video.resolution = v1280x720p_50Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  9. 720P_50         (0x09000000)    =\n");
+
+    /* 1080P_60 */
+    video.resolution = v1920x1080p_60Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  a. 1080P_60        (0x0a000000)    =\n");
+
+    /* 1080P_50 */
+    video.resolution = v1920x1080p_50Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  b. 1080P_50        (0x0b000000)    =\n");
+
+    /* 1080I_60 */
+    video.resolution = v1920x1080i_60Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  c. 1080I_60        (0x0c000000)    =\n");
+
+    /* 1080I_50 */
+    video.resolution = v1920x1080i_50Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  d. 1080I_50        (0x0d000000)    =\n");
+
+    /* 1080P_30 */
+    video.resolution = v1920x1080p_30Hz;
+    video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  e. 1080P_30        (0x12000000)    =\n");
+
+    LOGI("===========    HDMI 3D Format   ========\n");
+
+    /* 720P_60_SBS_HALF */
+    video.resolution = v1280x720p_60Hz;
+    video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  f. 720P_60_SBS_HALF    (0x13000000)    =\n");
+
+    /* 720P_59_SBS_HALF */
+    video.resolution = v1280x720p_60Hz;
+    video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  10. 720P_59_SBS_HALF    (0x14000000)    =\n");
+
+    /* 720P_50_TB */
+    video.resolution = v1280x720p_50Hz;
+    video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  11. 720P_50_TB          (0x15000000)    =\n");
+
+    /* 1080P_24_TB */
+    video.resolution = v1920x1080p_24Hz;
+    video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  12. 1080P_24_TB          (0x16000000)    =\n");
+
+    /* 1080P_23_TB */
+    video.resolution = v1920x1080p_24Hz;
+    video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+    if (EDIDVideoResolutionSupport(&video))
+        LOGI("=  13. 1080P_24_TB          (0x17000000)    =\n");
+    LOGI("=========================================\n");
+}
+
+int tvout_init(int fd_tvout, __u32 preset_id)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::preset_id = 0x%x", __func__, preset_id);
+#endif
+
+    int ret;
+    struct v4l2_output output;
+    struct v4l2_dv_preset preset;
+
+    unsigned int matched = 0, i = 0;
+    int output_index;
+
+    if (fd_tvout <= 0) {
+        fd_tvout = open(TVOUT0_DEV_G0, O_RDWR);
+        if (fd_tvout < 0) {
+            LOGE("%s::fd_tvout open failed", __func__);
+            return -1;
+        }
+    }
+/*
+    if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL &&
+        output_type <= V4L2_OUTPUT_TYPE_DVI)
+        if (ioctl(fd_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0)
+            LOGE("%s::VIDIOC_HDCP_ENABLE failed %d", __func__, errno);
+*/
+    i = 0;
+
+    do {
+        output.index = i;
+        ret = tvout_v4l2_enum_output(fd_tvout, &output);
+        LOGV("%s::output_type=%d output.index=%d .name=%s", __func__, output_type, output.index, output.name);
+        if (output.type == output_type) {
+            matched = 1;
+            break;
+        }
+        i++;
+    } while (ret >=0);
+/*
+    if (!matched) {
+        LOGE("%s::no matched output type [type=0x%08x]", __func__, output_type);
+        return -1;
+    }
+
+    tvout_v4l2_s_output(fd_tvout, output.index);
+    output_index = 0;
+    tvout_v4l2_g_output(fd_tvout, &output_index);
+*/
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::input preset_id=0x%08x", __func__, preset_id);
+#endif
+
+    if (output.capabilities & V4L2_OUT_CAP_PRESETS) {
+        tvout_std_v4l2_enum_dv_presets(fd_tvout);
+        preset.preset = preset_id;
+        if (tvout_std_v4l2_s_dv_preset(fd_tvout, &preset) < 0 ) {
+            LOGE("%s::tvout_std_v4l2_s_dv_preset failed", __func__);
+            return -1;
+        }
+    }
+
+    return fd_tvout;
+}
+
+int tvout_deinit()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+
+    return 0;
+}
+
+int tvout_std_v4l2_querycap(int fd, char *node)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_capability v4l2cap;
+
+    if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) {
+        LOGE("%s::VIDIOC_QUERYCAP failed", __func__);
+        return -1;
+    }
+
+    if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) {
+        LOGE("%s::%s is not support streaming", __func__, node);
+        return -1;
+    }
+
+    if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
+        LOGE("%s::%s is not support video output mplane", __func__, node);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+
+    struct v4l2_format fmt;
+
+    fmt.type = type;
+    if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_G_FMT failed", __func__);
+        return -1;
+    }
+
+    switch (fmt.type) {
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        fmt.fmt.pix.width       = w;
+        fmt.fmt.pix.height      = h;
+        fmt.fmt.pix.pixelformat = colorformat;
+        fmt.fmt.pix.field       = field;
+        break;
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+        fmt.fmt.pix_mp.width       = w;
+        fmt.fmt.pix_mp.height      = h;
+        fmt.fmt.pix_mp.pixelformat = colorformat;
+        fmt.fmt.pix_mp.field       = field;
+        fmt.fmt.pix_mp.num_planes  = num_planes;
+        break;
+    default:
+        LOGE("%s::invalid buffer type", __func__);
+        return -1;
+        break;
+    }
+
+    if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_S_FMT failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field, int x, int y, int w, int h)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_crop crop;
+
+    crop.type     = type;
+    crop.c.left   = x;
+    crop.c.top    = y;
+    crop.c.width  = w;
+    crop.c.height = h;
+
+    if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
+            __func__, x, y, w, h);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_s_ctrl(int fd, int id, int value)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_control vc;
+
+    vc.id    = id;
+    vc.value = value;
+
+    if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+        LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_requestbuffers reqbuf;
+
+    reqbuf.type   = type;
+    reqbuf.memory = memory;
+    reqbuf.count  = num_bufs;
+
+    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
+        LOGE("%s::VIDIOC_REQBUFS failed", __func__);
+        return -1;
+    }
+
+    if (reqbuf.count < num_bufs) {
+        LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
+            __func__, reqbuf.count, num_bufs);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_MIXER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_MIXER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    if (MAX_BUFFERS_MIXER <= buf_index || MAX_PLANES_MIXER <= num_planes) {
+        LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_planes);
+        return -1;
+    }
+
+    buf.type     = type;
+    buf.memory   = V4L2_MEMORY_MMAP;
+    buf.index    = buf_index;
+    buf.length   = num_planes;
+    buf.m.planes = planes;
+
+    if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
+        return -1;
+    }
+
+    for (unsigned int i = 0; i < num_planes; i++) {
+        if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length,
+                 PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) {
+            LOGE("%s::mmap failed", __func__);
+            LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset);
+            LOGE("%s::Legnth = %d"  , __func__, buf.m.planes[i].length);
+            LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
+            return -1;
+        }
+        secBuf->size.extS[i] = buf.m.planes[i].length;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::vaddr[bufindex=%d][planeidx=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
+    LOGD("%s::Legnth = %d"  , __func__, buf.m.planes[i].length);
+#endif
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_MIXER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_MIXER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+    buf.type     = type;
+    buf.memory   = memory;
+    buf.length   = num_planes;
+    buf.index    = buf_index;
+    buf.m.planes = planes;
+
+    for (unsigned int i = 0; i < buf.length; i++) {
+        buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i];
+        buf.m.planes[i].length    = secBuf->size.extS[i];
+        buf.m.planes[i].bytesused = buf.m.planes[i].length;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+        LOGD("%s::buf.index=%d", __func__, buf.index);
+        LOGD("%s::buf.m.planes[%d].m.userptr=0x%08x", __func__, i, (unsigned int)buf.m.planes[i].m.userptr);
+        LOGD("%s::buf.m.planes[%d].length   =0x%08x", __func__, i, buf.m.planes[i].length);
+        LOGD("%s::buf.m.planes[%d].bytesused=0x%08x", __func__, i, buf.m.planes[i].bytesused);
+#endif
+    }
+
+    if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_QBUF failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_buffer buf;
+    struct v4l2_plane  planes[MAX_PLANES_MIXER];
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    for (int i = 0; i < MAX_PLANES_GSCALER; i++)
+        memset(&planes[i], 0, sizeof(struct v4l2_plane));
+
+
+    buf.type     = type;
+    buf.memory   = memory;
+    buf.length   = num_planes;
+    buf.m.planes = planes;
+
+    if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
+        LOGE("%s::VIDIOC_DQBUF failed", __func__);
+        return -1;
+    }
+    *buf_index = buf.index;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::buf.index=%d", __func__, buf.index);
+#endif
+
+    return 0;
+}
+
+int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
+        LOGE("%s::VIDIOC_STREAMON failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
+        LOGE("%s::VIDIOC_STREAMOFF failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_v4l2_enum_output(int fd, struct v4l2_output *output)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    int ret = -1 ;
+    ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output);
+
+    if (ret < 0) {
+        if (errno == EINVAL)
+            return -1;
+        LOGE("%s::VIDIOC_ENUMOUTPUT", __func__);
+        return -1;
+    }
+    LOGD("%s::index=%d, type=0x%08x, name=%s",
+          __func__, output->index, output->type, output->name);
+
+    return ret;
+}
+
+int tvout_v4l2_s_output(int fd, int index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_S_OUTPUT, &index) < 0) {
+        LOGE("%s::VIDIOC_S_OUTPUT failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_v4l2_g_output(int fd, int *index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_G_OUTPUT, index) < 0) {
+        LOGE("%s::VIDIOC_G_OUTPUT failed", __func__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_enum_dv_presets(int fd)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_dv_enum_preset enum_preset;
+    int ret = -1;
+
+    for (int index = 0; ; index++) {
+        enum_preset.index = index;
+        ret = ioctl(fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset);
+
+        if (ret < 0) {
+            if (errno == EINVAL)
+                break;
+            LOGE("%s::VIDIOC_ENUM_DV_PRESETS", __func__);
+            return -1;
+        }
+        LOGD("%s::index=%d, preset=0x%08x, name=%s, w=%d, h=%d",
+              __func__, enum_preset.index, enum_preset.preset, enum_preset.name, enum_preset.width, enum_preset.height);
+    }
+
+    return 0;
+}
+
+int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (ioctl(fd, VIDIOC_S_DV_PRESET, preset) < 0) {
+        LOGE("%s::VIDIOC_S_DV_PRESET failed preset_id=%d", __func__, preset->preset);
+        return -1;
+    }
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::preset_id=%d", __func__, preset->preset);
+#endif
+    return 0;
+}
+
+int tvout_std_subdev_s_fmt(int fd, unsigned int pad, int w, int h, enum v4l2_mbus_pixelcode code)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_subdev_format fmt;
+
+    fmt.pad   = pad;
+    fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    fmt.format.width  = w;
+    fmt.format.height = h;
+    fmt.format.code   = code;
+
+    if (ioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_FMT", __func__);
+        return -1;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::format w=%d, h=%d", __func__, fmt.format.width, fmt.format.height);
+#endif
+    return 0;
+}
+int tvout_std_subdev_s_crop(int fd, unsigned int pad, int x, int y, int w, int h)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::pad=%d, crop x=%d, y=%d, w=%d, h=%d", __func__, pad, x, y, w, h);
+#endif
+
+    struct v4l2_subdev_crop   crop;
+
+    crop.pad   = pad;
+    crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+    crop.rect.left   = x;
+    crop.rect.top    = y;
+    crop.rect.width  = w;
+    crop.rect.height = h;
+
+    if (ioctl(fd, VIDIOC_SUBDEV_S_CROP, &crop) < 0) {
+        LOGE("%s::VIDIOC_SUBDEV_S_CROP", __func__);
+        return -1;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s::pad=%d, crop x=%d, y=%d, w=%d, h=%d", __func__, pad, crop.rect.left, crop.rect.top, crop.rect.width, crop.rect.height);
+#endif
+
+    return 0;
+}
+
+#define ROUND_UP(value, boundary) ((((uint32_t)(value)) + \
+                                  (((uint32_t) boundary)-1)) & \
+                                  (~(((uint32_t) boundary)-1)))
+
+void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect)
+{
+    if (dst_w * src_h <= dst_h * src_w) {
+        dst_rect->left   = 0;
+        dst_rect->top    = (dst_h - ((dst_w * src_h) / src_w)) >> 1;
+        dst_rect->width  = dst_w;
+        dst_rect->height = ((dst_w * src_h) / src_w);
+    } else {
+        dst_rect->left   = (dst_w - ((dst_h * src_w) / src_h)) >> 1;
+        dst_rect->top    = 0;
+        dst_rect->width  = ((dst_h * src_w) / src_h);
+        dst_rect->height = dst_h;
+    }
+}
+
+int hdmi_set_videolayer(int fd, int hdmiW, int hdmiH, struct v4l2_rect * rect)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    if (tvout_std_subdev_s_fmt(fd, MIXER_V_SUBDEV_PAD_SINK, hdmiW, hdmiH, V4L2_MBUS_FMT_YUV8_1X24) < 0) {
+        LOGE("%s::tvout_std_subdev_s_fmt(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SINK);
+        return -1;
+    }
+
+    if (tvout_std_subdev_s_crop(fd, MIXER_V_SUBDEV_PAD_SINK, 0, 0, rect->width, rect->height) < 0) {
+        LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SINK);
+        return -1;
+    }
+
+    if (tvout_std_subdev_s_crop(fd, MIXER_V_SUBDEV_PAD_SOURCE, rect->left, rect->top, rect->width, rect->height) < 0) {
+        LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SOURCE);
+        return -1;
+    }
+    return 0;
+}
+
+int hdmi_set_graphiclayer(int fd_subdev, int fd_videodev,int layer,
+        int srcColorFormat,
+        int src_w, int src_h,
+        unsigned int src_address, SecBuffer * dstBuffer,
+        int dst_x, int dst_y, int dst_w, int dst_h,
+        int rotVal)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+    int             dst_color_format;
+    int             dst_bpp;
+    unsigned char   *dst_addr;
+    fimg2d_blit     BlitParam;
+    rotation        g2d_rotation;
+
+    fimg2d_addr  srcAddr;
+    fimg2d_image srcImage;
+    fimg2d_rect  srcRect;
+
+    fimg2d_addr  dstAddr;
+    fimg2d_image dstImage;
+    fimg2d_rect  dstRect;
+
+    fimg2d_clip  dstClip;
+    fimg2d_scale Scaling;
+
+    switch (t_std_id) {
+    case V4L2_STD_1080P_60:
+    case V4L2_STD_1080P_30:
+    case V4L2_STD_1080I_60:
+    case V4L2_STD_TVOUT_720P_60_SBS_HALF:
+    case V4L2_STD_TVOUT_720P_59_SBS_HALF:
+    case V4L2_STD_TVOUT_1080P_24_TB:
+    case V4L2_STD_TVOUT_1080P_23_TB:
+        dst_color_format = CF_ARGB_8888;
+        dst_bpp = 4;
+        break;
+    case V4L2_STD_480P_60_16_9:
+    case V4L2_STD_576P_50_16_9:
+    case V4L2_STD_720P_60:
+    case V4L2_STD_TVOUT_720P_50_TB:
+    default:
+        dst_color_format = CF_ARGB_4444;
+        dst_bpp = 2;
+        break;
+    }
+
+    static unsigned int prev_src_addr = 0;
+
+    if ((cur_g2d_address == 0) || (src_address != prev_src_addr)) {
+        if ((cur_g2d_address == 0) || (cur_g2d_address == g2d_reserved_memory1))
+            dst_addr = (unsigned char *)g2d_reserved_memory0;
+        else
+            dst_addr = (unsigned char *)g2d_reserved_memory1;
+
+        cur_g2d_address = (unsigned int)dst_addr;
+        prev_src_addr = src_address;
+
+        srcAddr  = {(addr_space)ADDR_USER, (unsigned long)src_address, src_w*src_h*4, 1, 0};
+        srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888};
+        srcRect = {0, 0, src_w, src_h};
+
+        dstAddr  = {(addr_space)ADDR_USER, (unsigned long)dst_addr, dst_w*dst_h*dst_bpp, 1, 0};
+        dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format};
+        dstRect  = {0, 0, dst_w, dst_h};
+        dstClip  = {0, 0, 0, dst_w, dst_h};
+
+        if (rotVal == 0 || rotVal == 180)
+            Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h};
+        else
+            Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w};
+
+        switch (rotVal) {
+        case 0:
+            g2d_rotation = ORIGIN;
+            break;
+        case 90:
+            g2d_rotation = ROT_90;
+            break;
+        case 180:
+            g2d_rotation = ROT_180;
+            break;
+        case 270:
+            g2d_rotation = ROT_270;
+            break;
+        default:
+            LOGE("%s::invalid rotVal(%d) : failed", __func__, rotVal);
+            return -1;
+            break;
+        }
+
+        BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0};
+
+        if (stretchFimgApi(&BlitParam) < 0) {
+            LOGE("%s::stretchFimgApi() failed", __func__);
+            return -1;
+        }
+
+        dstBuffer->virt.p = (char *)dst_addr;
+    }
+#else
+    dstBuffer->virt.p = (char *)src_address;
+#endif
+
+    return 0;
+}
+
+int hdmi_set_g_Params(int fd_subdev, int fd_videodev, int layer,
+                      int srcColorFormat,
+                      int src_w, int src_h,
+                      int dst_x, int dst_y, int dst_w, int dst_h)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+    struct v4l2_rect rect;
+    int src_pad = 0;
+    int sink_pad = 0;
+    int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
+
+    switch (layer) {
+    case HDMI_LAYER_GRAPHIC_0:
+        sink_pad = MIXER_G0_SUBDEV_PAD_SINK;
+        src_pad  = MIXER_G0_SUBDEV_PAD_SOURCE;
+        break;
+    case HDMI_LAYER_GRAPHIC_1:
+        sink_pad = MIXER_G1_SUBDEV_PAD_SINK;
+        src_pad  = MIXER_G1_SUBDEV_PAD_SOURCE;
+        break;
+    default:
+        LOGE("%s::invalid layer(%d)", __func__, layer);
+        break;
+    };
+
+    rect.left   = dst_x;
+    rect.top    = dst_y;
+
+#if defined(BOARD_USES_HDMI_FIMGAPI)
+    rect.width  = dst_w;
+    rect.height = dst_h;
+#else
+    rect.width  = src_w;
+    rect.height = src_h;
+#endif
+
+    /* set sub device for mixer graphic layer input */
+    if (tvout_std_subdev_s_fmt(fd_subdev, sink_pad, rect.width, rect.height, V4L2_MBUS_FMT_XRGB8888_4X8_LE) < 0) {
+        LOGE("%s::tvout_std_subdev_s_fmt(PAD=%d)[graphic layer] failed", __func__, sink_pad);
+        return -1;
+    }
+
+    if (tvout_std_subdev_s_crop(fd_subdev, sink_pad, 0, 0, rect.width, rect.height) < 0) {
+        LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[graphic layer] failed", __func__, sink_pad);
+        return -1;
+    }
+
+    if (tvout_std_subdev_s_crop(fd_subdev, src_pad, rect.left, rect.top, rect.width, rect.height) < 0) {
+        LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[graphic layer] failed", __func__, src_pad);
+        return -1;
+    }
+
+    /* set format for mixer graphic layer input device*/
+    if (tvout_std_v4l2_s_fmt(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.width, rect.height, v4l2ColorFormat, 1) < 0) {
+        LOGE("%s::tvout_std_v4l2_s_fmt()[graphic layer] failed", __func__);
+        return -1;
+    }
+
+    if (tvout_std_v4l2_s_crop(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) {
+        LOGE("%s::tvout_std_v4l2_s_crop()[graphic layer] failed", __func__);
+        return -1;
+    }
+
+    /* request buffer for mixer graphic layer input device */
+    if (tvout_std_v4l2_reqbuf(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 2) < 0) {
+        LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 2);
+        return -1;
+    }
+
+    return 0;
+}
+
+int hdmi_cable_status()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("%s", __func__);
+#endif
+
+    int cable_status = 0;
+    int fd = 0;
+    struct v4l2_control ctrl;
+
+    fd = open(TVOUT0_DEV_G0, O_RDWR);
+    if (fd <= 0) {
+        LOGE("%s: graphic layer 0 drv open failed", __func__);
+        return -1;
+    }
+
+    ctrl.id = V4L2_CID_TV_HPD_STATUS;
+
+    if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
+        LOGE("Get HPD_STATUS fail");
+        cable_status = -1;
+    } else {
+        cable_status = ctrl.value;
+    }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+    LOGD("HPD_STATUS = %d", cable_status);
+#endif
+
+    close(fd);
+
+    return cable_status;
+}
+
+int hdmi_outputmode_2_v4l2_output_type(int output_mode)
+{
+    int v4l2_output_type = -1;
+
+    switch (output_mode) {
+    case HDMI_OUTPUT_MODE_YCBCR:
+        v4l2_output_type = V4L2_OUTPUT_TYPE_DIGITAL;
+        break;
+    case HDMI_OUTPUT_MODE_RGB:
+        v4l2_output_type = V4L2_OUTPUT_TYPE_HDMI_RGB;
+        break;
+    case HDMI_OUTPUT_MODE_DVI:
+        v4l2_output_type = V4L2_OUTPUT_TYPE_DVI;
+        break;
+    case COMPOSITE_OUTPUT_MODE:
+        v4l2_output_type = V4L2_OUTPUT_TYPE_COMPOSITE;
+        break;
+    default:
+        LOGE("%s::unmathced HDMI_mode(%d)", __func__, output_mode);
+        v4l2_output_type = -1;
+        break;
+    }
+
+    return v4l2_output_type;
+}
+
+int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type)
+{
+    int outputMode = -1;
+
+    switch (v4l2_output_type) {
+    case V4L2_OUTPUT_TYPE_DIGITAL:
+        outputMode = HDMI_OUTPUT_MODE_YCBCR;
+        break;
+    case V4L2_OUTPUT_TYPE_HDMI_RGB:
+        outputMode = HDMI_OUTPUT_MODE_RGB;
+        break;
+    case V4L2_OUTPUT_TYPE_DVI:
+        outputMode = HDMI_OUTPUT_MODE_DVI;
+        break;
+    case V4L2_OUTPUT_TYPE_COMPOSITE:
+        outputMode = COMPOSITE_OUTPUT_MODE;
+        break;
+    default:
+        LOGE("%s::unmathced v4l2_output_type(%d)", __func__, v4l2_output_type);
+        outputMode = -1;
+        break;
+    }
+
+    return outputMode;
+}
+
+int composite_std_2_v4l2_std_id(int std)
+{
+    int std_id = -1;
+
+    switch (std) {
+    case COMPOSITE_STD_NTSC_M:
+        std_id = V4L2_STD_NTSC_M;
+        break;
+    case COMPOSITE_STD_NTSC_443:
+        std_id = V4L2_STD_NTSC_443;
+        break;
+    case COMPOSITE_STD_PAL_BDGHI:
+        std_id = V4L2_STD_PAL_BDGHI;
+        break;
+    case COMPOSITE_STD_PAL_M:
+        std_id = V4L2_STD_PAL_M;
+        break;
+    case COMPOSITE_STD_PAL_N:
+        std_id = V4L2_STD_PAL_N;
+        break;
+    case COMPOSITE_STD_PAL_Nc:
+        std_id = V4L2_STD_PAL_Nc;
+        break;
+    case COMPOSITE_STD_PAL_60:
+        std_id = V4L2_STD_PAL_60;
+        break;
+    default:
+        LOGE("%s::unmathced composite_std(%d)", __func__, std);
+        break;
+    }
+
+    return std_id;
+}
+
+int hdmi_check_output_mode(int v4l2_output_type)
+{
+    struct HDMIVideoParameter video;
+    struct HDMIAudioParameter audio;
+    int    calbirate_v4l2_mode = v4l2_output_type;
+
+    audio.formatCode = LPCM_FORMAT;
+    audio.outPacket  = HDMI_ASP;
+    audio.channelNum = CH_2;
+    audio.sampleFreq = SF_44KHZ;
+
+    switch (v4l2_output_type) {
+    case V4L2_OUTPUT_TYPE_DIGITAL :
+        video.mode = HDMI;
+        if (!EDIDHDMIModeSupport(&video)) {
+            calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI;
+            LOGI("Change mode into DVI\n");
+            break;
+        }
+
+        video.colorSpace = HDMI_CS_YCBCR444;
+        if (!EDIDColorSpaceSupport(&video)) {
+            calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB;
+            LOGI("Change mode into HDMI_RGB\n");
+        }
+        break;
+
+    case V4L2_OUTPUT_TYPE_HDMI_RGB:
+        video.mode = HDMI;
+        if (!EDIDHDMIModeSupport(&video)) {
+            calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI;
+            LOGI("Change mode into DVI\n");
+            break;
+        }
+
+        video.colorSpace = HDMI_CS_RGB;
+        if (!EDIDColorSpaceSupport(&video)) {
+            calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL;
+            LOGI("Change mode into HDMI_YCBCR\n");
+        }
+        break;
+
+    case V4L2_OUTPUT_TYPE_DVI:
+        video.mode = DVI;
+        if (!EDIDHDMIModeSupport(&video)) {
+            video.colorSpace = HDMI_CS_YCBCR444;
+            if (!EDIDColorSpaceSupport(&video)) {
+                calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB;
+                LOGI("Change mode into HDMI_RGB\n");
+            } else {
+                calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL;
+                LOGI("Change mode into HDMI_YCBCR\n");
+            }
+            break;
+        }
+
+        break;
+
+    default:
+        break;
+    }
+    return calbirate_v4l2_mode;
+}
+
+int hdmi_check_resolution(v4l2_std_id std_id)
+{
+    struct HDMIVideoParameter video;
+    struct HDMIAudioParameter audio;
+
+    switch (std_id) {
+    case V4L2_STD_480P_60_16_9:
+        video.resolution = v720x480p_60Hz;
+        video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_480P_60_4_3:
+        video.resolution = v640x480p_60Hz;
+        video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_576P_50_16_9:
+        video.resolution = v720x576p_50Hz;
+        video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_576P_50_4_3:
+        video.resolution = v720x576p_50Hz;
+        video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_720P_60:
+        video.resolution = v1280x720p_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_720P_50:
+        video.resolution = v1280x720p_50Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080P_60:
+        video.resolution = v1920x1080p_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080P_50:
+        video.resolution = v1920x1080p_50Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080I_60:
+        video.resolution = v1920x1080i_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080I_50:
+        video.resolution = v1920x1080i_50Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_480P_59:
+        video.resolution = v720x480p_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_720P_59:
+        video.resolution = v1280x720p_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080I_59:
+        video.resolution = v1920x1080i_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080P_59:
+        video.resolution = v1920x1080p_60Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_1080P_30:
+        video.resolution = v1920x1080p_30Hz;
+        video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+        break;
+    case V4L2_STD_TVOUT_720P_60_SBS_HALF:
+        video.resolution = v1280x720p_60Hz;
+        video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+        break;
+    case V4L2_STD_TVOUT_720P_59_SBS_HALF:
+        video.resolution = v1280x720p_60Hz;
+        video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+        break;
+    case V4L2_STD_TVOUT_720P_50_TB:
+        video.resolution = v1280x720p_50Hz;
+        video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+        break;
+    case V4L2_STD_TVOUT_1080P_24_TB:
+        video.resolution = v1920x1080p_24Hz;
+        video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+        break;
+    case V4L2_STD_TVOUT_1080P_23_TB:
+        video.resolution = v1920x1080p_24Hz;
+        video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+        break;
+    default:
+        LOGE("%s::unmathced std_id(%lld)", __func__, std_id);
+        return -1;
+        break;
+    }
+
+    if (!EDIDVideoResolutionSupport(&video)) {
+#ifdef DEBUG_MSG_ENABLE
+        LOGD("%s::EDIDVideoResolutionSupport(%llx) fail (not suppoted std_id) \n", __func__, std_id);
+#endif
+        return -1;
+    }
+
+    return 0;
+}
+
+int hdmi_resolution_2_std_id(unsigned int resolution, int * w, int * h, v4l2_std_id * std_id, __u32 *preset_id)
+{
+    int ret = 0;
+
+    switch (resolution) {
+    case 1080960:
+        *std_id = V4L2_STD_1080P_60;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080P60;
+        break;
+    case 1080950:
+        *std_id = V4L2_STD_1080P_50;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080P50;
+        break;
+    case 1080930:
+        *std_id = V4L2_STD_1080P_30;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080P30;
+        break;
+    case 1080924:
+        *std_id = V4L2_STD_TVOUT_1080P_24_TB;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080P24_TB;
+        break;
+    case 1080160:
+        *std_id = V4L2_STD_1080I_60;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080I60;
+        break;
+    case 1080150:
+        *std_id = V4L2_STD_1080I_50;
+        *w      = 1920;
+        *h      = 1080;
+        *preset_id = V4L2_DV_1080I50;
+        break;
+    case 720960:
+        *std_id = V4L2_STD_720P_60;
+        *w      = 1280;
+        *h      = 720;
+        *preset_id = V4L2_DV_720P60;
+        break;
+    case 7209601:
+        *std_id = V4L2_STD_TVOUT_720P_60_SBS_HALF;
+        *w      = 1280;
+        *h      = 720;
+        *preset_id = V4L2_DV_720P60_SB_HALF;
+        break;
+    case 720950:
+        *std_id = V4L2_STD_720P_50;
+        *w      = 1280;
+        *h      = 720;
+        *preset_id = V4L2_DV_720P50;
+        break;
+    case 7209501:
+        *std_id = V4L2_STD_TVOUT_720P_50_TB;
+        *w      = 1280;
+        *h      = 720;
+        *preset_id = V4L2_DV_720P50_TB;
+        break;
+    case 5769501:
+        *std_id = V4L2_STD_576P_50_16_9;
+        *w      = 720;
+        *h      = 576;
+        *preset_id = V4L2_DV_576P50;
+        break;
+    case 5769502:
+        *std_id = V4L2_STD_576P_50_4_3;
+        *w      = 720;
+        *h      = 576;
+        *preset_id = V4L2_DV_576P50;
+       break;
+    case 4809601:
+        *std_id = V4L2_STD_480P_60_16_9;
+        *w      = 720;
+        *h      = 480;
+        *preset_id = V4L2_DV_480P60;
+       break;
+    case 4809602:
+        *std_id = V4L2_STD_480P_60_4_3;
+        *w     = 720;
+        *h     = 480;
+        *preset_id = V4L2_DV_480P60;
+      break;
+    default:
+        LOGE("%s::unmathced resolution(%d)", __func__, resolution);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+int hdmi_enable_hdcp(int fd, unsigned int hdcp_en)
+{
+    if (ioctl(fd, VIDIOC_HDCP_ENABLE, hdcp_en) < 0) {
+        LOGD("%s::VIDIOC_HDCP_ENABLE(%d) fail \n", __func__, hdcp_en);
+        return -1;
+    }
+
+    return 0;
+}
+
+int hdmi_check_audio(int fd)
+{
+    struct HDMIAudioParameter audio;
+    enum state audio_state = ON;
+    int ret = 0;
+
+    audio.formatCode = LPCM_FORMAT;
+    audio.outPacket  = HDMI_ASP;
+    audio.channelNum = CH_2;
+    audio.sampleFreq = SF_44KHZ;
+
+#if defined(BOARD_USES_EDID)
+    if (!EDIDAudioModeSupport(&audio))
+        audio_state = NOT_SUPPORT;
+    else
+        audio_state = ON;
+#endif
+    if (audio_state == ON) {
+        if (ioctl(fd, VIDIOC_INIT_AUDIO, 1) < 0) {
+            LOGE("%s::VIDIOC_INIT_AUDIO(1) failed", __func__);
+            ret = -1;
+        }
+    } else {
+        if (ioctl(fd, VIDIOC_INIT_AUDIO, 0) < 0) {
+            LOGE("%s::VIDIOC_INIT_AUDIO(0) failed", __func__);
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
+}
diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h
new file mode 100644
index 0000000..67c0729
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HDMI_HAL_V4L2_UTILS_H__
+#define __HDMI_HAL_V4L2_UTILS_H__
+
+//#define LOG_NDEBUG 0
+//#define LOG_TAG "libhdmi"
+
+#include "fimd_api.h"
+#include "SecBuffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace android {
+
+void display_menu(void);
+
+int tvout_init(int fd_tvout, __u32 preset_id);
+int tvout_deinit();
+int tvout_std_v4l2_querycap(int fd, char *node);
+int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes);
+int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field field, int x, int y, int w, int h);
+int tvout_std_v4l2_s_ctrl(int fd, int id, int value);
+int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs);
+int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf);
+int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf);
+int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes);
+int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type);
+int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type);
+
+int tvout_v4l2_enum_output(int fp, struct v4l2_output *output);
+int tvout_v4l2_s_output(int fp, int index);
+int tvout_v4l2_g_output(int fp, int *index);
+int tvout_std_v4l2_enum_dv_presets(int fd);
+int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset);
+int tvout_std_subdev_s_fmt(int fd, unsigned int pad, int w, int h, enum v4l2_mbus_pixelcode code);
+int tvout_std_subdev_s_crop(int fd, unsigned int pad, int w, int h, int x, int y);
+
+void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect);
+int hdmi_set_videolayer(int fd, int hdmiW, int hdmiH, struct v4l2_rect * rect);
+int hdmi_set_graphiclayer(int fd_subdev, int fd_videodev,int layer,
+        int srcColorFormat,
+        int src_w, int src_h,
+        unsigned int src_address, SecBuffer * dstBuffer,
+        int dst_x, int dst_y, int dst_w, int dst_h,
+        int rotVal);
+int hdmi_set_g_Params(int fd_subdev, int fd_videodev, int layer,
+                      int srcColorFormat,
+                      int src_w, int src_h,
+                      int dst_x, int dst_y, int dst_w, int dst_h);
+
+int hdmi_cable_status();
+int hdmi_outputmode_2_v4l2_output_type(int output_mode);
+int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type);
+int composite_std_2_v4l2_std_id(int std);
+
+int hdmi_check_output_mode(int v4l2_output_type);
+int hdmi_check_resolution(v4l2_std_id std_id);
+
+int hdmi_resolution_2_std_id(unsigned int resolution, int *w, int *h, v4l2_std_id *std_id, __u32 *preset_id);
+int hdmi_enable_hdcp(int fd, unsigned int hdcp_en);
+int hdmi_check_audio(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+}  //namespace android
+
+#endif //__HDMI_HAL_V4L2_UTILS_H__
diff --git a/exynos5/hal/libhdmi/SecHdmi/fimd_api.c b/exynos5/hal/libhdmi/SecHdmi/fimd_api.c
new file mode 100644
index 0000000..0e07ef3
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/fimd_api.c
@@ -0,0 +1,229 @@
+/*
+* Copyright@ Samsung Electronics Co. LTD
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <linux/vt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <signal.h>
+#include <cutils/log.h>
+
+#include "fimd_api.h"
+
+int fb_open(int win)
+{
+    char node[20];
+    int fp = -1;
+
+    sprintf(node, "%s%d", PFX_NODE_FB, win);
+
+    fp = open(node, O_RDWR);
+    if (fp < 0)
+        LOGE("%s: fb[%d] open failed", __func__, win);
+
+    return fp;
+}
+
+int fb_close(int fp)
+{
+    if (fp)
+        close(fp);
+    else
+        LOGE("%s: fb is not allocated %d", __func__, fp);
+
+    return 0;
+}
+
+int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, FBIOGET_FSCREENINFO, fix);
+    if (ret)
+        LOGE("%s: FBIOGET_FSCREENINFO failed", __func__);
+
+    return ret;
+}
+
+int get_vscreeninfo(int fp, struct fb_var_screeninfo *var)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, FBIOGET_VSCREENINFO, var);
+    if (ret)
+        LOGE("%s:: FBIOGET_VSCREENINFO failed", __func__);
+
+    return ret;
+}
+
+int put_vscreeninfo(int fp, struct fb_var_screeninfo *var)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, FBIOPUT_VSCREENINFO, var);
+    if (ret)
+        LOGE("%s:: FBIOPUT_VSCREENINFO failed", __func__);
+
+    return ret;
+}
+
+int get_bytes_per_pixel(int bits_per_pixel)
+{
+    return (bits_per_pixel == 24 || bits_per_pixel == 25 ||
+        bits_per_pixel == 28) ? 4 : bits_per_pixel / 8;
+}
+
+char *fb_mmap(__u32 size, int fp)
+{
+    char *buffer;
+
+    buffer = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
+                  MAP_SHARED, fp, 0);
+    if (!buffer) {
+        LOGE("%s:: mmap failed", __func__);
+        return NULL;
+    }
+
+    return buffer;
+}
+
+int fb_ioctl(int fp, __u32 cmd, void *arg)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, cmd, arg);
+    if (ret < 0)
+        LOGE("%s:: ioctl (%d) failed", __func__, cmd);
+
+    return ret;
+}
+
+int fb_on(int fp)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, FBIOBLANK, FB_BLANK_UNBLANK);
+    if (ret)
+        LOGE("%s:: FBIOBLANK failed", __func__);
+
+    return ret;
+}
+
+int fb_off(int fp)
+{
+    int ret = -1;
+
+    ret = ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN);
+    if (ret)
+        LOGE("%s:: FBIOBLANK failed", __func__);
+
+    return ret;
+}
+
+int fb_off_all()
+{
+    int fp, i;
+
+    for (i = 0; i < TOTAL_FB_NUM; i++) {
+        fp = fb_open(i);
+        if (fp < 0)
+            return -1;
+
+        if (ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN) < 0)
+            LOGE("%s:: FBIOBLANK failed", __func__);
+
+        fb_off(fp);
+        fb_close(fp);
+    }
+
+    return 0;
+}
+
+char *fb_init_display(int fp, int width, int height, int left_x, int top_y,
+              int bpp)
+{
+    struct fb_var_screeninfo var;
+    struct s5ptvfb_user_window window;
+    int fb_size;
+    char *fb = NULL;
+
+    var.xres = width;
+    var.yres = height;
+    var.bits_per_pixel = bpp;
+    window.x = left_x;
+    window.y = top_y;
+
+    var.xres_virtual = var.xres;
+    var.yres_virtual = var.yres;
+    var.xoffset = 0;
+    var.yoffset = 0;
+    var.width = 0;
+    var.height = 0;
+    var.transp.length = 0;
+    var.activate = FB_ACTIVATE_FORCE;
+    fb_size = var.xres_virtual * var.yres_virtual * bpp / 8;
+
+    /* FBIOPUT_VSCREENINFO should be first */
+    put_vscreeninfo(fp, &var);
+    fb_ioctl(fp, S5PTVFB_WIN_POSITION, &window);
+
+    /* draw image */
+    fb = fb_mmap(fb_size, fp);
+    memset(fb, 0x0, fb_size);
+
+    return fb;
+}
+
+int simple_draw(char *dest, const char *src, int img_width,
+        struct fb_var_screeninfo *var)
+{
+    int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel);
+    unsigned int y;
+
+    for (y = 0; y < var->yres; y++)
+        memcpy(dest + y * var->xres * bytes_per_pixel,
+               src + y * img_width * bytes_per_pixel,
+               var->xres * bytes_per_pixel);
+
+    return 0;
+}
+
+int draw(char *dest, const char *src, int img_width,
+     struct fb_var_screeninfo *var)
+{
+    int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel);
+    unsigned int y;
+
+    if (var->bits_per_pixel == 16) {
+        memcpy(dest, src, var->xres * var->yres * 2);
+    } else {
+        for (y = 0; y < var->yres; y++)
+            memcpy(dest + y * var->xres * bytes_per_pixel,
+                   src + y * img_width * bytes_per_pixel,
+                   var->xres * bytes_per_pixel);
+    }
+
+    return 0;
+}
diff --git a/exynos5/hal/libhdmi/SecHdmi/fimd_api.h b/exynos5/hal/libhdmi/SecHdmi/fimd_api.h
new file mode 100644
index 0000000..a8561a4
--- /dev/null
+++ b/exynos5/hal/libhdmi/SecHdmi/fimd_api.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FIMD_API_H__
+#define __FIMD_API_H__
+
+#include <linux/fb.h>
+#include "s5p_tvout.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TOTAL_FB_NUM        5
+
+int fb_open(int win);
+int fb_close(int fp);
+int fb_on(int fp);
+int fb_off(int fp);
+int fb_off_all(void);
+char *fb_init_display(int fp, int width, int height,\
+            int left_x, int top_y, int bpp);
+int fb_ioctl(int fp, __u32 cmd, void *arg);
+char *fb_mmap(__u32 size, int fp);
+int simple_draw(char *dest, const char *src,\
+        int img_width, struct fb_var_screeninfo *var);
+int draw(char *dest, const char *src,\
+    int img_width, struct fb_var_screeninfo *var);
+int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix);
+int get_vscreeninfo(int fp, struct fb_var_screeninfo *var);
+int put_vscreeninfo(int fp, struct fb_var_screeninfo *var);
+int get_bytes_per_pixel(int bits_per_pixel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FIMD_API_H__ */
diff --git a/exynos5/hal/libhdmi/libhdmiservice/Android.mk b/exynos5/hal/libhdmi/libhdmiservice/Android.mk
new file mode 100644
index 0000000..bc0aa0d
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/Android.mk
@@ -0,0 +1,95 @@
+# 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.
+
+ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),)
+ifeq ($(BOARD_USES_HDMI),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libTVOut
+#
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := \
+	SecTVOutService.cpp \
+	ISecTVOut.cpp \
+	MessageQueue.cpp
+
+LOCAL_C_INCLUDES := \
+
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libutils \
+	libcutils
+
+LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/include
+LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/libhdmi
+LOCAL_SHARED_LIBRARIES += libhdmi
+
+ifeq ($(BOARD_USES_HDMI_SUBTITLES),true)
+	LOCAL_CFLAGS  += -DBOARD_USES_HDMI_SUBTITLES
+endif
+
+LOCAL_MODULE := libTVOut
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# libhdmiclient
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES:= \
+    SecHdmiClient.cpp
+
+LOCAL_C_INCLUDES += \
+	$(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libutils \
+	libTVOut
+
+ifeq ($(TARGET_SIMULATOR),true)
+ifeq ($(TARGET_OS),linux)
+ifeq ($(TARGET_ARCH),x86)
+LOCAL_LDLIBS += -lpthread -ldl -lrt
+endif
+endif
+endif
+
+ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
+	LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
+endif
+
+ifeq ($(TARGET_SOC),exynos5250)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250
+endif
+
+LOCAL_CFLAGS     += -DBOARD_USES_HDMI
+
+LOCAL_MODULE:= libhdmiclient
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
+endif
diff --git a/exynos5/hal/libhdmi/libhdmiservice/Barrier.h b/exynos5/hal/libhdmi/libhdmiservice/Barrier.h
new file mode 100644
index 0000000..6f8507e
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/Barrier.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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_BARRIER_H
+#define ANDROID_BARRIER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class Barrier
+{
+public:
+    inline Barrier() : state(CLOSED) { }
+    inline ~Barrier() { }
+    void open() {
+        Mutex::Autolock _l(lock);
+        state = OPENED;
+        cv.broadcast();
+    }
+    void close() {
+        Mutex::Autolock _l(lock);
+        state = CLOSED;
+    }
+    void wait() const {
+        Mutex::Autolock _l(lock);
+        while (state == CLOSED) {
+            cv.wait(lock);
+        }
+    }
+private:
+    enum { OPENED, CLOSED };
+    mutable     Mutex       lock;
+    mutable     Condition   cv;
+    volatile    int         state;
+};
+
+}; // namespace android
+
+#endif // ANDROID_BARRIER_H
diff --git a/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp
new file mode 100644
index 0000000..a013bf1
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp
@@ -0,0 +1,111 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+#include "ISecTVOut.h"
+
+namespace android {
+
+    enum {
+        SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION,
+        SET_HDMI_MODE,
+        SET_HDMI_RESOLUTION,
+        SET_HDMI_HDCP,
+        SET_HDMI_ROTATE,
+        SET_HDMI_HWCLAYER,
+        BLIT_2_HDMI
+    };
+
+    void BpSecTVOut::setHdmiCableStatus(uint32_t status)
+    {
+        Parcel data, reply;
+        data.writeInt32(status);
+        remote()->transact(SET_HDMI_STATUS, data, &reply);
+    }
+
+    void BpSecTVOut::setHdmiMode(uint32_t mode)
+    {
+        Parcel data, reply;
+        data.writeInt32(mode);
+        remote()->transact(SET_HDMI_MODE, data, &reply);
+    }
+
+    void BpSecTVOut::setHdmiResolution(uint32_t resolution)
+    {
+        Parcel data, reply;
+        data.writeInt32(resolution);
+        remote()->transact(SET_HDMI_RESOLUTION, data, &reply);
+    }
+
+    void BpSecTVOut::setHdmiHdcp(uint32_t resolution)
+    {
+        Parcel data, reply;
+        data.writeInt32(resolution);
+        remote()->transact(SET_HDMI_HDCP, data, &reply);
+    }
+
+    void BpSecTVOut::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer)
+    {
+        Parcel data, reply;
+        data.writeInt32(rotVal);
+        data.writeInt32(hwcLayer);
+        remote()->transact(SET_HDMI_ROTATE, data, &reply);
+    }
+
+    void BpSecTVOut::setHdmiHwcLayer(uint32_t hwcLayer)
+    {
+        Parcel data, reply;
+        data.writeInt32(hwcLayer);
+        remote()->transact(SET_HDMI_HWCLAYER, data, &reply);
+    }
+
+    void BpSecTVOut::blit2Hdmi(uint32_t w, uint32_t h,
+                                        uint32_t colorFormat,
+                                        uint32_t physYAddr,
+                                        uint32_t physCbAddr,
+                                        uint32_t physCrAddr,
+                                        uint32_t dstX,
+                                        uint32_t dstY,
+                                        uint32_t hdmiLayer,
+                                        uint32_t num_of_hwc_layer)
+    {
+        Parcel data, reply;
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(colorFormat);
+        data.writeInt32(physYAddr);
+        data.writeInt32(physCbAddr);
+        data.writeInt32(physCrAddr);
+        data.writeInt32(dstX);
+        data.writeInt32(dstY);
+        data.writeInt32(hdmiLayer);
+        data.writeInt32(num_of_hwc_layer);
+        remote()->transact(BLIT_2_HDMI, data, &reply);
+    }
+
+    IMPLEMENT_META_INTERFACE(SecTVOut, "android.os.ISecTVOut");
+};
diff --git a/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h
new file mode 100644
index 0000000..5506b57
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h
@@ -0,0 +1,74 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#ifndef ISECTVOUT_H
+#define ISECTVOUT_H
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+    class ISecTVOut: public IInterface
+    {
+        public:
+            DECLARE_META_INTERFACE(SecTVOut);
+            virtual void setHdmiCableStatus(uint32_t status) = 0;
+            virtual void setHdmiMode(uint32_t mode) = 0;
+            virtual void setHdmiResolution(uint32_t resolution) = 0;
+            virtual void setHdmiHdcp(uint32_t enHdcp) = 0;
+            virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) = 0;
+            virtual void setHdmiHwcLayer(uint32_t hwcLayer) = 0;
+            virtual void blit2Hdmi(uint32_t w, uint32_t h,
+                                        uint32_t colorFormat,
+                                        uint32_t physYAddr,
+                                        uint32_t physCbAddr,
+                                        uint32_t physCrAddr,
+                                        uint32_t dstX,
+                                        uint32_t dstY,
+                                        uint32_t hdmiLayer,
+                                        uint32_t num_of_hwc_layer) = 0;
+    };
+    //--------------------------------------------------------------
+    class BpSecTVOut: public BpInterface<ISecTVOut>
+    {
+        public:
+            BpSecTVOut(const sp<IBinder>& impl): BpInterface<ISecTVOut>(impl){}
+            virtual void setHdmiCableStatus(uint32_t status);
+            virtual void setHdmiMode(uint32_t mode);
+            virtual void setHdmiResolution(uint32_t resolution);
+            virtual void setHdmiHdcp(uint32_t enHdcp);
+            virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer);
+            virtual void setHdmiHwcLayer(uint32_t hwcLayer);
+            virtual void blit2Hdmi(uint32_t w, uint32_t h,
+                                        uint32_t colorFormat,
+                                        uint32_t physYAddr,
+                                        uint32_t physCbAddr,
+                                        uint32_t physCrAddr,
+                                        uint32_t dstX,
+                                        uint32_t dstY,
+                                        uint32_t hdmiLayer,
+                                        uint32_t num_of_hwc_layer);
+    };
+};
+#endif
diff --git a/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp
new file mode 100644
index 0000000..fb58ef9
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+
+#include "MessageQueue.h"
+
+namespace android {
+
+void MessageList::insert(const sp<MessageBase>& node)
+{
+    LIST::iterator cur(mList.begin());
+    LIST::iterator end(mList.end());
+    while (cur != end) {
+        if (*node < **cur) {
+            mList.insert(cur, node);
+            return;
+        }
+        ++cur;
+    }
+    mList.insert(++end, node);
+}
+
+void MessageList::remove(MessageList::LIST::iterator pos)
+{
+    mList.erase(pos);
+}
+
+MessageQueue::MessageQueue()
+    : mInvalidate(false)
+{
+    mInvalidateMessage = new MessageBase(INVALIDATE);
+}
+
+MessageQueue::~MessageQueue()
+{
+}
+
+sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
+{
+    sp<MessageBase> result;
+
+    bool again;
+    do {
+        const nsecs_t timeoutTime = systemTime() + timeout;
+        while (true) {
+            Mutex::Autolock _l(mLock);
+            nsecs_t now = systemTime();
+            nsecs_t nextEventTime = -1;
+
+            LIST::iterator cur(mMessages.begin());
+            if (cur != mMessages.end()) {
+                result = *cur;
+            }
+
+            if (result != 0) {
+                if (result->when <= now) {
+                    // there is a message to deliver
+                    mMessages.remove(cur);
+                    break;
+                }
+                nextEventTime = result->when;
+                result = 0;
+            }
+
+            // see if we have an invalidate message
+            if (mInvalidate) {
+                mInvalidate = false;
+                mInvalidateMessage->when = now;
+                result = mInvalidateMessage;
+                break;
+            }
+
+            if (timeout >= 0) {
+                if (timeoutTime < now) {
+                    // we timed-out, return a NULL message
+                    result = 0;
+                    break;
+                }
+                if (nextEventTime > 0) {
+                    if (nextEventTime > timeoutTime) {
+                        nextEventTime = timeoutTime;
+                    }
+                } else {
+                    nextEventTime = timeoutTime;
+                }
+            }
+
+            if (nextEventTime >= 0) {
+                //LOGD("nextEventTime = %lld ms", nextEventTime);
+                if (nextEventTime > 0) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    const nsecs_t reltime = nextEventTime - systemTime();
+                    if (reltime > 0) {
+                        mCondition.waitRelative(mLock, reltime);
+                    }
+                }
+            } else {
+                //LOGD("going to wait");
+                // we're about to wait, flush the binder command buffer
+                IPCThreadState::self()->flushCommands();
+                mCondition.wait(mLock);
+            }
+        }
+        // here we're not holding the lock anymore
+
+        if (result == 0)
+            break;
+
+        again = result->handler();
+        if (again) {
+            // the message has been processed. release our reference to it
+            // without holding the lock.
+            result->notify();
+            result = 0;
+        }
+    } while (again);
+
+    return result;
+}
+
+status_t MessageQueue::postMessage(
+        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
+{
+    return queueMessage(message, relTime, flags);
+}
+
+status_t MessageQueue::invalidate() {
+    Mutex::Autolock _l(mLock);
+    mInvalidate = true;
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+status_t MessageQueue::queueMessage(
+        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
+{
+    Mutex::Autolock _l(mLock);
+    message->when = systemTime() + relTime;
+    mMessages.insert(message);
+
+    //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
+    //dumpLocked(message);
+
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+void MessageQueue::dump(const sp<MessageBase>& message)
+{
+    Mutex::Autolock _l(mLock);
+    dumpLocked(message);
+}
+
+void MessageQueue::dumpLocked(const sp<MessageBase>& message)
+{
+    LIST::const_iterator cur(mMessages.begin());
+    LIST::const_iterator end(mMessages.end());
+    int c = 0;
+    while (cur != end) {
+        const char tick = (*cur == message) ? '>' : ' ';
+        LOGD("%c %d: msg{.what=%08x, when=%lld}",
+                tick, c, (*cur)->what, (*cur)->when);
+        ++cur;
+        c++;
+    }
+}
+
+}; // namespace android
diff --git a/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h
new file mode 100644
index 0000000..4fc752f
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 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_MESSAGE_QUEUE_H
+#define ANDROID_MESSAGE_QUEUE_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/List.h>
+
+#include "Barrier.h"
+
+namespace android {
+
+class MessageBase;
+
+class MessageList
+{
+    List< sp<MessageBase> > mList;
+    typedef List< sp<MessageBase> > LIST;
+public:
+    inline LIST::iterator begin()                { return mList.begin(); }
+    inline LIST::const_iterator begin() const    { return mList.begin(); }
+    inline LIST::iterator end()                  { return mList.end(); }
+    inline LIST::const_iterator end() const      { return mList.end(); }
+    inline bool isEmpty() const { return mList.empty(); }
+    void insert(const sp<MessageBase>& node);
+    void remove(LIST::iterator pos);
+};
+
+class MessageBase :
+    public LightRefBase<MessageBase>
+{
+public:
+    nsecs_t     when;
+    uint32_t    what;
+    int32_t     arg0;
+
+    MessageBase() : when(0), what(0), arg0(0) { }
+    MessageBase(uint32_t what, int32_t arg0=0)
+        : when(0), what(what), arg0(arg0) { }
+
+    // return true if message has a handler
+    virtual bool handler() { return false; }
+
+    // waits for the handler to be processed
+    void wait() const { barrier.wait(); }
+
+    // releases all waiters. this is done automatically if
+    // handler returns true
+    void notify() const { barrier.open(); }
+
+protected:
+    virtual ~MessageBase() { }
+
+private:
+    mutable Barrier barrier;
+    friend class LightRefBase<MessageBase>;
+};
+
+inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) {
+    return lhs.when < rhs.when;
+}
+
+class MessageQueue
+{
+    typedef List< sp<MessageBase> > LIST;
+public:
+
+    MessageQueue();
+    ~MessageQueue();
+
+    // pre-defined messages
+    enum {
+        INVALIDATE = '_upd'
+    };
+
+    sp<MessageBase> waitMessage(nsecs_t timeout = -1);
+
+    status_t postMessage(const sp<MessageBase>& message,
+            nsecs_t reltime=0, uint32_t flags = 0);
+
+    status_t invalidate();
+
+    void dump(const sp<MessageBase>& message);
+
+private:
+    status_t queueMessage(const sp<MessageBase>& message,
+            nsecs_t reltime, uint32_t flags);
+    void dumpLocked(const sp<MessageBase>& message);
+
+    Mutex           mLock;
+    Condition       mCondition;
+    MessageList     mMessages;
+    bool            mInvalidate;
+    sp<MessageBase> mInvalidateMessage;
+};
+
+}; // namespace android
+
+#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp
new file mode 100644
index 0000000..150aadf
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp
@@ -0,0 +1,139 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#define LOG_TAG "libhdmiclient"
+
+#include "SecHdmiClient.h"
+
+namespace android {
+
+static sp<ISecTVOut> g_SecTVOutService = 0;
+
+SecHdmiClient::SecHdmiClient()
+{
+    g_SecTVOutService = m_getSecTVOutService();
+}
+
+SecHdmiClient::~SecHdmiClient()
+{
+}
+
+SecHdmiClient * SecHdmiClient::getInstance(void)
+{
+    static SecHdmiClient singleton;
+    return &singleton;
+}
+
+void SecHdmiClient::setHdmiCableStatus(int status)
+{
+    LOGD("%s HDMI status: %d\n", __func__, status);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiCableStatus(status);
+}
+
+void SecHdmiClient::setHdmiMode(int mode)
+{
+    //LOGD("%s HDMI Mode: %d\n", __func__, mode);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiMode(mode);
+}
+
+void SecHdmiClient::setHdmiResolution(int resolution)
+{
+    //LOGD("%s HDMI Resolution: %d\n", __func__, resolution);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiResolution(resolution);
+}
+
+void SecHdmiClient::setHdmiHdcp(int enHdcp)
+{
+    //LOGD("%s HDMI HDCP: %d\n", __func__, enHdcp);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiHdcp(enHdcp);
+}
+
+void SecHdmiClient::setHdmiRotate(int rotVal, uint32_t hwcLayer)
+{
+    //LOGD("%s HDMI ROTATE: %d\n", __func__, rotVal);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiRotate(rotVal, hwcLayer);
+}
+
+void SecHdmiClient::setHdmiHwcLayer(uint32_t hwcLayer)
+{
+    //LOGD("%s HDMI HWCLAYER: %d\n", __func__, hwcLayer);
+
+    if (g_SecTVOutService != 0)
+        g_SecTVOutService->setHdmiHwcLayer(hwcLayer);
+}
+
+void SecHdmiClient::blit2Hdmi(uint32_t w, uint32_t h,
+                                uint32_t colorFormat,
+                                uint32_t physYAddr,
+                                uint32_t physCbAddr,
+                                uint32_t physCrAddr,
+                                uint32_t dstX,
+                                uint32_t dstY,
+                                uint32_t hdmiLayer,
+                                uint32_t num_of_hwc_layer)
+{
+    if (g_SecTVOutService != 0 )
+        g_SecTVOutService->blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer);
+}
+
+sp<ISecTVOut> SecHdmiClient::m_getSecTVOutService(void)
+{
+    int ret = 0;
+
+    if (g_SecTVOutService == 0) {
+        sp<IBinder> binder;
+        sp<ISecTVOut> sc;
+        sp<IServiceManager> sm = defaultServiceManager();
+        int getSvcTimes = 0;
+        for(getSvcTimes = 0; getSvcTimes < GETSERVICETIMEOUT; getSvcTimes++) {
+            binder = sm->getService(String16("SecTVOutService"));
+            if (binder == 0) {
+                LOGW("SecTVOutService not published, waiting...");
+                usleep(500000); // 0.5 s
+            } else {
+                break;
+            }
+        }
+        // grab the lock again for updating g_surfaceFlinger
+        if (getSvcTimes < GETSERVICETIMEOUT) {
+            sc = interface_cast<ISecTVOut>(binder);
+            g_SecTVOutService = sc;
+        } else {
+            LOGW("Failed to get SecTVOutService... SecHdmiClient will get it later..");
+        }
+    }
+    return g_SecTVOutService;
+}
+
+}
diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h
new file mode 100644
index 0000000..e94e19a
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h
@@ -0,0 +1,84 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#ifndef __SEC_HDMI_CLIENT_H__
+#define __SEC_HDMI_CLIENT_H__
+
+#include "utils/Log.h"
+
+#include <linux/errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/RefBase.h>
+#include <cutils/log.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include "ISecTVOut.h"
+
+#define GETSERVICETIMEOUT (5)
+
+namespace android {
+
+class SecHdmiClient
+{
+public:
+    enum HDMI_MODE
+    {
+        HDMI_MODE_NONE = 0,
+        HDMI_MODE_UI,
+        HDMI_MODE_VIDEO,
+    };
+
+private:
+    SecHdmiClient();
+    virtual ~SecHdmiClient();
+
+public:
+        static SecHdmiClient * getInstance(void);
+        void setHdmiCableStatus(int status);
+        void setHdmiMode(int mode);
+        void setHdmiResolution(int resolution);
+        void setHdmiHdcp(int enHdcp);
+        void setHdmiRotate(int rotVal, uint32_t hwcLayer);
+        void setHdmiHwcLayer(uint32_t hwcLayer);
+        virtual void blit2Hdmi(uint32_t w, uint32_t h,
+                                        uint32_t colorFormat,
+                                        uint32_t physYAddr,
+                                        uint32_t physCbAddr,
+                                        uint32_t physCrAddr,
+                                        uint32_t dstX,
+                                        uint32_t dstY,
+                                        uint32_t hdmiLayer,
+                                        uint32_t num_of_hwc_layer);
+
+private:
+        sp<ISecTVOut> m_getSecTVOutService(void);
+
+};
+
+};
+
+#endif
diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp
new file mode 100644
index 0000000..39ef742
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp
@@ -0,0 +1,377 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#define LOG_TAG "SecTVOutService"
+
+#include <binder/IServiceManager.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+#include "SecTVOutService.h"
+#include <linux/fb.h>
+
+namespace android {
+#define DEFAULT_LCD_WIDTH               1280
+#define DEFAULT_LCD_HEIGHT              800
+
+#define DIRECT_VIDEO_RENDERING          (1)
+#define DIRECT_UI_RENDERING             (0)
+
+    enum {
+        SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION,
+        SET_HDMI_MODE,
+        SET_HDMI_RESOLUTION,
+        SET_HDMI_HDCP,
+        SET_HDMI_ROTATE,
+        SET_HDMI_HWCLAYER,
+        BLIT_2_HDMI
+    };
+
+    int SecTVOutService::HdmiFlushThread()
+    {
+        while (!mExitHdmiFlushThread) {
+            nsecs_t timeout = -1;
+            sp<MessageBase> msg = mHdmiEventQueue.waitMessage(timeout);
+        }
+
+        return 0;
+    }
+
+    int SecTVOutService::instantiate()
+    {
+        LOGD("SecTVOutService instantiate");
+        int r = defaultServiceManager()->addService(String16( "SecTVOutService"), new SecTVOutService ());
+        LOGD("SecTVOutService r=%d", r);
+
+        return r;
+    }
+
+    SecTVOutService::SecTVOutService () {
+        LOGV("SecTVOutService created");
+        mHdmiCableInserted = false;
+#ifdef SUPPORT_G2D_UI_MODE
+        mUILayerMode = SecHdmi::HDMI_LAYER_GRAPHIC_1;
+#else
+        mUILayerMode = SecHdmi::HDMI_LAYER_VIDEO;
+#endif
+        mHwcLayer = 0;
+        mExitHdmiFlushThread = false;
+
+        setLCDsize();
+        if (mSecHdmi.create(mLCD_width, mLCD_height) == false)
+            LOGE("%s::mSecHdmi.create() fail", __func__);
+        else
+            setHdmiStatus(1);
+
+        mHdmiFlushThread = new HDMIFlushThread(this);
+    }
+
+    void SecTVOutService::setLCDsize(void) {
+            char const * const device_template[] = {
+                "/dev/graphics/fb%u",
+                "/dev/fb%u",
+                0 };
+
+            int fd = -1;
+            int i = 0;
+            char name[64];
+
+            while ((fd==-1) && device_template[i]) {
+                snprintf(name, 64, device_template[i], 0);
+                fd = open(name, O_RDWR, 0);
+                i++;
+            }
+            if (fd > 0) {
+                struct fb_var_screeninfo info;
+                if (ioctl(fd, FBIOGET_VSCREENINFO, &info) != -1) {
+                    mLCD_width  = info.xres;
+                    mLCD_height = info.yres;
+                } else {
+                    mLCD_width  = DEFAULT_LCD_WIDTH;
+                    mLCD_height = DEFAULT_LCD_HEIGHT;
+                }
+                close(fd);
+            }
+            return;
+    }
+
+    SecTVOutService::~SecTVOutService () {
+        LOGV ("SecTVOutService destroyed");
+
+        if (mHdmiFlushThread != NULL) {
+            mHdmiFlushThread->requestExit();
+            mExitHdmiFlushThread = true;
+            mHdmiFlushThread->requestExitAndWait();
+            mHdmiFlushThread.clear();
+        }
+    }
+
+    status_t SecTVOutService::onTransact(uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags)
+    {
+        switch (code) {
+        case SET_HDMI_STATUS: {
+            int status = data.readInt32();
+            setHdmiStatus(status);
+        } break;
+
+        case SET_HDMI_MODE: {
+            int mode = data.readInt32();
+            setHdmiMode(mode);
+        } break;
+
+        case SET_HDMI_RESOLUTION: {
+            int resolution = data.readInt32();
+            setHdmiResolution(resolution);
+        } break;
+
+        case SET_HDMI_HDCP: {
+            int enHdcp = data.readInt32();
+            setHdmiHdcp(enHdcp);
+        } break;
+
+        case SET_HDMI_ROTATE: {
+            int rotVal = data.readInt32();
+            int hwcLayer = data.readInt32();
+            setHdmiRotate(rotVal, hwcLayer);
+        } break;
+
+        case SET_HDMI_HWCLAYER: {
+            int hwcLayer = data.readInt32();
+            setHdmiHwcLayer((uint32_t)hwcLayer);
+        } break;
+
+        case BLIT_2_HDMI: {
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            uint32_t colorFormat = data.readInt32();
+            uint32_t physYAddr  = data.readInt32();
+            uint32_t physCbAddr = data.readInt32();
+            uint32_t physCrAddr = data.readInt32();
+            uint32_t dstX   = data.readInt32();
+            uint32_t dstY   = data.readInt32();
+            uint32_t hdmiLayer   = data.readInt32();
+            uint32_t num_of_hwc_layer = data.readInt32();
+
+            blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer);
+        } break;
+
+        default :
+            LOGE ( "onTransact::default");
+            return BBinder::onTransact (code, data, reply, flags);
+        }
+
+        return NO_ERROR;
+    }
+
+    void SecTVOutService::setHdmiStatus(uint32_t status)
+    {
+        LOGD("%s HDMI cable status = %d", __func__, status);
+        {
+            Mutex::Autolock _l(mLock);
+
+            bool hdmiCableInserted = (bool)status;
+
+            if (mHdmiCableInserted == hdmiCableInserted)
+                return;
+
+            if (hdmiCableInserted == true) {
+                if (mSecHdmi.connect() == false) {
+                    LOGE("%s::mSecHdmi.connect() fail", __func__);
+                    hdmiCableInserted = false;
+                }
+            } else {
+                if (mSecHdmi.disconnect() == false)
+                    LOGE("%s::mSecHdmi.disconnect() fail", __func__);
+            }
+
+            mHdmiCableInserted = hdmiCableInserted;
+        }
+
+        if (hdmiCableInserted() == true)
+            this->blit2Hdmi(mLCD_width, mLCD_height, HAL_PIXEL_FORMAT_BGRA_8888, 0, 0, 0, 0, 0, HDMI_MODE_UI, 0);
+    }
+
+    void SecTVOutService::setHdmiMode(uint32_t mode)
+    {
+        LOGD("%s TV mode = %d", __func__, mode);
+        Mutex::Autolock _l(mLock);
+
+        if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiOutputMode(mode)) == false) {
+            LOGE("%s::mSecHdmi.setHdmiOutputMode() fail", __func__);
+            return;
+        }
+    }
+
+    void SecTVOutService::setHdmiResolution(uint32_t resolution)
+    {
+        LOGD("%s TV resolution = %d", __func__, resolution);
+        Mutex::Autolock _l(mLock);
+
+        if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiResolution(resolution)) == false) {
+            LOGE("%s::mSecHdmi.setHdmiResolution() fail", __func__);
+            return;
+        }
+    }
+
+    void SecTVOutService::setHdmiHdcp(uint32_t hdcp_en)
+    {
+        LOGD("%s TV HDCP = %d", __func__, hdcp_en);
+        Mutex::Autolock _l(mLock);
+
+        if ((hdmiCableInserted() == true) && (mSecHdmi.setHdcpMode(hdcp_en)) == false) {
+            LOGE("%s::mSecHdmi.setHdcpMode() fail", __func__);
+            return;
+        }
+    }
+
+    void SecTVOutService::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer)
+    {
+        //LOGD("%s TV ROTATE = %d", __func__, rotVal);
+        Mutex::Autolock _l(mLock);
+
+        if ((hdmiCableInserted() == true) && (mSecHdmi.setUIRotation(rotVal, hwcLayer)) == false) {
+            LOGE("%s::mSecHdmi.setUIRotation() fail", __func__);
+            return;
+        }
+    }
+
+    void SecTVOutService::setHdmiHwcLayer(uint32_t hwcLayer)
+    {
+        //LOGD("%s TV HWCLAYER = %d", __func__, hwcLayer);
+        Mutex::Autolock _l(mLock);
+
+        mHwcLayer = hwcLayer;
+        return;
+    }
+
+    void SecTVOutService::blit2Hdmi(uint32_t w, uint32_t h, uint32_t colorFormat,
+                                 uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr,
+                                 uint32_t dstX, uint32_t dstY,
+                                 uint32_t hdmiMode,
+                                 uint32_t num_of_hwc_layer)
+    {
+        Mutex::Autolock _l(mLock);
+
+        if (hdmiCableInserted() == false)
+            return;
+
+        int hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO;
+#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME)
+        nsecs_t start, end;
+#endif
+
+        sp<MessageBase> msg;
+
+        switch (hdmiMode) {
+        case HDMI_MODE_UI :
+            if (mHwcLayer >= 2)
+                hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_0;
+            else if (mHwcLayer == 1)
+                hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1;
+            else
+#ifdef SUPPORT_G2D_UI_MODE
+                hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1;
+#else
+                hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO;
+#endif
+
+            if (mHwcLayer == 0) {
+                for (int layer = SecHdmi::HDMI_LAYER_BASE + 1; layer < SecHdmi::HDMI_LAYER_MAX; layer++) {
+                    if (layer != mUILayerMode) {
+                        if (mSecHdmi.clear(layer) == false)
+                            LOGE("%s::mSecHdmi.clear(%d) fail", __func__, layer);
+                    }
+                }
+            }
+
+            if (mUILayerMode != hdmiLayer) {
+                if (mSecHdmi.clear(mUILayerMode) == false)
+                    LOGE("%s::mSecHdmi.clear(%d) fail", __func__, mUILayerMode);
+            }
+
+            mUILayerMode = hdmiLayer;
+
+#if !defined(BOARD_USES_HDMI_SUBTITLES)
+            if (mHwcLayer == 0)
+#endif
+#if (DIRECT_UI_RENDERING == 1)
+            {
+#ifdef CHECK_UI_TIME
+                start = systemTime();
+#endif
+                if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY,
+                                    mUILayerMode, mHwcLayer) == false)
+                    LOGE("%s::mSecHdmi.flush() on HDMI_MODE_UI fail", __func__);
+#ifdef CHECK_UI_TIME
+                end = systemTime();
+                LOGD("[UI] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
+#endif
+            }
+#else
+            {
+                msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr,
+                                            dstX, dstY, mUILayerMode, mHwcLayer, HDMI_MODE_UI);
+
+                /* post to HdmiEventQueue */
+                mHdmiEventQueue.postMessage(msg, 0, 0);
+            }
+#endif
+            break;
+
+        case HDMI_MODE_VIDEO :
+#if (DIRECT_VIDEO_RENDERING == 1)
+#ifdef CHECK_VIDEO_TIME
+            start = systemTime();
+#endif
+            if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY,
+                                SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer) == false)
+                LOGE("%s::mSecHdmi.flush() on HDMI_MODE_VIDEO fail", __func__);
+#ifdef CHECK_VIDEO_TIME
+            end = systemTime();
+            LOGD("[Video] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
+#endif
+#else
+            msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr,
+                                        dstX, dstY, SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer, HDMI_MODE_VIDEO);
+
+            /* post to HdmiEventQueue */
+            mHdmiEventQueue.postMessage(msg, 0, 0);
+#endif
+            break;
+
+        default:
+            LOGE("unmatched HDMI_MODE : %d", hdmiMode);
+            break;
+        }
+
+        return;
+    }
+
+    bool SecTVOutService::hdmiCableInserted(void)
+    {
+        return mHdmiCableInserted;
+    }
+
+}
diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h
new file mode 100644
index 0000000..caece73
--- /dev/null
+++ b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h
@@ -0,0 +1,175 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+**
+** @author  Taikyung, Yu(taikyung.yu@samsung.com)
+** @date    2011-07-06
+*/
+
+#ifndef SECTVOUTSERVICE_H
+#define SECTVOUTSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
+
+#include "ISecTVOut.h"
+#include "SecHdmi.h"
+#include "sec_format.h"
+#include "sec_utils_v4l2.h"
+#include "MessageQueue.h"
+
+namespace android {
+//#define CHECK_VIDEO_TIME
+//#define CHECK_UI_TIME
+
+    class SecTVOutService : public BBinder
+    {
+        public :
+            enum {
+                HDMI_MODE_NONE = 0,
+                HDMI_MODE_UI,
+                HDMI_MODE_VIDEO,
+            };
+
+            mutable Mutex mLock;
+
+            class HDMIFlushThread : public Thread {
+                SecTVOutService *mTVOutService;
+            public:
+                HDMIFlushThread(SecTVOutService *service):
+                Thread(false),
+                mTVOutService(service) { }
+                virtual void onFirstRef() {
+                    run("HDMIFlushThread", PRIORITY_URGENT_DISPLAY);
+                }
+                virtual bool threadLoop() {
+                    mTVOutService->HdmiFlushThread();
+                    return false;
+                }
+            };
+
+            sp<HDMIFlushThread> mHdmiFlushThread;
+            int                 HdmiFlushThread();
+
+            mutable MessageQueue    mHdmiEventQueue;
+            bool                mExitHdmiFlushThread;
+
+            SecTVOutService();
+            static int instantiate ();
+            virtual status_t onTransact(uint32_t, const Parcel &, Parcel *, uint32_t);
+            virtual ~SecTVOutService ();
+
+            virtual void                        setHdmiStatus(uint32_t status);
+            virtual void                        setHdmiMode(uint32_t mode);
+            virtual void                        setHdmiResolution(uint32_t resolution);
+            virtual void                        setHdmiHdcp(uint32_t enHdcp);
+            virtual void                        setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer);
+            virtual void                        setHdmiHwcLayer(uint32_t hwcLayer);
+            virtual void                        blit2Hdmi(uint32_t w, uint32_t h,
+                                                uint32_t colorFormat,
+                                                uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr,
+                                                uint32_t dstX, uint32_t dstY,
+                                                uint32_t hdmiMode, uint32_t num_of_hwc_layer);
+            bool                                hdmiCableInserted(void);
+            void                                setLCDsize(void);
+
+        private:
+            SecHdmi                     mSecHdmi;
+            bool                        mHdmiCableInserted;
+            int                         mUILayerMode;
+            uint32_t                    mLCD_width, mLCD_height;
+            uint32_t                    mHwcLayer;
+    };
+
+    class SecHdmiEventMsg : public MessageBase {
+        public:
+            enum {
+                HDMI_MODE_NONE = 0,
+                HDMI_MODE_UI,
+                HDMI_MODE_VIDEO,
+            };
+
+            mutable     Mutex mBlitLock;
+
+            SecHdmi     *pSecHdmi;
+            uint32_t                    mSrcWidth, mSrcHeight;
+            uint32_t                    mSrcColorFormat;
+            uint32_t                    mSrcYAddr, mSrcCbAddr, mSrcCrAddr;
+            uint32_t                    mDstX, mDstY;
+            uint32_t                    mHdmiMode;
+            uint32_t    mHdmiLayer, mHwcLayer;
+
+            SecHdmiEventMsg(SecHdmi *SecHdmi, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcColorFormat,
+                    uint32_t srcYAddr, uint32_t srcCbAddr, uint32_t srcCrAddr,
+                    uint32_t dstX, uint32_t dstY, uint32_t hdmiLayer, uint32_t hwcLayer, uint32_t hdmiMode)
+                : pSecHdmi(SecHdmi), mSrcWidth(srcWidth), mSrcHeight(srcHeight), mSrcColorFormat(srcColorFormat),
+                mSrcYAddr(srcYAddr), mSrcCbAddr(srcCbAddr), mSrcCrAddr(srcCrAddr),
+                mDstX(dstX), mDstY(dstY), mHdmiLayer(hdmiLayer), mHwcLayer(hwcLayer), mHdmiMode(hdmiMode) {
+            }
+
+            virtual bool handler() {
+                Mutex::Autolock _l(mBlitLock);
+                bool ret = true;
+#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME)
+                nsecs_t start, end;
+#endif
+
+                switch (mHdmiMode) {
+                case HDMI_MODE_UI:
+#ifdef CHECK_UI_TIME
+                    start = systemTime();
+#endif
+                    if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr,
+                                mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) {
+                        LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_UI", __func__);
+                        ret = false;
+                    }
+
+#ifdef CHECK_UI_TIME
+                    end = systemTime();
+                    LOGD("[UI] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
+#endif
+                    break;
+                case HDMI_MODE_VIDEO:
+#ifdef CHECK_VIDEO_TIME
+                    start = systemTime();
+#endif
+                    if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr,
+                                mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) {
+                        LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_VIDEO", __func__);
+                        ret = false;
+                    }
+#ifdef CHECK_VIDEO_TIME
+                    end = systemTime();
+                    LOGD("[VIDEO] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
+#endif
+                    break;
+                default:
+                    LOGE("Undefined HDMI_MODE");
+                    ret = false;
+                    break;
+                }
+                return ret;
+            }
+    };
+
+};
+#endif
diff --git a/exynos5/hal/libhdmi/libsForhdmi/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/Android.mk
new file mode 100644
index 0000000..9acbc52
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/Android.mk
@@ -0,0 +1,17 @@
+# 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.
+
+ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),)
+include $(all-subdir-makefiles)
+endif
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk
new file mode 100644
index 0000000..9a4b721
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+
+ifeq ($(BOARD_USES_HDMI),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := libcec.c
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../../../include
+
+LOCAL_MODULE := libcec
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h b/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h
new file mode 100644
index 0000000..4b0d3af
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CEC_H_
+#define _LINUX_CEC_H_
+
+#define CEC_IOC_MAGIC        'c'
+
+/**
+ * CEC device request code to set logical address.
+ */
+#define CEC_IOC_SETLADDR     _IOW(CEC_IOC_MAGIC, 0, unsigned int)
+
+#endif /* _LINUX_CEC_H_ */
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c
new file mode 100644
index 0000000..e688051
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c
@@ -0,0 +1,386 @@
+/*
+* Copyright@ Samsung Electronics Co. LTD
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <cutils/log.h>
+
+/* drv. header */
+#include "cec.h"
+
+#include "libcec.h"
+
+#define CEC_DEBUG 0
+
+/**
+ * @def CEC_DEVICE_NAME
+ * Defines simbolic name of the CEC device.
+ */
+#define CEC_DEVICE_NAME         "/dev/CEC"
+
+static struct {
+    enum CECDeviceType devtype;
+    unsigned char laddr;
+} laddresses[] = {
+    { CEC_DEVICE_RECODER, 1  },
+    { CEC_DEVICE_RECODER, 2  },
+    { CEC_DEVICE_TUNER,   3  },
+    { CEC_DEVICE_PLAYER,  4  },
+    { CEC_DEVICE_AUDIO,   5  },
+    { CEC_DEVICE_TUNER,   6  },
+    { CEC_DEVICE_TUNER,   7  },
+    { CEC_DEVICE_PLAYER,  8  },
+    { CEC_DEVICE_RECODER, 9  },
+    { CEC_DEVICE_TUNER,   10 },
+    { CEC_DEVICE_PLAYER,  11 },
+};
+
+static int CECSetLogicalAddr(unsigned int laddr);
+
+#ifdef CEC_DEBUG
+inline static void CECPrintFrame(unsigned char *buffer, unsigned int size);
+#endif
+
+static int fd = -1;
+
+/**
+ * Open device driver and assign CEC file descriptor.
+ *
+ * @return  If success to assign CEC file descriptor, return 1; otherwise, return 0.
+ */
+int CECOpen()
+{
+    int res = 1;
+
+    if (fd != -1)
+        CECClose();
+
+    if ((fd = open(CEC_DEVICE_NAME, O_RDWR)) < 0) {
+        LOGE("Can't open %s!\n", CEC_DEVICE_NAME);
+        res = 0;
+    }
+
+    return res;
+}
+
+/**
+ * Close CEC file descriptor.
+ *
+ * @return  If success to close CEC file descriptor, return 1; otherwise, return 0.
+ */
+int CECClose()
+{
+    int res = 1;
+
+    if (fd != -1) {
+        if (close(fd) != 0) {
+            LOGE("close() failed!\n");
+            res = 0;
+        }
+        fd = -1;
+    }
+
+    return res;
+}
+
+/**
+ * Allocate logical address.
+ *
+ * @param paddr   [in] CEC device physical address.
+ * @param devtype [in] CEC device type.
+ *
+ * @return new logical address, or 0 if an arror occured.
+ */
+int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype)
+{
+    unsigned char laddr = CEC_LADDR_UNREGISTERED;
+    int i = 0;
+
+    if (fd == -1) {
+        LOGE("open device first!\n");
+        return 0;
+    }
+
+    if (CECSetLogicalAddr(laddr) < 0) {
+        LOGE("CECSetLogicalAddr() failed!\n");
+        return 0;
+    }
+
+    if (paddr == CEC_NOT_VALID_PHYSICAL_ADDRESS)
+        return CEC_LADDR_UNREGISTERED;
+
+    /* send "Polling Message" */
+    while (i < sizeof(laddresses)/sizeof(laddresses[0])) {
+        if (laddresses[i].devtype == devtype) {
+            unsigned char _laddr = laddresses[i].laddr;
+            unsigned char message = ((_laddr << 4) | _laddr);
+            if (CECSendMessage(&message, 1) != 1) {
+                laddr = _laddr;
+                break;
+            }
+        }
+        i++;
+    }
+
+    if (laddr == CEC_LADDR_UNREGISTERED) {
+        LOGE("All LA addresses in use!!!\n");
+        return CEC_LADDR_UNREGISTERED;
+    }
+
+    if (CECSetLogicalAddr(laddr) < 0) {
+        LOGE("CECSetLogicalAddr() failed!\n");
+        return 0;
+    }
+
+    /* broadcast "Report Physical Address" */
+    unsigned char buffer[5];
+    buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
+    buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
+    buffer[2] = (paddr >> 8) & 0xFF;
+    buffer[3] = paddr & 0xFF;
+    buffer[4] = devtype;
+
+    if (CECSendMessage(buffer, 5) != 5) {
+        LOGE("CECSendMessage() failed!\n");
+        return 0;
+    }
+
+    return laddr;
+}
+
+/**
+ * Send CEC message.
+ *
+ * @param *buffer   [in] pointer to buffer address where message located.
+ * @param size      [in] message size.
+ *
+ * @return number of bytes written, or 0 if an arror occured.
+ */
+int CECSendMessage(unsigned char *buffer, int size)
+{
+    if (fd == -1) {
+        LOGE("open device first!\n");
+        return 0;
+    }
+
+    if (size > CEC_MAX_FRAME_SIZE) {
+        LOGE("size should not exceed %d\n", CEC_MAX_FRAME_SIZE);
+        return 0;
+    }
+
+#if CEC_DEBUG
+    LOGI("CECSendMessage() : ");
+    CECPrintFrame(buffer, size);
+#endif
+
+    return write(fd, buffer, size);
+}
+
+/**
+ * Receive CEC message.
+ *
+ * @param *buffer   [in] pointer to buffer address where message will be stored.
+ * @param size      [in] buffer size.
+ * @param timeout   [in] timeout in microseconds.
+ *
+ * @return number of bytes received, or 0 if an arror occured.
+ */
+int CECReceiveMessage(unsigned char *buffer, int size, long timeout)
+{
+    int bytes = 0;
+    fd_set rfds;
+    struct timeval tv;
+    int retval;
+
+    if (fd == -1) {
+        LOGE("open device first!\n");
+        return 0;
+    }
+
+    tv.tv_sec = 0;
+    tv.tv_usec = timeout;
+
+    FD_ZERO(&rfds);
+    FD_SET(fd, &rfds);
+
+    retval = select(fd + 1, &rfds, NULL, NULL, &tv);
+
+    if (retval == -1) {
+        return 0;
+    } else if (retval) {
+        bytes = read(fd, buffer, size);
+#if CEC_DEBUG
+        LOGI("CECReceiveMessage() : size(%d)", bytes);
+        if(bytes > 0)
+            CECPrintFrame(buffer, bytes);
+#endif
+    }
+
+    return bytes;
+}
+
+/**
+ * Set CEC logical address.
+ *
+ * @return 1 if success, otherwise, return 0.
+ */
+int CECSetLogicalAddr(unsigned int laddr)
+{
+    if (ioctl(fd, CEC_IOC_SETLADDR, &laddr)) {
+        LOGE("ioctl(CEC_IOC_SETLA) failed!\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+#if CEC_DEBUG
+/**
+ * Print CEC frame.
+ */
+void CECPrintFrame(unsigned char *buffer, unsigned int size)
+{
+    if (size > 0) {
+        int i;
+        LOGI("fsize: %d ", size);
+        LOGI("frame: ");
+        for (i = 0; i < size; i++)
+            LOGI("0x%02x ", buffer[i]);
+
+        LOGI("\n");
+    }
+}
+#endif
+
+/**
+ * Check CEC message.
+ *
+ * @param opcode   [in] pointer to buffer address where message will be stored.
+ * @param lsrc     [in] buffer size.
+ *
+ * @return 1 if message should be ignored, otherwise, return 0.
+ */
+//TODO: not finished
+int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc)
+{
+    int retval = 0;
+
+    /* if a message coming from address 15 (unregistered) */
+    if (lsrc == CEC_LADDR_UNREGISTERED) {
+        switch (opcode) {
+        case CEC_OPCODE_DECK_CONTROL:
+        case CEC_OPCODE_PLAY:
+            retval = 1;
+        default:
+            break;
+        }
+    }
+
+    return retval;
+}
+
+/**
+ * Check CEC message.
+ *
+ * @param opcode   [in] pointer to buffer address where message will be stored.
+ * @param size     [in] message size.
+ *
+ * @return 0 if message should be ignored, otherwise, return 1.
+ */
+//TODO: not finished
+int CECCheckMessageSize(unsigned char opcode, int size)
+{
+    int retval = 1;
+
+    switch (opcode) {
+    case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+        if (size != 1)
+            retval = 0;
+        break;
+    case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
+        if (size != 2)
+            retval = 0;
+        break;
+    case CEC_OPCODE_PLAY:
+    case CEC_OPCODE_DECK_CONTROL:
+    case CEC_OPCODE_SET_MENU_LANGUAGE:
+    case CEC_OPCODE_ACTIVE_SOURCE:
+    case CEC_OPCODE_ROUTING_INFORMATION:
+    case CEC_OPCODE_SET_STREAM_PATH:
+        if (size != 3)
+            retval = 0;
+        break;
+    case CEC_OPCODE_FEATURE_ABORT:
+    case CEC_OPCODE_DEVICE_VENDOR_ID:
+    case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
+        if (size != 4)
+            retval = 0;
+        break;
+    case CEC_OPCODE_ROUTING_CHANGE:
+        if (size != 5)
+            retval = 0;
+        break;
+    /* CDC - 1.4 */
+    case 0xf8:
+        if (!(size > 5 && size <= 16))
+            retval = 0;
+        break;
+    default:
+        break;
+    }
+
+    return retval;
+}
+
+/**
+ * Check CEC message.
+ *
+ * @param opcode    [in] pointer to buffer address where message will be stored.
+ * @param broadcast [in] broadcast/direct message.
+ *
+ * @return 0 if message should be ignored, otherwise, return 1.
+ */
+//TODO: not finished
+int CECCheckMessageMode(unsigned char opcode, int broadcast)
+{
+    int retval = 1;
+
+    switch (opcode) {
+    case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+    case CEC_OPCODE_SET_MENU_LANGUAGE:
+    case CEC_OPCODE_ACTIVE_SOURCE:
+        if (!broadcast)
+            retval = 0;
+        break;
+    case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+    case CEC_OPCODE_DECK_CONTROL:
+    case CEC_OPCODE_PLAY:
+    case CEC_OPCODE_FEATURE_ABORT:
+    case CEC_OPCODE_ABORT:
+        if (broadcast)
+            retval = 0;
+        break;
+    default:
+        break;
+    }
+
+    return retval;
+}
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h
new file mode 100644
index 0000000..5bbfc15
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBCEC_H_
+#define _LIBCEC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Maximum CEC frame size */
+#define CEC_MAX_FRAME_SIZE                16
+/** Not valid CEC physical address */
+#define CEC_NOT_VALID_PHYSICAL_ADDRESS    0xFFFF
+
+/** CEC broadcast address (as destination address) */
+#define CEC_MSG_BROADCAST        0x0F
+/** CEC unregistered address (as initiator address) */
+#define CEC_LADDR_UNREGISTERED   0x0F
+
+/*
+ * CEC Messages
+ */
+
+//@{
+/** @name Messages for the One Touch Play Feature */
+#define CEC_OPCODE_ACTIVE_SOURCE            0x82
+#define CEC_OPCODE_IMAGE_VIEW_ON            0x04
+#define CEC_OPCODE_TEXT_VIEW_ON             0x0D
+//@}
+
+//@{
+/** @name Messages for the Routing Control Feature */
+#define CEC_OPCODE_INACTIVE_SOURCE          0x9D
+#define CEC_OPCODE_REQUEST_ACTIVE_SOURCE    0x85
+#define CEC_OPCODE_ROUTING_CHANGE           0x80
+#define CEC_OPCODE_ROUTING_INFORMATION      0x81
+#define CEC_OPCODE_SET_STREAM_PATH          0x86
+//@}
+
+//@{
+/** @name Messages for the Standby Feature */
+#define CEC_OPCODE_STANDBY                  0x36
+//@}
+
+//@{
+/** @name Messages for the One Touch Record Feature */
+#define CEC_OPCODE_RECORD_OFF               0x0B
+#define CEC_OPCODE_RECORD_ON                0x09
+#define CEC_OPCODE_RECORD_STATUS            0x0A
+#define CEC_OPCODE_RECORD_TV_SCREEN         0x0F
+//@}
+
+//@{
+/** @name Messages for the Timer Programming Feature */
+#define CEC_OPCODE_CLEAR_ANALOGUE_TIMER     0x33
+#define CEC_OPCODE_CLEAR_DIGITAL_TIMER      0x99
+#define CEC_OPCODE_CLEAR_EXTERNAL_TIMER     0xA1
+#define CEC_OPCODE_SET_ANALOGUE_TIMER       0x34
+#define CEC_OPCODE_SET_DIGITAL_TIMER        0x97
+#define CEC_OPCODE_SET_EXTERNAL_TIMER       0xA2
+#define CEC_OPCODE_SET_TIMER_PROGRAM_TITLE  0x67
+#define CEC_OPCODE_TIMER_CLEARED_STATUS     0x43
+#define CEC_OPCODE_TIMER_STATUS             0x35
+//@}
+
+//@{
+/** @name Messages for the System Information Feature */
+#define CEC_OPCODE_CEC_VERSION              0x9E
+#define CEC_OPCODE_GET_CEC_VERSION          0x9F
+#define CEC_OPCODE_GIVE_PHYSICAL_ADDRESS    0x83
+#define CEC_OPCODE_GET_MENU_LANGUAGE        0x91
+//#define CEC_OPCODE_POLLING_MESSAGE
+#define CEC_OPCODE_REPORT_PHYSICAL_ADDRESS  0x84
+#define CEC_OPCODE_SET_MENU_LANGUAGE        0x32
+//@}
+
+//@{
+/** @name Messages for the Deck Control Feature */
+#define CEC_OPCODE_DECK_CONTROL             0x42
+#define CEC_OPCODE_DECK_STATUS              0x1B
+#define CEC_OPCODE_GIVE_DECK_STATUS         0x1A
+#define CEC_OPCODE_PLAY                     0x41
+//@}
+
+//@{
+/** @name Messages for the Tuner Control Feature */
+#define CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS 0x08
+#define CEC_OPCODE_SELECT_ANALOGUE_SERVICE  0x92
+#define CEC_OPCODE_SELECT_DIGITAL_SERVICE   0x93
+#define CEC_OPCODE_TUNER_DEVICE_STATUS      0x07
+#define CEC_OPCODE_TUNER_STEP_DECREMENT     0x06
+#define CEC_OPCODE_TUNER_STEP_INCREMENT     0x05
+//@}
+
+//@{
+/** @name Messages for the Vendor Specific Commands Feature */
+#define CEC_OPCODE_DEVICE_VENDOR_ID         0x87
+#define CEC_OPCODE_GET_DEVICE_VENDOR_ID     0x8C
+#define CEC_OPCODE_VENDOR_COMMAND           0x89
+#define CEC_OPCODE_VENDOR_COMMAND_WITH_ID   0xA0
+#define CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN 0x8A
+#define CEC_OPCODE_VENDOR_REMOVE_BUTTON_UP  0x8B
+//@}
+
+//@{
+/** @name Messages for the OSD Display Feature */
+#define CEC_OPCODE_SET_OSD_STRING           0x64
+//@}
+
+//@{
+/** @name Messages for the Device OSD Transfer Feature */
+#define CEC_OPCODE_GIVE_OSD_NAME            0x46
+#define CEC_OPCODE_SET_OSD_NAME             0x47
+//@}
+
+//@{
+/** @name Messages for the Device Menu Control Feature */
+#define CEC_OPCODE_MENU_REQUEST             0x8D
+#define CEC_OPCODE_MENU_STATUS              0x8E
+#define CEC_OPCODE_USER_CONTROL_PRESSED     0x44
+#define CEC_OPCODE_USER_CONTROL_RELEASED    0x45
+//@}
+
+//@{
+/** @name Messages for the Remote Control Passthrough Feature */
+//@}
+
+//@{
+/** @name Messages for the Power Status Feature */
+#define CEC_OPCODE_GIVE_DEVICE_POWER_STATUS 0x8F
+#define CEC_OPCODE_REPORT_POWER_STATUS      0x90
+//@}
+
+//@{
+/** @name Messages for General Protocol messages */
+#define CEC_OPCODE_FEATURE_ABORT            0x00
+#define CEC_OPCODE_ABORT                    0xFF
+//@}
+
+//@{
+/** @name Messages for the System Audio Control Feature */
+#define CEC_OPCODE_GIVE_AUDIO_STATUS        0x71
+#define CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7D
+#define CEC_OPCODE_REPORT_AUDIO_STATUS      0x7A
+#define CEC_OPCODE_SET_SYSTEM_AUDIO_MODE    0x72
+#define CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST 0x70
+#define CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS 0x7E
+//@}
+
+//@{
+/** @name Messages for the Audio Rate Control Feature */
+#define CEC_OPCODE_SET_AUDIO_RATE           0x9A
+//@}
+
+//@{
+/** @name CEC Operands */
+
+//TODO: not finished
+
+#define CEC_DECK_CONTROL_MODE_STOP      0x03
+#define CEC_PLAY_MODE_PLAY_FORWARD      0x24
+//@}
+
+/**
+ * @enum CECDeviceType
+ * Type of CEC device
+ */
+enum CECDeviceType {
+    /** TV */
+    CEC_DEVICE_TV,
+    /** Recording Device */
+    CEC_DEVICE_RECODER,
+    /** Tuner */
+    CEC_DEVICE_TUNER,
+    /** Playback Device */
+    CEC_DEVICE_PLAYER,
+    /** Audio System */
+    CEC_DEVICE_AUDIO,
+};
+
+int CECOpen();
+int CECClose();
+int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype);
+int CECSendMessage(unsigned char *buffer, int size);
+int CECReceiveMessage(unsigned char *buffer, int size, long timeout);
+
+int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc);
+int CECCheckMessageSize(unsigned char opcode, int size);
+int CECCheckMessageMode(unsigned char opcode, int broadcast);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBCEC_H_ */
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk
new file mode 100644
index 0000000..99af09b
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk
@@ -0,0 +1,49 @@
+# 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.
+
+ifeq ($(BOARD_USES_HDMI),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := libddc.c
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../../../include
+
+ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_7)
+LOCAL_CFLAGS  += -DDDC_CH_I2C_7
+endif
+
+ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_1)
+LOCAL_CFLAGS  += -DDDC_CH_I2C_1
+endif
+
+ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_2)
+LOCAL_CFLAGS  += -DDDC_CH_I2C_2
+endif
+
+ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_8)
+LOCAL_CFLAGS  += -DDDC_CH_I2C_8
+endif
+
+LOCAL_MODULE := libddc
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c
new file mode 100644
index 0000000..4e6e374
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c
@@ -0,0 +1,289 @@
+/*
+* Copyright@ Samsung Electronics Co. LTD
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/i2c.h>
+#include <cutils/log.h>
+#include "i2c-dev.h"
+
+#include "libddc.h"
+
+#define DDC_DEBUG 0
+
+/**
+ * @brief DDC device name.
+ * User should change this.
+ */
+#ifdef DDC_CH_I2C_1
+#define DEV_NAME    "/dev/i2c-1"
+#endif
+
+#ifdef DDC_CH_I2C_2
+#define DEV_NAME    "/dev/i2c-2"
+#endif
+
+#ifdef DDC_CH_I2C_7
+#define DEV_NAME    "/dev/i2c-7"
+#endif
+
+#ifdef DDC_CH_I2C_8
+#define DEV_NAME    "/dev/i2c-8"
+#endif
+
+/**
+ * DDC file descriptor
+ */
+static int ddc_fd = -1;
+
+/**
+ * Reference count of DDC file descriptor
+ */
+static unsigned int ref_cnt = 0;
+
+/**
+ * Check if DDC file is already opened or not
+ * @return  If DDC file is already opened, return 1; Otherwise, return 0.
+ */
+static int DDCFileAvailable()
+{
+    return (ddc_fd < 0) ? 0 : 1;
+}
+
+/**
+ * Initialze DDC library. Open DDC device
+ * @return  If succeed in opening DDC device or it is already opened, return 1;@n
+ *         Otherwise, return 0.
+ */
+int DDCOpen()
+{
+    int ret = 1;
+
+    // check already open??
+    if (ref_cnt > 0) {
+        ref_cnt++;
+        return 1;
+    }
+
+    // open
+    if ((ddc_fd = open(DEV_NAME,O_RDWR)) < 0) {
+        LOGE("%s: Cannot open I2C_DDC : %s",__func__, DEV_NAME);
+        ret = 0;
+    }
+
+    ref_cnt++;
+    return ret;
+}
+
+/**
+ * Finalize DDC library. Close DDC device
+ * @return  If succeed in closing DDC device or it is being used yet, return 1;@n
+ *          Otherwise, return 0.
+ */
+int DDCClose()
+{
+    int ret = 1;
+    // check if fd is available
+    if (ref_cnt == 0) {
+#if DDC_DEBUG
+        LOGE("%s: I2C_DDC is not available!!!!", __func__);
+#endif
+        return 1;
+    }
+
+    // close
+    if (ref_cnt > 1) {
+        ref_cnt--;
+        return 1;
+    }
+
+    if (close(ddc_fd) < 0) {
+#if DDC_DEBUG
+        LOGE("%s: Cannot close I2C_DDC : %s",__func__,DEV_NAME);
+#endif
+        ret = 0;
+    }
+
+    ref_cnt--;
+    ddc_fd = -1;
+
+    return ret;
+}
+
+/**
+ * Read data though DDC. For more information of DDC, refer DDC Spec.
+ * @param   addr    [in]    Device address
+ * @param   offset  [in]    Byte offset
+ * @param   size    [in]    Sizes of data
+ * @param   buffer  [out]   Pointer to buffer to store data
+ * @return  If succeed in reading, return 1; Otherwise, return 0.
+ */
+int DDCRead(unsigned char addr, unsigned char offset,
+            unsigned int size, unsigned char* buffer)
+{
+    struct i2c_rdwr_ioctl_data msgset;
+    struct i2c_msg msgs[2];
+    int ret = 1;
+
+    if (!DDCFileAvailable()) {
+#if DDC_DEBUG
+        LOGE("%s: I2C_DDC is not available!!!!", __func__);
+#endif
+        return 0;
+    }
+
+    // set offset
+    msgs[0].addr = addr>>1;
+    msgs[0].flags = 0;
+    msgs[0].len = 1;
+    msgs[0].buf = &offset;
+
+    // read data
+    msgs[1].addr = addr>>1;
+    msgs[1].flags = I2C_M_RD;
+    msgs[1].len = size;
+    msgs[1].buf = buffer;
+
+    // set rdwr ioctl data
+    msgset.nmsgs = 2;
+    msgset.msgs = msgs;
+
+    // i2c fast read
+    if ((ret = ioctl(ddc_fd, I2C_RDWR, &msgset)) < 0) {
+        perror("ddc error:");
+        ret = 0;
+    }
+
+    return ret;
+}
+
+/**
+ * Read data though E-DDC. For more information of E-DDC, refer E-DDC Spec.
+ * @param   segpointer  [in]    Segment pointer
+ * @param   segment     [in]    Segment number
+ * @param   addr        [in]    Device address
+ * @param   offset      [in]    Byte offset
+ * @param   size        [in]    Sizes of data
+ * @param   buffer      [out]   Pointer to buffer to store data
+ * @return  If succeed in reading, return 1; Otherwise, return 0.
+ */
+
+int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr,
+  unsigned char offset, unsigned int size, unsigned char* buffer)
+{
+    struct i2c_rdwr_ioctl_data msgset;
+    struct i2c_msg msgs[3];
+    int ret = 1;
+
+    if (!DDCFileAvailable()) {
+#if DDC_DEBUG
+        LOGE("%s: I2C_DDC is not available!!!!", __func__);
+#endif
+        return 0;
+    }
+
+    // set segment pointer
+    msgs[0].addr  = segpointer>>1;
+    // ignore ack only if segment is "0"
+    if (segment == 0)
+        msgs[0].flags = I2C_M_IGNORE_NAK;
+    else
+        msgs[0].flags = 0;
+
+    msgs[0].len   = 1;
+    msgs[0].buf   = &segment;
+
+    // set offset
+    msgs[1].addr  = addr>>1;
+    msgs[1].flags = 0;
+    msgs[1].len   = 1;
+    msgs[1].buf   = &offset;
+
+    // read data
+    msgs[2].addr  = addr>>1;
+    msgs[2].flags = I2C_M_RD;
+    msgs[2].len   = size;
+    msgs[2].buf   = buffer;
+
+    msgset.nmsgs = 3;
+    msgset.msgs  = msgs;
+
+    // eddc read
+    if (ioctl(ddc_fd, I2C_RDWR, &msgset) < 0) {
+#if DDC_DEBUG
+        LOGE("%s: ioctl(I2C_RDWR) failed!!!", __func__);
+#endif
+        ret = 0;
+    }
+    return ret;
+}
+
+/**
+ * Write data though DDC. For more information of DDC, refer DDC Spec.
+ * @param   addr    [in]    Device address
+ * @param   offset  [in]    Byte offset
+ * @param   size    [in]    Sizes of data
+ * @param   buffer  [out]   Pointer to buffer to write
+ * @return  If succeed in writing, return 1; Otherwise, return 0.
+ */
+int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer)
+{
+    unsigned char* temp;
+    int bytes;
+    int retval = 0;
+
+    // allocate temporary buffer
+    temp = (unsigned char*) malloc((size+1)*sizeof(unsigned char));
+    if (!temp) {
+        LOGE("%s: not enough resources at %s", __FUNCTION__);
+        goto exit;
+    }
+
+    temp[0] = offset;
+    memcpy(temp+1,buffer,size);
+
+    if (!DDCFileAvailable()) {
+        LOGE("%s: I2C_DDC is not available!!!!", __func__);
+        goto exit;
+    }
+
+    if (ioctl(ddc_fd, I2C_SLAVE, addr>>1) < 0) {
+        LOGE("%s: cannot set slave address 0x%02x", __func__,addr);
+        goto exit;
+    }
+
+    // write temp buffer
+    if ((bytes = write(ddc_fd,temp,size+1)) != (size+1)) {
+        LOGE("%s: fail to write %d bytes, only write %d bytes",__func__, size, bytes);
+        goto exit;
+    }
+
+    retval = 1;
+
+exit:
+    // free temp buffer
+    if (temp)
+        free(temp);
+
+    return retval;
+}
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h
new file mode 100644
index 0000000..368855b
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBDDC_H_
+#define _LIBDDC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int DDCOpen();
+int DDCRead(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer);
+int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer);
+int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr,
+  unsigned char offset, unsigned int size, unsigned char* buffer);
+int DDCClose();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBDDC_H_ */
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk
new file mode 100644
index 0000000..602ae4d
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk
@@ -0,0 +1,34 @@
+# 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.
+
+ifeq ($(BOARD_USES_HDMI),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := liblog libddc
+LOCAL_SRC_FILES := libedid.c
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/../../../include
+
+LOCAL_MODULE := libedid
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h b/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h
new file mode 100644
index 0000000..aea1309
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _EDID_H_
+#define _EDID_H_
+
+//@{
+/**
+ * @name EDID Addresses
+ */
+#define EDID_ADDR                                       (0xA0)
+#define EDID_SEGMENT_POINTER                            (0x60)
+//@}
+
+//@{
+/**
+ * @name EDID offset and bit values
+ */
+#define SIZEOFBYTE                                      (8)
+#define SIZEOFEDIDBLOCK                                 (0x80)
+#define EDID_EXTENSION_NUMBER_POS                       (0x7E)
+
+#define EDID_TIMING_EXT_TAG_ADDR_POS                    (0)
+#define EDID_TIMING_EXT_REV_NUMBER_POS                  (1)
+#define EDID_DETAILED_TIMING_OFFSET_POS                 (2)
+#define EDID_DATA_BLOCK_START_POS                       (4)
+
+// for Extension Data Block
+#define EDID_TIMING_EXT_TAG_VAL                         (0x02)
+#define EDID_BLOCK_MAP_EXT_TAG_VAL                      (0xF0)
+
+#define EDID_SHORT_AUD_DEC_TAG_VAL                      (1<<5)
+#define EDID_SHORT_VID_DEC_TAG_VAL                      (2<<5)
+#define EDID_VSDB_TAG_VAL                               (3<<5)
+#define EDID_SPEAKER_ALLOCATION_TAG_VAL                 (4<<5)
+#define EDID_VESA_DTC_TAG_VAL                           (5<<5)
+#define EDID_RESERVED_TAG_VAL                           (6<<5)
+
+#define EDID_EXTENDED_TAG_VAL                           (7<<5)
+#define EDID_EXTENDED_COLORIMETRY_VAL                   (5)
+#define EDID_EXTENDED_COLORIMETRY_BLOCK_LEN             (3)
+
+#define EDID_TAG_CODE_MASK                              (1<<7 | 1<<6 | 1<<5)
+#define EDID_DATA_BLOCK_SIZE_MASK                       (1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0)
+
+#define EDID_VSDB_MIN_LENGTH_VAL                        (5)
+
+// for Established Timings
+#define EDID_ET_POS                                     (0x23)
+#define EDID_ET_640x480p_VAL                            (0x20)
+
+// for DTD
+#define EDID_DTD_START_ADDR                             (0x36)
+#define EDID_DTD_BYTE_LENGTH                            (18)
+#define EDID_DTD_TOTAL_LENGTH                           (EDID_DTD_BYTE_LENGTH*4)
+
+#define EDID_DTD_PIXELCLOCK_POS1                        (0)
+#define EDID_DTD_PIXELCLOCK_POS2                        (1)
+
+#define EDID_DTD_HBLANK_POS1                            (3)
+#define EDID_DTD_HBLANK_POS2                            (4)
+#define EDID_DTD_HBLANK_POS2_MASK                       (0xF)
+
+#define EDID_DTD_HACTIVE_POS1                           (2)
+#define EDID_DTD_HACTIVE_POS2                           (4)
+#define EDID_DTD_HACTIVE_POS2_MASK                      (0xF0)
+
+#define EDID_DTD_VBLANK_POS1                            (6)
+#define EDID_DTD_VBLANK_POS2                            (7)
+#define EDID_DTD_VBLANK_POS2_MASK                       (0x0F)
+
+#define EDID_DTD_VACTIVE_POS1                           (5)
+#define EDID_DTD_VACTIVE_POS2                           (7)
+#define EDID_DTD_VACTIVE_POS2_MASK                      (0xF0)
+
+#define EDID_DTD_INTERLACE_POS                          (17)
+#define EDID_DTD_INTERLACE_MASK                         (1<<7)
+
+// for SVD
+#define EDID_SVD_VIC_MASK                               (0x7F)
+
+// for CS
+#define EDID_COLOR_SPACE_POS                            (3)
+#define EDID_YCBCR444_CS_MASK                           (1<<5)
+#define EDID_YCBCR422_CS_MASK                           (1<<4)
+
+// for Color Depth
+#define EDID_DC_48_VAL                                  (1<<6)
+#define EDID_DC_36_VAL                                  (1<<5)
+#define EDID_DC_30_VAL                                  (1<<4)
+#define EDID_DC_YCBCR_VAL                               (1<<3)
+
+#define EDID_DC_POS                                     (6)
+#define EDID_DC_MASK                                    (EDID_DC_48_VAL | EDID_DC_36_VAL| EDID_DC_30_VAL | EDID_DC_YCBCR_VAL)
+
+// for colorimetry
+#define EDID_XVYCC601_MASK                              (1<<0)
+#define EDID_XVYCC709_MASK                              (1<<1)
+#define EDID_EXTENDED_MASK                              (1<<0|1<<1|1<<2)
+
+// for SAD
+#define SHORT_AUD_DESCRIPTOR_LPCM                       (1<<0)
+#define SHORT_AUD_DESCRIPTOR_AC3                        (1<<1)
+#define SHORT_AUD_DESCRIPTOR_MPEG1                      (1<<2)
+#define SHORT_AUD_DESCRIPTOR_MP3                        (1<<3)
+#define SHORT_AUD_DESCRIPTOR_MPEG2                      (1<<4)
+#define SHORT_AUD_DESCRIPTOR_AAC                        (1<<5)
+#define SHORT_AUD_DESCRIPTOR_DTS                        (1<<6)
+#define SHORT_AUD_DESCRIPTOR_ATRAC                      (1<<7)
+
+#define EDID_SAD_CODE_MASK                              (1<<6 | 1<<5 | 1<<4 | 1<<3)
+#define EDID_SAD_CHANNEL_MASK                           (1<<2 | 1<<1 | 1<<0)
+#define EDID_SAD_192KHZ_MASK                            (1<<6)
+#define EDID_SAD_176KHZ_MASK                            (1<<5)
+#define EDID_SAD_96KHZ_MASK                             (1<<4)
+#define EDID_SAD_88KHZ_MASK                             (1<<3)
+#define EDID_SAD_48KHZ_MASK                             (1<<2)
+#define EDID_SAD_44KHZ_MASK                             (1<<1)
+#define EDID_SAD_32KHZ_MASK                             (1<<0)
+
+#define EDID_SAD_WORD_24_MASK                           (1<<2)
+#define EDID_SAD_WORD_20_MASK                           (1<<1)
+#define EDID_SAD_WORD_16_MASK                           (1<<0)
+
+// for CEC
+#define EDID_CEC_PHYICAL_ADDR                           (4)
+
+// for 3D
+#define EDID_HDMI_EXT_POS                               (8)
+#define EDID_HDMI_VIDEO_PRESENT_MASK                    (1<<5)
+
+// latency
+#define EDID_HDMI_LATENCY_MASK                          (1<<7|1<<6)
+#define EDID_HDMI_LATENCY_POS                           (6)
+
+#define EDID_HDMI_3D_PRESENT_POS                        (13)
+#define EDID_HDMI_3D_PRESENT_MASK                       (1<<7)
+#define EDID_HDMI_3D_MULTI_PRESENT_MASK                 (1<<6 | 1<<5)
+#define EDID_HDMI_3D_MULTI_PRESENT_BIT                  5
+
+#define EDID_3D_STRUCTURE_ONLY_EXIST                    (1<<5)
+#define EDID_3D_STRUCTURE_MASK_EXIST                    (1<<6)
+
+#define EDID_3D_STRUCTURE_FP                            (0)
+#define EDID_3D_STRUCTURE_FA                            (1)
+#define EDID_3D_STRUCTURE_LA                            (2)
+#define EDID_3D_STRUCTURE_SSF                           (3)
+#define EDID_3D_STRUCTURE_LD                            (4)
+#define EDID_3D_STRUCTURE_LDGFX                         (5)
+#define EDID_3D_STRUCTURE_TB                            (6)
+#define EDID_3D_STRUCTURE_SSH                           (8)
+
+#define EDID_HDMI_EXT_LENGTH_POS                        (14)
+#define EDID_HDMI_VSDB_VIC_LEN_BIT                      (5)
+#define EDID_HDMI_VSDB_VIC_LEN_MASK                     (1<<7|1<<6|1<<5)
+#define EDID_HDMI_VSDB_3D_LEN_MASK                      (1<<4|1<<3|1<<2|1<<1|1<<0)
+
+#define EDID_HDMI_2D_VIC_ORDER_MASK                     (1<<7|1<<6|1<<5|1<<4)
+#define EDID_HDMI_3D_STRUCTURE_MASK                     (1<<3|1<<2|1<<1|1<<0)
+
+// for MAX TMDS
+#define EDID_MAX_TMDS_POS                               (7)
+
+// for 3D Structure
+#define NUM_OF_VIC_FOR_3D                               16
+//@}
+
+#endif /* _EDID_H_ */
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c
new file mode 100644
index 0000000..c6bed50
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c
@@ -0,0 +1,1265 @@
+/*
+* Copyright@ Samsung Electronics Co. LTD
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <cutils/log.h>
+
+#include "edid.h"
+#include "libedid.h"
+#include "../libddc/libddc.h"
+
+//#define EDID_DEBUG 1
+
+#ifdef EDID_DEBUG
+#define DPRINTF(args...)    LOGI(args)
+#else
+#define DPRINTF(args...)
+#endif
+
+#define NUM_OF_VIC_FOR_3D           16
+
+/**
+ * @var gEdidData
+ * Pointer to EDID data
+ */
+static unsigned char* gEdidData;
+
+/**
+ * @var gExtensions
+ * Number of EDID extensions
+ */
+static int gExtensions;
+
+
+/**
+ * @var aVIC
+ * This contains first 16 VIC in EDID
+ */
+static unsigned char aVIC[NUM_OF_VIC_FOR_3D];
+
+//! Structure for parsing video timing parameter in EDID
+static const struct edid_params {
+    /** H Total */
+    unsigned int HTotal;
+
+    /** H Blank */
+    unsigned int HBlank;
+
+    /** V Total */
+    unsigned int VTotal;
+
+    /** V Blank */
+    unsigned int VBlank;
+
+    /** CEA VIC */
+    unsigned char  VIC;
+
+    /** CEA VIC for 16:9 aspect ratio */
+    unsigned char  VIC16_9;
+
+    /** 0 if progressive, 1 if interlaced */
+    unsigned char  interlaced;
+
+    /** Pixel frequency */
+    enum PixelFreq PixelClock;
+} aVideoParams[] =
+{
+    { 800 , 160 , 525 , 45, 1 , 1 , 0, PIXEL_FREQ_25_200 ,},        // v640x480p_60Hz
+    { 858 , 138 , 525 , 45, 2 , 3 , 0, PIXEL_FREQ_27_027 ,},        // v720x480p_60Hz
+    { 1650, 370 , 750 , 30, 4 , 4 , 0, PIXEL_FREQ_74_250 ,},        // v1280x720p_60Hz
+    { 2200, 280 , 1125, 22, 5 , 5 , 1, PIXEL_FREQ_74_250 ,},        // v1920x1080i_60H
+    { 1716, 276 , 525 , 22, 6 , 7 , 1, PIXEL_FREQ_74_250 ,},        // v720x480i_60Hz
+    { 1716, 276 , 262 , 22, 8 , 9 , 0, PIXEL_FREQ_27_027 ,},        // v720x240p_60Hz
+    //{ 1716, 276 , 263 , 23, 8 , 9 , 0, PIXEL_FREQ_27_027 , },     // v720x240p_60Hz(mode 2)
+    { 3432, 552 , 525 , 22, 10, 11, 1, PIXEL_FREQ_54_054 , },       // v2880x480i_60Hz
+    { 3432, 552 , 262 , 22, 12, 13, 0, PIXEL_FREQ_54_054 , },       // v2880x240p_60Hz
+    //{ 3432, 552 , 263 , 23, 12, 13, 0, PIXEL_FREQ_54_054 , },     // v2880x240p_60Hz(mode 2)
+    { 1716, 276 , 525 , 45, 14, 15, 0, PIXEL_FREQ_54_054 , },       // v1440x480p_60Hz
+    { 2200, 280 , 1125, 45, 16, 16, 0, PIXEL_FREQ_148_500, },       // v1920x1080p_60H
+    { 864 , 144 , 625 , 49, 17, 18, 0, PIXEL_FREQ_27 , },           // v720x576p_50Hz
+    { 1980, 700 , 750 , 30, 19, 19, 0, PIXEL_FREQ_74_250 , },       // v1280x720p_50Hz
+    { 2640, 720 , 1125, 22, 20, 20, 1, PIXEL_FREQ_74_250 , },       // v1920x1080i_50H
+    { 1728, 288 , 625 , 24, 21, 22, 1, PIXEL_FREQ_27 , },           // v720x576i_50Hz
+    { 1728, 288 , 312 , 24, 23, 24, 0, PIXEL_FREQ_27 , },           // v720x288p_50Hz
+    //{ 1728, 288 , 313 , 25, 23, 24, 0, PIXEL_FREQ_27 , },         // v720x288p_50Hz(mode 2)
+    //{ 1728, 288 , 314 , 26, 23, 24, 0, PIXEL_FREQ_27 , },         // v720x288p_50Hz(mode 3)
+    { 3456, 576 , 625 , 24, 25, 26, 1, PIXEL_FREQ_54 , },           // v2880x576i_50Hz
+    { 3456, 576 , 312 , 24, 27, 28, 0, PIXEL_FREQ_54 , },           // v2880x288p_50Hz
+    //{ 3456, 576 , 313 , 25, 27, 28, 0, PIXEL_FREQ_54 , },         // v2880x288p_50Hz(mode 2)
+    //{ 3456, 576 , 314 , 26, 27, 28, 0, PIXEL_FREQ_54 , },         // v2880x288p_50Hz(mode 3)
+    { 1728, 288 , 625 , 49, 29, 30, 0, PIXEL_FREQ_54 , },           // v1440x576p_50Hz
+    { 2640, 720 , 1125, 45, 31, 31, 0, PIXEL_FREQ_148_500,},        // v1920x1080p_50Hz
+    { 2750, 830 , 1125, 45, 32, 32, 0, PIXEL_FREQ_74_250 ,},        // v1920x1080p_24Hz
+    { 2640, 720 , 1125, 45, 33, 33, 0, PIXEL_FREQ_74_250 ,},        // v1920x1080p_25Hz
+    { 2200, 280 , 1125, 45, 34, 34, 0, PIXEL_FREQ_74_250 ,},        // v1920x1080p_30Hz
+    { 3432, 552 , 525 , 45, 35, 36, 0, PIXEL_FREQ_108_108,},        // v2880x480p_60Hz
+    { 3456, 576 , 625 , 49, 37, 38, 0, PIXEL_FREQ_108 ,},           // v2880x576p_50Hz
+    { 2304, 384 , 1250, 85, 39, 39, 1, PIXEL_FREQ_72 ,},            // v1920x1080i_50Hz(1250)
+    { 2640, 720 , 1125, 22, 40, 40, 1, PIXEL_FREQ_148_500, },       // v1920x1080i_100Hz
+    { 1980, 700 , 750 , 30, 41, 41, 0, PIXEL_FREQ_148_500, },       // v1280x720p_100Hz
+    { 864 , 144 , 625 , 49, 42, 43, 0, PIXEL_FREQ_54 , },           // v720x576p_100Hz
+    { 1728, 288 , 625 , 24, 44, 45, 1, PIXEL_FREQ_54 , },           // v720x576i_100Hz
+    { 2200, 280 , 1125, 22, 46, 46, 1, PIXEL_FREQ_148_500, },       // v1920x1080i_120Hz
+    { 1650, 370 , 750 , 30, 47, 47, 0, PIXEL_FREQ_148_500, },       // v1280x720p_120Hz
+    { 858 , 138 , 525 , 54, 48, 49, 0, PIXEL_FREQ_54_054 , },       // v720x480p_120Hz
+    { 1716, 276 , 525 , 22, 50, 51, 1, PIXEL_FREQ_54_054 , },       // v720x480i_120Hz
+    { 864 , 144 , 625 , 49, 52, 53, 0, PIXEL_FREQ_108 , },          // v720x576p_200Hz
+    { 1728, 288 , 625 , 24, 54, 55, 1, PIXEL_FREQ_108 , },          // v720x576i_200Hz
+    { 858 , 138 , 525 , 45, 56, 57, 0, PIXEL_FREQ_108_108, },       // v720x480p_240Hz
+    { 1716, 276 , 525 , 22, 58, 59, 1, PIXEL_FREQ_108_108, },       // v720x480i_240Hz
+    // PHY Freq is not available yet
+    //{ 3300, 2020, 750 , 30, 60, 60, 0, PIXEL_FREQ_59_400 ,},      // v1280x720p24Hz
+    { 3960, 2680, 750 , 30, 61, 61, 0, PIXEL_FREQ_74_250 , },       // v1280x720p25Hz
+    { 3300, 2020, 750 , 30, 62, 62, 0, PIXEL_FREQ_74_250 ,},        // v1280x720p30Hz
+    // PHY Freq is not available yet
+    //{ 2200, 280 , 1125, 45, 63, 63, 0, PIXEL_FREQ_297, },         // v1920x1080p120Hz
+    //{ 2640, 720 , 1125, 45, 64, 64, 0, PIXEL_FREQ_297, },         // v1920x1080p100Hz
+    //{ 4400, 560 , 2250, 90,  1, 1, 0, 0,  PIXEL_FREQ_297, },      // v4Kx2K30Hz
+};
+
+//! Structure for Checking 3D Mandatory Format in EDID
+static const struct edid_3d_mandatory {
+    /** video Format */
+    enum VideoFormat resolution;
+
+    /** 3D Structure */
+    enum HDMI3DVideoStructure hdmi_3d_format;
+} edid_3d [] =
+{
+    { v1920x1080p_24Hz, HDMI_3D_FP_FORMAT },    // 1920x1080p @ 23.98/24Hz
+    { v1280x720p_60Hz, HDMI_3D_FP_FORMAT },     // 1280x720p @ 59.94/60Hz
+    { v1920x1080i_60Hz, HDMI_3D_SSH_FORMAT },   // 1920x1080i @ 59.94/60Hz
+    { v1920x1080p_24Hz, HDMI_3D_TB_FORMAT },    // 1920x1080p @ 23.98/24Hz
+    { v1280x720p_60Hz, HDMI_3D_TB_FORMAT },     // 1280x720p @ 59.94/60Hz
+    { v1280x720p_50Hz, HDMI_3D_FP_FORMAT },     // 1280x720p @ 50Hz
+    { v1920x1080i_50Hz, HDMI_3D_SSH_FORMAT },   // 1920x1080i @ 50Hz
+    { v1280x720p_50Hz, HDMI_3D_TB_FORMAT },     // 1280x720p @ 50Hz
+};
+
+/**
+ * Calculate a checksum.
+ *
+ * @param   buffer  [in]    Pointer to data to calculate a checksum
+ * @param   size    [in]    Sizes of data
+ *
+ * @return  If checksum result is 0, return 1; Otherwise, return 0.
+ */
+static int CalcChecksum(const unsigned char* const buffer, const int size)
+{
+    unsigned char i,sum;
+    int ret = 1;
+
+    // check parameter
+    if (buffer == NULL ) {
+        DPRINTF("invalid parameter : buffer\n");
+        return 0;
+    }
+    for (sum = 0, i = 0 ; i < size; i++)
+        sum += buffer[i];
+
+    // check checksum
+    if (sum != 0)
+        ret = 0;
+
+    return ret;
+}
+
+/**
+ * Read EDID Block(128 bytes)
+ *
+ * @param   blockNum    [in]    Number of block to read @n
+ *                  For example, EDID block = 0, EDID first Extension = 1, and so on.
+ * @param   outBuffer   [out]   Pointer to buffer to store EDID data
+ *
+ * @return  If fail to read, return 0; Otherwise, return 1.
+ */
+static int ReadEDIDBlock(const unsigned int blockNum, unsigned char* const outBuffer)
+{
+    int segNum, offset, dataPtr;
+
+    // check parameter
+    if (outBuffer == NULL) {
+        DPRINTF("invalid parameter : outBuffer\n");
+        return 0;
+    }
+
+    // calculate
+    segNum = blockNum / 2;
+    offset = (blockNum % 2) * SIZEOFEDIDBLOCK;
+    dataPtr = (blockNum) * SIZEOFEDIDBLOCK;
+
+    // read block
+    if (!EDDCRead(EDID_SEGMENT_POINTER, segNum, EDID_ADDR, offset, SIZEOFEDIDBLOCK, outBuffer)) {
+        DPRINTF("Fail to Read %dth EDID Block\n", blockNum);
+        return 0;
+    }
+
+    if (!CalcChecksum(outBuffer, SIZEOFEDIDBLOCK)) {
+        DPRINTF("CheckSum fail : %dth EDID Block\n", blockNum);
+        return 0;
+    }
+
+    // print data
+#ifdef EDID_DEBUG
+    offset = 0;
+    do {
+        LOGI("0x%02X", outBuffer[offset++]);
+        if (offset % 16)
+            LOGI(" ");
+        else
+            LOGI("\n");
+    } while (SIZEOFEDIDBLOCK > offset);
+#endif // EDID_DEBUG
+    return 1;
+}
+
+/**
+ * Check if EDID data is valid or not.
+ *
+ * @return  if EDID data is valid, return 1; Otherwise, return 0.
+ */
+static inline int EDIDValid(void)
+{
+    return (gEdidData == NULL) ?  0 : 1;
+}
+
+/**
+ * Search HDMI Vender Specific Data Block(VSDB) in EDID extension block.
+ *
+ * @param   extension   [in]    the number of EDID extension block to check
+ *
+ * @return  if there is a HDMI VSDB, return the offset from start of @n
+ *        EDID extension block. if there is no VSDB, return 0.
+ */
+static int GetVSDBOffset(const int extension)
+{
+    unsigned int BlockOffset = extension*SIZEOFEDIDBLOCK;
+    unsigned int offset = BlockOffset + EDID_DATA_BLOCK_START_POS;
+    unsigned int tag,blockLen,DTDOffset;
+
+    if (!EDIDValid() || (extension > gExtensions)) {
+        DPRINTF("EDID Data is not available\n");
+        return 0;
+    }
+
+    DTDOffset = gEdidData[BlockOffset + EDID_DETAILED_TIMING_OFFSET_POS];
+
+    // check if there is HDMI VSDB
+    while (offset < BlockOffset + DTDOffset) {
+        // find the block tag and length
+        // tag
+        tag = gEdidData[offset] & EDID_TAG_CODE_MASK;
+        // block len
+        blockLen = (gEdidData[offset] & EDID_DATA_BLOCK_SIZE_MASK) + 1;
+
+        // check if it is HDMI VSDB
+        // if so, check identifier value, if it's hdmi vsbd - return offset
+        if (tag == EDID_VSDB_TAG_VAL &&
+            gEdidData[offset+1] == 0x03 &&
+            gEdidData[offset+2] == 0x0C &&
+            gEdidData[offset+3] == 0x0 &&
+            blockLen > EDID_VSDB_MIN_LENGTH_VAL )
+            return offset;
+
+        // else find next block
+        offset += blockLen;
+    }
+
+    // return error
+    return 0;
+}
+
+/**
+ * Check if Sink supports the HDMI mode.
+ * @return  If Sink supports HDMI mode, return 1; Otherwise, return 0.
+ */
+static int CheckHDMIMode(void)
+{
+    int i;
+
+    // read EDID
+    if (!EDIDRead())
+        return 0;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++)
+        if (GetVSDBOffset(i) > 0) // if there is a VSDB, it means RX support HDMI mode
+            return 1;
+
+    return 0;
+}
+
+/**
+ * Check if EDID extension block is timing extension block or not.
+ * @param   extension   [in] The number of EDID extension block to check
+ * @return  If the block is timing extension, return 1; Otherwise, return 0.
+ */
+static int IsTimingExtension(const int extension)
+{
+    int ret = 0;
+    if (!EDIDValid() || (extension > gExtensions)) {
+        DPRINTF("EDID Data is not available\n");
+        return ret;
+    }
+
+    if (gEdidData[extension*SIZEOFEDIDBLOCK] == EDID_TIMING_EXT_TAG_VAL) {
+        // check extension revsion number
+        // revision num == 3
+        if (gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] == 3)
+            ret = 1;
+        // revison num != 3 && DVI mode
+        else if (!CheckHDMIMode() &&
+                gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] != 2)
+            ret = 1;
+    }
+    return ret;
+}
+
+/**
+ * Check if the video format is contained in - @n
+ * Detailed Timing Descriptor(DTD) of EDID extension block.
+ * @param   extension   [in]    Number of EDID extension block to check
+ * @param   videoFormat [in]    Video format to check
+ * @return  If the video format is contained in DTD of EDID extension block, -@n
+ *        return 1; Otherwise, return 0.
+ */
+static int IsContainVideoDTD(const int extension,const enum VideoFormat videoFormat)
+{
+    int i, StartOffset, EndOffset;
+
+    if (!EDIDValid() || (extension > gExtensions)) {
+        DPRINTF("EDID Data is not available\n");
+        return 0;
+    }
+
+    // if edid block( 0th block )
+    if (extension == 0) {
+        StartOffset = EDID_DTD_START_ADDR;
+        EndOffset = StartOffset + EDID_DTD_TOTAL_LENGTH;
+    } else { // if edid extension block
+        StartOffset = extension*SIZEOFEDIDBLOCK + gEdidData[extension*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS];
+        EndOffset = (extension+1)*SIZEOFEDIDBLOCK;
+    }
+
+    // check DTD(Detailed Timing Description)
+    for (i = StartOffset; i < EndOffset; i+= EDID_DTD_BYTE_LENGTH) {
+        unsigned int hblank = 0, hactive = 0, vblank = 0, vactive = 0, interlaced = 0, pixelclock = 0;
+        unsigned int vHActive = 0, vVActive = 0, vVBlank = 0;
+
+        // get pixel clock
+        pixelclock = (gEdidData[i+EDID_DTD_PIXELCLOCK_POS2] << SIZEOFBYTE);
+        pixelclock |= gEdidData[i+EDID_DTD_PIXELCLOCK_POS1];
+
+        if (!pixelclock)
+            continue;
+
+        // get HBLANK value in pixels
+        hblank = gEdidData[i+EDID_DTD_HBLANK_POS2] & EDID_DTD_HBLANK_POS2_MASK;
+        hblank <<= SIZEOFBYTE; // lower 4 bits
+        hblank |= gEdidData[i+EDID_DTD_HBLANK_POS1];
+
+        // get HACTIVE value in pixels
+        hactive = gEdidData[i+EDID_DTD_HACTIVE_POS2] & EDID_DTD_HACTIVE_POS2_MASK;
+        hactive <<= (SIZEOFBYTE/2); // upper 4 bits
+        hactive |= gEdidData[i+EDID_DTD_HACTIVE_POS1];
+
+        // get VBLANK value in pixels
+        vblank = gEdidData[i+EDID_DTD_VBLANK_POS2] & EDID_DTD_VBLANK_POS2_MASK;
+        vblank <<= SIZEOFBYTE; // lower 4 bits
+        vblank |= gEdidData[i+EDID_DTD_VBLANK_POS1];
+
+        // get VACTIVE value in pixels
+        vactive = gEdidData[i+EDID_DTD_VACTIVE_POS2] & EDID_DTD_VACTIVE_POS2_MASK;
+        vactive <<= (SIZEOFBYTE/2); // upper 4 bits
+        vactive |= gEdidData[i+EDID_DTD_VACTIVE_POS1];
+
+        vHActive = aVideoParams[videoFormat].HTotal - aVideoParams[videoFormat].HBlank;
+        if (aVideoParams[videoFormat].interlaced == 1) {
+            if (aVideoParams[videoFormat].VIC == v1920x1080i_50Hz_1250) { // VTOP and VBOT are same
+                vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2)/2;
+                vVBlank = aVideoParams[videoFormat].VBlank;
+            } else {
+                vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2 - 1)/2;
+                vVBlank = aVideoParams[videoFormat].VBlank;
+            }
+        } else {
+            vVActive = aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank;
+            vVBlank = aVideoParams[videoFormat].VBlank;
+        }
+
+        // get Interlaced Mode Value
+        interlaced = (int)(gEdidData[i+EDID_DTD_INTERLACE_POS] & EDID_DTD_INTERLACE_MASK);
+        if (interlaced)
+            interlaced = 1;
+
+        DPRINTF("EDID: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n"
+                            ,hblank,vblank,hactive,vactive);
+        DPRINTF("REQ: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n"
+                            ,aVideoParams[videoFormat].HBlank
+                            ,vVBlank,vHActive,vVActive);
+
+        if (hblank == aVideoParams[videoFormat].HBlank && vblank == vVBlank // blank
+            && hactive == vHActive && vactive == vVActive) { //line
+            unsigned int EDIDpixelclock = aVideoParams[videoFormat].PixelClock;
+            EDIDpixelclock /= 100; pixelclock /= 100;
+
+            if (pixelclock == EDIDpixelclock) {
+                DPRINTF("Sink Support the Video mode\n");
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**
+ * Check if a VIC(Video Identification Code) is contained in -@n
+ * EDID extension block.
+ * @param   extension   [in]    Number of EDID extension block to check
+ * @param   VIC      [in]   VIC to check
+ * @return  If the VIC is contained in contained in EDID extension block, -@n
+ *        return 1; Otherwise, return 0.
+ */
+static int IsContainVIC(const int extension, const int VIC)
+{
+    unsigned int StartAddr = extension*SIZEOFEDIDBLOCK;
+    unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS;
+    unsigned int tag,blockLen;
+    unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS];
+
+    if (!EDIDValid() || (extension > gExtensions)) {
+        DPRINTF("EDID Data is not available\n");
+        return 0;
+    }
+
+    // while
+    while (ExtAddr < StartAddr + DTDStartAddr) {
+        // find the block tag and length
+        // tag
+        tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK;
+        // block len
+        blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1;
+        DPRINTF("tag = %d\n",tag);
+        DPRINTF("blockLen = %d\n",blockLen-1);
+
+        // check if it is short video description
+        if (tag == EDID_SHORT_VID_DEC_TAG_VAL) {
+            // if so, check SVD
+            unsigned int i;
+            for (i = 1; i < blockLen; i++) {
+                DPRINTF("EDIDVIC = %d\n",gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK);
+                DPRINTF("VIC = %d\n",VIC);
+
+                // check VIC with SVDB
+                if (VIC == (gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK)) {
+                    DPRINTF("Sink Device supports requested video mode\n");
+                    return 1;
+                }
+            }
+        }
+        // else find next block
+        ExtAddr += blockLen;
+    }
+
+    return 0;
+}
+
+/**
+ * Check if EDID contains the video format.
+ * @param   videoFormat [in]    Video format to check
+ * @param   pixelRatio  [in]    Pixel aspect ratio of video format to check
+ * @return  if EDID contains the video format, return 1; Otherwise, return 0.
+ */
+static int CheckResolution(const enum VideoFormat videoFormat,
+                            const enum PixelAspectRatio pixelRatio)
+{
+    int i, vic;
+
+    // read EDID
+    if (!EDIDRead())
+        return 0;
+
+    // check ET(Established Timings) for 640x480p@60Hz
+    if (videoFormat == v640x480p_60Hz // if it's 640x480p@60Hz
+        && (gEdidData[EDID_ET_POS] & EDID_ET_640x480p_VAL)) // it support
+         return 1;
+
+    // check STI(Standard Timing Identification)
+    // do not need
+
+    // check DTD(Detailed Timing Description) of EDID block(0th)
+    if (IsContainVideoDTD(0,videoFormat))
+        return 1;
+
+    // check EDID Extension
+    vic = (pixelRatio == HDMI_PIXEL_RATIO_16_9) ?
+            aVideoParams[videoFormat].VIC16_9 : aVideoParams[videoFormat].VIC;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i)) // if it's timing block
+            if (IsContainVIC(i, vic) || IsContainVideoDTD(i, videoFormat))
+                return 1;
+    }
+
+    return 0;
+}
+
+/**
+ * Check if EDID supports the color depth.
+ * @param   depth [in]  Color depth
+ * @param   space [in]  Color space
+ * @return  If EDID supports the color depth, return 1; Otherwise, return 0.
+ */
+static int CheckColorDepth(const enum ColorDepth depth,const enum ColorSpace space)
+{
+    int i;
+    unsigned int StartAddr;
+
+    // if color depth == 24 bit, no need to check
+    if (depth == HDMI_CD_24)
+        return 1;
+
+    // check EDID data is valid or not
+    // read EDID
+    if (!EDIDRead())
+        return 0;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i) // if it's timing block
+            && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block
+            int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK;
+            if (blockLength >= EDID_DC_POS) {
+                // get supported DC value
+                int deepColor = gEdidData[StartAddr + EDID_DC_POS] & EDID_DC_MASK;
+                DPRINTF("EDID deepColor = %x\n",deepColor);
+                // check supported DeepColor
+                // if YCBCR444
+                if (space == HDMI_CS_YCBCR444) {
+                    if ( !(deepColor & EDID_DC_YCBCR_VAL))
+                        return 0;
+                }
+
+                // check colorDepth
+                switch (depth) {
+                case HDMI_CD_36:
+                    deepColor &= EDID_DC_36_VAL;
+                    break;
+                case HDMI_CD_30:
+                    deepColor &= EDID_DC_30_VAL;
+                    break;
+                case HDMI_CD_24:
+                    deepColor = 1;
+                    break;
+                default :
+                    deepColor = 0;
+                }
+                if (deepColor)
+                    return 1;
+                else
+                    return 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Check if EDID supports the color space.
+ * @param   space [in]  Color space
+ * @return  If EDID supports the color space, return 1; Otherwise, return 0.
+ */
+static int CheckColorSpace(const enum ColorSpace space)
+{
+    int i;
+
+    // RGB is default
+    if (space == HDMI_CS_RGB)
+        return 1;
+
+    // check EDID data is valid or not
+    // read EDID
+    if (!EDIDRead())
+        return 0;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i)) { // if it's timing block
+            // read Color Space
+            int CS = gEdidData[i*SIZEOFEDIDBLOCK + EDID_COLOR_SPACE_POS];
+
+            if ((space == HDMI_CS_YCBCR444 && (CS & EDID_YCBCR444_CS_MASK)) || // YCBCR444
+                    (space == HDMI_CS_YCBCR422 && (CS & EDID_YCBCR422_CS_MASK))) // YCBCR422
+                return 1;
+        }
+    }
+    return 0;
+}
+
+/**
+ * Check if EDID supports the colorimetry.
+ * @param   color [in]  Colorimetry
+ * @return  If EDID supports the colorimetry, return 1; Otherwise, return 0.
+ */
+static int CheckColorimetry(const enum HDMIColorimetry color)
+{
+    int i;
+
+    // do not need to parse if not extended colorimetry
+    if (color == HDMI_COLORIMETRY_NO_DATA ||
+            color == HDMI_COLORIMETRY_ITU601 ||
+            color == HDMI_COLORIMETRY_ITU709)
+        return 1;
+
+    // read EDID
+    if (!EDIDRead())
+       return 0;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i)) { // if it's timing block
+            // check address
+            unsigned int ExtAddr = i*SIZEOFEDIDBLOCK + EDID_DATA_BLOCK_START_POS;
+            unsigned int EndAddr = i*SIZEOFEDIDBLOCK + gEdidData[i*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS];
+            unsigned int tag,blockLen;
+
+            while (ExtAddr < EndAddr) {
+                // find the block tag and length
+                // tag
+                tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK;
+                // block len
+                blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1;
+
+                // check if it is colorimetry block
+                if (tag == EDID_EXTENDED_TAG_VAL && // extended tag
+                    gEdidData[ExtAddr+1] == EDID_EXTENDED_COLORIMETRY_VAL && // colorimetry block
+                    (blockLen-1) == EDID_EXTENDED_COLORIMETRY_BLOCK_LEN) { // check length
+                    // get supported DC value
+                    int colorimetry = (gEdidData[ExtAddr + 2]);
+                    int metadata = (gEdidData[ExtAddr + 3]);
+
+                    DPRINTF("EDID extened colorimetry = %x\n",colorimetry);
+                    DPRINTF("EDID gamut metadata profile = %x\n",metadata);
+
+                    // check colorDepth
+                    switch (color) {
+                    case HDMI_COLORIMETRY_EXTENDED_xvYCC601:
+                        if (colorimetry & EDID_XVYCC601_MASK && metadata)
+                            return 1;
+                        break;
+                    case HDMI_COLORIMETRY_EXTENDED_xvYCC709:
+                        if (colorimetry & EDID_XVYCC709_MASK && metadata)
+                            return 1;
+                        break;
+                    default:
+                        break;
+                    }
+                    return 0;
+                }
+                // else find next block
+                ExtAddr += blockLen;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Get Max TMDS clock that HDMI Rx can receive.
+ * @return  If available, return MaxTMDS clock; Otherwise, return 0.
+ */
+static unsigned int GetMaxTMDS(void)
+{
+    int i;
+    unsigned int StartAddr;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i) // if it's timing block
+            && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block
+            int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK;
+            if (blockLength >= EDID_MAX_TMDS_POS) {
+                // get supported DC value
+                return gEdidData[StartAddr + EDID_MAX_TMDS_POS];
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Save first 16 VIC of EDID
+ */
+static void SaveVIC(void)
+{
+    int extension;
+    int vic_count = 0;
+    for (extension = 1; extension <= gExtensions && vic_count < NUM_OF_VIC_FOR_3D; extension++) {
+        unsigned int StartAddr = extension*SIZEOFEDIDBLOCK;
+        unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS;
+        unsigned int tag,blockLen;
+        unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS];
+
+        while (ExtAddr < StartAddr + DTDStartAddr) {
+            // find the block tag and length
+            // tag
+            tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK;
+            // block len
+            blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1;
+
+            // check if it is short video description
+            if (tag == EDID_SHORT_VID_DEC_TAG_VAL) {
+                // if so, check SVD
+                unsigned int edid_index;
+                for (edid_index = 1; edid_index < blockLen && vic_count < NUM_OF_VIC_FOR_3D; edid_index++) {
+                    DPRINTF("EDIDVIC = %d\r\n", gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK);
+
+                    // check VIC with SVDB
+                    aVIC[vic_count++] = (gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK);
+                }
+            }
+            // else find next block
+            ExtAddr += blockLen;
+        }
+    }
+}
+
+/**
+ * Check if Rx supports requested 3D format.
+ * @param   pVideo [in]   HDMI Video Parameter
+ * @return  If Rx supports requested 3D format, return 1; Otherwise, return 0.
+ */
+static int EDID3DFormatSupport(const struct HDMIVideoParameter * const pVideo)
+{
+    int edid_index;
+    unsigned int StartAddr;
+    unsigned int vic;
+    vic = (pVideo->pixelAspectRatio == HDMI_PIXEL_RATIO_16_9) ?
+            aVideoParams[pVideo->resolution].VIC16_9 : aVideoParams[pVideo->resolution].VIC;
+
+    // if format == 2D, no need to check
+    if (pVideo->hdmi_3d_format == HDMI_2D_VIDEO_FORMAT)
+        return 1;
+
+    // check EDID data is valid or not
+    if (!EDIDRead())
+        return 0;
+
+    // save first 16 VIC to check
+    SaveVIC();
+
+    // find VSDB
+    for (edid_index = 1; edid_index <= gExtensions; edid_index++) {
+        if (IsTimingExtension(edid_index) // if it's timing block
+            && ((StartAddr = GetVSDBOffset(edid_index)) > 0)) { // check block
+            unsigned int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK;
+            unsigned int VSDBHdmiVideoPre = 0;
+            unsigned int VSDB3DPresent = 0;
+            unsigned int VSDB3DMultiPresent = 0;
+            unsigned int HDMIVICLen;
+            unsigned int HDMI3DLen;
+            int Hdmi3DStructure = 0;
+            unsigned int Hdmi3DMask = 0xFFFF;
+            unsigned int latency_offset = 0;
+
+            DPRINTF("VSDB Block length[0x%x] = 0x%x\r\n",StartAddr,blockLength);
+
+            // get HDMI Video Present  value
+            if (blockLength >= EDID_HDMI_EXT_POS) {
+                VSDBHdmiVideoPre = gEdidData[StartAddr + EDID_HDMI_EXT_POS]
+                            & EDID_HDMI_VIDEO_PRESENT_MASK;
+                DPRINTF("EDID HDMI Video Present = 0x%x\n",VSDBHdmiVideoPre);
+            } else { // data related to 3D format is not available
+                return 0;
+            }
+
+            // check if latency field is available
+            latency_offset = (gEdidData[StartAddr + EDID_HDMI_EXT_POS]
+                                                        & EDID_HDMI_LATENCY_MASK) >> EDID_HDMI_LATENCY_POS;
+            if (latency_offset == 0)
+                latency_offset = 4;
+            else if (latency_offset == 3)
+                latency_offset = 0;
+            else
+                latency_offset = 2;
+
+            StartAddr -= latency_offset;
+
+            // HDMI_VIC_LEN
+            HDMIVICLen = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS]
+                    & EDID_HDMI_VSDB_VIC_LEN_MASK) >> EDID_HDMI_VSDB_VIC_LEN_BIT;
+
+            if (pVideo->hdmi_3d_format == HDMI_VIC_FORMAT) {
+                if (HDMIVICLen) {
+                    for (edid_index = 0; edid_index < (int)HDMIVICLen; edid_index++) {
+                        if (vic == gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + edid_index])
+                            return 1;
+                    }
+                    return 0;
+                } else {
+                    return 0;
+                }
+            }
+
+            // HDMI_3D_LEN
+            HDMI3DLen = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS]
+                        & EDID_HDMI_VSDB_3D_LEN_MASK;
+
+            DPRINTF("HDMI VIC LENGTH[%x] = %x\r\n",
+                                    StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMIVICLen);
+            DPRINTF("HDMI 3D LENGTH[%x] = %x\r\n",
+                                    StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMI3DLen);
+
+            // check 3D_Present bit
+            if (blockLength >= (EDID_HDMI_3D_PRESENT_POS - latency_offset)) {
+                VSDB3DPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS]
+                                & EDID_HDMI_3D_PRESENT_MASK;
+                VSDB3DMultiPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS]
+                                & EDID_HDMI_3D_MULTI_PRESENT_MASK;
+            }
+
+            if (VSDB3DPresent) {
+                DPRINTF("VSDB 3D Present!!!\r\n");
+                // check with 3D madatory format
+                if (CheckResolution(pVideo->resolution, pVideo->pixelAspectRatio)) {
+                    int size = sizeof(edid_3d)/sizeof(struct edid_3d_mandatory);
+                    for (edid_index = 0; edid_index < size; edid_index++) {
+                        if (edid_3d[edid_index].resolution == pVideo->resolution &&
+                            edid_3d[edid_index].hdmi_3d_format == pVideo->hdmi_3d_format )
+                            return 1;
+                    }
+                }
+            }
+
+            // check 3D_Multi_Present bit
+            if (VSDB3DMultiPresent) {
+                DPRINTF("VSDB 3D Multi Present!!! = 0x%02x\r\n",VSDB3DMultiPresent);
+                // 3D Structure only
+                if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_ONLY_EXIST) {
+                    // 3D Structure All
+                    Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8);
+                    Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2];
+                    DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure);
+                }
+
+                // 3D Structure and Mask
+                if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_MASK_EXIST) {
+                    // 3D Structure All
+                    Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8);
+                    Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2];
+                    // 3D Structure Mask
+                    Hdmi3DMask |= (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 3] << 8);
+                    Hdmi3DMask |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 4];
+                    DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure);
+                    DPRINTF("VSDB 3D Mask!!! = [0x%02x]\r\n",Hdmi3DMask);
+                    DPRINTF("Current 3D Video format!!! = [%d]\r\n",pVideo->hdmi_3d_format);
+                    DPRINTF("Current 3D Video format!!! = [0x%02x]\r\n",1<<pVideo->hdmi_3d_format);
+                }
+
+                // check 3D Structure and Mask
+                if (Hdmi3DStructure & (1<<pVideo->hdmi_3d_format)) {
+                    DPRINTF("VSDB 3D Structure Contains Current Video Structure!!!\r\n");
+                    // check first 16 EDID
+                    for (edid_index = 0; edid_index < NUM_OF_VIC_FOR_3D; edid_index++) {
+                        DPRINTF("VIC = %d, EDID Vic = %d!!!\r\n",vic,aVIC[edid_index]);
+                        if (Hdmi3DMask & (1<<edid_index)) {
+                            if (vic == aVIC[edid_index]) {
+                                DPRINTF("VSDB 3D Mask Contains Current Video format!!!\r\n");
+                                return 1;
+                            }
+                        }
+                    }
+                }
+            }
+
+            // check block length if HDMI_VIC or HDMI Multi available
+            if (blockLength >= (EDID_HDMI_EXT_LENGTH_POS - latency_offset)) {
+                unsigned int HDMI3DExtLen = HDMI3DLen - (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT)*2;
+                unsigned int VICOrder;
+
+                // check if there is 3D extra data ?
+                //TODO: check 3D_Detail in case of SSH
+                if (HDMI3DExtLen) {
+                    // check HDMI 3D Extra Data
+                    for (edid_index = 0; edid_index < (int)(HDMI3DExtLen / 2); edid_index++) {
+                        VICOrder = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen +
+                                          (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2]
+                                                    & EDID_HDMI_2D_VIC_ORDER_MASK;
+                        VICOrder = (1<<VICOrder);
+                        Hdmi3DStructure = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen +
+                                                 (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2]
+                                                 & EDID_HDMI_3D_STRUCTURE_MASK;
+                        Hdmi3DStructure = (1<<Hdmi3DStructure);
+                        if (Hdmi3DStructure == pVideo->hdmi_3d_format && vic == aVIC[VICOrder])
+                            return 1;
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Initialize EDID library. This will intialize DDC library.
+ * @return  If success, return 1; Otherwise, return 0.
+ */
+int EDIDOpen(void)
+{
+    // init DDC
+    return DDCOpen();
+}
+
+/**
+ * Finalize EDID library. This will finalize DDC library.
+ * @return  If success, return 1; Otherwise, return 0.
+ */
+int EDIDClose(void)
+{
+    // reset EDID
+    EDIDReset();
+
+    // close EDDC
+    return DDCClose();
+}
+
+/**
+ * Read EDID data of Rx.
+ * @return If success, return 1; Otherwise, return 0;
+ */
+int EDIDRead(void)
+{
+    int block,dataPtr;
+    unsigned char temp[SIZEOFEDIDBLOCK];
+
+    // if already read??
+    if (EDIDValid())
+        return 1;
+
+    // read EDID Extension Number
+    // read EDID
+    if (!ReadEDIDBlock(0,temp))
+        return 0;
+
+    // get extension
+    gExtensions = temp[EDID_EXTENSION_NUMBER_POS];
+
+    // prepare buffer
+    gEdidData = (unsigned char*)malloc((gExtensions+1)*SIZEOFEDIDBLOCK);
+    if (!gEdidData)
+        return 0;
+
+    // copy EDID Block 0
+    memcpy(gEdidData,temp,SIZEOFEDIDBLOCK);
+
+    // read EDID Extension
+    for (block = 1,dataPtr = SIZEOFEDIDBLOCK; block <= gExtensions; block++,dataPtr+=SIZEOFEDIDBLOCK) {
+        // read extension 1~gExtensions
+        if (!ReadEDIDBlock(block, gEdidData+dataPtr)) {
+            // reset buffer
+            EDIDReset();
+            return 0;
+        }
+    }
+
+    // check if extension is more than 1, and first extension block is not block map.
+    if (gExtensions > 1 && gEdidData[SIZEOFEDIDBLOCK] != EDID_BLOCK_MAP_EXT_TAG_VAL) {
+        // reset buffer
+        DPRINTF("EDID has more than 1 extension but, first extension block is not block map\n");
+        EDIDReset();
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * Reset stored EDID data.
+ */
+void EDIDReset(void)
+{
+    if (gEdidData) {
+        free(gEdidData);
+        gEdidData = NULL;
+        DPRINTF("\t\t\t\tEDID is reset!!!\n");
+    }
+}
+
+/**
+ * Get CEC physical address.
+ * @param   outAddr [out]   CEC physical address. LSB 2 bytes is available. [0:0:AB:CD]
+ * @return  If success, return 1; Otherwise, return 0.
+ */
+int EDIDGetCECPhysicalAddress(int* const outAddr)
+{
+    int i;
+    unsigned int StartAddr;
+
+    // check EDID data is valid or not
+    // read EDID
+    if (!EDIDRead())
+        return 0;
+
+    // find VSDB
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i) // if it's timing block
+            && (StartAddr = GetVSDBOffset(i)) > 0) { // check block
+            // get supported DC value
+            // int tempDC1 = (int)(gEdidData[tempAddr+EDID_DC_POS]);
+            int phyAddr = gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR] << 8;
+            phyAddr |= gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR+1];
+
+            DPRINTF("phyAddr = %x\n",phyAddr);
+
+            *outAddr = phyAddr;
+
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Check if Rx supports HDMI/DVI mode or not.
+ * @param   video [in]   HDMI or DVI mode to check
+ * @return  If Rx supports requested mode, return 1; Otherwise, return 0.
+ */
+int EDIDHDMIModeSupport(struct HDMIVideoParameter * const video)
+{
+    // check if read edid?
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+
+    // check hdmi mode
+    if (video->mode == HDMI) {
+        if (!CheckHDMIMode()) {
+            DPRINTF("HDMI mode Not Supported\n");
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**
+ * Check if Rx supports requested video resoultion or not.
+ * @param   video [in]   Video parameters to check
+ * @return  If Rx supports video parameters, return 1; Otherwise, return 0.
+ */
+int EDIDVideoResolutionSupport(struct HDMIVideoParameter * const video)
+{
+    unsigned int TMDSClock;
+    unsigned int MaxTMDS = 0;
+
+    // check if read edid?
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+
+    // get max tmds
+    MaxTMDS = GetMaxTMDS()*5;
+
+    // Check MAX TMDS
+    TMDSClock = aVideoParams[video->resolution].PixelClock/100;
+    if (video->colorDepth == HDMI_CD_36)
+        TMDSClock *= 1.5;
+    else if (video->colorDepth == HDMI_CD_30)
+        TMDSClock *=1.25;
+
+    DPRINTF("MAX TMDS = %d, Current TMDS = %d\n",MaxTMDS, TMDSClock);
+    if (MaxTMDS != 0 && MaxTMDS < TMDSClock) {
+        DPRINTF("Pixel clock is beyond Maximun TMDS in EDID\n");
+        return 0;
+    }
+
+    // check resolution
+    if (!CheckResolution(video->resolution,video->pixelAspectRatio)) {
+        DPRINTF("Video Resolution Not Supported\n");
+        return 0;
+    }
+
+    // check 3D format
+    if (!EDID3DFormatSupport(video)) {
+        DPRINTF("3D Format Not Supported\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * Check if Rx supports requested color depth or not.
+ * @param   video [in]   Video parameters to check
+ * @return  If Rx supports video parameters, return 1; Otherwise, return 0.
+ */
+int EDIDColorDepthSupport(struct HDMIVideoParameter * const video)
+{
+    // check if read edid?
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+
+    // check resolution
+    if (!CheckColorDepth(video->colorDepth,video->colorSpace)) {
+        DPRINTF("Color Depth Not Supported\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * Check if Rx supports requested color space or not.
+ * @param   video [in]   Video parameters to check
+ * @return  If Rx supports video parameters, return 1; Otherwise, return 0.
+ */
+int EDIDColorSpaceSupport(struct HDMIVideoParameter * const video)
+{
+    // check if read edid?
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+    // check color space
+    if (!CheckColorSpace(video->colorSpace)) {
+        DPRINTF("Color Space Not Supported\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * Check if Rx supports requested colorimetry or not.
+ * @param   video [in]   Video parameters to check
+ * @return  If Rx supports video parameters, return 1; Otherwise, return 0.
+ */
+int EDIDColorimetrySupport(struct HDMIVideoParameter * const video)
+{
+    // check if read edid?
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+
+    // check colorimetry
+    if (!CheckColorimetry(video->colorimetry)) {
+        DPRINTF("Colorimetry Not Supported\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * Check if Rx supports requested audio parameters or not.
+ * @param   audio [in]   Audio parameters to check
+ * @return  If Rx supports audio parameters, return 1; Otherwise, return 0.
+ */
+int EDIDAudioModeSupport(struct HDMIAudioParameter * const audio)
+{
+    int i;
+
+    // read EDID
+    if (!EDIDRead()) {
+        DPRINTF("EDID Read Fail!!!\n");
+        return 0;
+    }
+
+    // check EDID Extension
+    // find timing block
+    for (i = 1; i <= gExtensions; i++) {
+        if (IsTimingExtension(i)) { // if it's timing block
+            // find Short Audio Description
+            unsigned int StartAddr = i*SIZEOFEDIDBLOCK;
+            unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS;
+            unsigned int tag,blockLen;
+            unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS];
+
+            while (ExtAddr < StartAddr + DTDStartAddr) {
+                // find the block tag and length
+                // tag
+                tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK;
+                // block len
+                blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1;
+
+                DPRINTF("tag = %d\n",tag);
+                DPRINTF("blockLen = %d\n",blockLen-1);
+
+                // check if it is short video description
+                if (tag == EDID_SHORT_AUD_DEC_TAG_VAL) {
+                    // if so, check SAD
+                    unsigned int j, channelNum;
+                    int audioFormat,sampleFreq,wordLen;
+                    for (j = 1; j < blockLen; j += 3) {
+                        audioFormat = gEdidData[ExtAddr+j] & EDID_SAD_CODE_MASK;
+                        channelNum = gEdidData[ExtAddr+j] & EDID_SAD_CHANNEL_MASK;
+                        sampleFreq = gEdidData[ExtAddr+j+1];
+                        wordLen = gEdidData[ExtAddr+j+2];
+
+                        DPRINTF("request = %d, EDIDAudioFormatCode = %d\n",(audio->formatCode)<<3, audioFormat);
+                        DPRINTF("request = %d, EDIDChannelNumber= %d\n",(audio->channelNum)-1, channelNum);
+                        DPRINTF("request = %d, EDIDSampleFreq= %d\n",1<<(audio->sampleFreq), sampleFreq);
+                        DPRINTF("request = %d, EDIDWordLeng= %d\n",1<<(audio->wordLength), wordLen);
+
+                        // check parameter
+                        // check audioFormat
+                        if (audioFormat & ( (audio->formatCode) << 3) &&  // format code
+                                channelNum >= ( (audio->channelNum) -1) &&  // channel number
+                                (sampleFreq & (1<<(audio->sampleFreq)))) { // sample frequency
+                            if (audioFormat == LPCM_FORMAT) { // check wordLen
+                                int ret = 0;
+                                switch (audio->wordLength) {
+                                case WORD_16:
+                                case WORD_17:
+                                case WORD_18:
+                                case WORD_19:
+                                case WORD_20:
+                                    ret = wordLen & (1<<1);
+                                    break;
+                                case WORD_21:
+                                case WORD_22:
+                                case WORD_23:
+                                case WORD_24:
+                                    ret = wordLen & (1<<2);
+                                    break;
+                                }
+                                return ret;
+                            }
+                            return 1; // if not LPCM
+                        }
+                    }
+                }
+                // else find next block
+                ExtAddr += blockLen;
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h
new file mode 100644
index 0000000..dfd3096
--- /dev/null
+++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBEDID_H_
+#define _LIBEDID_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "video.h"
+#include "audio.h"
+
+int EDIDOpen(void);
+int EDIDRead(void);
+void EDIDReset(void);
+int EDIDHDMIModeSupport(struct HDMIVideoParameter *video);
+int EDIDVideoResolutionSupport(struct HDMIVideoParameter *video);
+int EDIDColorDepthSupport(struct HDMIVideoParameter *video);
+int EDIDColorSpaceSupport(struct HDMIVideoParameter *video);
+int EDIDColorimetrySupport(struct HDMIVideoParameter *video);
+int EDIDAudioModeSupport(struct HDMIAudioParameter *audio);
+int EDIDGetCECPhysicalAddress(int* outAddr);
+int EDIDClose(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _LIBEDID_H_ */