summaryrefslogtreecommitdiffstats
path: root/exynos4/hal/libhdmi
diff options
context:
space:
mode:
Diffstat (limited to 'exynos4/hal/libhdmi')
-rw-r--r--exynos4/hal/libhdmi/Android.mk17
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/Android.mk88
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp1957
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h138
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp2434
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h132
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/fimd_api.c229
-rw-r--r--exynos4/hal/libhdmi/SecHdmi/fimd_api.h51
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/Android.mk126
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/Barrier.h55
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp111
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h74
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp197
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h126
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp148
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h86
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp387
-rw-r--r--exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h174
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/Android.mk17
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk33
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h11
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c386
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h209
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk45
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c285
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h35
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk34
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h181
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c1262
-rw-r--r--exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h42
30 files changed, 9070 insertions, 0 deletions
diff --git a/exynos4/hal/libhdmi/Android.mk b/exynos4/hal/libhdmi/Android.mk
new file mode 100644
index 0000000..237c53c
--- /dev/null
+++ b/exynos4/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 exynos4,$(TARGET_BOARD_PLATFORM)),)
+include $(all-subdir-makefiles)
+endif
diff --git a/exynos4/hal/libhdmi/SecHdmi/Android.mk b/exynos4/hal/libhdmi/SecHdmi/Android.mk
new file mode 100644
index 0000000..e728309
--- /dev/null
+++ b/exynos4/hal/libhdmi/SecHdmi/Android.mk
@@ -0,0 +1,88 @@
+# 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 \
+ fimd_api.c
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
+
+ifeq ($(TARGET_SOC),exynos4210)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+LOCAL_CFLAGS += \
+ -DSCREEN_WIDTH=$(SCREEN_WIDTH) \
+ -DSCREEN_HEIGHT=$(SCREEN_HEIGHT) \
+ -DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM)
+
+LOCAL_SHARED_LIBRARIES += libfimc
+
+ifeq ($(BOARD_USES_HDMI_SUBTITLES),true)
+LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES
+endif
+
+ifeq ($(BOARD_USES_FIMGAPI),true)
+LOCAL_CFLAGS += -DBOARD_USES_FIMGAPI
+LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/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
+
+ifeq ($(BOARD_USE_V4L2),true)
+LOCAL_CFLAGS += -DBOARD_USE_V4L2
+endif
+
+ifeq ($(BOARD_USE_V4L2_ION),true)
+LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION
+LOCAL_SHARED_LIBRARIES += libion
+endif
+
+LOCAL_MODULE := libhdmi
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp b/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp
new file mode 100644
index 0000000..444a9db
--- /dev/null
+++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp
@@ -0,0 +1,1957 @@
+/*
+ * 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"
+#include <cutils/log.h>
+
+#if defined(BOARD_USE_V4L2_ION)
+#include "ion.h"
+#endif
+
+#include "SecHdmi.h"
+#include "SecHdmiV4L2Utils.h"
+
+#define CHECK_GRAPHIC_LAYER_TIME (0)
+
+namespace android {
+
+extern unsigned int output_type;
+#if defined(BOARD_USE_V4L2)
+extern unsigned int g_preset_id;
+#endif
+extern v4l2_std_id t_std_id;
+extern int g_hpd_state;
+extern unsigned int g_hdcp_en;
+
+#if !defined(BOARD_USE_V4L2)
+extern int fp_tvout;
+extern int fp_tvout_v;
+extern int fp_tvout_g0;
+extern int fp_tvout_g1;
+#endif
+
+#if defined(BOARD_USES_FIMGAPI)
+extern unsigned int g2d_reserved_memory[HDMI_G2D_OUTPUT_BUF_NUM];
+extern unsigned int g2d_reserved_memory_size;
+extern unsigned int cur_g2d_address;
+extern unsigned int g2d_buf_index;
+#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),
+ mHdmiDstWidth(0),
+ mHdmiDstHeight(0),
+ mHdmiSrcYAddr(0),
+ mHdmiSrcCbCrAddr(0),
+ mHdmiOutputMode(DEFAULT_OUPUT_MODE),
+ mHdmiResolutionValue(DEFAULT_HDMI_RESOLUTION_VALUE), // 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),
+ mFimcDstColorFormat(0),
+ mFimcCurrentOutBufIndex(0),
+ mFBaddr(NULL),
+ mFBsize(0),
+ mFBionfd(-1),
+ mFBIndex(0),
+ mDefaultFBFd(-1),
+ 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;
+ mHdmiFd[i] = -1;
+ mDstWidth [i] = 0;
+ mDstHeight [i] = 0;
+ mPrevDstWidth [i] = 0;
+ mPrevDstHeight [i] = 0;
+ }
+
+ mHdmiPresetId = DEFAULT_HDMI_PRESET_ID;
+ mHdmiStdId = DEFAULT_HDMI_STD_ID;
+
+ //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
+
+ SecBuffer zeroBuf;
+ for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++)
+ mFimcReservedMem[i] = zeroBuf;
+#if defined(BOARD_USE_V4L2)
+ for (int i = 0; i < HDMI_LAYER_MAX; i++)
+ for (int j = 0; j < MAX_BUFFERS_MIXER; j++)
+ mMixerBuffer[i][j] = zeroBuf;
+#endif
+
+ memset(&mDstRect, 0 , sizeof(struct v4l2_rect));
+}
+
+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;
+ unsigned int gralloc_buf_size = 0;
+ mFimcCurrentOutBufIndex = 0;
+ int stride;
+ int vstride;
+ int BufNum = 0;
+#if defined(BOARD_USE_V4L2_ION)
+ int IonClient = -1;
+ int IonFd = -1;
+ void *ion_base_addr = NULL;
+#endif
+
+/*
+ * 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;
+ gralloc_buf_size = GRALLOC_BUF_SIZE * SIZE_1K;
+#if defined(BOARD_USES_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 fail", __func__);
+ goto CREATE_FAIL;
+ }
+
+ if (mDefaultFBFd <= 0) {
+ if ((mDefaultFBFd = fb_open(DEFAULT_FB)) < 0) {
+ LOGE("%s:Failed to open default FB", __func__);
+ return false;
+ }
+ }
+
+#ifdef BOARD_USE_V4L2
+ BufNum = HDMI_FIMC_OUTPUT_BUF_NUM;
+#else
+ BufNum = 1;
+#endif
+
+ if (mSecFimc.create(SecFimc::DEV_3, SecFimc::MODE_SINGLE_BUF, BufNum) == false) {
+ LOGE("%s::SecFimc create() fail", __func__);
+ goto CREATE_FAIL;
+ }
+
+#if defined(BOARD_USE_V4L2_ION)
+ IonClient = ion_client_create();
+ if (IonClient < 0) {
+ LOGE("%s::ion_client_create() failed", __func__);
+ goto CREATE_FAIL;
+ }
+#if defined(BOARD_USES_FIMGAPI)
+ IonFd = ion_alloc(IonClient, g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, 0, ION_HEAP_EXYNOS_MASK);
+
+ if (IonFd < 0) {
+ LOGE("%s::ION memory allocation failed", __func__);
+ } else {
+ ion_base_addr = ion_map(IonFd, ALIGN(g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, PAGE_SIZE), 0);
+ if (ion_base_addr == MAP_FAILED)
+ LOGE("%s::ION mmap failed", __func__);
+ }
+
+ for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++)
+ g2d_reserved_memory[i] = ion_base_addr + (g2d_reserved_memory_size * i);
+#endif
+#else
+#ifndef BOARD_USE_V4L2
+ for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++)
+ mFimcReservedMem[i].phys.p = mSecFimc.getMemAddr()->phys.p + gralloc_buf_size + (fimc_buf_size * i);
+#endif
+
+#if defined(BOARD_USES_FIMGAPI)
+#if defined(BOARD_USES_HDMI_SUBTITLES)
+ for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++)
+ g2d_reserved_memory[i] = mFimcReservedMem[HDMI_FIMC_OUTPUT_BUF_NUM - 1].phys.p + fimc_buf_size + (g2d_reserved_memory_size * i);
+#else
+ for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++)
+ g2d_reserved_memory[i] = mSecFimc.getMemAddr()->phys.p + gralloc_buf_size + (g2d_reserved_memory_size * i);
+#endif
+#endif
+#endif
+
+ v4l2_std_id std_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 defined(BOARD_USE_V4L2)
+ unsigned int preset_id;
+
+ if (hdmi_resolution_2_preset_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &preset_id) < 0) {
+ LOGE("%s::hdmi_resolution_2_preset_id(%d) fail\n", __func__, mHdmiResolutionValue);
+ goto CREATE_FAIL;
+ }
+#else
+ if (hdmi_resolution_2_std_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &std_id) < 0) {
+ LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, mHdmiResolutionValue);
+ goto CREATE_FAIL;
+ }
+#endif
+ }
+
+ mFlagCreate = true;
+
+ return true;
+
+CREATE_FAIL :
+
+ if (mSecFimc.flagCreate() == true &&
+ mSecFimc.destroy() == false)
+ LOGE("%s::fimc destory fail", __func__);
+
+ return false;
+}
+
+bool SecHdmi::destroy(void)
+{
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s", __func__);
+#endif
+
+ 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_GRAPHIC_0; layer++) {
+ if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
+ LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, layer);
+ goto DESTROY_FAIL;
+ }
+
+ if (hdmi_deinit_layer(layer) < 0) {
+ LOGE("%s::hdmi_deinit_layer(%d) fail \n", __func__, layer);
+ goto DESTROY_FAIL;
+ }
+ }
+
+#if !defined(BOARD_USE_V4L2)
+ tvout_deinit();
+#endif
+
+ if (mSecFimc.flagCreate() == true && mSecFimc.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_USE_V4L2_ION)
+ if (mFBaddr != NULL)
+ ion_unmap((void *)mFBaddr, ALIGN(mFBsize * 4 * 2, PAGE_SIZE));
+
+ if (mFBionfd > 0)
+ ion_free(mFBionfd);
+
+ mFBaddr = NULL;
+ mFBionfd = -1;
+ mFBsize = 0;
+#endif
+
+#if defined(BOARD_USE_V4L2_ION) && defined(BOARD_USES_FIMGAPI)
+ ion_unmap((void *)g2d_reserved_memory[0], ALIGN(g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, PAGE_SIZE));
+#endif
+
+ 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);
+
+ mHdmiInfoChange = true;
+ mFlagConnected = true;
+
+#if defined(BOARD_USES_EDID)
+ // show display..
+ 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 = SecHdmi::HDMI_LAYER_BASE + 1; layer <= SecHdmi::HDMI_LAYER_GRAPHIC_0; layer++) {
+ if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
+ LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, layer);
+ return false;
+ }
+ }
+
+#if defined(BOARD_USE_V4L2)
+ for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+ if (hdmi_deinit_layer(layer) < 0)
+ LOGE("%s::hdmi_deinit_layer(%d) fail", __func__, layer);
+ }
+#else
+ tvout_deinit();
+#endif
+
+ mFlagConnected = false;
+
+ mHdmiOutputMode = DEFAULT_OUPUT_MODE;
+ mHdmiResolutionValue = DEFAULT_HDMI_RESOLUTION_VALUE;
+#if defined(BOARD_USE_V4L2)
+ mHdmiPresetId = DEFAULT_HDMI_PRESET_ID;
+#else
+ mHdmiStdId = DEFAULT_HDMI_STD_ID;
+#endif
+ mCompositeStd = DEFAULT_COMPOSITE_STD;
+ mAudioMode = 2;
+ mCurrentHdmiOutputMode = -1;
+ mCurrentHdmiResolutionValue = 0;
+ mCurrentAudioMode = -1;
+ mFimcCurrentOutBufIndex = 0;
+
+ 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 [srcW=%d, srcH=%d, srcColorFormat=0x%x, srcYAddr=0x%x, srcCbAddr=0x%x, srcCrAddr=0x%x, dstX=%d, dstY=%d, hdmiLayer=%d]",
+ __func__, srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, srcCrAddr, dstX, dstY, hdmiLayer);
+#endif
+
+ Mutex::Autolock lock(mLock);
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not Yet Created \n", __func__);
+ return false;
+ }
+
+#if defined(BOARD_USE_V4L2)
+ if (hdmiLayer == HDMI_LAYER_VIDEO) {
+ mDstWidth[hdmiLayer] = mHdmiDstWidth;
+ mDstHeight[hdmiLayer] = mHdmiDstHeight;
+ } else {
+ if (num_of_hwc_layer == 0) {
+ struct v4l2_rect rect;
+ int tempSrcW, tempSrcH;
+
+ if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) {
+ tempSrcW = srcW;
+ tempSrcH = srcH;
+ } else {
+ tempSrcW = srcH;
+ tempSrcH = srcW;
+ }
+
+ hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
+ mDstWidth[hdmiLayer] = rect.width;
+ mDstHeight[hdmiLayer] = rect.height;
+ mDstWidth[HDMI_LAYER_VIDEO] = 0;
+ mDstHeight[HDMI_LAYER_VIDEO] = 0;
+ } else {
+ mDstWidth[hdmiLayer] = mHdmiDstWidth;
+ mDstHeight[hdmiLayer] = mHdmiDstHeight;
+ }
+ }
+#ifdef DEBUG_MSG_ENABLE
+ LOGE("m_reset param(%d, %d, %d, %d)",
+ mDstWidth[hdmiLayer], mDstHeight[hdmiLayer], \
+ mPrevDstWidth[hdmiLayer], mPrevDstHeight[hdmiLayer]);
+#endif
+#endif
+
+ if (srcW != mSrcWidth[hdmiLayer] ||
+ srcH != mSrcHeight[hdmiLayer] ||
+ srcColorFormat != mSrcColorFormat[hdmiLayer] ||
+ mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
+ mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
+#if defined(BOARD_USE_V4L2)
+ mDstWidth[hdmiLayer] != mPrevDstWidth[hdmiLayer] ||
+ mDstHeight[hdmiLayer] != mPrevDstHeight[hdmiLayer] ||
+#endif
+ 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, srcColorFormat, hdmiLayer, num_of_hwc_layer) == false) {
+ LOGE("%s::m_reset(%d, %d, %d, %d, %d) fail", __func__, srcW, srcH, srcColorFormat, hdmiLayer, num_of_hwc_layer);
+ return false;
+ }
+ }
+
+ if (srcYAddr == 0) {
+#if defined(BOARD_USE_V4L2_ION)
+ unsigned int FB_size = ALIGN(srcW, 16) * ALIGN(srcH, 16) * HDMI_FB_BPP_SIZE;
+ void *virFBAddr = 0;
+ struct s3c_fb_user_ion_client ion_handle;
+
+ if (mFBaddr != NULL) {
+ ion_unmap((void *)mFBaddr, ALIGN(mFBsize * 2, PAGE_SIZE));
+ ion_free(mFBionfd);
+ }
+
+ // get framebuffer virtual address for LCD
+ if (ioctl(mDefaultFBFd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) < 0) {
+ LOGE("%s:ioctl(S3CFB_GET_ION_USER_HANDLE) fail", __func__);
+ return false;
+ }
+
+ virFBAddr = ion_map(ion_handle.fd, ALIGN(FB_size * 2, PAGE_SIZE), 0);
+ if (virFBAddr == MAP_FAILED) {
+ LOGE("%s::ion_map fail", __func__);
+ ion_free(ion_handle.fd);
+ mFBaddr = NULL;
+ return false;
+ }
+
+ if ((mFBIndex % 2) == 0)
+ srcYAddr = (unsigned int)virFBAddr;
+ else
+ srcYAddr = (unsigned int)virFBAddr + FB_size;
+
+ srcCbAddr = srcYAddr;
+
+ mFBIndex++;
+ mFBaddr = virFBAddr;
+ mFBsize = FB_size;
+ mFBionfd = ion_handle.fd;
+#else
+ unsigned int phyFBAddr = 0;
+
+ // get physical framebuffer address for LCD
+ if (ioctl(mDefaultFBFd, S3CFB_GET_FB_PHY_ADDR, &phyFBAddr) == -1) {
+ LOGE("%s:ioctl(S3CFB_GET_FB_PHY__ADDR) fail", __func__);
+ return false;
+ }
+
+ /*
+ * when early suspend, FIMD IP off.
+ * so physical framebuffer address for LCD is 0x00000000
+ * so JUST RETURN.
+ */
+ if (phyFBAddr == 0) {
+ LOGE("%s::S3CFB_GET_FB_PHY_ADDR fail", __func__);
+ return true;
+ }
+ srcYAddr = phyFBAddr;
+ srcCbAddr = srcYAddr;
+#endif
+ }
+
+ if (hdmiLayer == HDMI_LAYER_VIDEO) {
+ if (srcColorFormat == HAL_PIXEL_FORMAT_YCbCr_420_SP ||
+ srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP) {
+#if defined(BOARD_USE_V4L2)
+ mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr;
+ mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr;
+#else
+ hdmi_set_v_param(hdmiLayer,
+ srcW, srcH, V4L2_PIX_FMT_NV12,
+ srcYAddr, srcCbAddr,
+ mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ } else if (srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) {
+#if defined(BOARD_USE_V4L2)
+ mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr;
+ mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr;
+#else
+ hdmi_set_v_param(hdmiLayer,
+ srcW, srcH, V4L2_PIX_FMT_NV12T,
+ srcYAddr, srcCbAddr,
+ mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ } else if (srcColorFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
+ srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP) {
+#if defined(BOARD_USE_V4L2)
+ mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr;
+ mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr;
+#else
+ hdmi_set_v_param(hdmiLayer,
+ srcW, srcH, V4L2_PIX_FMT_NV21,
+ srcYAddr, srcCbAddr,
+ mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ } else {
+ if (mSecFimc.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) {
+ LOGE("%s::setSrcAddr(%d, %d, %d) fail",
+ __func__, srcYAddr, srcCbAddr, srcCrAddr);
+ return false;
+ }
+
+ int y_size = 0;
+ if (mUIRotVal == 0 || mUIRotVal == 180)
+ y_size = ALIGN(ALIGN(srcW,128) * ALIGN(srcH, 32), SZ_8K);
+ else
+ y_size = ALIGN(ALIGN(srcH,128) * ALIGN(srcW, 32), SZ_8K);
+
+ mHdmiSrcYAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[0];
+#ifdef BOARD_USE_V4L2
+ mHdmiSrcCbCrAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[1];
+#else
+ mHdmiSrcCbCrAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[0] + y_size;
+#endif
+ if (mSecFimc.setDstAddr(mHdmiSrcYAddr, mHdmiSrcCbCrAddr, 0, mFimcCurrentOutBufIndex) == false) {
+ LOGE("%s::mSecFimc.setDstAddr(%d, %d) fail \n",
+ __func__, mHdmiSrcYAddr, mHdmiSrcCbCrAddr);
+ return false;
+ }
+
+ if (mSecFimc.draw(0, mFimcCurrentOutBufIndex) == false) {
+ LOGE("%s::mSecFimc.draw() fail \n", __func__);
+ return false;
+ }
+#if defined(BOARD_USE_V4L2)
+ mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)mHdmiSrcYAddr;
+ mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)mHdmiSrcCbCrAddr;
+#else
+ if (mUIRotVal == 0 || mUIRotVal == 180)
+ hdmi_set_v_param(hdmiLayer,
+ srcW, srcH, V4L2_PIX_FMT_NV12T,
+ mHdmiSrcYAddr, mHdmiSrcCbCrAddr,
+ mHdmiDstWidth, mHdmiDstHeight);
+ else
+ hdmi_set_v_param(hdmiLayer,
+ srcH, srcW, V4L2_PIX_FMT_NV12T,
+ mHdmiSrcYAddr, mHdmiSrcCbCrAddr,
+ mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ mFimcCurrentOutBufIndex++;
+ if (mFimcCurrentOutBufIndex >= HDMI_FIMC_OUTPUT_BUF_NUM)
+ mFimcCurrentOutBufIndex = 0;
+ }
+
+ } else {
+ if (srcColorFormat != HAL_PIXEL_FORMAT_BGRA_8888 &&
+ srcColorFormat != HAL_PIXEL_FORMAT_RGBA_8888 &&
+ srcColorFormat != HAL_PIXEL_FORMAT_RGB_565) {
+ if (mSecFimc.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) {
+ LOGE("%s::setSrcAddr(%d, %d, %d) fail",
+ __func__, srcYAddr, srcCbAddr, srcCrAddr);
+ return false;
+ }
+
+ if (mSecFimc.draw(0, mFimcCurrentOutBufIndex) == false) {
+ LOGE("%s::mSecFimc.draw() failed", __func__);
+ return false;
+ }
+#if defined(BOARD_USE_V4L2)
+ if (hdmi_set_g_scaling(hdmiLayer,
+ HAL_PIXEL_FORMAT_BGRA_8888,
+ mDstRect.width, mDstRect.height,
+ mHdmiSrcYAddr, &mMixerBuffer[hdmiLayer][0],
+ mDstRect.left , mDstRect.top,
+ mHdmiDstWidth, mHdmiDstHeight,
+ mG2DUIRotVal,
+ num_of_hwc_layer) < 0)
+ return false;
+#else
+ if (hdmi_gl_set_param(hdmiLayer,
+ HAL_PIXEL_FORMAT_BGRA_8888,
+ mDstRect.width, mDstRect.height,
+ mHdmiSrcYAddr, mHdmiSrcCbCrAddr,
+ mDstRect.left , mDstRect.top,
+ mHdmiDstWidth, mHdmiDstHeight,
+ mG2DUIRotVal) < 0)
+#endif
+ 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 defined(BOARD_USE_V4L2)
+ if (hdmi_set_g_scaling(hdmiLayer,
+ srcColorFormat,
+ srcW, srcH,
+ srcYAddr, &mMixerBuffer[hdmiLayer][0],
+ rect.left, rect.top,
+ rect.width, rect.height,
+ mG2DUIRotVal,
+ num_of_hwc_layer) < 0)
+ return false;
+#else
+ if (hdmi_gl_set_param(hdmiLayer,
+ srcColorFormat,
+ srcW, srcH,
+ srcYAddr, srcCbAddr,
+ rect.left, rect.top,
+ rect.width, rect.height,
+ mG2DUIRotVal) < 0)
+ return false;
+#endif
+ } else { /* Video Playback Mode */
+#if defined(BOARD_USE_V4L2)
+ if (hdmi_set_g_scaling(hdmiLayer,
+ srcColorFormat,
+ srcW, srcH,
+ srcYAddr, &mMixerBuffer[hdmiLayer][0],
+ dstX, dstY,
+ mHdmiDstWidth, mHdmiDstHeight,
+ mG2DUIRotVal,
+ num_of_hwc_layer) < 0)
+ return false;
+#else
+ if (hdmi_gl_set_param(hdmiLayer,
+ srcColorFormat,
+ srcW, srcH,
+ srcYAddr, srcCbAddr,
+ dstX, dstY,
+ mHdmiDstWidth, mHdmiDstHeight,
+ mG2DUIRotVal) < 0)
+ return false;
+#endif
+ }
+#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 defined(BOARD_USE_V4L2)
+ unsigned int num_of_plane;
+
+ if (hdmi_get_src_plane(srcColorFormat, &num_of_plane) < 0) {
+ LOGE("%s::hdmi_get_src_plane(%d) fail", __func__, srcColorFormat);
+ return false;
+ }
+
+ if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer, num_of_plane) == false) {
+ LOGE("%s::hdmiLayer(%d) fail", __func__, hdmiLayer);
+ return false;
+ }
+#else
+ if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer) == false) {
+ LOGE("%s::hdmiLayer(%d) fail", __func__, hdmiLayer);
+ return false;
+ }
+#endif
+ }
+
+ 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;
+}
+
+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;
+
+#if defined(BOARD_USES_EDID)
+ // find perfect resolutions..
+#if defined(BOARD_USE_V4L2)
+ unsigned int preset_id;
+ if (hdmi_resolution_2_preset_id(newHdmiResolutionValue, &w, &h, &preset_id) < 0 ||
+ hdmi_check_resolution(preset_id) < 0) {
+ bool flagFoundIndex = false;
+ int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue);
+
+ for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) {
+ if (hdmi_resolution_2_preset_id(mHdmiResolutionValueList[i], &w, &h, &preset_id) == 0 &&
+ hdmi_check_resolution(preset_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
+ v4l2_std_id std_id;
+ if (hdmi_resolution_2_std_id(newHdmiResolutionValue, &w, &h, &std_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) == 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);
+ }
+ }
+#endif
+ 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) {
+ mSecFimc.setRotVal(rotVal);
+ mUIRotVal = rotVal;
+ mHdmiInfoChange = true;
+ }
+ } else { /* Don't rotate video layer when video is played. */
+ rotVal = 0;
+ if (rotVal != mUIRotVal) {
+ mSecFimc.setRotVal(rotVal);
+ mUIRotVal = rotVal;
+ mHdmiInfoChange = true;
+ }
+ }
+
+ return true;
+}
+
+bool SecHdmi::setDisplaySize(int width, int height)
+{
+ mDisplayWidth = width;
+ mDisplayHeight = height;
+
+ return true;
+}
+
+bool SecHdmi::m_reset(int w, int h, int colorFormat, int hdmiLayer, int hwcLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s", __func__);
+#endif
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s called", __func__);
+#endif
+ v4l2_std_id std_id = 0;
+ mFimcCurrentOutBufIndex = 0;
+
+ int srcW = w;
+ int srcH = h;
+
+#if defined(BOARD_USE_V4L2)
+ if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) {
+ LOGE("%s::m_stopHdmi: layer[%d] fail", __func__, hdmiLayer);
+ return false;
+ }
+#else
+ // stop all..
+ 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", __func__, layer);
+ return false;
+ }
+ }
+#endif
+
+#if defined(BOARD_USE_V4L2)
+ if (hdmi_deinit_layer(hdmiLayer) < 0)
+ LOGE("%s::hdmi_deinit_layer(%d) fail", __func__, hdmiLayer);
+
+ mHdmiFd[hdmiLayer] = hdmi_init_layer(hdmiLayer);
+ if (mHdmiFd[hdmiLayer] < 0)
+ LOGE("%s::hdmi_init_layer(%d) fail", __func__, hdmiLayer);
+
+ if (tvout_std_v4l2_init(mHdmiFd[hdmiLayer], mHdmiPresetId) < 0)
+ LOGE("%s::tvout_std_v4l2_init fail", __func__);
+#endif
+
+ if (w != mSrcWidth [hdmiLayer] ||
+ h != mSrcHeight [hdmiLayer] ||
+ mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
+ mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
+#if defined(BOARD_USE_V4L2)
+ mDstWidth[hdmiLayer] != mPrevDstWidth[hdmiLayer] ||
+ mDstHeight[hdmiLayer] != mPrevDstHeight[hdmiLayer] ||
+#endif
+ colorFormat != mSrcColorFormat[hdmiLayer]) {
+ 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\n", __func__, preVideoSrcColorFormat);
+ preVideoSrcColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
+ }
+
+ if (hdmiLayer == HDMI_LAYER_VIDEO) {
+ if (colorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP &&
+ colorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
+ colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP &&
+ colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP &&
+ colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s call mSecFimc.setSrcParams\n", __func__);
+#endif
+ unsigned int full_wdith = ALIGN(w, 16);
+ unsigned int full_height = ALIGN(h, 2);
+
+ if (mSecFimc.setSrcParams(full_wdith, full_height, 0, 0,
+ (unsigned int*)&w, (unsigned int*)&h, colorFormat, true) == false) {
+ LOGE("%s::mSecFimc.setSrcParams(%d, %d, %d) fail \n",
+ __func__, w, h, colorFormat);
+ return false;
+ }
+
+ mFimcDstColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s call mSecFimc.setDstParams\n", __func__);
+#endif
+ if (mUIRotVal == 0 || mUIRotVal == 180) {
+ if (mSecFimc.setDstParams((unsigned int)w, (unsigned int)h, 0, 0,
+ (unsigned int*)&w, (unsigned int*)&h, mFimcDstColorFormat, true) == false) {
+ LOGE("%s::mSecFimc.setDstParams(%d, %d, %d) fail \n",
+ __func__, w, h, mFimcDstColorFormat);
+ return false;
+ }
+#if defined(BOARD_USE_V4L2)
+ hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer,
+ mFimcDstColorFormat, srcW, srcH,
+ &mMixerBuffer[hdmiLayer][0],
+ 0, 0, mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ } else {
+ if (mSecFimc.setDstParams((unsigned int)h, (unsigned int)w, 0, 0,
+ (unsigned int*)&h, (unsigned int*)&w, mFimcDstColorFormat, true) == false) {
+ LOGE("%s::mSecFimc.setDstParams(%d, %d, %d) fail \n",
+ __func__, w, h, mFimcDstColorFormat);
+ return false;
+ }
+#if defined(BOARD_USE_V4L2)
+ hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer,
+ mFimcDstColorFormat, srcH, srcW,
+ &mMixerBuffer[hdmiLayer][0],
+ 0, 0, mHdmiDstWidth, mHdmiDstHeight);
+#endif
+ }
+ }
+#if defined(BOARD_USE_V4L2)
+ else {
+ hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer,
+ colorFormat, srcW, srcH,
+ &mMixerBuffer[hdmiLayer][0],
+ 0, 0, mHdmiDstWidth, mHdmiDstHeight);
+ }
+#endif
+ mPrevDstWidth[hdmiLayer] = mHdmiDstWidth;
+ mPrevDstHeight[hdmiLayer] = mHdmiDstHeight;
+ } else {
+#if defined(BOARD_USE_V4L2)
+ struct v4l2_rect rect;
+ int tempSrcW, tempSrcH;
+
+ 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 (hwcLayer == 0) { /* UI only mode */
+ hdmi_set_g_param(mHdmiFd[hdmiLayer], hdmiLayer,
+ colorFormat, srcW, srcH,
+ &mMixerBuffer[hdmiLayer][0],
+ rect.left, rect.top, rect.width, rect.height);
+ mPrevDstWidth[hdmiLayer] = rect.width;
+ mPrevDstHeight[hdmiLayer] = rect.height;
+ mPrevDstWidth[HDMI_LAYER_VIDEO] = 0;
+ mPrevDstHeight[HDMI_LAYER_VIDEO] = 0;
+ } else { /* Video Playback + UI Mode */
+ hdmi_set_g_param(mHdmiFd[hdmiLayer], hdmiLayer,
+ colorFormat, srcW, srcH,
+ &mMixerBuffer[hdmiLayer][0],
+ 0, 0, mHdmiDstWidth, mHdmiDstHeight);
+ mPrevDstWidth[hdmiLayer] = mHdmiDstWidth;
+ mPrevDstHeight[hdmiLayer] = mHdmiDstHeight;
+ }
+#endif
+ }
+
+ if (preVideoSrcColorFormat != videoSrcColorFormat)
+ mHdmiInfoChange = true;
+
+ mSrcWidth[hdmiLayer] = srcW;
+ mSrcHeight[hdmiLayer] = srcH;
+ mSrcColorFormat[hdmiLayer] = colorFormat;
+
+ mHdmiResolutionWidth[hdmiLayer] = mHdmiDstWidth;
+ mHdmiResolutionHeight[hdmiLayer] = mHdmiDstHeight;
+
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("m_reset saved param(%d, %d, %d, %d, %d, %d, %d) \n",
+ srcW, mSrcWidth[hdmiLayer], \
+ srcH, mSrcHeight[hdmiLayer], \
+ colorFormat,mSrcColorFormat[hdmiLayer], \
+ hdmiLayer);
+#endif
+ }
+
+ if (mHdmiInfoChange == true) {
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("mHdmiInfoChange: %d\n", mHdmiInfoChange);
+#endif
+ // stop all..
+#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() fail \n", __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) fail\n", __func__, mCompositeStd);
+ return false;
+ }
+ if (m_setCompositeResolution(mCompositeStd) == false) {
+ LOGE("%s::m_setCompositeRsolution() fail \n", __func__);
+ return false;
+ }
+ } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+ mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+ if (m_setHdmiResolution(mHdmiResolutionValue) == false) {
+ LOGE("%s::m_setHdmiResolution() fail \n", __func__);
+ return false;
+ }
+
+ if (m_setHdcpMode(mHdcpMode) == false) {
+ LOGE("%s::m_setHdcpMode() fail \n", __func__);
+ return false;
+ }
+#if !defined(BOARD_USE_V4L2)
+ std_id = mHdmiStdId;
+#endif
+ }
+
+#if !defined(BOARD_USE_V4L2)
+ fp_tvout = tvout_init(std_id);
+
+ for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+ if (hdmi_deinit_layer(layer) < 0)
+ LOGE("%s::hdmi_init_layer(%d) fail \n", __func__, layer);
+ }
+
+ for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
+ if (hdmi_init_layer(layer) < 0)
+ LOGE("%s::hdmi_init_layer(%d) fail \n", __func__, layer);
+ }
+#endif
+
+ 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() fail \n", __func__);
+ }
+
+ mHdmiInfoChange = false;
+#ifdef BOARD_USE_V4L2
+ for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++)
+ mFimcReservedMem[i] = *(mSecFimc.getMemAddr(i));
+#endif
+ }
+
+ return true;
+}
+
+#if defined(BOARD_USE_V4L2)
+bool SecHdmi::m_startHdmi(int hdmiLayer, unsigned int num_of_plane)
+{
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s", __func__);
+#endif
+
+ bool ret = true;
+ int buf_index = 0;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s: hdmiLayer(%d) called\n", __func__, hdmiLayer);
+#endif
+
+ if (mFlagLayerEnable[hdmiLayer]) {
+ static unsigned int index = 0;
+
+ if (mFlagHdmiStart[hdmiLayer] == false) {
+ index = 0;
+ if (tvout_std_v4l2_qbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
+ index, num_of_plane, &mMixerBuffer[hdmiLayer][0]) < 0) {
+ LOGE("%s::tvout_std_v4l2_qbuf(index : %d) (mSrcBufNum : %d) failed", __func__, index, HDMI_NUM_MIXER_BUF);
+ return false;
+ }
+ index++;
+
+ if (tvout_std_v4l2_streamon(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+ LOGE("%s::tvout_std_v4l2_streamon() failed", __func__);
+ return false;
+ }
+
+ mFlagHdmiStart[hdmiLayer] = true;
+ } else {
+ if (tvout_std_v4l2_qbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
+ index, num_of_plane, &mMixerBuffer[hdmiLayer][0]) < 0) {
+ LOGE("%s::tvout_std_v4l2_qbuf() failed", __func__);
+ return false;
+ }
+
+ if (tvout_std_v4l2_dqbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, &buf_index, num_of_plane) < 0) {
+ LOGE("%s::tvout_std_v4l2_dqbuf() failed", __func__);
+ return false;
+ }
+ index = buf_index;
+ }
+ }
+
+ return true;
+}
+#else
+bool SecHdmi::m_startHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s", __func__);
+#endif
+
+ bool ret = true;
+ int buf_index = 0;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s: hdmiLayer(%d) called\n", __func__, hdmiLayer);
+#endif
+
+ switch (hdmiLayer) {
+ case HDMI_LAYER_VIDEO:
+ tvout_v4l2_start_overlay(fp_tvout_v);
+ mFlagHdmiStart[hdmiLayer] = true;
+ break;
+ case HDMI_LAYER_GRAPHIC_0 :
+ if (mFlagLayerEnable[hdmiLayer]) {
+ if (ioctl(fp_tvout_g0, FBIOBLANK, (void *)FB_BLANK_UNBLANK) != -1)
+ mFlagHdmiStart[hdmiLayer] = true;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_1 :
+ if (mFlagLayerEnable[hdmiLayer]) {
+ if (ioctl(fp_tvout_g1, FBIOBLANK, (void *)FB_BLANK_UNBLANK) != -1)
+ mFlagHdmiStart[hdmiLayer] = true;
+ }
+ break;
+ default :
+ LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer);
+ ret = false;
+ break;
+ }
+
+ return true;
+}
+#endif
+
+bool SecHdmi::m_stopHdmi(int hdmiLayer)
+{
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s", __func__);
+#endif
+
+ bool ret = true;
+ if (mFlagHdmiStart[hdmiLayer] == false) {
+ LOGD("%s::already HDMI(%d layer) stopped.. \n", __func__, hdmiLayer);
+ return true;
+ }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s : layer[%d] called\n", __func__, hdmiLayer);
+#endif
+
+#if defined(BOARD_USE_V4L2)
+ int fd;
+
+ switch (hdmiLayer) {
+ case HDMI_LAYER_VIDEO:
+ break;
+ case HDMI_LAYER_GRAPHIC_0 :
+ break;
+ case HDMI_LAYER_GRAPHIC_1 :
+#if defined(BOARD_USES_FIMGAPI)
+ cur_g2d_address = 0;
+ g2d_buf_index = 0;
+#endif
+ break;
+ default :
+ LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer);
+ ret = false;
+ break;
+ }
+
+ if (mFlagLayerEnable[hdmiLayer]) {
+ if (tvout_std_v4l2_streamoff(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
+ LOGE("%s::tvout_std_v4l2_streamon layer(%d) failed", __func__, hdmiLayer);
+ return false;
+ }
+
+ /* clear buffer */
+ if (tvout_std_v4l2_reqbuf(mHdmiFd[hdmiLayer], 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;
+ }
+
+ mFlagHdmiStart[hdmiLayer] = false;
+ }
+#else
+ switch (hdmiLayer) {
+ case HDMI_LAYER_VIDEO:
+ tvout_v4l2_stop_overlay(fp_tvout_v);
+ mFlagHdmiStart[hdmiLayer] = false;
+ break;
+ case HDMI_LAYER_GRAPHIC_0 :
+ if (mFlagLayerEnable[hdmiLayer]) {
+ if (ioctl(fp_tvout_g0, FBIOBLANK, (void *)FB_BLANK_POWERDOWN) != -1)
+ mFlagHdmiStart[hdmiLayer] = false;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_1 :
+#if defined(BOARD_USES_FIMGAPI)
+ cur_g2d_address = 0;
+ g2d_buf_index = 0;
+#endif
+ if (mFlagLayerEnable[hdmiLayer]) {
+ if (ioctl(fp_tvout_g1, FBIOBLANK, (void *)FB_BLANK_POWERDOWN) != -1)
+ mFlagHdmiStart[hdmiLayer] = false;
+ }
+ break;
+ default :
+ LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer);
+ ret = false;
+ break;
+ }
+#endif
+
+ 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;
+
+#if defined(BOARD_USE_V4L2)
+ unsigned int preset_id;
+#else
+ v4l2_std_id std_id;
+#endif
+
+ if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
+ mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
+#if defined(BOARD_USE_V4L2)
+ if (hdmi_resolution_2_preset_id(hdmiResolutionValue, &w, &h, &preset_id) < 0) {
+ LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue);
+ return false;
+ }
+ mHdmiPresetId = preset_id;
+#else
+ if (hdmi_resolution_2_std_id(hdmiResolutionValue, &w, &h, &std_id) < 0) {
+ LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue);
+ return false;
+ }
+ mHdmiStdId = std_id;
+#endif
+ } else {
+ LOGE("%s:: not supported output type \n", __func__);
+ return false;
+ }
+
+#if defined(BOARD_USE_V4L2)
+ g_preset_id = preset_id;
+#else
+ t_std_id = std_id;
+#endif
+
+ mHdmiDstWidth = w;
+ mHdmiDstHeight = h;
+
+ mCurrentHdmiResolutionValue = hdmiResolutionValue;
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+#if defined(BOARD_USE_V4L2)
+ LOGD("%s:: mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiPresetId = 0x%x, hdmiResolutionValue = 0x%x\n",
+ __func__,
+ mHdmiDstWidth,
+ mHdmiDstHeight,
+ mHdmiPresetId,
+ hdmiResolutionValue);
+#else
+ LOGD("%s:: mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiStdId = 0x%x, hdmiResolutionValue = 0x%x\n",
+ __func__,
+ mHdmiDstWidth,
+ mHdmiDstHeight,
+ mHdmiStdId,
+ hdmiResolutionValue);
+#endif
+#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() < 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/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h b/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h
new file mode 100644
index 0000000..203dfe4
--- /dev/null
+++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h
@@ -0,0 +1,138 @@
+/*
+ * 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 "videodev2.h"
+#if defined(BOARD_USE_V4L2)
+#include "s5p_tvout_v4l2.h"
+#else
+#include "s5p_tvout.h"
+#endif
+
+//#define DEBUG_MSG_ENABLE
+//#define DEBUG_HDMI_HW_LEVEL
+#define BOARD_USES_EDID
+//#define BOARD_USES_CEC
+#if defined(SAMSUNG_EXYNOS4x12)
+//#define SUPPORT_G2D_UI_MODE
+#endif
+
+#define DEFAULT_FB (0)
+#define TVOUT_FB_G0 (10)
+#define TVOUT_FB_G1 (11)
+
+#define MAX_BUFFERS_MIXER (1)
+#define MAX_PLANES_MIXER (3)
+
+#define HDMI_NUM_MIXER_BUF (2)
+#define GRALLOC_BUF_SIZE (32768)
+#define SIZE_1K (1024)
+
+#define HDMI_FIMC_OUTPUT_BUF_NUM (4)
+#define HDMI_G2D_OUTPUT_BUF_NUM (2)
+#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 HDMI_FB_BPP_SIZE (4) //ARGB888 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_PRESET_ID (V4L2_DV_1080P60)
+ #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_PRESET_ID (V4L2_DV_1080P60)
+ #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_PRESET_ID (V4L2_DV_720P60)
+ #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_PRESET_ID (V4L2_DV_480P60)
+ #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_PRESET_ID (V4L2_DV_480P60)
+ #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/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp
new file mode 100644
index 0000000..217ce51
--- /dev/null
+++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp
@@ -0,0 +1,2434 @@
+/*
+ * 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"
+#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>
+
+#if defined(BOARD_USE_V4L2)
+#include "sec_utils_v4l2.h"
+#include "s5p_tvout_v4l2.h"
+#include "videodev2.h"
+#else
+#include "sec_utils.h"
+#include "s5p_tvout.h"
+#endif
+#include "SecFimc.h"
+#if defined(BOARD_USES_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 "SecHdmiCommon.h"
+#include "SecHdmiV4L2Utils.h"
+
+namespace android {
+
+unsigned int output_type = V4L2_OUTPUT_TYPE_DIGITAL;
+#if defined(BOARD_USE_V4L2)
+unsigned int g_preset_id = V4L2_DV_1080P30;
+#endif
+v4l2_std_id t_std_id = V4L2_STD_1080P_30;
+int g_hpd_state = HPD_CABLE_OUT;
+unsigned int g_hdcp_en = 0;
+
+int fp_tvout = -1;
+int fp_tvout_v = -1;
+int fp_tvout_g0 = -1;
+int fp_tvout_g1 = -1;
+
+struct vid_overlay_param vo_param;
+
+#if defined(BOARD_USES_FIMGAPI)
+unsigned int g2d_reserved_memory[HDMI_G2D_OUTPUT_BUF_NUM];
+unsigned int g2d_reserved_memory_size = 0;
+unsigned int cur_g2d_address = 0;
+unsigned int g2d_buf_index = 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_open(const char *fp_name)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int fp;
+
+ fp = open(fp_name, O_RDWR);
+ if (fp < 0)
+ LOGE("drv (%s) open failed!!\n", fp_name);
+
+ return fp;
+}
+#if defined(BOARD_USE_V4L2)
+int tvout_std_v4l2_init(int fd, unsigned int 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 (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_std_v4l2_enum_output(fd, &output);
+ LOGD("tvout_v4l2_enum_output():: output_type=%d output.index=%d output.name=%s", 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=%d]", __func__, output_type);
+// return -1;
+ }
+
+ // set output
+// tvout_std_v4l2_s_output(fp_tvout, output.index);
+// output_index = 0;
+// tvout_std_v4l2_g_output(fp_tvout, &output_index);
+
+// if (output.capabilities & V4L2_OUT_CAP_PRESETS) {
+ tvout_std_v4l2_enum_dv_presets(fd);
+ preset.preset = preset_id;
+ if (tvout_std_v4l2_s_dv_preset(fd, &preset) < 0 ) {
+ LOGE("%s::tvout_std_v4l2_s_dv_preset failed", __func__);
+ return -1;
+ }
+// }
+
+ 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_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;
+ }
+#ifdef DEBUG_HDMI_HW_LEVEL
+ 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);
+#endif
+ }
+
+ 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", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ ioctl VIDIOC_ENUMOUTPUT
+ To query the attributes of a video outputs applications initialize the index field of struct v4l2_output
+ and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the
+ structure or return an EINVAL error code when the index is out of bounds
+ */
+int tvout_std_v4l2_enum_output(int fd, struct v4l2_output *output)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output);
+
+ if (ret >=0)
+ LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n",
+ output->index,output->type,output->name);
+
+ return ret;
+}
+
+/*
+ ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT
+ To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an
+ integer where the driver stores the number of the output, as in the struct v4l2_output index field.
+ This ioctl will fail only when there are no video outputs, returning the EINVAL error code
+ */
+int tvout_std_v4l2_s_output(int fd, int index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s:: index = 0x%x", __func__, index);
+#endif
+
+ int ret;
+
+ ret = ioctl(fd, VIDIOC_S_OUTPUT, &index);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno);
+ return ret;
+ }
+
+ return ret;
+}
+
+int tvout_std_v4l2_g_output(int fd, int *index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fd, VIDIOC_G_OUTPUT, index);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno);
+ return ret;
+ } else {
+ LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index);
+ }
+
+ return ret;
+}
+
+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_LIB_FIMC
+ LOGD("%s::vaddr[bufidx=%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];
+ }
+
+ 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_MIXER; 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;
+
+ 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;
+}
+#else
+int tvout_init(v4l2_std_id std_id)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s:: std_id = 0x%x", __func__, std_id);
+#endif
+
+ int ret;
+ struct v4l2_output output;
+ struct v4l2_standard std;
+ v4l2_std_id std_g_id;
+ struct tvout_param tv_g_param;
+
+ unsigned int matched = 0, i = 0;
+ int output_index;
+
+ // It was initialized already
+ if (fp_tvout <= 0) {
+ fp_tvout = tvout_open(TVOUT_DEV);
+ if (fp_tvout < 0) {
+ LOGE("tvout video drv open failed\n");
+ return -1;
+ }
+ }
+
+ if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL &&
+ output_type <= V4L2_OUTPUT_TYPE_DVI)
+ if (ioctl(fp_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0)
+ LOGE("tvout_init" "VIDIOC_HDCP_ENABLE failed %d\n", errno);
+
+ /* ============== query capability============== */
+ tvout_v4l2_querycap(fp_tvout);
+
+ tvout_v4l2_enum_std(fp_tvout, &std, std_id);
+
+ // set std
+ tvout_v4l2_s_std(fp_tvout, std_id);
+ tvout_v4l2_g_std(fp_tvout, &std_g_id);
+
+ i = 0;
+
+ do {
+ output.index = i;
+ ret = tvout_v4l2_enum_output(fp_tvout, &output);
+ if (output.type == output_type) {
+ matched = 1;
+ break;
+ }
+ i++;
+ } while (ret >=0);
+
+ if (!matched) {
+ LOGE("no matched output type [type : 0x%08x]\n", output_type);
+ return -1;
+ }
+
+ // set output
+ tvout_v4l2_s_output(fp_tvout, output.index);
+ output_index = 0;
+ tvout_v4l2_g_output(fp_tvout, &output_index);
+
+ //set fmt param
+ vo_param.src.base_y = (void *)0x0;
+ vo_param.src.base_c = (void *)0x0;
+ vo_param.src.pix_fmt.width = 0;
+ vo_param.src.pix_fmt.height = 0;
+ vo_param.src.pix_fmt.field = V4L2_FIELD_NONE;
+ vo_param.src.pix_fmt.pixelformat = V4L2_PIX_FMT_NV12T;
+
+ vo_param.src_crop.left = 0;
+ vo_param.src_crop.top = 0;
+ vo_param.src_crop.width = 0;
+ vo_param.src_crop.height = 0;
+
+ return fp_tvout;
+}
+
+int tvout_deinit()
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ if (0 < fp_tvout) {
+ close(fp_tvout);
+ fp_tvout = -1;
+ }
+ return 0;
+}
+
+int tvout_v4l2_querycap(int fp)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s:: fp = 0x%x", __func__, fp);
+#endif
+
+ struct v4l2_capability cap;
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
+
+ if (ret < 0) {
+ LOGE("tvout_v4l2_querycap" "VIDIOC_QUERYCAP failed %d\n", errno);
+ return ret;
+ }
+
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("tvout_v4l2_querycap" "DRIVER : %s, CARD : %s, CAP.: 0x%08x\n",
+ cap.driver, cap.card, cap.capabilities);
+#endif
+
+ return ret;
+}
+
+/*
+ ioctl VIDIOC_G_STD, VIDIOC_S_STD
+ To query and select the current video standard applications use the VIDIOC_G_STD and
+ VIDIOC_S_STD ioctls which take a pointer to a v4l2_std_id type as argument. VIDIOC_G_STD can
+ return a single flag or a set of flags as in struct v4l2_standard field id
+ */
+
+int tvout_v4l2_g_std(int fp, v4l2_std_id *std_id)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_G_STD, std_id);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_std" "VIDIOC_G_STD failed %d\n", errno);
+ return ret;
+ }
+
+ return ret;
+}
+
+int tvout_v4l2_s_std(int fp, v4l2_std_id std_id)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s:: std_id = 0x%x", __func__, std_id);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_S_STD, &std_id);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_std" "VIDIOC_S_STD failed %d\n", errno);
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+ ioctl VIDIOC_ENUMSTD
+ To query the attributes of a video standard, especially a custom (driver defined) one, applications
+ initialize the index field of struct v4l2_standard and call the VIDIOC_ENUMSTD ioctl with a pointer
+ to this structure. Drivers fill the rest of the structure or return an EINVAL error code when the index
+ is out of bounds.
+ */
+int tvout_v4l2_enum_std(int fp, struct v4l2_standard *std, v4l2_std_id std_id)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ std->index = 0;
+ while (0 == ioctl (fp, VIDIOC_ENUMSTD, std)) {
+ if (std->id & std_id)
+ LOGV("tvout_v4l2_enum_std" "Current video standard: %s\n", std->name);
+
+ std->index++;
+ }
+
+ return 0;
+}
+
+/*
+ ioctl VIDIOC_ENUMOUTPUT
+ To query the attributes of a video outputs applications initialize the index field of struct v4l2_output
+ and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the
+ structure or return an EINVAL error code when the index is out of bounds
+ */
+int tvout_v4l2_enum_output(int fp, struct v4l2_output *output)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_ENUMOUTPUT, output);
+
+ if (ret >=0)
+ LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n",
+ output->index,output->type,output->name);
+
+ return ret;
+}
+
+/*
+ ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT
+ To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an
+ integer where the driver stores the number of the output, as in the struct v4l2_output index field.
+ This ioctl will fail only when there are no video outputs, returning the EINVAL error code
+ */
+int tvout_v4l2_s_output(int fp, int index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s:: index = 0x%x", __func__, index);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_S_OUTPUT, &index);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno);
+ return ret;
+ }
+
+ return ret;
+}
+
+int tvout_v4l2_g_output(int fp, int *index)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_G_OUTPUT, index);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno);
+ return ret;
+ } else {
+ LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index);
+ }
+
+ return ret;
+}
+
+/*
+ ioctl VIDIOC_ENUM_FMT
+ To enumerate image formats applications initialize the type and index field of struct v4l2_fmtdesc
+ and call the VIDIOC_ENUM_FMT ioctl with a pointer to this structure. Drivers fill the rest of the
+ structure or return an EINVAL error code. All formats are enumerable by beginning at index zero
+ and incrementing by one until EINVAL is returned.
+ */
+int tvout_v4l2_enum_fmt(int fp, struct v4l2_fmtdesc *desc)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ desc->index = 0;
+ while (0 == ioctl(fp, VIDIOC_ENUM_FMT, desc)) {
+ LOGV("tvout_v4l2_enum_fmt" "enum. fmt [id : 0x%08x] :: type = 0x%08x, name = %s, pxlfmt = 0x%08x\n",
+ desc->index,
+ desc->type,
+ desc->description,
+ desc->pixelformat);
+ desc->index++;
+ }
+
+ return 0;
+}
+
+int tvout_v4l2_g_fmt(int fp, int buf_type, void* ptr)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+ struct v4l2_format format;
+ struct v4l2_pix_format_s5p_tvout *fmt_param = (struct v4l2_pix_format_s5p_tvout*)ptr;
+
+ format.type = (enum v4l2_buf_type)buf_type;
+
+ ret = ioctl(fp, VIDIOC_G_FMT, &format);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_fmt" "type : %d, VIDIOC_G_FMT failed %d\n", buf_type, errno);
+ return ret;
+ } else {
+ memcpy(fmt_param, format.fmt.raw_data, sizeof(struct v4l2_pix_format_s5p_tvout));
+ LOGV("tvout_v4l2_g_fmt" "get. fmt [base_c : 0x%08x], [base_y : 0x%08x] type = 0x%08x, width = %d, height = %d\n",
+ fmt_param->base_c,
+ fmt_param->base_y,
+ fmt_param->pix_fmt.pixelformat,
+ fmt_param->pix_fmt.width,
+ fmt_param->pix_fmt.height);
+ }
+
+ return 0;
+}
+
+int tvout_v4l2_s_fmt(int fp, int buf_type, void *ptr)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ struct v4l2_format format;
+ int ret;
+
+ format.type = (enum v4l2_buf_type)buf_type;
+ switch (buf_type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ format.fmt.win = *((struct v4l2_window *) ptr);
+ break;
+
+ case V4L2_BUF_TYPE_PRIVATE: {
+ struct v4l2_vid_overlay_src *fmt_param =
+ (struct v4l2_vid_overlay_src *) ptr;
+
+ memcpy(format.fmt.raw_data, fmt_param,
+ sizeof(struct v4l2_vid_overlay_src));
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
+ struct v4l2_pix_format_s5p_tvout *fmt_param =
+ (struct v4l2_pix_format_s5p_tvout *)ptr;
+ memcpy(format.fmt.raw_data, fmt_param,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+ break;
+ }
+ default:
+ break;
+ }
+
+ ret = ioctl(fp, VIDIOC_S_FMT, &format);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_fmt [tvout_v4l2_s_fmt] : type : %d, VIDIOC_S_FMT failed %d\n",
+ buf_type, errno);
+ return ret;
+ }
+ return 0;
+
+}
+
+int tvout_v4l2_g_fbuf(int fp, struct v4l2_framebuffer *frame)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_G_FBUF, frame);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_fbuf" "VIDIOC_STREAMON failed %d\n", errno);
+ return ret;
+ }
+
+ LOGV("tvout_v4l2_g_fbuf" "get. fbuf: base = 0x%08X, pixel format = %d\n",
+ frame->base,
+ frame->fmt.pixelformat);
+ return 0;
+}
+
+int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_S_FBUF, frame);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_fbuf" "VIDIOC_STREAMON failed %d\n", errno);
+ return ret;
+ }
+ return 0;
+}
+
+int tvout_v4l2_s_baseaddr(int fp, void *base_addr)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+
+ ret = ioctl(fp, S5PTVFB_WIN_SET_ADDR, base_addr);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_baseaddr" "VIDIOC_S_BASEADDR failed %d\n", errno);
+ return ret;
+ }
+ return 0;
+}
+
+int tvout_v4l2_g_crop(int fp, unsigned int type, struct v4l2_rect *rect)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret;
+ struct v4l2_crop crop;
+ crop.type = (enum v4l2_buf_type)type;
+ ret = ioctl(fp, VIDIOC_G_CROP, &crop);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_g_crop" "VIDIOC_G_CROP failed %d\n", errno);
+ return ret;
+ }
+
+ rect->left = crop.c.left;
+ rect->top = crop.c.top;
+ rect->width = crop.c.width;
+ rect->height = crop.c.height;
+
+ LOGV("tvout_v4l2_g_crop" "get. crop : left = %d, top = %d, width = %d, height = %d\n",
+ rect->left,
+ rect->top,
+ rect->width,
+ rect->height);
+ return 0;
+}
+
+int tvout_v4l2_s_crop(int fp, unsigned int type, struct v4l2_rect *rect)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ struct v4l2_crop crop;
+ int ret;
+
+ crop.type = (enum v4l2_buf_type)type;
+
+ crop.c.left = rect->left;
+ crop.c.top = rect->top;
+ crop.c.width = rect->width;
+ crop.c.height = rect->height;
+
+ ret = ioctl(fp, VIDIOC_S_CROP, &crop);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_s_crop" "VIDIOC_S_CROP failed %d\n", errno);
+ return ret;
+ }
+
+ return 0;
+}
+
+int tvout_v4l2_start_overlay(int fp)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret, start = 1;
+
+ ret = ioctl(fp, VIDIOC_OVERLAY, &start);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_start_overlay" "VIDIOC_OVERLAY failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int tvout_v4l2_stop_overlay(int fp)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int ret, stop =0;
+
+ ret = ioctl(fp, VIDIOC_OVERLAY, &stop);
+ if (ret < 0) {
+ LOGE("tvout_v4l2_stop_overlay" "VIDIOC_OVERLAY failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+#endif
+
+int hdmi_init_layer(int layer)
+{
+ int fd = -1;
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s (layer = %d) called", __func__, layer);
+#endif
+
+ switch (layer) {
+ case HDMI_LAYER_VIDEO :
+ if (fp_tvout_v <= 0) {
+ fp_tvout_v = tvout_open(TVOUT_DEV_V);
+ if (fp_tvout_v < 0) {
+ LOGE("tvout video layer open failed\n");
+ return -1;
+ }
+ fd = fp_tvout_v;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_0 :
+ if (fp_tvout_g0 <= 0) {
+#if defined(BOARD_USE_V4L2)
+ fp_tvout_g0 = tvout_open(TVOUT_DEV_G0);
+#else
+ fp_tvout_g0 = fb_open(TVOUT_FB_G0);
+#endif
+ if (fp_tvout_g0 < 0) {
+ LOGE("tvout graphic layer 0 open failed\n");
+ return -1;
+ }
+ fd = fp_tvout_g0;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_1 :
+ if (fp_tvout_g1 <= 0) {
+#if defined(BOARD_USE_V4L2)
+ fp_tvout_g1 = tvout_open(TVOUT_DEV_G1);
+#else
+ fp_tvout_g1 = fb_open(TVOUT_FB_G1);
+#endif
+ if (fp_tvout_g1 < 0) {
+ LOGE("tvout graphic layer 1 open failed\n");
+ return -1;
+ }
+ fd = fp_tvout_g1;
+ }
+ break;
+ default :
+ LOGE("%s::unmathced layer(%d) fail", __func__, layer);
+ fd = -1;
+ break;
+ }
+
+ return fd;
+}
+
+int hdmi_deinit_layer(int layer)
+{
+ int ret = 0;
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("### %s(layer = %d) called", __func__, layer);
+#endif
+ switch (layer) {
+ case HDMI_LAYER_VIDEO :
+ if (0 < fp_tvout_v) {
+ close(fp_tvout_v);
+ fp_tvout_v = -1;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_0 :
+ if (0 < fp_tvout_g0) {
+ close(fp_tvout_g0);
+ fp_tvout_g0 = -1;
+ }
+ break;
+ case HDMI_LAYER_GRAPHIC_1 :
+ if (0 < fp_tvout_g1) {
+ close(fp_tvout_g1);
+ fp_tvout_g1 = -1;
+ }
+ break;
+ default :
+ LOGE("%s::unmathced layer(%d) fail", __func__, layer);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+#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;
+ }
+}
+
+#if defined(BOARD_USE_V4L2)
+int hdmi_get_src_plane(int srcColorFormat, unsigned int *num_of_plane)
+{
+ int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
+
+ switch (v4l2ColorFormat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565X:
+ *num_of_plane = 1;
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12MT:
+ case V4L2_PIX_FMT_NV21M:
+ *num_of_plane = 2;
+ break;
+ default:
+ LOGE("%s::invalid color type", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+#if defined(BOARD_USE_V4L2)
+int hdmi_set_v_param(int fd, int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ SecBuffer * dstBuffer,
+ int dst_x, int dst_y, int dst_w, int dst_h)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
+ int round_up_src_w;
+ int round_up_src_h;
+ unsigned int num_of_plane;
+ struct v4l2_rect rect;
+
+ /* src_w, src_h round up to DWORD because of VP restriction */
+#if defined(SAMSUNG_EXYNOS4x12)
+ round_up_src_w = ROUND_UP(src_w, 16);
+#else defined(SAMSUNG_EXYNOS4210)
+ round_up_src_w = ROUND_UP(src_w, 8);
+#endif
+ round_up_src_h = ROUND_UP(src_h, 8);
+
+ switch (v4l2ColorFormat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ dstBuffer->size.s = (round_up_src_w * round_up_src_h * 3) >> 1;
+ num_of_plane = 1;
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12MT:
+ case V4L2_PIX_FMT_NV21M:
+ dstBuffer->size.extS[0] = (round_up_src_w * round_up_src_h * 3) >> 1;
+ dstBuffer->size.extS[1] = (round_up_src_w * round_up_src_h * 3) >> 2;
+ num_of_plane = 2;
+ break;
+ default:
+ LOGE("%s::invalid color type", __func__);
+ return false;
+ break;
+ }
+
+ hdmi_cal_rect(src_w, src_h, dst_w, dst_h, &rect);
+ rect.left = ALIGN(rect.left, 16);
+
+ /* set format for VP input */
+ if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, round_up_src_w, round_up_src_h, v4l2ColorFormat, num_of_plane) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_fmt()[video layer] failed", __func__);
+ return -1;
+ }
+
+ /* set crop for VP input */
+ if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY, V4L2_FIELD_ANY, 0, 0, src_w, src_h) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_crop()[video layer] failed", __func__);
+ return -1;
+ }
+
+ /* set crop for VP output */
+ if (tvout_std_v4l2_s_crop(fd, 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()[video layer] failed", __func__);
+ return -1;
+ }
+
+ /* request buffer for VP input */
+ if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) {
+ LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[video layer] failed", __func__, HDMI_NUM_MIXER_BUF);
+ return -1;
+ }
+
+ return 0;
+}
+
+int hdmi_set_g_param(int fd, int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ SecBuffer * dstBuffer,
+ 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 v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
+
+ rect.left = dst_x;
+ rect.top = dst_y;
+
+#if defined(BOARD_USES_FIMGAPI)
+ rect.width = dst_w;
+ rect.height = dst_h;
+#else
+ rect.width = src_w;
+ rect.height = src_h;
+#endif
+
+ switch (v4l2ColorFormat) {
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_RGB32:
+ dstBuffer->size.s = rect.width * rect.height << 2;
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ dstBuffer->size.s = rect.width * rect.height << 1;
+ break;
+ default:
+ LOGE("%s::invalid color type", __func__);
+ return false;
+ break;
+ }
+
+ /* set format for mixer graphic layer input device*/
+ if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.width, rect.height, v4l2ColorFormat, 1) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_fmt() [layer=%d] failed", __func__, layer);
+ return -1;
+ }
+
+ /* set crop for mixer graphic layer input device*/
+ if (tvout_std_v4l2_s_crop(fd, 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() [layer=%d] failed", __func__, layer);
+ return -1;
+ }
+
+ /* request buffer for mixer graphic layer input device */
+ if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) {
+ LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d) [layer=%d] failed", __func__, HDMI_NUM_MIXER_BUF, layer);
+ return -1;
+ }
+
+ /* enable alpha blending for mixer graphic layer */
+ if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer);
+ return -1;
+ }
+
+ /* enable per-pixel blending for mixer graphic layer */
+ if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] failed", __func__, layer);
+ return false;
+ }
+
+ /* set global alpha value for mixer graphic layer */
+ if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
+ LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer);
+ return -1;
+ }
+
+ return 0;
+}
+
+int hdmi_set_g_scaling(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, unsigned int hwc_layer)
+{
+#if defined(BOARD_USES_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 (g_preset_id) {
+ case V4L2_DV_1080P60:
+ case V4L2_DV_1080P30:
+ case V4L2_DV_1080I60:
+ case V4L2_DV_720P60_SB_HALF:
+ case V4L2_DV_720P59_94_SB_HALF:
+ case V4L2_DV_1080P24_TB:
+ case V4L2_DV_1080P23_98_TB:
+ dst_color_format = CF_ARGB_8888;
+ dst_bpp = 4;
+ break;
+ case V4L2_DV_480P60:
+ case V4L2_DV_576P50:
+ case V4L2_DV_720P60:
+ case V4L2_DV_720P50_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)) {
+ dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index];
+
+ g2d_buf_index++;
+ if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM)
+ g2d_buf_index = 0;
+
+ 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) fail", __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() fail", __func__);
+ return -1;
+ }
+
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("hdmi_set_g_scaling:: \n \\
+ layer=%d,\n \\
+ srcColorFormat=%d,\n \\
+ src_w=%d, src_h=%d,\n\\
+ src_address=0x%x, dst_addr=0x%x,\n\\
+ dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ",
+ layer,
+ srcColorFormat,
+ src_w, src_h,
+ src_address, dst_addr,
+ dst_x, dst_y, dst_w, dst_h);
+#endif
+ dstBuffer->virt.p = (char *)dst_addr;
+ }
+#else
+ dstBuffer->virt.p = (char *)src_address;
+#endif
+
+ return 0;
+}
+#else
+int hdmi_set_v_param(int layer,
+ int src_w, int src_h, int colorFormat,
+ unsigned int src_y_address, unsigned int src_c_address,
+ int dst_w, int dst_h)
+{
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int round_up_src_w;
+ int round_up_src_h;
+ if (fp_tvout_v <= 0) {
+ LOGE("fp_tvout is < 0 fail\n");
+ return -1;
+ }
+
+ /* src_w, src_h round up to DWORD because of VP restriction */
+#if defined(SAMSUNG_EXYNOS4x12)
+ round_up_src_w = ROUND_UP(src_w, 16);
+#else defined(SAMSUNG_EXYNOS4210)
+ round_up_src_w = ROUND_UP(src_w, 8);
+#endif
+ round_up_src_h = ROUND_UP(src_h, 8);
+
+ vo_param.src.base_y = (void *)src_y_address;
+ vo_param.src.base_c = (void *)src_c_address;
+ vo_param.src.pix_fmt.width = round_up_src_w;
+ vo_param.src.pix_fmt.height = round_up_src_h;
+ vo_param.src.pix_fmt.field = V4L2_FIELD_NONE;
+ vo_param.src.pix_fmt.pixelformat = colorFormat;
+
+ tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src);
+
+ vo_param.src_crop.width = src_w;
+ vo_param.src_crop.height = src_h;
+
+ tvout_v4l2_s_crop(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src_crop);
+
+ if (dst_w * src_h <= dst_h * src_w) {
+ vo_param.dst_win.w.left = 0;
+ vo_param.dst_win.w.top = (dst_h - ((dst_w * src_h) / src_w)) >> 1;
+ vo_param.dst_win.w.width = dst_w;
+ vo_param.dst_win.w.height = ((dst_w * src_h) / src_w);
+ } else {
+ vo_param.dst_win.w.left = (dst_w - ((dst_h * src_w) / src_h)) >> 1;
+ vo_param.dst_win.w.top = 0;
+ vo_param.dst_win.w.width = ((dst_h * src_w) / src_h);
+ vo_param.dst_win.w.height = dst_h;
+ }
+
+ vo_param.dst.fmt.priv = 10;
+ vo_param.dst_win.global_alpha = 255;
+ tvout_v4l2_s_fbuf(fp_tvout_v, &vo_param.dst);
+ tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_VIDEO_OVERLAY, &vo_param.dst_win);
+
+ return 0;
+}
+
+int hdmi_gl_set_param(int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ unsigned int src_y_address, unsigned int src_c_address,
+ int dst_x, int dst_y, int dst_w, int dst_h,
+ int rotVal)
+{
+#if defined(BOARD_USES_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;
+
+ struct fb_var_screeninfo var;
+ struct s5ptvfb_user_window window;
+
+ int fp_tvout_g;
+
+ if(layer == HDMI_LAYER_GRAPHIC_0)
+ fp_tvout_g = fp_tvout_g0;
+ else
+ fp_tvout_g = fp_tvout_g1;
+
+ 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;
+ var.bits_per_pixel = 32;
+ var.transp.length = 8;
+ 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;
+ var.bits_per_pixel = 16;
+ var.transp.length = 4;
+ break;
+ }
+
+ static unsigned int prev_src_addr = 0;
+
+ if ((cur_g2d_address == 0) || (src_y_address != prev_src_addr)) {
+ dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index];
+
+ g2d_buf_index++;
+ if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM)
+ g2d_buf_index = 0;
+
+ cur_g2d_address = (unsigned int)dst_addr;
+ prev_src_addr = src_y_address;
+
+ srcAddr = {(addr_space)ADDR_PHYS, (unsigned long)src_y_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_PHYS, (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) fail", __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() fail", __func__);
+ return -1;
+ }
+
+ var.xres = dst_w;
+ var.yres = dst_h;
+
+ var.xres_virtual = var.xres;
+ var.yres_virtual = var.yres;
+ var.xoffset = 0;
+ var.yoffset = 0;
+ var.width = 0;
+ var.height = 0;
+ var.activate = FB_ACTIVATE_FORCE;
+
+ window.x = dst_x;
+ window.y = dst_y;
+
+ tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)dst_addr);
+ put_vscreeninfo(fp_tvout_g, &var);
+
+ if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) {
+ LOGE("%s::S5PTVFB_WIN_POSITION ioctl failed.", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+#else
+ struct fb_var_screeninfo var;
+ struct s5ptvfb_user_window window;
+
+ struct overlay_param ov_param;
+
+ // set base address for grp layer0 of mixer
+ int fp_tvout_g;
+
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("hdmi_gl_set_param:: \n \\
+ layer=%d,\n \\
+ srcColorFormat=%d,\n \\
+ src_w=%d, src_h=%d,\n\\
+ src_y_address=0x%x, src_c_address=0x%x,\n\\
+ dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ",
+ layer,
+ srcColorFormat,
+ src_w, src_h,
+ src_y_address, src_c_address,
+ dst_x, dst_y, dst_w, dst_h);
+#endif
+
+ if (layer == HDMI_LAYER_GRAPHIC_0)
+ fp_tvout_g = fp_tvout_g0;
+ else
+ fp_tvout_g = fp_tvout_g1;
+
+ var.xres = src_w;
+ var.yres = src_h;
+ var.xres_virtual = var.xres;
+ var.yres_virtual = var.yres;
+ var.xoffset = 0;
+ var.yoffset = 0;
+ var.width = src_w;
+ var.height = src_h;
+ var.activate = FB_ACTIVATE_FORCE;
+ if (srcColorFormat == HAL_PIXEL_FORMAT_RGB_565) {
+ var.bits_per_pixel = 16;
+ var.transp.length = 0;
+ }
+ else {
+ var.bits_per_pixel = 32;
+ var.transp.length = 8;
+ }
+
+ window.x = dst_x;
+ window.y = dst_y;
+
+ tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)src_y_address);
+ put_vscreeninfo(fp_tvout_g, &var);
+ if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) {
+ LOGE("%s:: S5PTVFB_WIN_POSITION ioctl failed.", __func__);
+ return -1;
+ }
+
+ return 0;
+#endif
+}
+#endif
+
+int hdmi_cable_status()
+{
+#if defined(BOARD_USE_V4L2)
+#ifdef DEBUG_HDMI_HW_LEVEL
+ LOGD("%s", __func__);
+#endif
+
+ int cable_status = 0;
+ int fd = 0;
+ struct v4l2_control ctrl;
+
+ fd = open(TVOUT_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;
+#else
+ int cable_status = 0;
+ int fp_hpd = 0;
+
+ fp_hpd = open(HPD_DEV, O_RDWR);
+ if (fp_hpd <= 0) {
+ LOGE("hpd drv open failed\n");
+ return -1;
+ }
+
+ //Delay about 0.3s
+ usleep(500000);
+ if (ioctl(fp_hpd, HPD_GET_STATE, &cable_status) < 0) {
+ LOGE("hpd drv HPD_GET_STATE ioctl failed\n");
+ cable_status = -1;
+ }
+
+ close(fp_hpd);
+
+ return cable_status;
+#endif
+}
+
+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;
+}
+
+#if defined(BOARD_USE_V4L2)
+int hdmi_check_resolution(unsigned int preset_id)
+{
+ struct HDMIVideoParameter video;
+ struct HDMIAudioParameter audio;
+
+ switch (preset_id) {
+ case V4L2_DV_480P60:
+ video.resolution = v720x480p_60Hz;
+ video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_576P50:
+ video.resolution = v720x576p_50Hz;
+ video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_720P60:
+ video.resolution = v1280x720p_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_720P50:
+ video.resolution = v1280x720p_50Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080P60:
+ video.resolution = v1920x1080p_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080P50:
+ video.resolution = v1920x1080p_50Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080I60:
+ video.resolution = v1920x1080i_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080I50:
+ video.resolution = v1920x1080i_50Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_480P59_94:
+ video.resolution = v720x480p_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_720P59_94:
+ video.resolution = v1280x720p_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080I59_94:
+ video.resolution = v1920x1080i_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080P59_94:
+ video.resolution = v1920x1080p_60Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_1080P30:
+ video.resolution = v1920x1080p_30Hz;
+ video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
+ break;
+ case V4L2_DV_720P60_SB_HALF:
+ video.resolution = v1280x720p_60Hz;
+ video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+ break;
+ case V4L2_DV_720P59_94_SB_HALF:
+ video.resolution = v1280x720p_60Hz;
+ video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
+ break;
+ case V4L2_DV_720P50_TB:
+ video.resolution = v1280x720p_50Hz;
+ video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+ break;
+ case V4L2_DV_1080P24_TB:
+ video.resolution = v1920x1080p_24Hz;
+ video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+ break;
+ case V4L2_DV_1080P23_98_TB:
+ video.resolution = v1920x1080p_24Hz;
+ video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
+ break;
+ default:
+ LOGE("%s::unmathced preset_id(%d)", __func__, preset_id);
+ return -1;
+ break;
+ }
+
+ if (!EDIDVideoResolutionSupport(&video)) {
+#ifdef DEBUG_MSG_ENABLE
+ LOGD("%s::EDIDVideoResolutionSupport(%d) fail (not suppoted preset_id) \n", __func__, preset_id);
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+int hdmi_resolution_2_preset_id(unsigned int resolution, int * w, int * h, unsigned int *preset_id)
+{
+ int ret = 0;
+
+ switch (resolution) {
+ case 1080960:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080P60;
+ break;
+ case 1080950:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080P50;
+ break;
+ case 1080930:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080P30;
+ break;
+ case 1080924:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080P24_TB;
+ break;
+ case 1080160:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080I60;
+ break;
+ case 1080150:
+ *w = 1920;
+ *h = 1080;
+ *preset_id = V4L2_DV_1080I50;
+ break;
+ case 720960:
+ *w = 1280;
+ *h = 720;
+ *preset_id = V4L2_DV_720P60;
+ break;
+ case 7209601:
+ *w = 1280;
+ *h = 720;
+ *preset_id = V4L2_DV_720P60_SB_HALF;
+ break;
+ case 720950:
+ *w = 1280;
+ *h = 720;
+ *preset_id = V4L2_DV_720P50;
+ break;
+ case 7209501:
+ *w = 1280;
+ *h = 720;
+ *preset_id = V4L2_DV_720P50_TB;
+ break;
+ case 5769501:
+ *w = 720;
+ *h = 576;
+ *preset_id = V4L2_DV_576P50;
+ break;
+ case 5769502:
+ *w = 720;
+ *h = 576;
+ *preset_id = V4L2_DV_576P50;
+ break;
+ case 4809601:
+ *w = 720;
+ *h = 480;
+ *preset_id = V4L2_DV_480P60;
+ break;
+ case 4809602:
+ *w = 720;
+ *h = 480;
+ *preset_id = V4L2_DV_480P60;
+ break;
+ default:
+ LOGE("%s::unmathced resolution(%d)", __func__, resolution);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+#else
+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)
+{
+ int ret = 0;
+
+ switch (resolution) {
+ case 1080960:
+ *std_id = V4L2_STD_1080P_60;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 1080950:
+ *std_id = V4L2_STD_1080P_50;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 1080930:
+ *std_id = V4L2_STD_1080P_30;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 1080924:
+ *std_id = V4L2_STD_TVOUT_1080P_24_TB;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 1080160:
+ *std_id = V4L2_STD_1080I_60;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 1080150:
+ *std_id = V4L2_STD_1080I_50;
+ *w = 1920;
+ *h = 1080;
+ break;
+ case 720960:
+ *std_id = V4L2_STD_720P_60;
+ *w = 1280;
+ *h = 720;
+ break;
+ case 7209601:
+ *std_id = V4L2_STD_TVOUT_720P_60_SBS_HALF;
+ *w = 1280;
+ *h = 720;
+ break;
+ case 720950:
+ *std_id = V4L2_STD_720P_50;
+ *w = 1280;
+ *h = 720;
+ break;
+ case 7209501:
+ *std_id = V4L2_STD_TVOUT_720P_50_TB;
+ *w = 1280;
+ *h = 720;
+ break;
+ case 5769501:
+ *std_id = V4L2_STD_576P_50_16_9;
+ *w = 720;
+ *h = 576;
+ break;
+ case 5769502:
+ *std_id = V4L2_STD_576P_50_4_3;
+ *w = 720;
+ *h = 576;
+ break;
+ case 4809601:
+ *std_id = V4L2_STD_480P_60_16_9;
+ *w = 720;
+ *h = 480;
+ break;
+ case 4809602:
+ *std_id = V4L2_STD_480P_60_4_3;
+ *w = 720;
+ *h = 480;
+ break;
+ default:
+ LOGE("%s::unmathced resolution(%d)", __func__, resolution);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+#endif
+
+int hdmi_enable_hdcp(unsigned int hdcp_en)
+{
+ if (ioctl(fp_tvout, 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(void)
+{
+ 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(fp_tvout, VIDIOC_INIT_AUDIO, 1) < 0) {
+ LOGE("%s::VIDIOC_INIT_AUDIO(1) fail", __func__);
+ ret = -1;
+ }
+ } else {
+ if (ioctl(fp_tvout, VIDIOC_INIT_AUDIO, 0) < 0) {
+ LOGE("%s::VIDIOC_INIT_AUDIO(0) fail", __func__);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+}
diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h
new file mode 100644
index 0000000..a4aa69c
--- /dev/null
+++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h
@@ -0,0 +1,132 @@
+/*
+ * 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"
+#if defined(BOARD_USE_V4L2)
+#include "SecBuffer.h"
+#endif
+#include "fimd_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace android {
+
+void display_menu(void);
+
+int tvout_open(const char *fp_name);
+#if defined(BOARD_USE_V4L2)
+int tvout_std_v4l2_init(int fd, unsigned int preset_id);
+int tvout_std_v4l2_querycap(int fd, char *node);
+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_v4l2_enum_output(int fd, struct v4l2_output *output);
+int tvout_std_v4l2_s_output(int fd, int index);
+int tvout_std_v4l2_g_output(int fd, int *index);
+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);
+#else
+int tvout_init(v4l2_std_id std_id);
+int tvout_deinit();
+int tvout_v4l2_querycap(int fp);
+int tvout_v4l2_g_std(int fp, v4l2_std_id *std_id);
+int tvout_v4l2_s_std(int fp, v4l2_std_id std_id);
+int tvout_v4l2_enum_std(int fp, struct v4l2_standard *std, v4l2_std_id std_id);
+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_v4l2_enum_fmt(int fp, struct v4l2_fmtdesc *desc);
+int tvout_v4l2_g_fmt(int fp, int buf_type, void* ptr);
+int tvout_v4l2_s_fmt(int fp, int buf_type, void *ptr);
+int tvout_v4l2_g_fbuf(int fp, struct v4l2_framebuffer *frame);
+int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame);
+int tvout_v4l2_s_baseaddr(int fp, void *base_addr);
+int tvout_v4l2_g_crop(int fp, unsigned int type, struct v4l2_rect *rect);
+int tvout_v4l2_s_crop(int fp, unsigned int type, struct v4l2_rect *rect);
+int tvout_v4l2_start_overlay(int fp);
+int tvout_v4l2_stop_overlay(int fp);
+#endif
+
+int hdmi_init_layer(int layer);
+int hdmi_deinit_layer(int layer);
+#if defined(BOARD_USE_V4L2)
+int hdmi_set_v_param(int fd, int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ SecBuffer * dstBuffer,
+ int dst_x, int dst_y, int dst_w, int dst_h);
+int hdmi_set_g_param(int fd, int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ SecBuffer * dstBuffer,
+ int dst_x, int dst_y, int dst_w, int dst_h);
+int hdmi_set_g_scaling(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, unsigned int hwc_layer);
+#else
+int hdmi_set_v_param(int layer,
+ int src_w, int src_h, int colorFormat,
+ unsigned int src_y_address, unsigned int src_c_address,
+ int dst_w, int dst_h);
+int hdmi_gl_set_param(int layer,
+ int srcColorFormat,
+ int src_w, int src_h,
+ unsigned int src_y_address, unsigned int src_c_address,
+ int dst_x, int dst_y, int dst_w, int dst_h,
+ int rotVal);
+#endif
+void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect);
+#if defined(BOARD_USE_V4L2)
+int hdmi_get_src_plane(int srcColorFormat, unsigned int *num_of_plane);
+#endif
+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);
+#if defined(BOARD_USE_V4L2)
+int hdmi_check_resolution(unsigned int preset_id);
+int hdmi_resolution_2_preset_id(unsigned int resolution, int * w, int * h, unsigned int *preset_id);
+#else
+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);
+#endif
+int hdmi_enable_hdcp(unsigned int hdcp_en);
+int hdmi_check_audio(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+} //namespace android
+
+#endif //__HDMI_HAL_V4L2_UTILS_H__
diff --git a/exynos4/hal/libhdmi/SecHdmi/fimd_api.c b/exynos4/hal/libhdmi/SecHdmi/fimd_api.c
new file mode 100644
index 0000000..0e07ef3
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/SecHdmi/fimd_api.h b/exynos4/hal/libhdmi/SecHdmi/fimd_api.h
new file mode 100644
index 0000000..a8561a4
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libhdmiservice/Android.mk b/exynos4/hal/libhdmi/libhdmiservice/Android.mk
new file mode 100644
index 0000000..ebfa9d5
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/Android.mk
@@ -0,0 +1,126 @@
+# 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 exynos4,$(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 += $(TARGET_HAL_PATH)/include
+LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/libhdmi
+LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/libfimc
+LOCAL_SHARED_LIBRARIES += libhdmi libfimc
+
+ifeq ($(BOARD_USES_HDMI_SUBTITLES),true)
+ LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES
+endif
+
+ifeq ($(TARGET_SOC),exynos4210)
+ LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+ LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+LOCAL_CFLAGS += -DBOARD_USES_HDMI
+
+ifeq ($(BOARD_USE_V4L2),true)
+ LOCAL_CFLAGS += -DBOARD_USE_V4L2
+endif
+
+ifeq ($(BOARD_USE_V4L2_ION),true)
+ LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION
+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),exynos4210)
+ LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+ LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+LOCAL_CFLAGS += -DBOARD_USES_HDMI
+
+ifeq ($(BOARD_USE_V4L2),true)
+ LOCAL_CFLAGS += -DBOARD_USE_V4L2
+endif
+
+ifeq ($(BOARD_USE_V4L2_ION),true)
+ LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION
+endif
+
+LOCAL_MODULE:= libhdmiclient
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
+endif
diff --git a/exynos4/hal/libhdmi/libhdmiservice/Barrier.h b/exynos4/hal/libhdmi/libhdmiservice/Barrier.h
new file mode 100644
index 0000000..6f8507e
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp
new file mode 100644
index 0000000..a013bf1
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h
new file mode 100644
index 0000000..5506b57
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp
new file mode 100644
index 0000000..aebe1b8
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h
new file mode 100644
index 0000000..890f809
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h
@@ -0,0 +1,126 @@
+/*
+ * 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/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp
new file mode 100644
index 0000000..c5cca78
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp
@@ -0,0 +1,148 @@
+/*
+**
+** 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();
+ mEnable = 0;
+}
+
+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::setHdmiEnable(uint32_t enable)
+{
+ //LOGD("%s HDMI ENABLE: %d\n", __func__, enable);
+
+ if (g_SecTVOutService != 0)
+ mEnable = enable;
+}
+
+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 && mEnable == 1)
+ 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/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h
new file mode 100644
index 0000000..ebee763
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h
@@ -0,0 +1,86 @@
+/*
+**
+** 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();
+ uint32_t mEnable;
+
+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);
+ void setHdmiEnable(uint32_t enable);
+ 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/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp
new file mode 100644
index 0000000..de98810
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp
@@ -0,0 +1,387 @@
+/*
+**
+** 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 800
+#define DEFAULT_LCD_HEIGHT 480
+
+#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
+
+#ifdef SUPPORT_G2D_UI_MODE
+ if (mHwcLayer == 0) {
+ if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_VIDEO) == false)
+ LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_VIDEO);
+ if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false)
+ LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0);
+ }
+#endif
+
+ 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 !defined(BOARD_USES_HDMI_SUBTITLES)
+#ifdef SUPPORT_G2D_UI_MODE
+ if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false)
+ LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0);
+ if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_1) == false)
+ LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_1);
+#endif
+#endif
+
+#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/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h
new file mode 100644
index 0000000..1f5f251
--- /dev/null
+++ b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h
@@ -0,0 +1,174 @@
+/*
+**
+** 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.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/exynos4/hal/libhdmi/libsForhdmi/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/Android.mk
new file mode 100644
index 0000000..237c53c
--- /dev/null
+++ b/exynos4/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 exynos4,$(TARGET_BOARD_PLATFORM)),)
+include $(all-subdir-makefiles)
+endif
diff --git a/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk
new file mode 100644
index 0000000..9a4b721
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h b/exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h
new file mode 100644
index 0000000..4b0d3af
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c
new file mode 100644
index 0000000..e688051
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h
new file mode 100644
index 0000000..5bbfc15
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk
new file mode 100644
index 0000000..38891be
--- /dev/null
+++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk
@@ -0,0 +1,45 @@
+# 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
+
+LOCAL_MODULE := libddc
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c
new file mode 100644
index 0000000..12910fb
--- /dev/null
+++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c
@@ -0,0 +1,285 @@
+/*
+* 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
+
+/**
+ * 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/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h
new file mode 100644
index 0000000..368855b
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk
new file mode 100644
index 0000000..602ae4d
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h b/exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h
new file mode 100644
index 0000000..aea1309
--- /dev/null
+++ b/exynos4/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/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c
new file mode 100644
index 0000000..c4af587
--- /dev/null
+++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c
@@ -0,0 +1,1262 @@
+/*
+* 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;
+ 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/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h
new file mode 100644
index 0000000..dfd3096
--- /dev/null
+++ b/exynos4/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_ */