summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Havlena <havlenapetr@gmail.com>2012-11-15 14:07:10 +0530
committerGerrit Code Review <gerrit@review.cyanogenmod.com>2012-11-16 05:12:41 -0800
commitc9288149a35eef64908085d9799f2ba908bfabd2 (patch)
tree557c4906a0f6d44d2003508ad1a591bb839a9468
parent1386f44a87281ecfb0309fc7b6ba00209cd7c05f (diff)
downloadandroid_hardware_samsung-c9288149a35eef64908085d9799f2ba908bfabd2.tar.gz
android_hardware_samsung-c9288149a35eef64908085d9799f2ba908bfabd2.tar.bz2
android_hardware_samsung-c9288149a35eef64908085d9799f2ba908bfabd2.zip
exynos3: libhdmi: initial commit
Change-Id: Iee23cf3b6e746c3a20adf7b90ab930a3cba50d5c
-rw-r--r--exynos3/s5pc110/Android.mk2
-rw-r--r--exynos3/s5pc110/include/s5p_tvout.h189
-rwxr-xr-xexynos3/s5pc110/include/sec_lcd.h18
-rw-r--r--exynos3/s5pc110/include/sec_utils.h2
-rw-r--r--exynos3/s5pc110/libhdmi/Android.mk38
-rw-r--r--exynos3/s5pc110/libhdmi/SecHDMI.cpp846
-rw-r--r--exynos3/s5pc110/libhdmi/SecHDMI.h113
-rw-r--r--exynos3/s5pc110/libhdmi/fimc.c722
-rw-r--r--exynos3/s5pc110/libhdmi/fimc.h76
-rw-r--r--exynos3/s5pc110/libhdmi/fimd.c231
-rw-r--r--exynos3/s5pc110/libhdmi/fimd.h54
-rw-r--r--exynos3/s5pc110/libhdmi/hal_module.cpp222
-rw-r--r--exynos3/s5pc110/libhdmi/test/Android.mk61
-rw-r--r--exynos3/s5pc110/libhdmi/test/test.h48
-rw-r--r--exynos3/s5pc110/libhdmi/test/test1.cpp116
-rw-r--r--exynos3/s5pc110/libhdmi/test/test2.cpp97
16 files changed, 2832 insertions, 3 deletions
diff --git a/exynos3/s5pc110/Android.mk b/exynos3/s5pc110/Android.mk
index 56cb24c..46596e9 100644
--- a/exynos3/s5pc110/Android.mk
+++ b/exynos3/s5pc110/Android.mk
@@ -17,7 +17,7 @@
ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
# audio, camera, sensor and light HALs are device specifc
-s5pc110_dirs := libhwcomposer libs3cjpeg libstagefrighthw sec_mm power
+s5pc110_dirs := libhdmi libhwcomposer libs3cjpeg libstagefrighthw sec_mm power
include $(call all-named-subdir-makefiles,$(s5pc110_dirs))
diff --git a/exynos3/s5pc110/include/s5p_tvout.h b/exynos3/s5pc110/include/s5p_tvout.h
new file mode 100644
index 0000000..85b8dad
--- /dev/null
+++ b/exynos3/s5pc110/include/s5p_tvout.h
@@ -0,0 +1,189 @@
+/*
+ * 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 __S5P_TVOUT_H__
+#define __S5P_TVOUT_H__
+
+#include <linux/fb.h>
+#include <linux/videodev2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************
+ * Define
+ *******************************************/
+/* TVOUT control */
+
+#define TVOUT_DEV "/dev/video14"
+#define TVOUT_DEV_V "/dev/video21"
+#define TVOUT_DEV_V2 "/dev/video22"
+
+/* ------------- Output -----------------*/
+/* type */
+#define V4L2_OUTPUT_TYPE_MSDMA 4
+#define V4L2_OUTPUT_TYPE_COMPOSITE 5
+#define V4L2_OUTPUT_TYPE_SVIDEO 6
+#define V4L2_OUTPUT_TYPE_YPBPR_INERLACED 7
+#define V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE 8
+#define V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE 9
+#define V4L2_OUTPUT_TYPE_DIGITAL 10
+#define V4L2_OUTPUT_TYPE_HDMI V4L2_OUTPUT_TYPE_DIGITAL
+#define V4L2_OUTPUT_TYPE_HDMI_RGB 11
+#define V4L2_OUTPUT_TYPE_DVI 12
+
+/* ------------- STD -------------------*/
+#define V4L2_STD_PAL_BDGHI\
+ (V4L2_STD_PAL_B|V4L2_STD_PAL_D|V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_PAL_I)
+
+#define V4L2_STD_480P_60_16_9 ((v4l2_std_id)0x04000000)
+#define V4L2_STD_480P_60_4_3 ((v4l2_std_id)0x05000000)
+#define V4L2_STD_576P_50_16_9 ((v4l2_std_id)0x06000000)
+#define V4L2_STD_576P_50_4_3 ((v4l2_std_id)0x07000000)
+#define V4L2_STD_720P_60 ((v4l2_std_id)0x08000000)
+#define V4L2_STD_720P_50 ((v4l2_std_id)0x09000000)
+#define V4L2_STD_1080P_60 ((v4l2_std_id)0x0a000000)
+#define V4L2_STD_1080P_50 ((v4l2_std_id)0x0b000000)
+#define V4L2_STD_1080I_60 ((v4l2_std_id)0x0c000000)
+#define V4L2_STD_1080I_50 ((v4l2_std_id)0x0d000000)
+#define V4L2_STD_480P_59 ((v4l2_std_id)0x0e000000)
+#define V4L2_STD_720P_59 ((v4l2_std_id)0x0f000000)
+#define V4L2_STD_1080I_59 ((v4l2_std_id)0x10000000)
+#define V4L2_STD_1080P_59 ((v4l2_std_id)0x11000000)
+#define V4L2_STD_1080P_30 ((v4l2_std_id)0x12000000)
+#define V4L2_STD_TVOUT_720P_60_SBS_HALF ((v4l2_std_id)0x13000000)
+#define V4L2_STD_TVOUT_720P_59_SBS_HALF ((v4l2_std_id)0x14000000)
+#define V4L2_STD_TVOUT_720P_50_TB ((v4l2_std_id)0x15000000)
+#define V4L2_STD_TVOUT_1080P_24_TB ((v4l2_std_id)0x16000000)
+#define V4L2_STD_TVOUT_1080P_23_TB ((v4l2_std_id)0x17000000)
+
+/* ------------- Input ------------------*/
+/* type */
+#define V4L2_INPUT_TYPE_MSDMA 3
+#define V4L2_INPUT_TYPE_FIFO 4
+
+/* TVOUT video */
+#define PFX_NODE_FB "/dev/graphics/fb"
+
+/*******************************************
+ * structures
+ *******************************************/
+
+/* TVOUT */
+struct v4l2_vid_overlay_src {
+ void *base_y;
+ void *base_c;
+ struct v4l2_pix_format pix_fmt;
+};
+
+struct v4l2_window_s5p_tvout {
+ __u32 capability;
+ __u32 flags;
+ __u32 priority;
+ struct v4l2_window win;
+};
+
+struct v4l2_pix_format_s5p_tvout {
+ void *base_y;
+ void *base_c;
+ __u32 src_img_endian;
+ struct v4l2_pix_format pix_fmt;
+};
+
+struct vid_overlay_param {
+ struct v4l2_vid_overlay_src src;
+ struct v4l2_rect src_crop;
+ struct v4l2_framebuffer dst;
+ struct v4l2_window dst_win;
+};
+
+struct tvout_param {
+ struct v4l2_pix_format_s5p_tvout tvout_src;
+ struct v4l2_window_s5p_tvout tvout_rect;
+ struct v4l2_rect tvout_dst;
+};
+
+struct overlay_param {
+ struct v4l2_framebuffer overlay_frame;
+ struct v4l2_window_s5p_tvout overlay_rect;
+ struct v4l2_rect overlay_dst;
+};
+
+/* FB */
+struct s5ptvfb_user_window {
+ int x;
+ int y;
+};
+
+struct s5ptvfb_user_plane_alpha {
+ int channel;
+ unsigned char alpha;
+};
+
+struct s5ptvfb_user_chroma {
+ int enabled;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+enum s5ptvfb_ver_scaling_t {
+ VERTICAL_X1,
+ VERTICAL_X2,
+};
+
+enum s5ptvfb_hor_scaling_t {
+ HORIZONTAL_X1,
+ HORIZONTAL_X2,
+};
+
+struct s5ptvfb_user_scaling {
+ enum s5ptvfb_ver_scaling_t ver;
+ enum s5ptvfb_hor_scaling_t hor;
+};
+
+/*******************************************
+ * custom ioctls
+ *******************************************/
+
+#define VIDIOC_S_BASEADDR _IOR('V', 83, int)
+
+#define VIDIOC_HDCP_ENABLE _IOWR('V', 100, unsigned int)
+#define VIDIOC_HDCP_STATUS _IOR('V', 101, unsigned int)
+#define VIDIOC_HDCP_PROT_STATUS _IOR('V', 102, unsigned int)
+
+#define VIDIOC_INIT_AUDIO _IOR('V', 103, unsigned int)
+#define VIDIOC_AV_MUTE _IOR('V', 104, unsigned int)
+#define VIDIOC_G_AVMUTE _IOR('V', 105, unsigned int)
+#define HPD_GET_STATE _IOR('H', 100, unsigned int)
+
+#define S5PTVFB_WIN_POSITION _IOW('F', 213, struct s5ptvfb_user_window)
+#define S5PTVFB_WIN_SET_PLANE_ALPHA _IOW('F', 214, struct s5ptvfb_user_plane_alpha)
+#define S5PTVFB_WIN_SET_CHROMA _IOW('F', 215, struct s5ptvfb_user_chroma)
+
+#define S5PTVFB_SET_VSYNC_INT _IOW('F', 216, unsigned int)
+#define S5PTVFB_WAITFORVSYNC _IO('F', 32)
+#define S5PTVFB_WIN_SET_ADDR _IOW('F', 219, unsigned int)
+#define S5PTVFB_SET_WIN_ON _IOW('F', 220, unsigned int)
+#define S5PTVFB_SET_WIN_OFF _IOW('F', 221, unsigned int)
+#define S5PTVFB_SCALING _IOW('F', 222, struct s5ptvfb_user_scaling)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __S5P_TVOUT_H__ */
diff --git a/exynos3/s5pc110/include/sec_lcd.h b/exynos3/s5pc110/include/sec_lcd.h
index 82ef42f..f104d2d 100755
--- a/exynos3/s5pc110/include/sec_lcd.h
+++ b/exynos3/s5pc110/include/sec_lcd.h
@@ -26,6 +26,18 @@ struct secfb_user_window {
int y;
};
+struct s3cfb_next_info {
+ unsigned int phy_start_addr;
+ unsigned int xres; /* visible resolution*/
+ unsigned int yres;
+ unsigned int xres_virtual; /* virtual resolution*/
+ unsigned int yres_virtual;
+ unsigned int xoffset; /* offset from virtual to visible */
+ unsigned int yoffset; /* resolution */
+ unsigned int lcd_offset_x;
+ unsigned int lcd_offset_y;
+};
+
/*
* C U S T O M I O C T L S
*
@@ -34,13 +46,15 @@ struct secfb_user_window {
#define FBIO_WAITFORVSYNC _IO ('F', 32)
#define SECFB_WIN_POSITION _IOW ('F', 203, struct secfb_user_window)
#define S3CFB_SET_VSYNC_INT _IOW ('F', 206, uint32_t)
+#define S3CFB_GET_CURR_FB_INFO _IOR ('F', 305, struct s3cfb_next_info)
#define S3CFB_WAIT_FOR_VSYNC _IOR ('F', 311, uint64_t)
-#define DEFAULT_LCD_WIDTH (480)
-#define DEFAULT_LCD_HEIGHT (800)
+#define DEFAULT_LCD_WIDTH (600)
+#define DEFAULT_LCD_HEIGHT (1024)
#define DEFAULT_LCD_BPP (32)
/***************** LCD frame buffer *****************/
+#define S3CFB_SIZE 5
#define FB0_NAME "/dev/fb0"
#define FB1_NAME "/dev/fb1"
#define FB2_NAME "/dev/fb2"
diff --git a/exynos3/s5pc110/include/sec_utils.h b/exynos3/s5pc110/include/sec_utils.h
index 3e41afe..be8eaba 100644
--- a/exynos3/s5pc110/include/sec_utils.h
+++ b/exynos3/s5pc110/include/sec_utils.h
@@ -22,6 +22,8 @@
//---------------------------------------------------------//
#include <hardware/hardware.h>
+#include <utils/Log.h>
+
#include "sec_format.h"
#ifdef __cplusplus
diff --git a/exynos3/s5pc110/libhdmi/Android.mk b/exynos3/s5pc110/libhdmi/Android.mk
new file mode 100644
index 0000000..9bfa180
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -fno-short-enums
+LOCAL_CFLAGS += -DLOG_TAG=\"hdmi.$(TARGET_BOARD_PLATFORM)\"
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES := \
+ fimc.c \
+ fimd.c \
+ SecHDMI.cpp \
+ hal_module.cpp
+
+LOCAL_MODULE := hdmi.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := liblog libutils
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/exynos3/s5pc110/libhdmi/SecHDMI.cpp b/exynos3/s5pc110/libhdmi/SecHDMI.cpp
new file mode 100644
index 0000000..eeacb4d
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/SecHDMI.cpp
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2011, Havlena Petr <havlenapetr@gmail.com>
+ *
+ * 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
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+
+#include <sec_lcd.h>
+
+#include "SecHDMI.h"
+#include "fimd.h"
+
+using namespace android;
+
+#define RETURN_IF(return_value) \
+ if (return_value < 0) { \
+ ALOGE("%s::%d fail. errno: %s", \
+ __func__, __LINE__, strerror(errno)); \
+ return -1; \
+ }
+
+#define ALOG_IF(return_value) \
+ if (return_value < 0) { \
+ ALOGE("%s::%d fail. errno: %s", \
+ __func__, __LINE__, strerror(errno)); \
+ }
+
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+
+struct s5p_tv_standart_internal {
+ int index;
+ unsigned long value;
+} s5p_tv_standards[] = {
+ {
+ S5P_TV_STD_NTSC_M,
+ V4L2_STD_NTSC_M,
+ }, {
+ S5P_TV_STD_PAL_BDGHI,
+ V4L2_STD_PAL_BDGHI,
+ }, {
+ S5P_TV_STD_PAL_M,
+ V4L2_STD_PAL_M,
+ }, {
+ S5P_TV_STD_PAL_N,
+ V4L2_STD_PAL_N,
+ }, {
+ S5P_TV_STD_PAL_Nc,
+ V4L2_STD_PAL_Nc,
+ }, {
+ S5P_TV_STD_PAL_60,
+ V4L2_STD_PAL_60,
+ }, {
+ S5P_TV_STD_NTSC_443,
+ V4L2_STD_NTSC_443,
+ }, {
+ S5P_TV_STD_480P_60_16_9,
+ V4L2_STD_480P_60_16_9,
+ }, {
+ S5P_TV_STD_480P_60_4_3,
+ V4L2_STD_480P_60_4_3,
+ }, {
+ S5P_TV_STD_576P_50_16_9,
+ V4L2_STD_576P_50_16_9,
+ }, {
+ S5P_TV_STD_576P_50_4_3,
+ V4L2_STD_576P_50_4_3,
+ }, {
+ S5P_TV_STD_720P_60,
+ V4L2_STD_720P_60,
+ }, {
+ S5P_TV_STD_720P_50,
+ V4L2_STD_720P_50,
+ },
+};
+
+static inline int calcFrameSize(int format, int width, int height)
+{
+ int size = 0;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ size = (width * height * 3 / 2);
+ break;
+
+ case V4L2_PIX_FMT_NV12T:
+ size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height)) +
+ ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2));
+ break;
+
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ size = (width * height * 2);
+ break;
+
+ default :
+ ALOGE("ERR(%s):Invalid V4L2 pixel format(%d)\n", __func__, format);
+ case V4L2_PIX_FMT_RGB565:
+ size = (width * height * 2);
+ break;
+ }
+ return size;
+}
+
+static int get_pixel_depth(unsigned int fmt)
+{
+ int depth = 0;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_NV12:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ depth = 12;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ depth = 16;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ depth = 32;
+ break;
+ }
+
+ return depth;
+}
+
+// ======================================================================
+// Video ioctls
+
+static int tv20_v4l2_querycap(int fp)
+{
+ struct v4l2_capability cap;
+
+ int ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ ALOGE("ERR(%s):no output devices\n", __func__);
+ return -1;
+ }
+ ALOGV("Name of cap driver is %s", cap.driver);
+
+ return ret;
+}
+
+static const __u8* tv20_v4l2_enum_output(int fp, int index)
+{
+ static struct v4l2_output output;
+
+ output.index = index;
+ if (ioctl(fp, VIDIOC_ENUMOUTPUT, &output) != 0) {
+ ALOGE("ERR(%s):No matching index found", __func__);
+ return NULL;
+ }
+ ALOGV("Name of output channel[%d] is %s", output.index, output.name);
+
+ return output.name;
+}
+
+static const __u8* tv20_v4l2_enum_standarts(int fp, int index)
+{
+ static struct v4l2_standard standart;
+
+ standart.index = index;
+ if (ioctl(fp, VIDIOC_ENUMSTD, &standart) != 0) {
+ ALOGE("ERR(%s):No matching index found\n", __func__);
+ return NULL;
+ }
+ ALOGV("Name of output standart[%d] is %s\n", standart.index, standart.name);
+
+ return standart.name;
+}
+
+static int tv20_v4l2_s_output(int fp, int index)
+{
+ struct v4l2_output output;
+ int ret;
+
+ output.index = index;
+
+ ret = ioctl(fp, VIDIOC_S_OUTPUT, &output);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_S_OUPUT failed\n", __func__);
+ return ret;
+ }
+ return ret;
+}
+
+static int tv20_v4l2_s_std(int fp, unsigned long id)
+{
+ v4l2_std_id std;
+ int ret;
+
+ std = id;
+
+ ret = ioctl(fp, VIDIOC_S_STD, &std);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_S_OUPUT failed\n", __func__);
+ return ret;
+ }
+ return ret;
+}
+
+static int tv20_v4l2_enum_fmt(int fp, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ fmtdesc.index = 0;
+
+ while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ ALOGV("passed fmt = %#x found pixel format[%d]: %s\n", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ ALOGE("unsupported pixel format\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tv20_v4l2_s_fmt(int fp, int width, int height,
+ unsigned int fmt, unsigned int yAddr, unsigned int cAddr)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format_s5p_tvout pixfmt;
+ int ret;
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+#if 0
+ ret = ioctl(fp, VIDIOC_G_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_G_FMT failed", __func__);
+ return -1;
+ }
+#endif
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+ pixfmt.pix_fmt.width = width;
+ pixfmt.pix_fmt.height = height;
+ pixfmt.pix_fmt.pixelformat = fmt;
+ pixfmt.pix_fmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
+ pixfmt.pix_fmt.field = V4L2_FIELD_NONE;
+
+ // here we must set addresses of our memory for video out
+ pixfmt.base_y = (void *)yAddr;
+ pixfmt.base_c = (void* )cAddr;
+
+ v4l2_fmt.fmt.pix = pixfmt.pix_fmt;
+ memcpy(v4l2_fmt.fmt.raw_data, &pixfmt,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+
+ /* Set up for capture */
+ ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+static int tv20_v4l2_streamon(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int tv20_v4l2_streamoff(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ int ret;
+
+ ALOGV("%s :", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_STREAMOFF failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int tv20_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ ret = ioctl(fp, VIDIOC_G_PARM, streamparm);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_G_PARM failed\n", __func__);
+ return -1;
+ }
+
+ ALOGV("%s : timeperframe: numerator %d, denominator %d\n", __func__,
+ streamparm->parm.capture.timeperframe.numerator,
+ streamparm->parm.capture.timeperframe.denominator);
+
+ return 0;
+}
+
+static int tv20_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+static int tv20_v4l2_s_crop(int fp, int offset_x, int offset_y, int width, int height)
+{
+ struct v4l2_crop crop;
+
+ crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ crop.c.left = offset_x;
+ crop.c.top = offset_y;
+ crop.c.width = width;
+ crop.c.height = height;
+
+ int ret = ioctl(fp, VIDIOC_S_CROP, &crop);
+ if (ret < 0) {
+ ALOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+static int tv20_v4l2_start_overlay(int fp)
+{
+ int ret, start = 1;
+
+ ret = ioctl(fp, VIDIOC_OVERLAY, &start);
+ if (ret < 0) {
+ ALOGE("ERR(%s): VIDIOC_OVERLAY start failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int tv20_v4l2_stop_overlay(int fp)
+{
+ int ret, stop = 0;
+
+ ret = ioctl(fp, VIDIOC_OVERLAY, &stop);
+ if (ret < 0) {
+ ALOGE("ERR(%s): VIDIOC_OVERLAY stop failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int tv20_v4l2_s_baseaddr(int fp, void *base_addr)
+{
+ int ret;
+
+ ret = ioctl(fp, S5PTVFB_WIN_SET_ADDR, base_addr);
+ if (ret < 0) {
+ ALOGE("ERR(%s): VIDIOC_S_BASEADDR failed %d", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tv20_v4l2_s_position(int fp, int x, int y)
+{
+ int ret;
+ struct s5ptvfb_user_window window;
+
+ memset(&window, 0, sizeof(struct s5ptvfb_user_window));
+ window.x = x;
+ window.y = y;
+
+ ret = ioctl(fp, S5PTVFB_WIN_POSITION, &window);
+ if (ret < 0) {
+ ALOGE("ERR(%s): VIDIOC_S_WIN_POSITION failed %d", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+// ======================================================================
+// Audio ioctls
+
+static int tv20_v4l2_audio_enable(int fp)
+{
+ return ioctl(fp, VIDIOC_INIT_AUDIO, 1);
+}
+
+static int tv20_v4l2_audio_disable(int fp)
+{
+ return ioctl(fp, VIDIOC_INIT_AUDIO, 0);
+}
+
+static int tv20_v4l2_audio_mute(int fp)
+{
+ return ioctl(fp, VIDIOC_AV_MUTE, 1);
+}
+
+static int tv20_v4l2_audio_unmute(int fp)
+{
+ return ioctl(fp, VIDIOC_AV_MUTE, 0);
+}
+
+static int tv20_v4l2_audio_get_mute_state(int fp)
+{
+ return ioctl(fp, VIDIOC_G_AVMUTE, 0);
+}
+
+// ======================================================================
+// Class which comunicate with kernel driver
+
+SecHDMI::SecHDMI()
+ : mTvOutFd(-1),
+ mTvOutVFd(-1),
+ mLcdFd(-1),
+ mHdcpEnabled(0),
+ mFlagConnected(false)
+{
+ ALOGV("%s", __func__);
+
+ memset(&mParams, 0, sizeof(struct v4l2_streamparm));
+ memset(&mFlagLayerEnable, 0, sizeof(bool) * S5P_TV_LAYER_MAX);
+
+ int ret = ioctl(mTvOutFd, VIDIOC_HDCP_ENABLE, &mHdcpEnabled);
+ ALOG_IF(ret);
+}
+
+SecHDMI::~SecHDMI()
+{
+ destroy();
+}
+
+/* static */
+int SecHDMI::getCableStatus()
+{
+ int fd = 0;
+ char value[8] = {0};
+
+ ALOGV("%s", __func__);
+
+ fd = open("/sys/class/switch/h2w/state", O_RDWR);
+ if(fd < 0) {
+ goto close;
+ }
+
+ if(read(fd, &value, 8) <= 0) {
+ goto close;
+ }
+
+close:
+ close(fd);
+ return strtol(value, NULL, 10);
+}
+
+const __u8* SecHDMI::getName(int index)
+{
+ ALOGV("%s", __func__);
+ return tv20_v4l2_enum_output(mTvOutFd, index);
+}
+
+int SecHDMI::destroy()
+{
+ ALOGV("%s", __func__);
+
+ if(mFlagConnected) {
+ disconnect();
+ }
+ if(mTvOutFd > 0) {
+ close(mTvOutFd);
+ mTvOutFd = -1;
+ }
+ if(mFimc.dev_fd > 0) {
+ fimc_close(&mFimc);
+ mFimc.dev_fd = -1;
+ }
+ if (mLcdFd > 0) {
+ fb_close(mLcdFd);
+ mLcdFd = -1;
+ }
+
+ return 0;
+}
+
+int SecHDMI::startLayer(s5p_tv_layer layer)
+{
+ int ret;
+
+ if (mFlagLayerEnable[layer]) {
+ return 0;
+ }
+
+ switch (layer) {
+ case S5P_TV_LAYER_VIDEO:
+ if(mTvOutVFd < 0) {
+ mTvOutVFd = open(TVOUT_DEV_V, O_RDWR);
+ RETURN_IF(mTvOutVFd);
+ }
+ ret = tv20_v4l2_start_overlay(mTvOutVFd);
+ RETURN_IF(ret);
+ break;
+ case S5P_TV_LAYER_GRAPHIC_0 :
+ ret = ioctl(0/*fp_tvout_g0*/, FBIOBLANK, (void *)FB_BLANK_UNBLANK);
+ RETURN_IF(ret);
+ break;
+ case S5P_TV_LAYER_GRAPHIC_1 :
+ ret = ioctl(0/*fp_tvout_g1*/, FBIOBLANK, (void *)FB_BLANK_UNBLANK);
+ RETURN_IF(ret);
+ break;
+ default :
+ RETURN_IF(-1);
+ }
+
+ mFlagLayerEnable[layer] = true;
+
+ return 0;
+}
+
+int SecHDMI::stopLayer(s5p_tv_layer layer)
+{
+ int ret;
+
+ if (!mFlagLayerEnable[layer]) {
+ return 0;
+ }
+
+ switch (layer) {
+ case S5P_TV_LAYER_VIDEO:
+ ret = tv20_v4l2_stop_overlay(mTvOutVFd);
+ RETURN_IF(ret);
+ close(mTvOutVFd);
+ mTvOutVFd = -1;
+ break;
+ case S5P_TV_LAYER_GRAPHIC_0 :
+ ret = ioctl(0/*fp_tvout_g0*/, FBIOBLANK, (void *)FB_BLANK_POWERDOWN);
+ RETURN_IF(ret);
+ break;
+ case S5P_TV_LAYER_GRAPHIC_1 :
+ ret = ioctl(0/*fp_tvout_g1*/, FBIOBLANK, (void *)FB_BLANK_POWERDOWN);
+ RETURN_IF(ret);
+ break;
+ default :
+ RETURN_IF(-1);
+ }
+
+ mFlagLayerEnable[layer] = false;
+
+ return 0;
+}
+
+int SecHDMI::create(int width, int height)
+{
+ int ret, y_size;
+ unsigned int addr;
+
+ ALOGV("%s", __func__);
+
+ mTvOutFd = open(TVOUT_DEV, O_RDWR);
+ RETURN_IF(mTvOutFd);
+
+ memset(&mFimc, 0, sizeof(s5p_fimc_t));
+ mFimc.dev_fd = -1;
+ ret = fimc_open(&mFimc, "/dev/video2");
+ RETURN_IF(ret);
+
+ ALOGV("query capabilities");
+ ret = tv20_v4l2_querycap(mTvOutFd);
+ RETURN_IF(ret);
+
+ struct s5p_tv_standart_internal std =
+ s5p_tv_standards[(int) S5P_TV_STD_PAL_BDGHI];
+
+ ALOGV("searching for standart: %i", std.index);
+ if(!tv20_v4l2_enum_standarts(mTvOutFd, std.index))
+ return -1;
+
+ ret = tv20_v4l2_s_std(mTvOutFd, std.value);
+ RETURN_IF(ret);
+
+ ALOGV("searching for output: %i", S5P_TV_OUTPUT_TYPE_COMPOSITE);
+ if (!tv20_v4l2_enum_output(mTvOutFd, S5P_TV_OUTPUT_TYPE_COMPOSITE))
+ return -1;
+
+ ret = tv20_v4l2_s_output(mTvOutFd, S5P_TV_OUTPUT_TYPE_COMPOSITE);
+ RETURN_IF(ret);
+
+ struct v4l2_window_s5p_tvout* p =
+ (struct v4l2_window_s5p_tvout*)&mParams.parm.raw_data;
+ p->win.w.top = 0;
+ p->win.w.left = 0;
+ p->win.w.width = width;
+ p->win.w.height = height;
+
+ ALOGV("searching for format: %i", V4L2_PIX_FMT_NV12);
+ ret = tv20_v4l2_enum_fmt(mTvOutFd, V4L2_PIX_FMT_NV12);
+ RETURN_IF(ret);
+
+ addr = (unsigned int) mFimc.out_buf.phys_addr;
+ y_size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height));
+ ret = tv20_v4l2_s_fmt(mTvOutFd, width, height, V4L2_PIX_FMT_NV12,
+ (unsigned int) addr,
+ (unsigned int) addr + y_size);
+ RETURN_IF(ret);
+
+ return 0;
+}
+
+int SecHDMI::connect()
+{
+ int ret;
+
+ ALOGV("%s", __func__);
+
+ RETURN_IF(mTvOutFd);
+
+ if(mFlagConnected) {
+ return 0;
+ }
+
+#if 0
+ ret = getCableStatus() <= 0 ? -1 : 0;
+ RETURN_IF(ret);
+#endif
+
+ ret = tv20_v4l2_s_parm(mTvOutFd, &mParams);
+ RETURN_IF(ret);
+
+ ret = tv20_v4l2_streamon(mTvOutFd);
+ RETURN_IF(ret);
+
+#if 0
+ ret = startLayer(S5P_TV_LAYER_VIDEO);
+ RETURN_IF(ret);
+#endif
+
+ mFlagConnected = true;
+
+ return 0;
+}
+
+int SecHDMI::disconnect()
+{
+ int ret;
+
+ ALOGV("%s", __func__);
+
+ RETURN_IF(mTvOutFd);
+
+ if(!mFlagConnected) {
+ return 0;
+ }
+
+ ret = tv20_v4l2_streamoff(mTvOutFd);
+ RETURN_IF(ret);
+
+#if 0
+ ret = stopLayer(S5P_TV_LAYER_VIDEO);
+ RETURN_IF(ret);
+#endif
+
+ mFlagConnected = false;
+
+ return 0;
+}
+
+int SecHDMI::flush(int srcW, int srcH, int srcColorFormat,
+ unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr,
+ int dstX, int dstY,
+ int layer,
+ int num_of_hwc_layer)
+{
+ int ret;
+
+#if 0
+ usleep(1000 * 10);
+#else
+ sec_img src_img;
+ sec_img dst_img;
+ sec_rect src_rect;
+ sec_rect dst_rect;
+ unsigned int phyAddr[3/*MAX_NUM_PLANES*/];
+
+ if(!srcYAddr) {
+ struct s3cfb_next_info fb_info;
+
+ if (mLcdFd < 0) {
+ mLcdFd = fb_open(0);
+ }
+
+ RETURN_IF(mLcdFd);
+
+ ret = ioctl(mLcdFd, S3CFB_GET_CURR_FB_INFO, &fb_info);
+ RETURN_IF(ret);
+
+ srcYAddr = fb_info.phy_start_addr;
+ srcCbAddr = srcYAddr;
+ }
+
+ memset(&src_img, 0, sizeof(src_img));
+ memset(&dst_img, 0, sizeof(src_img));
+ memset(&src_rect, 0, sizeof(src_rect));
+ memset(&dst_rect, 0, sizeof(src_rect));
+ memset(&phyAddr, 0, sizeof(int) * sizeof(phyAddr));
+
+ phyAddr[0] = srcYAddr;
+ phyAddr[1] = srcCbAddr;
+ phyAddr[2] = srcCrAddr;
+
+ src_img.w = srcW;
+ src_img.h = srcH;
+ src_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP/*srcColorFormat*/;
+ src_img.base = 0;
+ src_img.offset = 0;
+ src_img.mem_id = 0;
+ src_img.mem_type = FIMC_MEM_TYPE_PHYS;
+ src_img.w = (src_img.w + 15) & (~15);
+ src_img.h = (src_img.h + 1) & (~1) ;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.w = src_img.w;
+ src_rect.h = src_img.h;
+
+ struct v4l2_window_s5p_tvout* p =
+ (struct v4l2_window_s5p_tvout*)&mParams.parm.raw_data;
+ if (!p) {
+ return -1;
+ }
+
+ dst_img.w = p->win.w.width;
+ dst_img.h = p->win.w.height;
+ dst_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ dst_img.base = (unsigned int) mFimc.out_buf.phys_addr;
+ dst_img.offset = 0;
+ dst_img.mem_id = 0;
+ dst_img.mem_type = FIMC_MEM_TYPE_PHYS;
+
+ dst_rect.x = p->win.w.top;
+ dst_rect.y = p->win.w.left;
+ dst_rect.w = dst_img.w;
+ dst_rect.h = dst_img.h;
+
+ ALOGV("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
+ __func__, src_rect.x, src_rect.y, src_rect.w, src_rect.h,
+ dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+
+ ret = fimc_flush(&mFimc, &src_img, &src_rect, &dst_img, &dst_rect,
+ phyAddr, 0);
+ RETURN_IF(ret);
+
+/*
+ struct fb_var_screeninfo var;
+ var.xres = srcW;
+ var.yres = srcH;
+ var.xres_virtual = var.xres;
+ var.yres_virtual = var.yres;
+ var.xoffset = 0;
+ var.yoffset = 0;
+ var.width = srcW;
+ var.height = srcH;
+ 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;
+ }
+
+ ret = tv20_v4l2_s_baseaddr(mTvOutFd, (void *)srcYAddr);
+ RETURN_IF(ret);
+
+ ret = fb_put_vscreeninfo(mLcdFd, &var);
+ RETURN_IF(ret);
+
+ ret = tv20_v4l2_s_position(mTvOutFd, dstX, dstY);
+ RETURN_IF(ret);
+*/
+#endif
+
+ return 0;
+}
diff --git a/exynos3/s5pc110/libhdmi/SecHDMI.h b/exynos3/s5pc110/libhdmi/SecHDMI.h
new file mode 100644
index 0000000..c2f6f9b
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/SecHDMI.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011, Havlena Petr <havlenapetr@gmail.com>
+ *
+ * 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_HARDWARE_SEC_TV_H
+#define ANDROID_HARDWARE_SEC_TV_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+
+#include <linux/videodev2.h>
+#include <s5p_tvout.h>
+
+#include "fimc.h"
+
+namespace android {
+
+enum s5p_tv_standart {
+ S5P_TV_STD_NTSC_M = 0,
+ S5P_TV_STD_PAL_BDGHI,
+ S5P_TV_STD_PAL_M,
+ S5P_TV_STD_PAL_N,
+ S5P_TV_STD_PAL_Nc,
+ S5P_TV_STD_PAL_60,
+ S5P_TV_STD_NTSC_443,
+ S5P_TV_STD_480P_60_16_9,
+ S5P_TV_STD_480P_60_4_3,
+ S5P_TV_STD_576P_50_16_9,
+ S5P_TV_STD_576P_50_4_3,
+ S5P_TV_STD_720P_60,
+ S5P_TV_STD_720P_50
+};
+
+// must match with s5p_tv_outputs in s5p_tv_v4l.c
+enum s5p_tv_output {
+ S5P_TV_OUTPUT_TYPE_COMPOSITE = 0,
+ S5P_TV_OUTPUT_TYPE_SVIDEO,
+ S5P_TV_OUTPUT_TYPE_YPBPR_INERLACED,
+ S5P_TV_OUTPUT_TYPE_YPBPR_PROGRESSIVE,
+ S5P_TV_OUTPUT_TYPE_RGB_PROGRESSIVE,
+ S5P_TV_OUTPUT_TYPE_HDMI,
+};
+
+class SecHDMI {
+public:
+ SecHDMI();
+ ~SecHDMI();
+
+ static int getCableStatus();
+
+ int create(int width, int height);
+ int destroy();
+
+ int connect();
+ int disconnect();
+
+ int flush(int srcW, int srcH, int srcColorFormat,
+ unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr,
+ int dstX, int dstY,
+ int layer,
+ int num_of_hwc_layer);
+
+ const __u8* getName(int index);
+
+private:
+ enum s5p_tv_layer {
+ S5P_TV_LAYER_BASE = 0,
+ S5P_TV_LAYER_VIDEO,
+ S5P_TV_LAYER_GRAPHIC_0,
+ S5P_TV_LAYER_GRAPHIC_1,
+ S5P_TV_LAYER_MAX,
+ };
+
+ int mTvOutFd;
+ int mTvOutVFd;
+ int mLcdFd;
+ unsigned int mHdcpEnabled;
+ bool mFlagConnected;
+ bool mFlagLayerEnable[S5P_TV_LAYER_MAX];
+
+ s5p_fimc_t mFimc;
+ v4l2_streamparm mParams;
+
+ int startLayer(s5p_tv_layer layer);
+ int stopLayer(s5p_tv_layer layer);
+};
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_SEC_TV_H
diff --git a/exynos3/s5pc110/libhdmi/fimc.c b/exynos3/s5pc110/libhdmi/fimc.c
new file mode 100644
index 0000000..e229eb7
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/fimc.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2010 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 <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/videodev.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <cutils/log.h>
+
+#include "fimc.h"
+
+typedef struct sec_img sec_img;
+typedef struct sec_rect sec_rect;
+
+int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src)
+{
+ struct v4l2_format fmt;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_requestbuffers req;
+
+ /*
+ * To set size & format for source image (DMA-INPUT)
+ */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ fmt.fmt.pix.width = src->full_width;
+ fmt.fmt.pix.height = src->full_height;
+ fmt.fmt.pix.pixelformat = src->color_space;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ if (ioctl (fd, VIDIOC_S_FMT, &fmt) < 0) {
+ ALOGE("VIDIOC_S_FMT failed : errno=%d (%s) : fd=%d", errno,
+ strerror(errno), fd);
+ return -1;
+ }
+
+ /*
+ * crop input size
+ */
+ crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (0x50 == hw_ver) {
+ crop.c.left = src->start_x;
+ crop.c.top = src->start_y;
+ } else {
+ crop.c.left = 0;
+ crop.c.top = 0;
+ }
+ crop.c.width = src->width;
+ crop.c.height = src->height;
+ if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+ ALOGE("Error in video VIDIOC_S_CROP (%d, %d, %d, %d)",
+ crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+ return -1;
+ }
+
+ /*
+ * input buffer type
+ */
+ req.count = 1;
+ req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_REQBUFS, &req) < 0) {
+ ALOGE("Error in VIDIOC_REQBUFS");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_set_dst(int fd,
+ s5p_fimc_img_info *dst,
+ int rotation,
+ int flag_h_flip,
+ int flag_v_flip,
+ unsigned int addr)
+{
+ struct v4l2_format fmt;
+ struct v4l2_control vc;
+ struct v4l2_framebuffer fbuf;
+
+ /*
+ * set rotation configuration
+ */
+ vc.id = V4L2_CID_HFLIP;
+ vc.value = flag_h_flip;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ ALOGE("Error in video VIDIOC_S_CTRL - flag_h_flip (%d)", flag_h_flip);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_VFLIP;
+ vc.value = flag_v_flip;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ ALOGE("Error in video VIDIOC_S_CTRL - flag_v_flip (%d)", flag_v_flip);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_ROTATION;
+ vc.value = rotation;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ ALOGE("Error in video VIDIOC_S_CTRL - rotation (%d)", rotation);
+ return -1;
+ }
+
+ /*
+ * set size, format & address for destination image (DMA-OUTPUT)
+ */
+ if (ioctl (fd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ ALOGE("Error in video VIDIOC_G_FBUF");
+ return -1;
+ }
+
+ fbuf.base = (void *)addr;
+ fbuf.fmt.width = dst->full_width;
+ fbuf.fmt.height = dst->full_height;
+ fbuf.fmt.pixelformat = dst->color_space;
+ if (ioctl (fd, VIDIOC_S_FBUF, &fbuf) < 0) {
+ ALOGE("Error in video VIDIOC_S_FBUF 0x%x %d %d %d",
+ (void *)addr, dst->full_width, dst->full_height,
+ dst->color_space);
+ return -1;
+ }
+
+ /*
+ * set destination window
+ */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ fmt.fmt.win.w.left = dst->start_x;
+ fmt.fmt.win.w.top = dst->start_y;
+ fmt.fmt.win.w.width = dst->width;
+ fmt.fmt.win.w.height = dst->height;
+ if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
+ ALOGE("Error in video VIDIOC_S_FMT %d %d %d %d",
+ dst->start_x, dst->start_y, dst->width, dst->height);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
+{
+ if (ioctl (fd, VIDIOC_STREAMON, &type) < 0) {
+ ALOGE("Error in VIDIOC_STREAMON");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf)
+{
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.m.userptr = (unsigned long)fimc_buf;
+ buf.length = 0;
+ buf.index = 0;
+
+ if (ioctl (fd, VIDIOC_QBUF, &buf) < 0) {
+ ALOGE("Error in VIDIOC_QBUF");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_dequeue(int fd)
+{
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ buf.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_DQBUF, &buf) < 0) {
+ ALOGE("Error in VIDIOC_DQBUF");
+ return -1;
+ }
+
+ return buf.index;
+}
+
+static int fimc_v4l2_stream_off(int fd)
+{
+ enum v4l2_buf_type type;
+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ if (ioctl (fd, VIDIOC_STREAMOFF, &type) < 0) {
+ ALOGE("Error in VIDIOC_STREAMOFF");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_clr_buf(int fd)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = 0;
+ req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_REQBUFS, &req) < 0) {
+ ALOGE("Error in VIDIOC_REQBUFS");
+ }
+
+ return 0;
+}
+
+static int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_buf)
+{
+ int ret =0;
+
+ if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT) < 0) {
+ ALOGE("Fail : v4l2_stream_on()");
+ return -1;
+ }
+
+ if (fimc_v4l2_queue(fd, fimc_buf) < 0) {
+ ALOGE("Fail : v4l2_queue()");
+ ret = -1;
+ goto stream_off;
+ }
+
+ if (fimc_v4l2_dequeue(fd) < 0) {
+ ALOGE("Fail : v4l2_dequeue()");
+ ret = -1;
+ goto stream_off;
+ }
+
+stream_off:
+ if (fimc_v4l2_stream_off(fd) < 0) {
+ ALOGE("Fail : v4l2_stream_off()");
+ return -1;
+ }
+
+ if (fimc_v4l2_clr_buf(fd) < 0) {
+ ALOGE("Fail : v4l2_clr_buf()");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int get_src_phys_addr(s5p_fimc_t *fimc,
+ sec_img *src_img,
+ unsigned int *phyAddr)
+{
+ if(src_img->mem_type == FIMC_MEM_TYPE_PHYS) {
+ switch(src_img->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ fimc->params.src.buf_addr_phy_rgb_y = phyAddr[0];
+ fimc->params.src.buf_addr_phy_cb = phyAddr[1];
+ break;
+ default:
+ ALOGE("%s format error (format=0x%x)", __func__,
+ src_img->format);
+ return -1;
+ }
+ } else {
+ ALOGE("%s mem_type error (mem_type=%d)", __func__, src_img->mem_type);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int get_dst_phys_addr(s5p_fimc_t *fimc,
+ sec_img *dst_img)
+{
+ unsigned int dst_phys_addr = 0;
+
+ if (FIMC_MEM_TYPE_PHYS == dst_img->mem_type && 0 != dst_img->base)
+ dst_phys_addr = dst_img->base;
+ else {
+ ALOGE("%s::get_dst_phys_addr fail ", __func__);
+ dst_phys_addr = 0;
+ }
+ return dst_phys_addr;
+}
+
+static inline int rotateValueHAL2PP(unsigned char transform,
+ int *flag_h_flip,
+ int *flag_v_flip)
+{
+ int rotate_result = 0;
+ int rotate_flag = transform & 0x7;
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_ROT_90:
+ rotate_result = 90;
+ break;
+ case HAL_TRANSFORM_ROT_180:
+ rotate_result = 180;
+ break;
+ case HAL_TRANSFORM_ROT_270:
+ rotate_result = 270;
+ break;
+ }
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_FLIP_H:
+ *flag_h_flip = 1;
+ *flag_v_flip = 0;
+ break;
+ case HAL_TRANSFORM_FLIP_V:
+ *flag_h_flip = 0;
+ *flag_v_flip = 1;
+ break;
+ default:
+ *flag_h_flip = 0;
+ *flag_v_flip = 0;
+ break;
+ }
+
+ return rotate_result;
+}
+
+static inline int multipleOfN(int number, int N)
+{
+ int result = number;
+ switch (N) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ result = (number - (number & (N-1)));
+ break;
+ default:
+ result = number - (number % N);
+ break;
+ }
+ return result;
+}
+
+static inline int widthOfPP(unsigned int ver,
+ int pp_color_format,
+ int number)
+{
+ if (0x50 == ver) {
+ switch(pp_color_format) {
+ /* 422 1/2/3 plane */
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_YUV422P:
+
+ /* 420 2/3 plane */
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 2);
+
+ default :
+ return number;
+ }
+ } else {
+ switch(pp_color_format) {
+ case V4L2_PIX_FMT_RGB565:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_RGB32:
+ return multipleOfN(number, 4);
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ return multipleOfN(number, 4);
+
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_YUV422P:
+ return multipleOfN(number, 16);
+
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 16);
+
+ default :
+ return number;
+ }
+ }
+ return number;
+}
+
+static inline int heightOfPP(int pp_color_format,
+ int number)
+{
+ switch(pp_color_format) {
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 2);
+
+ default :
+ return number;
+ }
+ return number;
+}
+
+static int fimc_core(s5p_fimc_t *fimc,
+ sec_img *src_img,
+ sec_rect *src_rect,
+ uint32_t src_color_space,
+ unsigned int dst_phys_addr,
+ sec_img *dst_img,
+ sec_rect *dst_rect,
+ uint32_t dst_color_space,
+ int transform)
+{
+ s5p_fimc_params_t * params = &(fimc->params);
+
+ unsigned int frame_size = 0;
+ struct fimc_buf fimc_src_buf;
+
+ int src_bpp, src_planes;
+ int flag_h_flip = 0;
+ int flag_v_flip = 0;
+ int rotate_value = rotateValueHAL2PP(transform, &flag_h_flip, &flag_v_flip);
+
+ /* set post processor configuration */
+ params->src.full_width = src_img->w;
+ params->src.full_height = src_img->h;
+ params->src.start_x = src_rect->x;
+ params->src.start_y = src_rect->y;
+ params->src.width = widthOfPP(fimc->hw_ver, src_color_space, src_rect->w);
+ params->src.height = heightOfPP(src_color_space, src_rect->h);
+ params->src.color_space = src_color_space;
+
+
+ /* check minimum */
+ if (src_rect->w < 16 || src_rect->h < 8) {
+ ALOGE("%s src size is not supported by fimc : f_w=%d f_h=%d x=%d y=%d \
+ w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
+ params->src.full_width, params->src.full_height,
+ params->src.start_x, params->src.start_y, params->src.width,
+ params->src.height, src_rect->w, src_rect->h,
+ params->src.color_space);
+ return -1;
+ }
+
+ switch (rotate_value) {
+ case 0:
+ params->dst.full_width = dst_img->w;
+ params->dst.full_height = dst_img->h;
+
+ params->dst.start_x = dst_rect->x;
+ params->dst.start_y = dst_rect->y;
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+ params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
+ break;
+ case 90:
+ params->dst.full_width = dst_img->h;
+ params->dst.full_height = dst_img->w;
+
+ params->dst.start_x = dst_rect->y;
+ params->dst.start_y = dst_img->w - (dst_rect->x + dst_rect->w);
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
+ params->dst.height =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+
+ if (0x50 > fimc->hw_ver)
+ params->dst.start_y += (dst_rect->w - params->dst.height);
+ break;
+ case 180:
+ params->dst.full_width = dst_img->w;
+ params->dst.full_height = dst_img->h;
+
+ params->dst.start_x = dst_img->w - (dst_rect->x + dst_rect->w);
+ params->dst.start_y = dst_img->h - (dst_rect->y + dst_rect->h);
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+ params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
+ break;
+ case 270:
+ params->dst.full_width = dst_img->h;
+ params->dst.full_height = dst_img->w;
+
+ params->dst.start_x = dst_img->h - (dst_rect->y + dst_rect->h);
+ params->dst.start_y = dst_rect->x;
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
+ params->dst.height =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+
+ if (0x50 > fimc->hw_ver)
+ params->dst.start_y += (dst_rect->w - params->dst.height);
+ break;
+ }
+
+ params->dst.color_space = dst_color_space;
+
+ /* check minimum */
+ if (dst_rect->w < 8 || dst_rect->h < 4) {
+ ALOGE("%s dst size is not supported by fimc : \
+ f_w=%d f_h=%d x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x",
+ __func__, params->dst.full_width, params->dst.full_height,
+ params->dst.start_x, params->dst.start_y, params->dst.width,
+ params->dst.height, dst_rect->w, dst_rect->h,
+ params->dst.color_space);
+ return -1;
+ }
+
+ /* check scaling limit
+ * the scaling limie must not be more than MAX_RESIZING_RATIO_LIMIT
+ */
+ if (((src_rect->w > dst_rect->w) &&
+ ((src_rect->w / dst_rect->w) > MAX_RESIZING_RATIO_LIMIT)) ||
+ ((dst_rect->w > src_rect->w) &&
+ ((dst_rect->w / src_rect->w) > MAX_RESIZING_RATIO_LIMIT))) {
+ ALOGE("%s over scaling limit : src.w=%d dst.w=%d (limit=%d)",
+ __func__, src_rect->w, dst_rect->w, MAX_RESIZING_RATIO_LIMIT);
+ return -1;
+ }
+
+
+ /* set configuration related to destination (DMA-OUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+ if (fimc_v4l2_set_dst(fimc->dev_fd,
+ &params->dst,
+ rotate_value,
+ flag_h_flip,
+ flag_v_flip,
+ dst_phys_addr) < 0) {
+ return -1;
+ }
+
+ /* set configuration related to source (DMA-INPUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+ if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, &params->src) < 0)
+ return -1;
+
+ /* set input dma address (Y/RGB, Cb, Cr) */
+ switch (src_img->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ /* for video display zero copy case */
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ break;
+
+ default:
+ /* set source image */
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ break;
+ }
+
+ if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf) < 0) {
+ fimc_v4l2_clr_buf(fimc->dev_fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+static
+void* fimc_get_reserved_mem_addr(s5p_fimc_t *fimc)
+{
+ int ret;
+ struct v4l2_control vc;
+
+ vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR;
+ vc.value = 0;
+
+ ret = ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc);
+ if (ret < 0) {
+ ALOGE("Err(%s) in video VIDIOC_G_CTRL (%d)",ret);
+ return NULL;
+ }
+
+ return vc.value;
+}
+
+int fimc_open(s5p_fimc_t *fimc, const char* dev)
+{
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+ struct v4l2_control vc;
+
+ /* open device file */
+ if(fimc->dev_fd < 0) {
+ fimc->dev_fd = open(dev, O_RDWR);
+ if (fimc->dev_fd < 0) {
+ ALOGE("%s::Post processor open error (%d)", __func__, errno);
+ goto err;
+ }
+ }
+
+ /* check capability */
+ if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) {
+ ALOGE("VIDIOC_QUERYCAP failed");
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ ALOGE("%d has no streaming support", fimc->dev_fd);
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ ALOGE("%d is no video output", fimc->dev_fd);
+ goto err;
+ }
+
+ /*
+ * malloc fimc_outinfo structure
+ */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) {
+ ALOGE("%s::Error in video VIDIOC_G_FMT", __func__);
+ goto err;
+ }
+
+ fimc->out_buf.phys_addr = fimc_get_reserved_mem_addr(fimc);
+
+ vc.id = V4L2_CID_FIMC_VERSION;
+ vc.value = 0;
+
+ if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) {
+ ALOGE("%s::Error in video VIDIOC_G_CTRL", __func__);
+ goto err;
+ }
+ fimc->hw_ver = vc.value;
+
+ return 0;
+
+err:
+ if (0 <= fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd = -1;
+
+ return -1;
+}
+
+void fimc_close(s5p_fimc_t *fimc)
+{
+ /* close */
+ if (0 <= fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd = -1;
+}
+
+int fimc_flush(s5p_fimc_t *fimc,
+ struct sec_img *src_img,
+ struct sec_rect *src_rect,
+ struct sec_img *dst_img,
+ struct sec_rect *dst_rect,
+ unsigned int *phyAddr,
+ uint32_t transform)
+{
+ unsigned int dst_phys_addr = 0;
+ int32_t src_color_space;
+ int32_t dst_color_space;
+
+ /* 1 : source address and size */
+
+ if(0 > get_src_phys_addr(fimc, src_img, phyAddr))
+ return -1;
+
+ /* 2 : destination address and size */
+ if(0 == (dst_phys_addr = get_dst_phys_addr(fimc, dst_img)))
+ return -2;
+
+ /* check whether fimc supports the src format */
+ if (0 > (src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format)))
+ return -3;
+
+ if (0 > (dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format)))
+ return -4;
+
+ if(fimc_core(fimc, src_img, src_rect, (uint32_t)src_color_space,
+ dst_phys_addr, dst_img, dst_rect, (uint32_t)dst_color_space, transform) < 0)
+ return -5;
+
+ return 0;
+}
diff --git a/exynos3/s5pc110/libhdmi/fimc.h b/exynos3/s5pc110/libhdmi/fimc.h
new file mode 100644
index 0000000..dfd0525
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/fimc.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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 _FIMC_LIB_
+#define _FIMC_LIB_
+
+#include "s5p_fimc.h"
+#include "sec_utils.h"
+
+#define MAX_RESIZING_RATIO_LIMIT (63)
+
+enum {
+ FIMC_MEM_TYPE_UNKNOWN = 0,
+ FIMC_MEM_TYPE_PHYS,
+ FIMC_MEM_TYPE_VIRT,
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sec_rect {
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+};
+
+struct sec_img {
+ uint32_t w;
+ uint32_t h;
+ uint32_t format;
+ uint32_t base;
+ uint32_t offset;
+ int mem_id;
+ int mem_type;
+};
+
+inline int SEC_MIN(int x, int y) {
+ return ((x < y) ? x : y);
+}
+
+inline int SEC_MAX(int x, int y) {
+ return ((x > y) ? x : y);
+}
+
+int fimc_open(s5p_fimc_t *fimc, const char* dev);
+
+void fimc_close(s5p_fimc_t *fimc);
+
+int fimc_flush(s5p_fimc_t *fimc,
+ struct sec_img *src_img,
+ struct sec_rect *src_rect,
+ struct sec_img *dst_img,
+ struct sec_rect *dst_rect,
+ unsigned int *phyAddr,
+ uint32_t transform);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // end of _FIMC_LIB_
diff --git a/exynos3/s5pc110/libhdmi/fimd.c b/exynos3/s5pc110/libhdmi/fimd.c
new file mode 100644
index 0000000..0486597
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/fimd.c
@@ -0,0 +1,231 @@
+/*
+* 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.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)
+ ALOGE("%s: fb[%d] open failed", __func__, win);
+
+ return fp;
+}
+
+int fb_close(int fp)
+{
+ if (fp)
+ close(fp);
+ else
+ ALOGE("%s: fb is not allocated %d", __func__, fp);
+
+ return 0;
+}
+
+int fb_get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix)
+{
+ int ret = -1;
+
+ ret = ioctl(fp, FBIOGET_FSCREENINFO, fix);
+ if (ret)
+ ALOGE("%s: FBIOGET_FSCREENINFO failed", __func__);
+
+ return ret;
+}
+
+int fb_get_vscreeninfo(int fp, struct fb_var_screeninfo *var)
+{
+ int ret = -1;
+
+ ret = ioctl(fp, FBIOGET_VSCREENINFO, var);
+ if (ret)
+ ALOGE("%s:: FBIOGET_VSCREENINFO failed", __func__);
+
+ return ret;
+}
+
+int fb_put_vscreeninfo(int fp, struct fb_var_screeninfo *var)
+{
+ int ret = -1;
+
+ ret = ioctl(fp, FBIOPUT_VSCREENINFO, var);
+ if (ret)
+ ALOGE("%s:: FBIOPUT_VSCREENINFO failed", __func__);
+
+ return ret;
+}
+
+char* fb_mmap(int fp, __u32 size)
+{
+ char *buffer;
+
+ buffer = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fp, 0);
+ if (!buffer) {
+ ALOGE("%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)
+ ALOGE("%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)
+ ALOGE("%s:: FBIOBLANK failed", __func__);
+
+ return ret;
+}
+
+int fb_off(int fp)
+{
+ int ret = -1;
+
+ ret = ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN);
+ if (ret)
+ ALOGE("%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)
+ ALOGE("%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 */
+ fb_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;
+}
+
+#if 0
+
+static 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;
+}
+
+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;
+}
+#endif
diff --git a/exynos3/s5pc110/libhdmi/fimd.h b/exynos3/s5pc110/libhdmi/fimd.h
new file mode 100644
index 0000000..bb2f36c
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/fimd.h
@@ -0,0 +1,54 @@
+/*
+ * 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_H__
+#define __FIMD_H__
+
+#include <linux/fb.h>
+
+#include <s5p_tvout.h>
+
+#define TOTAL_FB_NUM 5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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(int fp, __u32 size);
+int fb_get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix);
+int fb_get_vscreeninfo(int fp, struct fb_var_screeninfo *var);
+int fb_put_vscreeninfo(int fp, struct fb_var_screeninfo *var);
+
+#if 0
+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);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FIMD_H__ */
diff --git a/exynos3/s5pc110/libhdmi/hal_module.cpp b/exynos3/s5pc110/libhdmi/hal_module.cpp
new file mode 100644
index 0000000..767e6b5
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/hal_module.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2011, Havlena Petr <havlenapetr@gmail.com>
+ *
+ * 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
+#include <cutils/log.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <linux/fb.h>
+
+#include "hardware/hdmi.h"
+
+#include "SecHDMI.h"
+
+using namespace android;
+
+#define RETURN_EINVAL_IF(hw) \
+ if(!hw) { \
+ ALOGE("%s: %i - Can't obtain hw driver!", __func__, __LINE__); \
+ return -EINVAL; \
+ }
+
+struct sec_hdmi_device_t {
+ hdmi_device_t base;
+ /* Sec specific "private" data can go here (base.priv) */
+ SecHDMI* hw;
+ int lcd_width;
+ int lcd_height;
+};
+
+static SecHDMI* sec_obtain_hw(struct hdmi_device_t* device)
+{
+ if(!device) {
+ ALOGE("Can't obtain hdmi base device!");
+ return NULL;
+ }
+
+ struct sec_hdmi_device_t* dev =
+ (struct sec_hdmi_device_t *) device;
+ if(!dev) {
+ ALOGE("Can't obtain SEC hdmi device!");
+ return NULL;
+ }
+
+ return dev->hw;
+}
+
+static int hdmi_connect(struct hdmi_device_t* dev)
+{
+ ALOGV("connect is called");
+
+ SecHDMI* hw = sec_obtain_hw(dev);
+ RETURN_EINVAL_IF(hw);
+
+ return hw->connect();
+}
+
+static int hdmi_disconnect(struct hdmi_device_t* dev)
+{
+ ALOGV("disconnect is called");
+
+ SecHDMI* hw = sec_obtain_hw(dev);
+ RETURN_EINVAL_IF(hw);
+
+ return hw->disconnect();
+}
+
+static int hdmi_clear(struct hdmi_device_t* dev, int hdmiLayer)
+{
+ ALOGV("clear is called");
+
+ SecHDMI* hw = sec_obtain_hw(dev);
+ RETURN_EINVAL_IF(hw);
+
+ return 0/*hw->clear(hdmiLayer) ? 0 : -1*/;
+}
+
+static int hdmi_blit(struct hdmi_device_t* dev, int srcW, int srcH, int srcColorFormat,
+ uint32_t srcYAddr, uint32_t srcCbAddr, uint32_t srcCrAddr,
+ int dstX, int dstY,
+ int layer,
+ int num_of_hwc_layer)
+{
+ ALOGV("blit is called");
+
+ SecHDMI* hw = sec_obtain_hw(dev);
+ RETURN_EINVAL_IF(hw);
+
+ return hw->flush(srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, srcCrAddr,
+ dstX, dstY, layer, num_of_hwc_layer);
+}
+
+static int hdmi_close(struct hdmi_device_t *dev)
+{
+ ALOGV("close is called");
+
+ if (!dev) {
+ return 0;
+ }
+
+ SecHDMI* hw = sec_obtain_hw(dev);
+ if(hw) {
+ hw->destroy();
+ delete hw;
+ }
+
+ free(dev);
+
+ return 0;
+}
+
+static int hdmi_get_lcd_size(int* width, int* height)
+{
+ char const * const device_template[] = {
+ "/dev/graphics/fb%u",
+ "/dev/fb%u",
+ 0 };
+
+ int fd = -1;
+ char name[64];
+
+ for(int i = 0; fd < 0 && device_template[i]; i++) {
+ snprintf(name, 64, device_template[i], 0);
+ fd = open(name, O_RDWR, 0);
+ }
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ struct fb_var_screeninfo info;
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &info) < 0) {
+ close(fd);
+ return -2;
+ }
+
+ *width = info.xres;
+ *height = info.yres;
+
+ close(fd);
+ return 0;
+}
+
+static int hdmi_open(const struct hw_module_t *module, char const *name,
+ struct hw_device_t **device)
+{
+ int lcdWidth, lcdHeight;
+
+ ALOGV("open: open with %s", name);
+
+ if (strcmp("hdmi-test", name) &&
+ strcmp("hdmi-service", name) &&
+ strcmp("hdmi-composer", name)) {
+ return -EINVAL;
+ }
+
+ if(hdmi_get_lcd_size(&lcdWidth, &lcdHeight) < 0) {
+ return -EINVAL;
+ }
+
+ struct sec_hdmi_device_t *hdmi_dev =
+ (struct sec_hdmi_device_t *) malloc(sizeof(struct sec_hdmi_device_t));
+ if(!hdmi_dev) {
+ return -ENOMEM;
+ }
+ memset(hdmi_dev, 0, sizeof(*hdmi_dev));
+
+ hdmi_dev->base.common.tag = HARDWARE_DEVICE_TAG;
+ hdmi_dev->base.common.version = 0;
+ hdmi_dev->base.common.module = (struct hw_module_t *)module;
+ hdmi_dev->base.common.close = (int (*)(struct hw_device_t *))hdmi_close;
+ hdmi_dev->base.connect = hdmi_connect;
+ hdmi_dev->base.disconnect = hdmi_disconnect;
+ hdmi_dev->base.clear = hdmi_clear;
+ hdmi_dev->base.blit = hdmi_blit;
+ hdmi_dev->lcd_width = lcdWidth;
+ hdmi_dev->lcd_height = lcdHeight;
+
+ *device = &hdmi_dev->base.common;
+
+ hdmi_dev->hw = new SecHDMI();
+ if(hdmi_dev->hw->create(lcdWidth, lcdHeight) < 0) {
+ hdmi_close((hdmi_device_t *)hdmi_dev);
+ return -EINVAL;
+ }
+
+ ALOGI("initzialized for lcd size: %dx%d", lcdWidth, lcdHeight);
+
+ return 0;
+}
+
+static struct hw_module_methods_t hal_module_methods = {
+ open: hdmi_open,
+};
+
+extern "C" {
+ struct hw_module_t HAL_MODULE_INFO_SYM = {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: HDMI_HARDWARE_MODULE_ID,
+ name: "Samsung S5PC11X hdmi module",
+ author: "Havlena Petr <havlenapetr@gmail.com>",
+ methods: &hal_module_methods,
+ };
+}
diff --git a/exynos3/s5pc110/libhdmi/test/Android.mk b/exynos3/s5pc110/libhdmi/test/Android.mk
new file mode 100644
index 0000000..bcdb787
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/test/Android.mk
@@ -0,0 +1,61 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+# --------------------------------------------- #
+# test1 binary
+# --------------------------------------------- #
+
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -fno-short-enums
+LOCAL_CFLAGS += -DLOG_TAG=\"test1-hdmi\" -DLOG_TYPE=1
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../../include
+
+LOCAL_SRC_FILES := \
+ test1.cpp
+
+LOCAL_MODULE := test1-hdmi
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := liblog libutils libhardware
+
+include $(BUILD_EXECUTABLE)
+
+# --------------------------------------------- #
+# test2 binary
+# --------------------------------------------- #
+
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -fno-short-enums
+LOCAL_CFLAGS += -DLOG_TAG=\"test2-hdmi\" -DLOG_TYPE=1
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../ \
+ $(LOCAL_PATH)/../../include
+
+LOCAL_SRC_FILES := \
+ ../fimc.c \
+ test2.cpp
+
+LOCAL_MODULE := test2-hdmi
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := liblog libutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/exynos3/s5pc110/libhdmi/test/test.h b/exynos3/s5pc110/libhdmi/test/test.h
new file mode 100644
index 0000000..58c934d
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/test/test.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Havlena Petr, <havlenapetr@gmail.com>
+ *
+ * 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_TEST_H_
+#define _HDMI_TEST_H_
+
+#if LOG_TYPE == 1
+#include <stdio.h>
+
+#define LOGI(fmt, ...) \
+ do { \
+ printf(LOG_TAG"/I: "fmt"\n", __VA_ARGS__); \
+ } while (0)
+
+#define LOGE(fmt, ...) \
+ do { \
+ printf(LOG_TAG"/E: "fmt"\n", __VA_ARGS__); \
+ } while (0)
+
+#elif LOG_TYPE == 2
+#include <utils/Log.h>
+
+#define LOGI(fmt, ...) \
+ do { \
+ ALOGI(fmt, __VA_ARGS__); \
+ } while (0)
+
+#define LOGE(fmt, ...) \
+ do { \
+ ALOGE(fmt, __VA_ARGS__); \
+ } while (0)
+
+#endif
+
+#endif // end of _HDMI_TEST_H_
diff --git a/exynos3/s5pc110/libhdmi/test/test1.cpp b/exynos3/s5pc110/libhdmi/test/test1.cpp
new file mode 100644
index 0000000..3e8c911
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/test/test1.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 Havlena Petr, <havlenapetr@gmail.com>
+ *
+ * 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 "hardware/hdmi.h"
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <linux/videodev2.h>
+
+#include "sec_lcd.h"
+
+#include "test.h"
+
+static void dump_fbs(int count) {
+ char name[64];
+ char const * const fb_template = {
+ "/dev/graphics/fb%u"};
+
+ for(int i = 0; i < count; i++) {
+ snprintf(name, 64, fb_template, i);
+ int fd = open(name, O_RDWR, 0);
+ if(fd < 0) {
+ LOGE("%s:: Can't open %s", __func__, name);
+ continue;
+ }
+
+ struct s3cfb_next_info fb_info;
+ int ret = ioctl(fd, S3CFB_GET_CURR_FB_INFO, &fb_info);
+ if (ret < 0) {
+ LOGE("%s:: ioctl(S3CFB_GET_FB_PHY__ADDR) fail: %d for %s",
+ __func__, ret, name);
+ goto close;
+ }
+
+ LOGI("%s:: %s addr=0x%08x", __func__, name, fb_info.phy_start_addr);
+
+close:
+ close(fd);
+ }
+}
+
+int main(int argc, char** argv) {
+ hw_module_t* module;
+ hdmi_device_t* hdmi;
+ int ret;
+
+ ret = hw_get_module(HDMI_HARDWARE_MODULE_ID,
+ (const hw_module_t**)&module);
+ if(ret) {
+ LOGE("%s:: Hdmi device not presented", __func__);
+ goto fail;
+ }
+
+ ret = module->methods->open(module, "hdmi-test",
+ (hw_device_t **)&hdmi);
+ if(ret < 0) {
+ LOGE("%s:: Can't open hdmi device", __func__);
+ goto fail;
+ }
+
+ ret = hdmi->connect(hdmi);
+ if(ret < 0) {
+ LOGE("%s:: Can't connect hdmi device", __func__);
+ goto close;
+ }
+
+#if 1
+ dump_fbs(5);
+#endif
+
+ for(int i = 0; i < 5; i++) {
+ LOGI("Blit cycle: %d", i);
+ ret = hdmi->blit(hdmi,
+ 600, /* default lcd width */
+ 1024, /* default lcd height */
+ HAL_PIXEL_FORMAT_BGRA_8888, /* our default pixel format */
+ 0, 0, 0, /* use default frame buffer */
+ 0, 0,
+ HDMI_MODE_UI,
+ 0);
+ if(ret < 0) {
+ LOGE("%s:: Can't blit to hdmi device", __func__);
+ break;
+ }
+ }
+
+disconnect:
+ if(hdmi->disconnect(hdmi) < 0) {
+ LOGE("%s:: Can't disconnect hdmi device", __func__);
+ }
+
+close:
+ if(hdmi->common.close(&hdmi->common) < 0) {
+ LOGE("%s:: Can't close hdmi device", __func__);
+ }
+
+fail:
+ LOGI("HDMI result: %d", ret);
+ return ret;
+}
diff --git a/exynos3/s5pc110/libhdmi/test/test2.cpp b/exynos3/s5pc110/libhdmi/test/test2.cpp
new file mode 100644
index 0000000..9f841e1
--- /dev/null
+++ b/exynos3/s5pc110/libhdmi/test/test2.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Havlena Petr, <havlenapetr@gmail.com>
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <fimc.h>
+
+#include "test.h"
+
+int main(int argc, char** argv) {
+ int ret;
+ s5p_fimc_t fimc;
+ /* fimc src and dest objects */
+ sec_img src_img;
+ sec_img dst_img;
+ sec_rect src_rect;
+ sec_rect dst_rect;
+ unsigned int phyAddr[3];
+
+ memset(&fimc, 0, sizeof(s5p_fimc_t));
+ fimc.dev_fd = -1;
+ ret = fimc_open(&fimc, "/dev/video2");
+ if(ret < 0) {
+ LOGE("%s:: Can't open fimc dev[%d]", __func__, ret);
+ return ret;
+ }
+
+ memset(&src_img, 0, sizeof(src_img));
+ memset(&dst_img, 0, sizeof(src_img));
+ memset(&src_rect, 0, sizeof(src_rect));
+ memset(&dst_rect, 0, sizeof(src_rect));
+ memset(&phyAddr, 0, sizeof(int) * sizeof(phyAddr));
+
+ phyAddr[0] = 0/*srcYAddr*/;
+ phyAddr[1] = 0/*srcCbAddr*/;
+ phyAddr[2] = 0/*srcCrAddr*/;
+
+ src_img.w = 600;
+ src_img.h = 1024;
+ src_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ src_img.base = 0;
+ src_img.offset = 0;
+ src_img.mem_id = 0;
+ src_img.mem_type = FIMC_MEM_TYPE_PHYS;
+ src_img.w = (src_img.w + 15) & (~15);
+ src_img.h = (src_img.h + 1) & (~1) ;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.w = src_img.w;
+ src_rect.h = src_img.h;
+
+ dst_img.w = 600;
+ dst_img.h = 1024;
+ dst_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ dst_img.base = (unsigned int) fimc.out_buf.phys_addr;
+ dst_img.offset = 0;
+ dst_img.mem_id = 0;
+ dst_img.mem_type = FIMC_MEM_TYPE_PHYS;
+
+ dst_rect.x = 0;
+ dst_rect.y = 0;
+ dst_rect.w = dst_img.w;
+ dst_rect.h = dst_img.h;
+
+ LOGI("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
+ __func__, src_rect.x, src_rect.y, src_rect.w, src_rect.h,
+ dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+
+ for(int i = 0; i < 5 && ret == 0; i++) {
+ ret = fimc_flush(&fimc, &src_img, &src_rect, &dst_img, &dst_rect,
+ phyAddr, 0);
+ if(ret < 0) {
+ LOGE("%s:: Can't flush to fimc dev[%d]", __func__, ret);
+ }
+ }
+
+ fimc_close(&fimc);
+ return ret;
+}