summaryrefslogtreecommitdiffstats
path: root/exynos4/hal
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-05-20 12:00:36 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-05-20 12:00:36 +0200
commit62f02ba4f4b7b561aa15408ebd9951600bdd71aa (patch)
treeac05dc645945a58edbc26e96df1a78ac16f27706 /exynos4/hal
parente54debb12ecdf92d12acab00a261c0c5a6ef1d64 (diff)
downloadhardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.zip
hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.gz
hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.bz2
exynos: reorganized and updated from insignal
Changes needed on exynos4210 devices: libcsc -> libseccscapi libswconverter -> remove TARGET_HAL_PATH := hardware/samsung/exynos4/hal TARGET_OMX_PATH := hardware/samsung/exynos/multimedia/openmax $(call inherit-product, hardware/samsung/exynos4210.mk) Change-Id: Ic59ef95b85ef37b3f38fb36cf6a364a5414685ee
Diffstat (limited to 'exynos4/hal')
-rw-r--r--exynos4/hal/Android.mk31
-rw-r--r--exynos4/hal/include/SecHdmi.h1
-rw-r--r--exynos4/hal/include/gralloc_priv.h313
-rw-r--r--exynos4/hal/include/s3c_lcd.h1
-rw-r--r--exynos4/hal/include/sec_format.h2
-rw-r--r--exynos4/hal/include/swconverter.h462
-rw-r--r--exynos4/hal/include/ump.h (renamed from exynos4/hal/libump/include/ump/ump.h)25
-rw-r--r--exynos4/hal/include/ump_platform.h46
-rw-r--r--exynos4/hal/include/ump_ref_drv.h (renamed from exynos4/hal/libump/include/ump/ump_ref_drv.h)37
-rw-r--r--exynos4/hal/libcamera/Android.mk38
-rw-r--r--exynos4/hal/libcamera/NOTICE (renamed from exynos4/hal/liblights/NOTICE)0
-rw-r--r--exynos4/hal/libcamera/SecCamera.cpp4360
-rw-r--r--exynos4/hal/libcamera/SecCamera.h695
-rw-r--r--exynos4/hal/libcamera/SecCameraHWInterface.cpp3410
-rw-r--r--exynos4/hal/libcamera/SecCameraHWInterface.h242
-rw-r--r--exynos4/hal/libfimc/Android.mk55
-rw-r--r--exynos4/hal/libfimc/SecFimc.cpp1701
-rw-r--r--exynos4/hal/libfimg3x/Android.mk (renamed from exynos4/hal/libfimg/Android.mk)14
-rw-r--r--exynos4/hal/libfimg3x/FimgApi.cpp (renamed from exynos4/hal/libfimg/FimgApi.cpp)0
-rw-r--r--exynos4/hal/libfimg3x/FimgApi.h (renamed from exynos4/hal/libfimg/FimgApi.h)0
-rw-r--r--exynos4/hal/libfimg3x/FimgC210.cpp (renamed from exynos4/hal/libfimg/FimgC210.cpp)0
-rw-r--r--exynos4/hal/libfimg3x/FimgC210.h (renamed from exynos4/hal/libfimg/FimgC210.h)0
-rw-r--r--exynos4/hal/libfimg4x/Android.mk22
-rw-r--r--exynos4/hal/libfimg4x/FimgApi.cpp376
-rw-r--r--exynos4/hal/libfimg4x/FimgApi.h114
-rw-r--r--exynos4/hal/libfimg4x/FimgExynos4.cpp302
-rw-r--r--exynos4/hal/libfimg4x/FimgExynos4.h169
-rw-r--r--exynos4/hal/libfimg4x/sec_g2d_4x.h326
-rw-r--r--exynos4/hal/libgralloc_ump/Android.mk56
-rw-r--r--exynos4/hal/libgralloc_ump/alloc_device.cpp498
-rw-r--r--exynos4/hal/libgralloc_ump/alloc_device.h27
-rw-r--r--exynos4/hal/libgralloc_ump/framebuffer_device.cpp465
-rw-r--r--exynos4/hal/libgralloc_ump/framebuffer_device.h31
-rw-r--r--exynos4/hal/libgralloc_ump/gr.h64
-rw-r--r--exynos4/hal/libgralloc_ump/gralloc_helper.h34
-rw-r--r--exynos4/hal/libgralloc_ump/gralloc_module.cpp480
-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.mk (renamed from exynos4/hal/liblights/Android.mk)20
-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.mk (renamed from exynos4/hal/libsensors/Android.mk)42
-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.mk (renamed from exynos4/hal/libump/ump.mak)38
-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
-rw-r--r--exynos4/hal/libhwcomposer/Android.mk88
-rw-r--r--exynos4/hal/libhwcomposer/SecHWC.cpp957
-rw-r--r--exynos4/hal/libhwcomposer/SecHWCLog.cpp51
-rw-r--r--exynos4/hal/libhwcomposer/SecHWCUtils.cpp2077
-rw-r--r--exynos4/hal/libhwcomposer/SecHWCUtils.h331
-rw-r--r--exynos4/hal/libhwconverter/Android.mk11
-rw-r--r--exynos4/hal/libhwconverter/HardwareConverter.cpp3
-rw-r--r--exynos4/hal/libhwjpeg/Android.mk33
-rw-r--r--exynos4/hal/libhwjpeg/jpeg_hal_unit.c572
-rw-r--r--exynos4/hal/liblights/lights.c253
-rw-r--r--exynos4/hal/libs5pjpeg/Android.mk5
-rw-r--r--exynos4/hal/libsensors/AkmSensor.cpp331
-rw-r--r--exynos4/hal/libsensors/AkmSensor.h64
-rw-r--r--exynos4/hal/libsensors/GyroSensor.cpp185
-rw-r--r--exynos4/hal/libsensors/GyroSensor.h55
-rw-r--r--exynos4/hal/libsensors/InputEventReader.cpp88
-rw-r--r--exynos4/hal/libsensors/InputEventReader.h47
-rw-r--r--exynos4/hal/libsensors/LightSensor.cpp160
-rw-r--r--exynos4/hal/libsensors/LightSensor.h55
-rw-r--r--exynos4/hal/libsensors/MODULE_LICENSE_APACHE20
-rw-r--r--exynos4/hal/libsensors/ProximitySensor.cpp144
-rw-r--r--exynos4/hal/libsensors/ProximitySensor.h54
-rw-r--r--exynos4/hal/libsensors/SensorBase.cpp128
-rw-r--r--exynos4/hal/libsensors/SensorBase.h65
-rw-r--r--exynos4/hal/libsensors/ak8973b.h51
-rw-r--r--exynos4/hal/libsensors/sensors.cpp326
-rw-r--r--exynos4/hal/libsensors/sensors.h144
-rw-r--r--exynos4/hal/libswconverter/Android.mk30
-rw-r--r--exynos4/hal/libump/Android.mk48
-rw-r--r--exynos4/hal/libump/Makefile38
-rw-r--r--exynos4/hal/libump/arch_011_udd/ump_arch.c260
-rw-r--r--exynos4/hal/libump/arch_011_udd/ump_arch.h65
-rw-r--r--exynos4/hal/libump/arch_011_udd/ump_frontend.c213
-rw-r--r--exynos4/hal/libump/arch_011_udd/ump_internal.h62
-rw-r--r--exynos4/hal/libump/arch_011_udd/ump_ref_drv.c124
-rw-r--r--exynos4/hal/libump/include/ump/ump_debug.h287
-rw-r--r--exynos4/hal/libump/include/ump/ump_osu.h430
-rw-r--r--exynos4/hal/libump/include/ump/ump_platform.h68
-rw-r--r--exynos4/hal/libump/include/ump/ump_uk_types.h147
-rw-r--r--exynos4/hal/libump/os/linux/ump_ioctl.h55
-rw-r--r--exynos4/hal/libump/os/linux/ump_osu_locks.c537
-rw-r--r--exynos4/hal/libump/os/linux/ump_osu_memory.c60
-rw-r--r--exynos4/hal/libump/os/linux/ump_uku.c193
-rw-r--r--exynos4/hal/libump/os/ump_uku.h56
-rw-r--r--exynos4/hal/libump/readme.txt31
111 files changed, 26902 insertions, 5535 deletions
diff --git a/exynos4/hal/Android.mk b/exynos4/hal/Android.mk
index c1c40da..5765418 100644
--- a/exynos4/hal/Android.mk
+++ b/exynos4/hal/Android.mk
@@ -1,2 +1,29 @@
-exynos4_dirs := libfimg libhwconverter liblights libs5pjpeg libsensors libswconverter libump
-include $(call all-named-subdir-makefiles,$(exynos4_dirs))
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+ifeq ($(TARGET_BOARD_PLATFORM),exynos4)
+#common_exynos4_dirs := libgralloc_ump libhdmi libfimc libhwcomposer libcamera libhwconverter
+common_exynos4_dirs := libgralloc_ump libhdmi libfimc libhwcomposer libhwconverter
+exynos4210_dirs := $(common_exynos4_dirs) libs5pjpeg libfimg3x
+
+exynos4x12_dirs := $(common_exynos4_dirs) libhwjpeg libfimg4x
+
+ifeq ($(TARGET_SOC),exynos4210)
+ include $(call all-named-subdir-makefiles,$(exynos4210_dirs))
+else
+ include $(call all-named-subdir-makefiles,$(exynos4x12_dirs))
+endif
+endif
diff --git a/exynos4/hal/include/SecHdmi.h b/exynos4/hal/include/SecHdmi.h
index 67c3378..08bee20 100644
--- a/exynos4/hal/include/SecHdmi.h
+++ b/exynos4/hal/include/SecHdmi.h
@@ -159,6 +159,7 @@ private :
void *mFBaddr;
unsigned int mFBsize;
int mFBionfd;
+ unsigned int mFBIndex;
int mHdmiFd[HDMI_LAYER_MAX];
int mDstWidth[HDMI_LAYER_MAX];
diff --git a/exynos4/hal/include/gralloc_priv.h b/exynos4/hal/include/gralloc_priv.h
index 9f3346a..8ffd161 100644
--- a/exynos4/hal/include/gralloc_priv.h
+++ b/exynos4/hal/include/gralloc_priv.h
@@ -1,6 +1,14 @@
/*
* Copyright (C) 2010 ARM Limited. All rights reserved.
*
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * struct private_handle_t
+ * * usesPhysicallyContiguousMemory()
+ * * validate()
+ * * dynamicCast()
+ *
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,145 +35,200 @@
#include <hardware/gralloc.h>
#include <cutils/native_handle.h>
-#include <ump/ump.h>
+/*#include <ump/ump.h>*/
+#include "ump.h"
+
+/*
+ * HWC_HWOVERLAY is flag for location of glReadPixels().
+ * Enable this define if you want that glReadPixesl() is in HWComposer.
+ * If you disable this define, glReadPixesl() is called in threadloop().
+ */
+#define HWC_HWOVERLAY 1
#define GRALLOC_ARM_UMP_MODULE 1
struct private_handle_t;
-struct private_module_t
-{
- gralloc_module_t base;
-
- private_handle_t* framebuffer;
- uint32_t flags;
- uint32_t numBuffers;
- uint32_t bufferMask;
- pthread_mutex_t lock;
- buffer_handle_t currentBuffer;
-
- struct fb_var_screeninfo info;
- struct fb_fix_screeninfo finfo;
- float xdpi;
- float ydpi;
- float fps;
-
- enum
- {
- // flag to indicate we'll post this buffer
- PRIV_USAGE_LOCKED_FOR_POST = 0x80000000
- };
+struct private_module_t {
+ gralloc_module_t base;
+
+ private_handle_t* framebuffer;
+ uint32_t flags;
+ uint32_t numBuffers;
+ uint32_t bufferMask;
+ pthread_mutex_t lock;
+ buffer_handle_t currentBuffer;
+ int ion_client;
+
+ struct fb_var_screeninfo info;
+ struct fb_fix_screeninfo finfo;
+ float xdpi;
+ float ydpi;
+ float fps;
+ int enableVSync;
+
+ enum {
+ PRIV_USAGE_LOCKED_FOR_POST = 0x80000000
+ };
};
+#ifdef USE_PARTIAL_FLUSH
+struct private_handle_rect {
+ int handle;
+ int stride;
+ int l;
+ int t;
+ int w;
+ int h;
+ int locked;
+ struct private_handle_rect *next;
+};
+#endif
+
#ifdef __cplusplus
struct private_handle_t : public native_handle
{
#else
-struct private_handle_t
-{
- struct native_handle nativeHandle;
+struct private_handle_t {
+ struct native_handle nativeHandle;
#endif
-
- enum
- {
- PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
- PRIV_FLAGS_USES_UMP = 0x00000002,
- };
-
- enum
- {
- LOCK_STATE_WRITE = 1<<31,
- LOCK_STATE_MAPPED = 1<<30,
- LOCK_STATE_READ_MASK = 0x3FFFFFFF
- };
-
- // ints
- int magic;
- int flags;
- int size;
- int base;
- int lockState;
- int writeOwner;
- int pid;
-
- // Following members are for UMP memory only
- int ump_id;
- int ump_mem_handle;
-
- // Following members is for framebuffer only
- int fd;
- int offset;
-
+ enum {
+ PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
+ PRIV_FLAGS_USES_UMP = 0x00000002,
+ PRIV_FLAGS_USES_PMEM = 0x00000004,
+ PRIV_FLAGS_USES_IOCTL = 0x00000008,
+ PRIV_FLAGS_USES_HDMI = 0x00000010,
+ PRIV_FLAGS_USES_ION = 0x00000020,
+ PRIV_FLAGS_NONE_CACHED = 0x00000040,
+ };
+
+ enum {
+ LOCK_STATE_WRITE = 1<<31,
+ LOCK_STATE_MAPPED = 1<<30,
+ LOCK_STATE_READ_MASK = 0x3FFFFFFF
+ };
+
+ int fd;
+
+ int magic;
+ int flags;
+ int size;
+ int base;
+ int lockState;
+ int writeOwner;
+ int pid;
+
+ /* Following members are for UMP memory only */
+ int ump_id;
+ int ump_mem_handle;
+ int offset;
+ int paddr;
+
+ int format;
+ int usage;
+ int width;
+ int height;
+ int bpp;
+ int stride;
+
+ /* Following members are for ION memory only */
+ int ion_client;
+
+ /* Following members ard for YUV information */
+ unsigned int yaddr;
+ unsigned int uoffset;
+ unsigned int voffset;
#ifdef __cplusplus
- static const int sNumInts = 11;
- static const int sNumFds = 0;
- static const int sMagic = 0x3141592;
-
- private_handle_t(int flags, int size, int base, int lock_state, ump_secure_id secure_id, ump_handle handle):
- magic(sMagic),
- flags(flags),
- size(size),
- base(base),
- lockState(lock_state),
- writeOwner(0),
- pid(getpid()),
- ump_id((int)secure_id),
- ump_mem_handle((int)handle),
- fd(0),
- offset(0)
- {
- version = sizeof(native_handle);
- numFds = sNumFds;
- numInts = sNumInts;
- }
-
- private_handle_t(int flags, int size, int base, int lock_state, int fb_file, int fb_offset):
- magic(sMagic),
- flags(flags),
- size(size),
- base(base),
- lockState(lock_state),
- writeOwner(0),
- pid(getpid()),
- ump_id((int)UMP_INVALID_SECURE_ID),
- ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE),
- fd(fb_file),
- offset(fb_offset)
- {
- version = sizeof(native_handle);
- numFds = sNumFds;
- numInts = sNumInts;
- }
-
- ~private_handle_t()
- {
- magic = 0;
- }
-
- bool usesPhysicallyContiguousMemory()
- {
- return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false;
- }
-
- static int validate(const native_handle* h)
- {
- const private_handle_t* hnd = (const private_handle_t*)h;
- if (!h || h->version != sizeof(native_handle) || h->numInts != sNumInts || h->numFds != sNumFds || hnd->magic != sMagic)
- {
- return -EINVAL;
- }
- return 0;
- }
-
- static private_handle_t* dynamicCast(const native_handle* in)
- {
- if (validate(in) == 0)
- {
- return (private_handle_t*) in;
- }
- return NULL;
- }
+ static const int sNumInts = 21;
+ static const int sNumFds = 1;
+ static const int sMagic = 0x3141592;
+
+ private_handle_t(int flags, int size, int base, int lock_state, ump_secure_id secure_id, ump_handle handle,int fd_val, int offset_val, int paddr_val):
+ fd(fd_val),
+ magic(sMagic),
+ flags(flags),
+ size(size),
+ base(base),
+ lockState(lock_state),
+ writeOwner(0),
+ pid(getpid()),
+ ump_id((int)secure_id),
+ ump_mem_handle((int)handle),
+ offset(offset_val),
+ paddr(paddr_val),
+ format(0),
+ usage(0),
+ width(0),
+ height(0),
+ bpp(0),
+ stride(0),
+ ion_client(0),
+ yaddr(0),
+ uoffset(0),
+ voffset(0)
+ {
+ version = sizeof(native_handle);
+ numFds = sNumFds;
+ numInts = sNumInts;
+ }
+
+ private_handle_t(int flags, int size, int base, int lock_state, int fb_file, int fb_offset):
+ fd(fb_file),
+ magic(sMagic),
+ flags(flags),
+ size(size),
+ base(base),
+ lockState(lock_state),
+ writeOwner(0),
+ pid(getpid()),
+ ump_id((int)UMP_INVALID_SECURE_ID),
+ ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE),
+ offset(fb_offset),
+ paddr(0),
+ format(0),
+ usage(0),
+ width(0),
+ height(0),
+ bpp(0),
+ stride(0),
+ ion_client(0),
+ yaddr(0),
+ uoffset(0),
+ voffset(0)
+ {
+ version = sizeof(native_handle);
+ numFds = sNumFds;
+ numInts = sNumInts;
+ }
+
+ ~private_handle_t()
+ {
+ magic = 0;
+ }
+
+ bool usesPhysicallyContiguousMemory()
+ {
+ return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false;
+ }
+
+ static int validate(const native_handle* h)
+ {
+ const private_handle_t* hnd = (const private_handle_t*)h;
+ if (!h || h->version != sizeof(native_handle) ||
+ h->numInts != sNumInts ||
+ h->numFds != sNumFds ||
+ hnd->magic != sMagic)
+ return -EINVAL;
+ return 0;
+ }
+
+ static private_handle_t* dynamicCast(const native_handle* in)
+ {
+ if (validate(in) == 0)
+ return (private_handle_t*) in;
+ return NULL;
+ }
#endif
};
diff --git a/exynos4/hal/include/s3c_lcd.h b/exynos4/hal/include/s3c_lcd.h
index 7f2dec7..2782542 100644
--- a/exynos4/hal/include/s3c_lcd.h
+++ b/exynos4/hal/include/s3c_lcd.h
@@ -55,7 +55,6 @@ typedef struct {
#ifdef BOARD_USE_V4L2_ION
struct s3c_fb_user_ion_client {
int fd;
- int offset;
};
#endif
diff --git a/exynos4/hal/include/sec_format.h b/exynos4/hal/include/sec_format.h
index 8722b45..23534c5 100644
--- a/exynos4/hal/include/sec_format.h
+++ b/exynos4/hal/include/sec_format.h
@@ -27,8 +27,6 @@ enum {
HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x104,
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x105,
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x106,
- HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x107,
- HAL_PIXEL_FORMAT_ARGB888 = 0x108,
// support custom format for zero copy
HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP = 0x110,
HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP = 0x111,
diff --git a/exynos4/hal/include/swconverter.h b/exynos4/hal/include/swconverter.h
deleted file mode 100644
index eb2eae3..0000000
--- a/exynos4/hal/include/swconverter.h
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- *
- * Copyright 2012 Samsung Electronics S.LSI Co. LTD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file swconverter.h
- * @brief SEC_OMX specific define. It support MFC 5.x tiled.
- * NV12T(tiled) layout:
- * Each element is not pixel. It is 64x32 pixel block.
- * uv pixel block is interleaved as u v u v u v ...
- * y1 y2 y7 y8 y9 y10 y15 y16
- * y3 y4 y5 y6 y11 y12 y13 y14
- * y17 y18 y23 y24 y25 y26 y31 y32
- * y19 y20 y21 y22 y27 y28 y29 y30
- * uv1 uv2 uv7 uv8 uv9 uv10 uv15 uv16
- * uv3 uv4 uv5 uv6 uv11 uv12 uv13 uv14
- * YUV420Planar(linear) layout:
- * Each element is not pixel. It is 64x32 pixel block.
- * y1 y2 y3 y4 y5 y6 y7 y8
- * y9 y10 y11 y12 y13 y14 y15 y16
- * y17 y18 y19 y20 y21 y22 y23 y24
- * y25 y26 y27 y28 y29 y30 y31 y32
- * u1 u2 u3 u4 u5 u6 u7 u8
- * v1 v2 v3 v4 v5 v6 v7 v8
- * YUV420Semiplanar(linear) layout:
- * Each element is not pixel. It is 64x32 pixel block.
- * uv pixel block is interleaved as u v u v u v ...
- * y1 y2 y3 y4 y5 y6 y7 y8
- * y9 y10 y11 y12 y13 y14 y15 y16
- * y17 y18 y19 y20 y21 y22 y23 y24
- * y25 y26 y27 y28 y29 y30 y31 y32
- * uv1 uv2 uv3 uv4 uv5 uv6 uv7 uv8
- * uv9 uv10 uv11 uv12 uv13 uv14 uv15 uv16
- * @author ShinWon Lee (shinwon.lee@samsung.com)
- * @version 1.0
- * @history
- * 2012.02.01 : Create
- */
-
-#ifndef SW_CONVERTOR_H_
-#define SW_CONVERTOR_H_
-
-/*--------------------------------------------------------------------------------*/
-/* Format Conversion API */
-/*--------------------------------------------------------------------------------*/
-/*
- * De-interleaves src to dest1, dest2
- *
- * @param dest1
- * Address of de-interleaved data[out]
- *
- * @param dest2
- * Address of de-interleaved data[out]
- *
- * @param src
- * Address of interleaved data[in]
- *
- * @param src_size
- * Size of interleaved data[in]
- */
-void csc_deinterleave_memcpy(
- unsigned char *dest1,
- unsigned char *dest2,
- unsigned char *src,
- unsigned int src_size);
-
-/*
- * Interleaves src1, src2 to dest
- *
- * @param dest
- * Address of interleaved data[out]
- *
- * @param src1
- * Address of de-interleaved data[in]
- *
- * @param src2
- * Address of de-interleaved data[in]
- *
- * @param src_size
- * Size of de-interleaved data[in]
- */
-void csc_interleave_memcpy(
- unsigned char *dest,
- unsigned char *src1,
- unsigned char *src2,
- unsigned int src_size);
-
-/* C Code */
-/*
- * Converts tiled data to linear
- * 1. y of nv12t to y of yuv420p
- * 2. y of nv12t to y of yuv420s
- *
- * @param dst
- * y address of yuv420[out]
- *
- * @param src
- * y address of nv12t[in]
- *
- * @param yuv420_width
- * real width of yuv420[in]
- * it should be even
- *
- * @param yuv420_height
- * real height of yuv420[in]
- * it should be even.
- *
- */
-void csc_tiled_to_linear_y(
- unsigned char *y_dst,
- unsigned char *y_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts tiled data to linear
- * 1. uv of nv12t to y of yuv420s
- *
- * @param dst
- * uv address of yuv420s[out]
- *
- * @param src
- * uv address of nv12t[in]
- *
- * @param yuv420_width
- * real width of yuv420s[in]
- *
- * @param yuv420_height
- * real height of yuv420s[in]
- *
- */
-void csc_tiled_to_linear_uv(
- unsigned char *uv_dst,
- unsigned char *uv_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts tiled data to linear
- * 1. uv of nt12t to uv of yuv420p
- *
- * @param u_dst
- * u address of yuv420p[out]
- *
- * @param v_dst
- * v address of yuv420p[out]
- *
- * @param uv_src
- * uv address of nt12t[in]
- *
- * @param yuv420_width
- * real width of yuv420p[in]
- *
- * @param yuv420_height
- * real height of yuv420p[in]
- */
-void csc_tiled_to_linear_uv_deinterleave(
- unsigned char *u_dst,
- unsigned char *v_dst,
- unsigned char *uv_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts linear data to tiled
- * 1. y of yuv420 to y of nv12t
- *
- * @param dst
- * y address of nv12t[out]
- *
- * @param src
- * y address of yuv420[in]
- *
- * @param yuv420_width
- * real width of yuv420[in]
- * it should be even
- *
- * @param yuv420_height
- * real height of yuv420[in]
- * it should be even.
- *
- */
-void csc_linear_to_tiled_y(
- unsigned char *y_dst,
- unsigned char *y_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts and interleaves linear data to tiled
- * 1. uv of nv12t to uv of yuv420
- *
- * @param dst
- * uv address of nv12t[out]
- *
- * @param src
- * u address of yuv420[in]
- *
- * @param src
- * v address of yuv420[in]
- *
- * @param yuv420_width
- * real width of yuv420[in]
- *
- * @param yuv420_height
- * real height of yuv420[in]
- *
- */
-void csc_linear_to_tiled_uv(
- unsigned char *uv_dst,
- unsigned char *u_src,
- unsigned char *v_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts tiled data to linear for mfc 6.x
- * 1. Y of NV12T to Y of YUV420P
- * 2. Y of NV12T to Y of YUV420S
- *
- * @param dst
- * Y address of YUV420[out]
- *
- * @param src
- * Y address of NV12T[in]
- *
- * @param yuv420_width
- * real width of YUV420[in]
- *
- * @param yuv420_height
- * Y: real height of YUV420[in]
- *
- */
-void csc_tiled_to_linear_y_neon(
- unsigned char *y_dst,
- unsigned char *y_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts tiled data to linear for mfc 6.x
- * 1. UV of NV12T to Y of YUV420S
- *
- * @param u_dst
- * UV plane address of YUV420P[out]
- *
- * @param nv12t_src
- * Y or UV plane address of NV12T[in]
- *
- * @param yuv420_width
- * real width of YUV420[in]
- *
- * @param yuv420_height
- * (real height)/2 of YUV420[in]
- */
-void csc_tiled_to_linear_uv_neon(
- unsigned char *uv_dst,
- unsigned char *uv_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts tiled data to linear for mfc 6.x
- * Deinterleave src to u_dst, v_dst
- * 1. UV of NV12T to Y of YUV420P
- *
- * @param u_dst
- * U plane address of YUV420P[out]
- *
- * @param v_dst
- * V plane address of YUV420P[out]
- *
- * @param nv12t_src
- * Y or UV plane address of NV12T[in]
- *
- * @param yuv420_width
- * real width of YUV420[in]
- *
- * @param yuv420_height
- * (real height)/2 of YUV420[in]
- */
-void csc_tiled_to_linear_uv_deinterleave_neon(
- unsigned char *u_dst,
- unsigned char *v_dst,
- unsigned char *uv_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts linear data to tiled
- * 1. y of yuv420 to y of nv12t
- *
- * @param dst
- * y address of nv12t[out]
- *
- * @param src
- * y address of yuv420[in]
- *
- * @param yuv420_width
- * real width of yuv420[in]
- * it should be even
- *
- * @param yuv420_height
- * real height of yuv420[in]
- * it should be even.
- *
- */
-void csc_linear_to_tiled_y_neon(
- unsigned char *y_dst,
- unsigned char *y_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts and interleaves linear data to tiled
- * 1. uv of nv12t to uv of yuv420
- *
- * @param dst
- * uv address of nv12t[out]
- *
- * @param src
- * u address of yuv420[in]
- *
- * @param src
- * v address of yuv420[in]
- *
- * @param yuv420_width
- * real width of yuv420[in]
- *
- * @param yuv420_height
- * real height of yuv420[in]
- *
- */
-void csc_linear_to_tiled_uv_neon(
- unsigned char *uv_dst,
- unsigned char *u_src,
- unsigned char *v_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts RGB565 to YUV420P
- *
- * @param y_dst
- * Y plane address of YUV420P[out]
- *
- * @param u_dst
- * U plane address of YUV420P[out]
- *
- * @param v_dst
- * V plane address of YUV420P[out]
- *
- * @param rgb_src
- * Address of RGB565[in]
- *
- * @param width
- * Width of RGB565[in]
- *
- * @param height
- * Height of RGB565[in]
- */
-void csc_RGB565_to_YUV420P(
- unsigned char *y_dst,
- unsigned char *u_dst,
- unsigned char *v_dst,
- unsigned char *rgb_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts RGB565 to YUV420S
- *
- * @param y_dst
- * Y plane address of YUV420S[out]
- *
- * @param uv_dst
- * UV plane address of YUV420S[out]
- *
- * @param rgb_src
- * Address of RGB565[in]
- *
- * @param width
- * Width of RGB565[in]
- *
- * @param height
- * Height of RGB565[in]
- */
-void csc_RGB565_to_YUV420SP(
- unsigned char *y_dst,
- unsigned char *uv_dst,
- unsigned char *rgb_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts ARGB8888 to YUV420P
- *
- * @param y_dst
- * Y plane address of YUV420P[out]
- *
- * @param u_dst
- * U plane address of YUV420P[out]
- *
- * @param v_dst
- * V plane address of YUV420P[out]
- *
- * @param rgb_src
- * Address of ARGB8888[in]
- *
- * @param width
- * Width of ARGB8888[in]
- *
- * @param height
- * Height of ARGB8888[in]
- */
-void csc_ARGB8888_to_YUV420P(
- unsigned char *y_dst,
- unsigned char *u_dst,
- unsigned char *v_dst,
- unsigned char *rgb_src,
- unsigned int width,
- unsigned int height);
-
-/*
- * Converts ARGB888 to YUV420SP
- *
- * @param y_dst
- * Y plane address of YUV420SP[out]
- *
- * @param uv_dst
- * UV plane address of YUV420SP[out]
- *
- * @param rgb_src
- * Address of ARGB8888[in]
- *
- * @param width
- * Width of ARGB8888[in]
- *
- * @param height
- * Height of ARGB8888[in]
- */
-void csc_ARGB8888_to_YUV420SP(
- unsigned char *y_dst,
- unsigned char *uv_dst,
- unsigned char *rgb_src,
- unsigned int width,
- unsigned int height);
-
-#endif /*COLOR_SPACE_CONVERTOR_H_*/
diff --git a/exynos4/hal/libump/include/ump/ump.h b/exynos4/hal/include/ump.h
index 2829113..fd01c44 100644
--- a/exynos4/hal/libump/include/ump/ump.h
+++ b/exynos4/hal/include/ump.h
@@ -1,17 +1,11 @@
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
*/
/**
@@ -31,6 +25,7 @@
#include "ump_platform.h"
+#include "ion.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -61,8 +56,8 @@ typedef unsigned int ump_secure_id;
*/
typedef enum
{
- UMP_OK = 0, /**< indicates success */
- UMP_ERROR, /**< indicates failure */
+ UMP_OK, /**< indicates success */
+ UMP_ERROR, /**< indicates failure */
} ump_result;
diff --git a/exynos4/hal/include/ump_platform.h b/exynos4/hal/include/ump_platform.h
new file mode 100644
index 0000000..9285aef
--- /dev/null
+++ b/exynos4/hal/include/ump_platform.h
@@ -0,0 +1,46 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_platform.h
+ *
+ * This file should define UMP_API_EXPORT,
+ * which dictates how the UMP user space API should be exported/imported.
+ * Modify this file, if needed, to match your platform setup.
+ */
+
+#ifndef __UMP_PLATFORM_H__
+#define __UMP_PLATFORM_H__
+
+/** @addtogroup ump_user_space_api
+ * @{ */
+
+/**
+ * A define which controls how UMP user space API functions are imported and exported.
+ * This define should be set by the implementor of the UMP API.
+ */
+#if defined(_WIN32)
+
+#define UMP_API_EXPORT
+
+#elif defined(__SYMBIAN32__)
+
+#define UMP_API_EXPORT IMPORT_C
+
+#else
+
+#define UMP_API_EXPORT
+
+#endif
+
+/** @} */ /* end group ump_user_space_api */
+
+
+#endif /* __UMP_PLATFORM_H__ */
diff --git a/exynos4/hal/libump/include/ump/ump_ref_drv.h b/exynos4/hal/include/ump_ref_drv.h
index 19fb28d..6320f1d 100644
--- a/exynos4/hal/libump/include/ump/ump_ref_drv.h
+++ b/exynos4/hal/include/ump_ref_drv.h
@@ -1,17 +1,11 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
*/
/**
@@ -29,12 +23,12 @@
extern "C" {
#endif
-typedef enum
-{
- /* This enum must match with the IOCTL enum in ump_ioctl.h */
- UMP_REF_DRV_CONSTRAINT_NONE = 0,
- UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1,
- UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4,
+typedef enum {
+ /* This enum must match with the IOCTL enum in ump_ioctl.h */
+ UMP_REF_DRV_CONSTRAINT_NONE = 0,
+ UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1,
+ /* This enum is included by samsung */
+ UMP_REF_DRV_CONSTRAINT_USE_CACHE = 128,
} ump_alloc_constraints;
/** Allocate an UMP handle containing a memory buffer.
@@ -44,8 +38,8 @@ typedef enum
* The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported.*/
UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage);
-typedef enum
-{
+UMP_API_EXPORT ump_handle ump_ref_drv_ion_import(int ion_fd, ump_alloc_constraints constraints);
+typedef enum {
UMP_MSYNC_CLEAN = 0 ,
UMP_MSYNC_CLEAN_AND_INVALIDATE = 1,
UMP_MSYNC_READOUT_CACHE_ENABLED = 128,
@@ -58,7 +52,6 @@ typedef enum
* Return value is 1 if cache is enabled, and 0 if it is disabled for the given allocation.*/
UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void* address, int size);
-
#ifdef __cplusplus
}
#endif
diff --git a/exynos4/hal/libcamera/Android.mk b/exynos4/hal/libcamera/Android.mk
new file mode 100644
index 0000000..9523db9
--- /dev/null
+++ b/exynos4/hal/libcamera/Android.mk
@@ -0,0 +1,38 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# HAL module implemenation stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES:= \
+ SecCamera.cpp SecCameraHWInterface.cpp
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+
+ifeq ($(TARGET_SOC), exynos4210)
+LOCAL_SHARED_LIBRARIES += libs5pjpeg
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC), exynos4x12)
+LOCAL_SHARED_LIBRARIES += libhwjpeg
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+ifeq ($(BOARD_USE_V4L2), true)
+LOCAL_CFLAGS += -DBOARD_USE_V4L2
+endif
+
+ifeq ($(BOARD_USE_V4L2_ION), true)
+LOCAL_CFLAGS += -DBOARD_USE_V4L2
+LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION
+endif
+
+LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM)
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos4/hal/liblights/NOTICE b/exynos4/hal/libcamera/NOTICE
index f921593..f921593 100644
--- a/exynos4/hal/liblights/NOTICE
+++ b/exynos4/hal/libcamera/NOTICE
diff --git a/exynos4/hal/libcamera/SecCamera.cpp b/exynos4/hal/libcamera/SecCamera.cpp
new file mode 100644
index 0000000..9c7bf94
--- /dev/null
+++ b/exynos4/hal/libcamera/SecCamera.cpp
@@ -0,0 +1,4360 @@
+/*
+ * 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.
+ */
+
+/*
+************************************
+* Filename: SecCamera.cpp
+* Author: Sachin P. Kamat
+* Purpose: This file interacts with the Camera and JPEG drivers.
+*************************************
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SecCamera"
+
+#include <utils/Log.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include "SecCamera.h"
+#include "cutils/properties.h"
+
+using namespace android;
+
+#define CHECK(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail. errno: %s, m_camera_id = %d", \
+ __func__, __LINE__, strerror(errno), m_camera_id); \
+ return -1; \
+ }
+
+#define CHECK_PTR(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail, errno: %s, m_camera_id = %d", \
+ __func__,__LINE__, strerror(errno), m_camera_id); \
+ return NULL; \
+ }
+
+namespace android {
+
+static struct timeval time_start;
+static struct timeval time_stop;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+unsigned long measure_time_camera(struct timeval *start, struct timeval *stop)
+{
+ unsigned long sec, usec, time;
+
+ sec = stop->tv_sec - start->tv_sec;
+
+ if (stop->tv_usec >= start->tv_usec) {
+ usec = stop->tv_usec - start->tv_usec;
+ } else {
+ usec = stop->tv_usec + 1000000 - start->tv_usec;
+ sec--;
+ }
+
+ time = (sec * 1000000) + usec;
+
+ return time;
+}
+#endif
+
+static int close_buffers(struct SecBuffer *buffers, int num_of_buf)
+{
+ int ret;
+
+ for (int i = 0; i < num_of_buf; i++) {
+ for(int j = 0; j < MAX_PLANES; j++) {
+ if (buffers[i].virt.extP[j]) {
+#ifndef BOARD_USE_V4L2_ION
+ ret = munmap(buffers[i].virt.extP[j], buffers[i].size.extS[j]);
+ LOGV("munmap():buffers[%d].virt.extP[%d]: 0x%x size = %d",
+ i, j, (unsigned int) buffers[i].virt.extP[j],
+ buffers[i].size.extS[j]);
+#endif
+ buffers[i].virt.extP[j] = NULL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int get_pixel_depth(unsigned int fmt)
+{
+ int depth = 0;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YVU420M:
+ 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;
+}
+
+static int fimc_poll(struct pollfd *events)
+{
+ int ret;
+
+ /* 10 second delay is because sensor can take a long time
+ * to do auto focus and capture in dark settings
+ */
+ ret = poll(events, 1, 10000);
+ if (ret < 0) {
+ LOGE("ERR(%s):poll error", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 10 secs..", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_querycap(int fp)
+{
+ struct v4l2_capability cap;
+
+ if (ioctl(fp, VIDIOC_QUERYCAP, &cap) < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ LOGE("ERR(%s):no capture devices", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static const __u8* fimc_v4l2_enuminput(int fp, int index)
+{
+ static struct v4l2_input input;
+
+ input.index = index;
+ if (ioctl(fp, VIDIOC_ENUMINPUT, &input) != 0) {
+ LOGE("ERR(%s):No matching index found", __func__);
+ return NULL;
+ }
+ LOGI("Name of input channel[%d] is %s", input.index, input.name);
+
+ return input.name;
+}
+
+static int fimc_v4l2_s_input(int fp, int index)
+{
+ struct v4l2_input input;
+
+ input.index = index;
+
+ if (ioctl(fp, VIDIOC_S_INPUT, &input) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_INPUT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_s_fmt(int fp, int width, int height, unsigned int fmt, enum v4l2_field field, unsigned int num_plane)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ unsigned int framesize;
+
+ memset(&v4l2_fmt, 0, sizeof(struct v4l2_format));
+ v4l2_fmt.type = V4L2_BUF_TYPE;
+
+#ifdef BOARD_USE_V4L2
+ framesize = (width * height * get_pixel_depth(fmt)) / 8;
+
+ v4l2_fmt.fmt.pix_mp.width = width;
+ v4l2_fmt.fmt.pix_mp.height = height;
+ v4l2_fmt.fmt.pix_mp.pixelformat = fmt;
+ v4l2_fmt.fmt.pix_mp.field = field;
+ if (num_plane == 1) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = framesize;
+ } else if (num_plane == 2) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width * height, 2048);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16) * 2;
+ } else if (num_plane == 3) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[2].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ } else {
+ LOGE("ERR(%s): Invalid plane number", __func__);
+ return -1;
+ }
+ v4l2_fmt.fmt.pix_mp.num_planes = num_plane;
+#else
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ pixfmt.field = V4L2_FIELD_NONE;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+ LOGV("fimc_v4l2_s_fmt : width(%d) height(%d)", width, height);
+#endif
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_s_fmt_cap(int fp, int width, int height, unsigned int fmt)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ if (fmt == V4L2_PIX_FMT_JPEG)
+ pixfmt.colorspace = V4L2_COLORSPACE_JPEG;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+ LOGV("fimc_v4l2_s_fmt_cap : width(%d) height(%d)", width, height);
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_s_fmt_is(int fp, int width, int height, unsigned int fmt, enum v4l2_field field)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ pixfmt.field = field;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+ LOGV("fimc_v4l2_s_fmt_is : width(%d) height(%d)", width, height);
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_enum_fmt(int fp, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ fmtdesc.type = V4L2_BUF_TYPE;
+ fmtdesc.index = 0;
+
+ while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ LOGV("passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ LOGE("unsupported pixel format");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = nr_bufs;
+ req.type = type;
+ req.memory = V4L2_MEMORY_TYPE;
+
+ if (ioctl(fp, VIDIOC_REQBUFS, &req) < 0) {
+ LOGE("ERR(%s):VIDIOC_REQBUFS failed", __func__);
+ return -1;
+ }
+
+ return req.count;
+}
+
+static int fimc_v4l2_querybuf(int fp, struct SecBuffer *buffers, enum v4l2_buf_type type, int nr_frames, int num_plane)
+{
+ struct v4l2_buffer v4l2_buf;
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+#endif
+ int i, ret, plane_index;
+
+ for (i = 0; i < nr_frames; i++) {
+ v4l2_buf.type = type;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+ v4l2_buf.index = i;
+#ifdef BOARD_USE_V4L2
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane; // this is for multi-planar
+ LOGV("QUERYBUF(index=%d)", i);
+ LOGV("memory plane is %d", v4l2_buf.length);
+#endif
+
+ ret = ioctl(fp, VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYBUF failed", __func__);
+ return -1;
+ }
+
+#ifdef BOARD_USE_V4L2
+ for (plane_index = 0; plane_index < num_plane; plane_index++) {
+ LOGV("Offset : 0x%x", v4l2_buf.m.planes[plane_index].m.mem_offset);
+ LOGV("Plane Length : 0x%x", v4l2_buf.m.planes[plane_index].length);
+
+ buffers[i].phys.extP[plane_index] = (unsigned int)v4l2_buf.m.planes[plane_index].cookie;
+
+ buffers[i].size.extS[plane_index] = v4l2_buf.m.planes[plane_index].length;
+ LOGV("length[%d] : 0x%x", i, buffers[i].size.extS[plane_index]);
+ if ((buffers[i].virt.extP[plane_index] = (char *)mmap(0, v4l2_buf.m.planes[plane_index].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fp, v4l2_buf.m.planes[plane_index].m.mem_offset)) < 0) {
+ LOGE("mmap failed");
+ return -1;
+ }
+ LOGV("vaddr[%d][%d] : 0x%x", i, plane_index, (__u32) buffers[i].virt.extP[plane_index]);
+ }
+#else
+ buffers[i].size.s = v4l2_buf.length;
+
+ if ((buffers[i].virt.p = (char *)mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fp, v4l2_buf.m.offset)) < 0) {
+ LOGE("%s %d] mmap() failed",__func__, __LINE__);
+ return -1;
+ }
+ LOGV("buffers[%d].virt.p = %p v4l2_buf.length = %d", i, buffers[i].virt.p, v4l2_buf.length);
+#endif
+ }
+ return 0;
+}
+
+static int fimc_v4l2_streamon(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE;
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMON failed", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_streamoff(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE;
+ int ret;
+
+ LOGV("%s :", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMOFF failed", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_qbuf(int fp, int width, int height, struct SecBuffer *vaddr, int index, int num_plane, int mode)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane;
+#endif
+
+ v4l2_buf.type = V4L2_BUF_TYPE;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+ v4l2_buf.index = index;
+
+#ifdef BOARD_USE_V4L2_ION
+ if (mode == PREVIEW_MODE) {
+ if (num_plane == 1) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = width * height * 2;
+ } else if (num_plane == 2) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ } else if (num_plane == 3) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ v4l2_buf.m.planes[2].m.userptr = (long unsigned int)vaddr[index].virt.extP[2];
+ v4l2_buf.m.planes[2].length = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ } else {
+ LOGE("ERR(%s): Invalid plane number", __func__);
+ return -1;
+ }
+ } else if (mode == CAPTURE_MODE) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = width * height * 2;
+ } else if (mode == RECORD_MODE) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(ALIGN(width, 16) * ALIGN(height, 16), 2048);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(ALIGN(width, 16) * ALIGN(height >> 1, 8), 2048);
+ } else {
+ LOGE("ERR(%s): Invalid mode", __func__);
+ return -1;
+ }
+#endif
+
+ ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QBUF failed", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_dqbuf(int fp, int num_plane)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane;
+#endif
+
+ v4l2_buf.type = V4L2_BUF_TYPE;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+
+ ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame", __func__);
+ return ret;
+ }
+
+ return v4l2_buf.index;
+}
+
+static int fimc_v4l2_g_ctrl(int fp, unsigned int id)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+
+ ret = ioctl(fp, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s): VIDIOC_G_CTRL(id = 0x%x (%d)) failed, ret = %d",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, ret);
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+ ctrl.value = value;
+
+ ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);
+
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ext_ctrl(int fp, unsigned int id, void *value)
+{
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+
+ ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
+ ctrls.count = 1;
+ ctrls.controls = &ctrl;
+
+ ret = ioctl(fp, VIDIOC_S_EXT_CTRLS, &ctrls);
+ if (ret < 0)
+ LOGE("ERR(%s):VIDIOC_S_EXT_CTRLS failed", __func__);
+
+ return ret;
+}
+
+static int fimc_v4l2_s_ext_ctrl_face_detection(int fp, unsigned int id, void *value)
+{
+ struct v4l2_ext_control ext_ctrl_fd[111];
+ struct v4l2_ext_controls ext_ctrls_fd;
+ struct v4l2_ext_controls *ctrls;
+ camera_frame_metadata_t *facedata = (camera_frame_metadata_t *)value;
+ int i, ret;
+
+ ext_ctrl_fd[0].id = V4L2_CID_IS_FD_GET_FACE_COUNT;
+ for (i = 0; i < 5; i++) {
+ ext_ctrl_fd[22*i+1].id = V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER;
+ ext_ctrl_fd[22*i+2].id = V4L2_CID_IS_FD_GET_FACE_CONFIDENCE;
+ ext_ctrl_fd[22*i+3].id = V4L2_CID_IS_FD_GET_FACE_SMILE_LEVEL;
+ ext_ctrl_fd[22*i+4].id = V4L2_CID_IS_FD_GET_FACE_BLINK_LEVEL;
+ ext_ctrl_fd[22*i+5].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_X;
+ ext_ctrl_fd[22*i+6].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_Y;
+ ext_ctrl_fd[22*i+7].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_X;
+ ext_ctrl_fd[22*i+8].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_Y;
+ ext_ctrl_fd[22*i+9].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_X;
+ ext_ctrl_fd[22*i+10].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_Y;
+ ext_ctrl_fd[22*i+11].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_X;
+ ext_ctrl_fd[22*i+12].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_Y;
+ ext_ctrl_fd[22*i+13].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_X;
+ ext_ctrl_fd[22*i+14].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_Y;
+ ext_ctrl_fd[22*i+15].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_X;
+ ext_ctrl_fd[22*i+16].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_Y;
+ ext_ctrl_fd[22*i+17].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_X;
+ ext_ctrl_fd[22*i+18].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_Y;
+ ext_ctrl_fd[22*i+19].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_X;
+ ext_ctrl_fd[22*i+20].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_Y;
+ ext_ctrl_fd[22*i+21].id = V4L2_CID_IS_FD_GET_ANGLE;
+ ext_ctrl_fd[22*i+22].id = V4L2_CID_IS_FD_GET_NEXT;
+ }
+
+ ext_ctrls_fd.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
+ ext_ctrls_fd.count = 111;
+ ext_ctrls_fd.controls = ext_ctrl_fd;
+ ctrls = &ext_ctrls_fd;
+
+ ret = ioctl(fp, VIDIOC_G_EXT_CTRLS, &ext_ctrls_fd);
+
+ facedata->number_of_faces = ext_ctrls_fd.controls[0].value;
+
+ for(i = 0; i < facedata->number_of_faces; i++) {
+ facedata->faces[i].rect[0] = ext_ctrl_fd[22*i+5].value;
+ facedata->faces[i].rect[1] = ext_ctrl_fd[22*i+6].value;
+ facedata->faces[i].rect[2] = ext_ctrl_fd[22*i+7].value;
+ facedata->faces[i].rect[3] = ext_ctrl_fd[22*i+8].value;
+ facedata->faces[i].score = ext_ctrl_fd[22*i+2].value;
+/* TODO : id is unique value for each face. We need to suppot this. */
+ facedata->faces[i].id = 0;
+ facedata->faces[i].left_eye[0] = (ext_ctrl_fd[22*i+9].value + ext_ctrl_fd[22*i+11].value) / 2;
+ facedata->faces[i].left_eye[1] = (ext_ctrl_fd[22*i+10].value + ext_ctrl_fd[22*i+12].value) / 2;
+ facedata->faces[i].right_eye[0] = (ext_ctrl_fd[22*i+13].value + ext_ctrl_fd[22*i+15].value) / 2;
+ facedata->faces[i].right_eye[1] = (ext_ctrl_fd[22*i+14].value + ext_ctrl_fd[22*i+16].value) / 2;
+ facedata->faces[i].mouth[0] = (ext_ctrl_fd[22*i+17].value + ext_ctrl_fd[22*i+19].value) / 2;
+ facedata->faces[i].mouth[1] = (ext_ctrl_fd[22*i+18].value + ext_ctrl_fd[22*i+20].value) / 2;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_G_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_G_PARM failed", __func__);
+ return -1;
+ }
+
+ LOGV("%s : timeperframe: numerator %d, denominator %d", __func__,
+ streamparm->parm.capture.timeperframe.numerator,
+ streamparm->parm.capture.timeperframe.denominator);
+
+ return 0;
+}
+
+static int fimc_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_PARM failed", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+SecCamera::SecCamera() :
+ m_flagCreate(0),
+ m_preview_state(0),
+ m_snapshot_state(0),
+ m_camera_id(CAMERA_ID_BACK),
+ m_camera_use_ISP(0),
+ m_cam_fd(-1),
+ m_cam_fd2(-1),
+ m_cam_fd3(-1),
+ m_cap_fd(-1),
+ m_rec_fd(-1),
+ m_jpeg_fd(-1),
+ m_flag_record_start(0),
+ m_preview_v4lformat(V4L2_PIX_FMT_YVU420),
+ m_preview_width (0),
+ m_preview_height (0),
+ m_preview_max_width (MAX_BACK_CAMERA_PREVIEW_WIDTH),
+ m_preview_max_height (MAX_BACK_CAMERA_PREVIEW_HEIGHT),
+ m_snapshot_v4lformat(V4L2_PIX_FMT_YUYV),
+ m_snapshot_width (0),
+ m_snapshot_height (0),
+ m_num_capbuf (0),
+ m_videosnapshot_width (0),
+ m_videosnapshot_height(0),
+ m_snapshot_max_width (MAX_BACK_CAMERA_SNAPSHOT_WIDTH),
+ m_snapshot_max_height (MAX_BACK_CAMERA_SNAPSHOT_HEIGHT),
+ m_recording_en (0),
+ m_record_hint (0),
+ m_recording_width (0),
+ m_recording_height (0),
+ m_angle(-1),
+ m_anti_banding(0),
+ m_wdr(0),
+ m_anti_shake(0),
+ m_zoom_level(-1),
+ m_object_tracking(-1),
+ m_smart_auto(-1),
+ m_beauty_shot(-1),
+ m_vintage_mode(-1),
+ m_face_detect(0),
+ m_object_tracking_start_stop(-1),
+ m_gps_latitude(-1),
+ m_gps_longitude(-1),
+ m_gps_altitude(-1),
+ m_gps_timestamp(-1),
+ m_sensor_mode(-1),
+ m_shot_mode(-1),
+ m_exif_orientation(-1),
+ m_chk_dataline(-1),
+ m_video_gamma(0),
+ m_slow_ae(0),
+ m_camera_af_flag(-1),
+ m_flag_camera_create(0),
+ m_flag_camera_start(0),
+ m_jpeg_thumbnail_width (0),
+ m_jpeg_thumbnail_height(0),
+ m_jpeg_thumbnail_quality(100),
+ m_jpeg_quality(100),
+ m_touch_af_start_stop(-1),
+ m_postview_offset(0),
+ m_auto_focus_state(0)
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ ,
+ m_esd_check_count(0)
+#endif // ENABLE_ESD_PREVIEW_CHECK
+{
+ initParameters(0);
+ memset(&mExifInfo, 0, sizeof(mExifInfo));
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+ memset(&m_events_c3, 0, sizeof(m_events_c3));
+}
+
+SecCamera::~SecCamera()
+{
+ LOGV("%s :", __func__);
+ DestroyCamera();
+}
+
+bool SecCamera::CreateCamera(int index)
+{
+ LOGV("%s :", __func__);
+ int ret = 0;
+
+ switch (index) {
+ case CAMERA_ID_FRONT:
+ m_preview_max_width = MAX_FRONT_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_FRONT_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+
+ case CAMERA_ID_BACK:
+ default:
+ m_preview_max_width = MAX_BACK_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_BACK_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+ }
+
+ if (!m_flagCreate) {
+ /* Arun C
+ * Reset the lense position only during camera starts; don't do
+ * reset between shot to shot
+ */
+ m_flagCreate = 1;
+ m_snapshot_state = 0;
+ m_camera_af_flag = -1;
+ m_camera_id = index;
+ m_recording_en = 0;
+
+ m_cam_fd = open(CAMERA_DEV_NAME, O_RDWR);
+ if (m_cam_fd < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME, strerror(errno));
+ return -1;
+ }
+ LOGV("%s: open(%s) --> m_cam_fd %d", __func__, CAMERA_DEV_NAME, m_cam_fd);
+
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd, index)) {
+ LOGE("m_cam_fd(%d) fimc_v4l2_enuminput fail", m_cam_fd);
+ return -1;
+ }
+ ret = fimc_v4l2_s_input(m_cam_fd, index);
+ CHECK(ret);
+
+ m_camera_use_ISP = getUseInternalISP();
+
+ if (m_camera_use_ISP) {
+ if (!m_recording_en)
+ fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_max_width, m_preview_max_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ else
+ fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_max_width, m_preview_max_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO);
+ }
+
+ ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_max_width, m_preview_max_height,
+ m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+
+ initParameters(m_camera_use_ISP);
+
+#ifdef SAMSUNG_EXYNOS4x12
+#ifdef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP) {
+ m_cam_fd2 = open(CAMERA_DEV_NAME2, O_RDWR);
+ LOGV("%s: open(%s) --> m_cam_fd2 = %d", __func__, CAMERA_DEV_NAME2, m_cam_fd2);
+ if (m_cam_fd2 < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME2, strerror(errno));
+ return -1;
+ }
+
+ ret = fimc_v4l2_querycap(m_cam_fd2);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd2, index)) {
+ LOGE("m_cam_fd2(%d) fimc_v4l2_enuminput fail", m_cam_fd2);
+ return -1;
+ }
+ ret = fimc_v4l2_s_input(m_cam_fd2, index);
+ CHECK(ret);
+ }
+#endif
+#endif
+
+ m_cam_fd3 = open(CAMERA_DEV_NAME3, O_RDWR);
+ LOGV("%s: open(%s) --> m_cam_fd3 = %d", __func__, CAMERA_DEV_NAME3, m_cam_fd3);
+ if (m_cam_fd3 < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME3, strerror(errno));
+ return -1;
+ }
+
+ ret = fimc_v4l2_querycap(m_cam_fd3);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd3, index)) {
+ LOGE("m_cam_fd3(%d) fimc_v4l2_enuminput fail", m_cam_fd3);
+ return -1;
+ }
+ ret = fimc_v4l2_s_input(m_cam_fd3, index);
+ CHECK(ret);
+
+ setExifFixedAttribute();
+ }
+
+#ifdef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP)
+ m_cap_fd = m_cam_fd2;
+ else
+ m_cap_fd = m_cam_fd;
+#else
+ m_cap_fd = m_cam_fd;
+#endif
+
+ m_rec_fd = m_cam_fd3;
+
+ if (m_camera_use_ISP)
+ m_num_capbuf = CAP_BUFFERS;
+ else
+ m_num_capbuf = 1;
+
+ m_flag_camera_create = 1;
+
+ return 0;
+}
+
+void SecCamera::resetCamera()
+{
+ LOGV("%s :", __func__);
+ DestroyCamera();
+ CreateCamera(m_camera_id);
+}
+
+bool SecCamera::DestroyCamera()
+{
+ LOGV("%s :", __func__);
+
+ if (m_flagCreate) {
+
+ stopRecord();
+
+ /* close m_cam_fd after stopRecord() because stopRecord()
+ * uses m_cam_fd to change frame rate
+ */
+ LOGI("DestroyCamera: m_cam_fd(%d)", m_cam_fd);
+ if (m_cam_fd > -1) {
+ close(m_cam_fd);
+ m_cam_fd = -1;
+ }
+
+#ifdef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP) {
+ LOGI("DestroyCamera: m_cam_fd2(%d)", m_cam_fd2);
+ if (m_cam_fd2 > -1) {
+ close(m_cam_fd2);
+ m_cam_fd2 = -1;
+ }
+ }
+#endif
+
+ LOGI("DestroyCamera: m_cam_fd3(%d)", m_cam_fd3);
+ if (m_cam_fd3 > -1) {
+ close(m_cam_fd3);
+ m_cam_fd3 = -1;
+ }
+
+ m_flagCreate = 0;
+ } else
+ LOGI("%s : already deinitialized", __func__);
+
+ return 0;
+}
+
+void SecCamera::initParameters(int internalISP)
+{
+ memset(&m_streamparm, 0, sizeof(m_streamparm));
+ m_params = (struct sec_cam_parm*)&m_streamparm.parm.raw_data;
+ struct v4l2_captureparm capture;
+
+ m_params->capture.timeperframe.numerator = 1;
+ m_params->capture.timeperframe.denominator = FRAME_RATE_AUTO;
+ m_params->flash_mode = FLASH_MODE_AUTO;
+ m_params->iso = ISO_AUTO;
+ m_params->metering = METERING_CENTER;
+ m_params->saturation = SATURATION_DEFAULT;
+ m_params->scene_mode = SCENE_MODE_NONE;
+ m_params->sharpness = SHARPNESS_DEFAULT;
+ m_params->white_balance = WHITE_BALANCE_AUTO;
+ m_params->anti_banding = ANTI_BANDING_OFF;
+ m_params->effects = IMAGE_EFFECT_NONE;
+ m_params->focus_mode = FOCUS_MODE_AUTO;
+
+ if (internalISP) {
+ m_params->contrast = IS_CONTRAST_DEFAULT;
+ m_params->brightness = IS_BRIGHTNESS_DEFAULT;
+ m_params->exposure = IS_EXPOSURE_DEFAULT;
+ m_params->hue = IS_HUE_DEFAULT;
+ m_params->aeawb_mode = AE_UNLOCK_AWB_UNLOCK;
+ } else {
+ m_params->contrast = CONTRAST_DEFAULT;
+ m_params->brightness = EV_DEFAULT;
+ m_params->exposure = EV_DEFAULT;
+ m_params->hue = -1;
+ m_params->aeawb_mode = -1;
+ }
+}
+
+int SecCamera::setMode(int recording_en)
+{
+ LOGV("%s :", __func__);
+ int mode;
+
+ m_recording_en = recording_en;
+
+ if (m_camera_use_ISP) {
+ if (!recording_en)
+ mode = IS_MODE_PREVIEW_STILL;
+ else
+ mode = IS_MODE_PREVIEW_VIDEO;
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_FORMAT_SCENARIO, mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_S_FORMAT_SCENARIO", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getCameraFd(enum CAM_MODE mode)
+{
+ int ret = -1;
+
+ switch (mode) {
+ case PREVIEW:
+ ret = m_cam_fd;
+ break;
+ case PICTURE:
+ ret = m_cap_fd;
+ break;
+ default:
+ ret = m_cam_fd;
+ break;
+ }
+
+ return ret;
+}
+
+int SecCamera::startPreview(void)
+{
+ v4l2_streamparm streamparm;
+ struct sec_cam_parm *parms;
+ parms = (struct sec_cam_parm*)&streamparm.parm.raw_data;
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_camera_start > 0) {
+ LOGE("ERR(%s):Preview was already started", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ /* enum_fmt, s_fmt sample */
+ int ret = fimc_v4l2_enum_fmt(m_cam_fd,m_preview_v4lformat);
+ CHECK(ret);
+
+ LOGV("m_camera_use_ISP(%d), %s", m_camera_use_ISP, (const char*)getCameraSensorName());
+
+ if (m_camera_use_ISP) {
+ if (!m_recording_en)
+ fimc_v4l2_s_fmt_is(m_cam_fd, m_videosnapshot_width, m_videosnapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ else
+ fimc_v4l2_s_fmt_is(m_cam_fd, m_videosnapshot_width, m_videosnapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO);
+ }
+
+ ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_width, m_preview_height, m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ if (!m_camera_use_ISP) {
+ fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_width, m_preview_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ }
+#endif
+
+ if (m_camera_use_ISP) {
+ if (!m_recording_en)
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL);
+ else
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_VIDEO);
+ }
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CACHEABLE, 1);
+ CHECK(ret);
+#endif
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, MAX_BUFFERS);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_querybuf(m_cam_fd, m_buffers_preview, V4L2_BUF_TYPE, MAX_BUFFERS, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+#endif
+
+ LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d",
+ __func__, m_preview_width, m_preview_height, m_angle);
+
+ LOGV("m_camera_id : %d", m_camera_id);
+
+ /* start with all buffers in queue */
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_cam_fd, m_preview_width, m_preview_height, m_buffers_preview, i, PREVIEW_NUM_PLANE, PREVIEW_MODE);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+
+#ifdef USE_FACE_DETECTION
+ if (m_camera_use_ISP) {
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_START);
+ CHECK(ret);
+ }
+#endif
+
+#ifdef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP && !m_recording_en) {
+ stopSnapshot();
+ startSnapshot(NULL);
+ }
+#endif
+
+ m_flag_camera_start = 1;
+
+ LOGV("%s: got the first frame of the preview", __func__);
+
+ return 0;
+}
+
+int SecCamera::stopPreview(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_camera_start == 0) {
+ LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__);
+ return 0;
+ }
+
+#ifdef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP && !m_recording_en)
+ stopSnapshot();
+#endif
+
+ if (m_params->flash_mode == FLASH_MODE_TORCH)
+ setFlashMode(FLASH_MODE_OFF);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+#ifdef USE_FACE_DETECTION
+ if (m_camera_use_ISP) {
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_STOP);
+ CHECK(ret);
+ }
+#endif
+ /* TODO : This code is temporary implementation. */
+ /* Because streamoff is failed when ae lock or awb lock state */
+ if (m_camera_use_ISP && m_params->aeawb_mode) {
+ if (m_params->aeawb_mode & 0x1) {
+ if (setAutoExposureLock(0) < 0) {
+ LOGE("ERR(%s): Fail on setAutoExposureLock()");
+ return -1;
+ }
+ }
+ if (m_params->aeawb_mode & (0x1 << 1)) {
+ if (setAutoWhiteBalanceLock(0) < 0) {
+ LOGE("ERR(%s): Fail on setAutoWhiteBalnaceLock()");
+ return -1;
+ }
+ }
+ m_params->aeawb_mode = 0;
+ }
+
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK(ret);
+
+ close_buffers(m_buffers_preview, MAX_BUFFERS);
+
+ fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, 0);
+
+ m_flag_camera_start = 0;
+
+ return ret;
+}
+
+int SecCamera::startSnapshot(SecBuffer *yuv_buf)
+{
+ LOGV("%s :", __func__);
+
+ // already started
+ if (m_snapshot_state) {
+ LOGI("%s: Doing nothing because snapshot is already started!", __func__);
+ return 0;
+ }
+
+ if (m_cap_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ m_snapshot_state = 1;
+
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+ m_events_c2.fd = m_cap_fd;
+ m_events_c2.events = POLLIN | POLLERR;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV420");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12T");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV21");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV422P");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUYV");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_UYVY");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("SnapshotFormat:UnknownFormat");
+#endif
+
+ int ret = fimc_v4l2_enum_fmt(m_cap_fd, m_snapshot_v4lformat);
+ CHECK(ret);
+
+ if (m_camera_use_ISP) {
+ fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ }
+
+ if (!m_recording_en)
+ ret = fimc_v4l2_s_fmt_cap(m_cap_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
+ else
+ ret = fimc_v4l2_s_fmt_cap(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height, m_snapshot_v4lformat);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ if (!m_camera_use_ISP)
+ if (!m_recording_en)
+ fimc_v4l2_s_fmt_is(m_cap_fd, m_snapshot_width, m_snapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ else
+ fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO);
+#endif
+
+#ifndef ZERO_SHUTTER_LAG
+ if (m_camera_use_ISP)
+ ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL);
+ CHECK(ret);
+#endif
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_CACHEABLE, 1);
+ CHECK(ret);
+#endif
+
+ ret = fimc_v4l2_reqbufs(m_cap_fd, V4L2_BUF_TYPE, m_num_capbuf);
+ CHECK(ret);
+
+#ifdef BOARD_USE_V4L2_ION
+#ifndef ZERO_SHUTTER_LAG
+ m_capture_buf[0].virt.p = (char *)yuv_buf->virt.p;
+#endif
+#else
+ ret = fimc_v4l2_querybuf(m_cap_fd, m_capture_buf, V4L2_BUF_TYPE, m_num_capbuf, 1);
+ CHECK(ret);
+#endif
+
+ /* start with all buffers in queue */
+ for (int i = 0; i < m_num_capbuf; i++) {
+ ret = fimc_v4l2_qbuf(m_cap_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, i, 1, CAPTURE_MODE);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cap_fd);
+ CHECK(ret);
+
+ return 0;
+}
+
+int SecCamera::stopSnapshot(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (!m_snapshot_state) {
+ LOGI("%s: Doing nothing because snapshot is not started!", __func__);
+ return 0;
+ }
+
+ if (m_cap_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ ret = fimc_v4l2_streamoff(m_cap_fd);
+ CHECK(ret);
+
+ endSnapshot();
+
+ m_snapshot_state = 0;
+
+ return ret;
+}
+
+//Recording
+int SecCamera::startRecord(bool recordHint)
+{
+ int ret, i;
+
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_record_start > 0) {
+ LOGE("ERR(%s):Preview was already started", __func__);
+ return 0;
+ }
+
+ if (m_rec_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ /* enum_fmt, s_fmt sample */
+ ret = fimc_v4l2_enum_fmt(m_rec_fd, RECORD_PIX_FMT);
+ CHECK(ret);
+
+ LOGI("%s: m_recording_width = %d, m_recording_height = %d",
+ __func__, m_recording_width, m_recording_height);
+
+ LOGV("m_camera_use_ISP(%d), %s", m_camera_use_ISP, (const char*)getCameraSensorName());
+
+ if (m_camera_use_ISP) {
+ fimc_v4l2_s_fmt_is(m_rec_fd, m_videosnapshot_width, m_videosnapshot_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO);
+
+ ret = fimc_v4l2_s_fmt(m_rec_fd, m_recording_width,
+ m_recording_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE);
+ CHECK(ret);
+ } else {
+ ret = fimc_v4l2_s_fmt(m_rec_fd, m_preview_width,
+ m_preview_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE);
+ CHECK(ret);
+#ifndef BOARD_USE_V4L2_ION
+ fimc_v4l2_s_fmt_is(m_rec_fd, m_preview_width, m_preview_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO);
+#endif
+ }
+
+ if (!m_camera_use_ISP) {
+ ret = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_CAMERA_BUSFREQ_LOCK, 267160);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_reqbufs(m_rec_fd, V4L2_BUF_TYPE, MAX_BUFFERS);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_querybuf(m_rec_fd, m_buffers_record, V4L2_BUF_TYPE, MAX_BUFFERS, RECORD_NUM_PLANE);
+ CHECK(ret);
+#endif
+
+ /* start with all buffers in queue */
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_rec_fd, m_recording_width, m_recording_height, m_buffers_record, i, RECORD_NUM_PLANE, RECORD_MODE);
+ CHECK(ret);
+ }
+
+ // Get and throw away the first frame since it is often garbled.
+ memset(&m_events_c3, 0, sizeof(m_events_c3));
+ m_events_c3.fd = m_rec_fd;
+ m_events_c3.events = POLLIN | POLLERR;
+
+ m_record_hint = recordHint;
+#ifdef VIDEO_SNAPSHOT
+ if (m_camera_use_ISP && m_record_hint) {
+ stopSnapshot();
+ startSnapshot(NULL);
+ }
+#endif
+
+ ret = fimc_v4l2_streamon(m_rec_fd);
+ CHECK(ret);
+
+ m_flag_record_start = 1;
+
+ return 0;
+}
+
+int SecCamera::stopRecord(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_record_start == 0) {
+ LOGW("%s: doing nothing because m_flag_record_start is zero", __func__);
+ return 0;
+ }
+
+#ifdef VIDEO_SNAPSHOT
+ if (m_camera_use_ISP && m_record_hint)
+ stopSnapshot();
+#endif
+
+ if (m_rec_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ m_flag_record_start = 0;
+
+ if (!m_camera_use_ISP) {
+ ret = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_CAMERA_BUSFREQ_UNLOCK, 0);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamoff(m_rec_fd);
+ CHECK(ret);
+
+ close_buffers(m_buffers_record, MAX_BUFFERS);
+
+ fimc_v4l2_reqbufs(m_rec_fd, V4L2_BUF_TYPE, 0);
+
+ return 0;
+}
+
+int SecCamera::getRecordAddr(int index, SecBuffer *buffer)
+{
+#ifdef BOARD_USE_V4L2
+ buffer->phys.extP[0] = (unsigned int)m_buffers_record[index].phys.extP[0];
+ buffer->phys.extP[1] = (unsigned int)(m_buffers_record[index].phys.extP[0] + (m_recording_width * m_recording_height));
+#else
+ buffer->phys.extP[0] = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_PADDR_Y, index);
+ CHECK((int)buffer->phys.extP[0]);
+ buffer->phys.extP[1] = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)buffer->phys.extP[1]);
+#endif
+ return 0;
+}
+
+int SecCamera::getPreviewAddr(int index, SecBuffer *buffer)
+{
+#ifdef BOARD_USE_V4L2
+ buffer->phys.extP[0] = (unsigned int)m_buffers_preview[index].phys.extP[0];
+ buffer->phys.extP[1] = (unsigned int)m_buffers_preview[index].phys.extP[1];
+ buffer->virt.extP[0] = m_buffers_preview[index].virt.extP[0];
+#else
+ buffer->phys.extP[0] = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_Y, index);
+ CHECK((int)buffer->phys.extP[0]);
+ buffer->phys.extP[1] = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)buffer->phys.extP[1]);
+#endif
+ return 0;
+}
+
+int SecCamera::getCaptureAddr(int index, SecBuffer *buffer)
+{
+ buffer->virt.extP[0] = m_capture_buf[index].virt.extP[0];
+ CHECK((int)buffer->virt.extP[0]);
+ return 0;
+}
+
+#ifdef BOARD_USE_V4L2_ION
+void SecCamera::setUserBufferAddr(void *ptr, int index, int mode)
+{
+ if (mode == PREVIEW_MODE) {
+ m_buffers_preview[index].virt.extP[0] = (char *)((unsigned int *)ptr)[0];
+ m_buffers_preview[index].virt.extP[1] = (char *)((unsigned int *)ptr)[1];
+ m_buffers_preview[index].virt.extP[2] = (char *)((unsigned int *)ptr)[2];
+ } else if (mode == CAPTURE_MODE) {
+ m_capture_buf[index].virt.extP[0] = (char *)ptr;
+ } else if (mode == RECORD_MODE) {
+ m_buffers_record[index].virt.extP[0] = (char *)ptr;
+ m_buffers_record[index].virt.extP[1] = (char *)ptr + (ALIGN((ALIGN(m_recording_width, 16) * ALIGN(m_recording_height, 16)), 2048));
+ } else
+ LOGE("%s: Invalid fd!!!", __func__);
+}
+#endif
+
+int SecCamera::getPreview(camera_frame_metadata_t *facedata)
+{
+ int index;
+ int ret;
+
+ if (m_flag_camera_start == 0 || fimc_poll(&m_events_c) == 0) {
+ LOGE("ERR(%s):Start Camera Device Reset", __func__);
+ /*
+ * When there is no data for more than 1 second from the camera we inform
+ * the FIMC driver by calling fimc_v4l2_s_input() with a special value = 1000
+ * FIMC driver identify that there is something wrong with the camera
+ * and it restarts the sensor.
+ */
+ stopPreview();
+ /* Reset Only Camera Device */
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (fimc_v4l2_enuminput(m_cam_fd, m_camera_id))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd, 1000);
+ CHECK(ret);
+#ifdef BOARD_USE_V4L2_ION
+ m_preview_state = 0;
+ return -1;
+#endif
+ ret = startPreview();
+ if (ret < 0) {
+ LOGE("ERR(%s): startPreview() return %d", __func__, ret);
+ return 0;
+ }
+ }
+
+ index = fimc_v4l2_dqbuf(m_cam_fd, PREVIEW_NUM_PLANE);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return -1;
+ }
+
+#ifdef USE_FACE_DETECTION
+ if (m_camera_use_ISP) {
+ fimc_v4l2_s_ext_ctrl_face_detection(m_cam_fd, 0, facedata);
+ }
+#endif
+
+ return index;
+}
+
+int SecCamera::setPreviewFrame(int index)
+{
+ int ret;
+ ret = fimc_v4l2_qbuf(m_cam_fd, m_preview_width, m_preview_height, m_buffers_preview, index, PREVIEW_NUM_PLANE, PREVIEW_MODE);
+ CHECK(ret);
+
+ return ret;
+}
+
+int SecCamera::getSnapshot()
+{
+ int index;
+ int ret;
+
+ if (m_snapshot_state) {
+ fimc_poll(&m_events_c2);
+
+ index = fimc_v4l2_dqbuf(m_cap_fd, 1);
+ if (!(0 <= index && index < m_num_capbuf)) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return -1;
+ }
+ return index;
+ }
+
+ return -1;
+}
+
+int SecCamera::setSnapshotFrame(int index)
+{
+ int ret;
+ ret = fimc_v4l2_qbuf(m_cap_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, index, PREVIEW_NUM_PLANE, CAPTURE_MODE);
+ CHECK(ret);
+
+ return ret;
+}
+
+int SecCamera::getRecordFrame()
+{
+ if (m_flag_record_start == 0) {
+ LOGE("%s: m_flag_record_start is 0", __func__);
+ return -1;
+ }
+
+ fimc_poll(&m_events_c3);
+ int index = fimc_v4l2_dqbuf(m_rec_fd, RECORD_NUM_PLANE);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return -1;
+ }
+
+ return index;
+}
+
+int SecCamera::releaseRecordFrame(int index)
+{
+ if (!m_flag_record_start) {
+ /* this can happen when recording frames are returned after
+ * the recording is stopped at the driver level. we don't
+ * need to return the buffers in this case and we've seen
+ * cases where fimc could crash if we called qbuf and it
+ * wasn't expecting it.
+ */
+ LOGI("%s: recording not in progress, ignoring", __func__);
+ return 0;
+ }
+
+ return fimc_v4l2_qbuf(m_rec_fd, m_recording_width, m_recording_height, m_buffers_record, index, RECORD_NUM_PLANE, RECORD_MODE);
+}
+
+int SecCamera::setPreviewSize(int width, int height, int pixel_format)
+{
+ LOGV("%s(width(%d), height(%d), format(%d))", __func__, width, height, pixel_format);
+
+ int v4lpixelformat = pixel_format;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (v4lpixelformat == V4L2_PIX_FMT_YUV420)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV420");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YVU420)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YVU420M)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420M");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12T)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12T");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV21)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV21");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV422P");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUYV)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUYV");
+ else if (v4lpixelformat == V4L2_PIX_FMT_RGB565)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("PreviewFormat:UnknownFormat");
+#endif
+ m_preview_width = width;
+ m_preview_height = height;
+ m_preview_v4lformat = v4lpixelformat;
+
+ return 0;
+}
+
+int SecCamera::getPreviewSize(int *width, int *height, int *frame_size)
+{
+ *width = m_preview_width;
+ *height = m_preview_height;
+ *frame_size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_preview_v4lformat), *width, *height);
+ return 0;
+}
+
+int SecCamera::getPreviewMaxSize(int *width, int *height)
+{
+ *width = m_preview_max_width;
+ *height = m_preview_max_height;
+
+ return 0;
+}
+
+int SecCamera::getPreviewPixelFormat(void)
+{
+ return m_preview_v4lformat;
+}
+
+/*
+ * Devide getJpeg() as two funcs, setSnapshotCmd() & getJpeg() because of the shutter sound timing.
+ * Here, just send the capture cmd to camera ISP to start JPEG capture.
+ */
+int SecCamera::setSnapshotCmd(void)
+{
+ LOGV("%s :", __func__);
+
+ int ret = 0;
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return 0;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__);
+ stopPreview();
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ int nframe = 1;
+
+ ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, V4L2_PIX_FMT_JPEG);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ if (!m_camera_use_ISP)
+ if (!m_recording_en)
+ fimc_v4l2_s_fmt_is(m_cap_fd, m_snapshot_width, m_snapshot_height,
+ V4L2_PIX_FMT_JPEG, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ else
+ fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height,
+ V4L2_PIX_FMT_JPEG, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO);
+#endif
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, nframe);
+ CHECK(ret);
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_querybuf(m_cam_fd, m_capture_buf, V4L2_BUF_TYPE, 1, 1);
+ CHECK(ret);
+#endif
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, 0, 1, CAPTURE_MODE);
+ CHECK(ret);
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+
+ return 0;
+}
+
+int SecCamera::endSnapshot(void)
+{
+ close_buffers(m_capture_buf, m_num_capbuf);
+
+ fimc_v4l2_reqbufs(m_cap_fd, V4L2_BUF_TYPE, 0);
+
+ return 0;
+}
+
+/*
+ * Set Jpeg quality & exif info and get JPEG data from camera ISP
+ */
+unsigned char* SecCamera::getJpeg(int *jpeg_size,
+ int *thumb_size,
+ unsigned int *thumb_addr,
+ unsigned int *phyaddr)
+{
+ int index, ret = 0;
+ unsigned char *addr;
+ SecBuffer jpegAddr;
+
+ // capture
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CAPTURE, 0);
+ CHECK_PTR(ret);
+ ret = fimc_poll(&m_events_c);
+ CHECK_PTR(ret);
+ index = fimc_v4l2_dqbuf(m_cam_fd, 1);
+
+ if (index != 0) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return NULL;
+ }
+
+ *jpeg_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE);
+ CHECK_PTR(*jpeg_size);
+
+ int main_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET);
+ CHECK_PTR(main_offset);
+
+ *thumb_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_THUMB_SIZE);
+ CHECK_PTR(*thumb_size);
+
+ int thumb_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_THUMB_OFFSET);
+ CHECK_PTR(thumb_offset);
+
+ m_postview_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET);
+ CHECK_PTR(m_postview_offset);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+
+ LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d",
+ index, m_snapshot_width, m_snapshot_height, *jpeg_size);
+
+ addr = (unsigned char*)(m_capture_buf[0].virt.extP[0]) + main_offset;
+
+ *thumb_addr = (unsigned int)(addr + thumb_offset);
+
+ getPreviewAddr(index, &jpegAddr);
+ *phyaddr = jpegAddr.phys.extP[0] + m_postview_offset;
+
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK_PTR(ret);
+
+ return addr;
+}
+
+int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc, int thumbSize)
+{
+#ifdef SAMSUNG_EXYNOS4210
+ /* JPEG encode for smdkv310 */
+ if (m_jpeg_fd > 0) {
+ if (api_jpeg_encode_deinit(m_jpeg_fd) != JPEG_OK)
+ LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__);
+ m_jpeg_fd = 0;
+ }
+
+ m_jpeg_fd = api_jpeg_encode_init();
+ LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd);
+
+ if (m_jpeg_fd <= 0) {
+ if (m_jpeg_fd < 0) {
+ m_jpeg_fd = 0;
+ LOGE("ERR(%s):Cannot open a jpeg device file", __func__);
+ return -1;
+ }
+ LOGE("ERR(%s):JPEG device was closed", __func__);
+ return -1;
+ }
+
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) {
+ LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__);
+ return -1;
+ }
+
+ struct jpeg_enc_param enc_param;
+ enum jpeg_frame_format inFormat = YUV_422;
+ enum jpeg_stream_format outFormat = JPEG_422;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ inFormat = YUV_420;
+ outFormat = JPEG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ inFormat = YUV_422;
+ outFormat = JPEG_422;
+ break;
+ }
+
+ // set encode parameters //
+ enc_param.width = m_jpeg_thumbnail_width;
+ enc_param.height = m_jpeg_thumbnail_width;
+ enc_param.in_fmt = inFormat; // YCBCR Only
+ enc_param.out_fmt = outFormat;
+
+ if (m_jpeg_thumbnail_quality >= 90)
+ enc_param.quality = QUALITY_LEVEL_1;
+ else if (m_jpeg_thumbnail_quality >= 80)
+ enc_param.quality = QUALITY_LEVEL_2;
+ else if (m_jpeg_thumbnail_quality >= 70)
+ enc_param.quality = QUALITY_LEVEL_3;
+ else
+ enc_param.quality = QUALITY_LEVEL_4;
+
+ api_jpeg_set_encode_param(&enc_param);
+
+ unsigned int thumbnail_size = m_jpeg_thumbnail_width * m_jpeg_thumbnail_height * 2;
+ unsigned char *pInBuf = (unsigned char *)api_jpeg_get_encode_in_buf(m_jpeg_fd, thumbnail_size);
+ if (pInBuf == NULL) {
+ LOGE("ERR(%s):JPEG input buffer is NULL!!", __func__);
+ return -1;
+ }
+
+ unsigned char *pOutBuf = (unsigned char *)api_jpeg_get_encode_out_buf(m_jpeg_fd);
+ if (pOutBuf == NULL) {
+ LOGE("ERR(%s):JPEG output buffer is NULL!!", __func__);
+ return -1;
+ }
+
+ memcpy(pInBuf, pThumbSrc, thumbnail_size);
+
+ enum jpeg_ret_type result = api_jpeg_encode_exe(m_jpeg_fd, &enc_param);
+ if (result != JPEG_ENCODE_OK) {
+ LOGE("ERR(%s):encode failed", __func__);
+ return -1;
+ }
+
+ unsigned int outbuf_size = enc_param.size;
+ unsigned int exifSize;
+
+ setExifChangedAttribute();
+
+ LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d",
+ __func__, mExifInfo.width, mExifInfo.height);
+
+ LOGV("%s : enableThumb set to true", __func__);
+ mExifInfo.enableThumb = true;
+
+ makeExif(pExifDst, pOutBuf, outbuf_size, &mExifInfo, &exifSize, true);
+#endif
+
+#ifdef SAMSUNG_EXYNOS4x12
+ /* JPEG encode for smdk4x12 */
+ unsigned int exifSize;
+
+ if (m_camera_use_ISP) {
+ LOGV("%s : m_jpeg_thumbnail_width = %d, height = %d",
+ __func__, m_jpeg_thumbnail_width, m_jpeg_thumbnail_height);
+ m_jpeg_fd = jpeghal_enc_init();
+ LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd);
+
+ if (m_jpeg_fd <= 0) {
+ if (m_jpeg_fd < 0) {
+ m_jpeg_fd = 0;
+ LOGE("ERR(%s):Cannot open a jpeg device file", __func__);
+ return -1;
+ }
+ LOGE("ERR(%s):JPEG device was closed", __func__);
+ return -1;
+ }
+
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) {
+ LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__);
+ return -1;
+ }
+
+ struct jpeg_config enc_config;
+ int outFormat;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = V4L2_PIX_FMT_JPEG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ outFormat = V4L2_PIX_FMT_JPEG_422;
+ break;
+ }
+
+ // set encode parameters //
+ enc_config.mode = JPEG_ENCODE;
+
+ if (m_jpeg_thumbnail_quality >= 90)
+ enc_config.enc_qual = QUALITY_LEVEL_1;
+ else if (m_jpeg_thumbnail_quality >= 80)
+ enc_config.enc_qual = QUALITY_LEVEL_2;
+ else if (m_jpeg_thumbnail_quality >= 70)
+ enc_config.enc_qual = QUALITY_LEVEL_3;
+ else
+ enc_config.enc_qual = QUALITY_LEVEL_4;
+
+ enc_config.width = m_jpeg_thumbnail_width;
+ enc_config.height = m_jpeg_thumbnail_height;
+ enc_config.pix.enc_fmt.in_fmt = m_snapshot_v4lformat;
+ enc_config.pix.enc_fmt.out_fmt = outFormat;
+
+ jpeghal_enc_setconfig(m_jpeg_fd, &enc_config);
+
+ jpeghal_s_ctrl(m_jpeg_fd, V4L2_CID_CACHEABLE, 1);
+
+ struct jpeg_buf m_jpeg_inbuf;
+ m_jpeg_inbuf.memory = V4L2_MEMORY_MMAP;
+ m_jpeg_inbuf.num_planes = 1;
+
+ if (jpeghal_set_inbuf(m_jpeg_fd, &m_jpeg_inbuf) < 0) {
+ LOGE("ERR(%s):Fail to JPEG input buffer!!", __func__);
+ return -1;
+ }
+
+ struct jpeg_buf m_jpeg_outbuf;
+ m_jpeg_outbuf.memory = V4L2_MEMORY_MMAP;
+ m_jpeg_outbuf.num_planes = 1;
+
+ if (jpeghal_set_outbuf(m_jpeg_fd, &m_jpeg_outbuf) < 0) {
+ LOGE("ERR(%s):Fail to JPEG output buffer!!", __func__);
+ return -1;
+ }
+
+ memcpy(m_jpeg_inbuf.start[0], pThumbSrc, m_jpeg_inbuf.length[0]);
+
+ if (jpeghal_enc_exe(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) {
+ LOGE("ERR(%s):encode failed", __func__);
+ return -1;
+ }
+
+ int outbuf_size = jpeghal_g_ctrl(m_jpeg_fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE);
+ if (outbuf_size < 0) {
+ LOGE("ERR(%s): jpeghal_g_ctrl fail on V4L2_CID_CAM_JPEG_ENCODEDSIZE", __func__);
+ return -1;
+ }
+
+ setExifChangedAttribute();
+
+ LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d",
+ __func__, mExifInfo.width, mExifInfo.height);
+
+ LOGV("%s : enableThumb set to true", __func__);
+ mExifInfo.enableThumb = true;
+
+ makeExif(pExifDst, (unsigned char *)m_jpeg_outbuf.start[0], (unsigned int)outbuf_size, &mExifInfo, &exifSize, true);
+
+ if (m_jpeg_fd > 0) {
+ if (jpeghal_deinit(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0)
+ LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__);
+ m_jpeg_fd = 0;
+ }
+ } else {
+ setExifChangedAttribute();
+ mExifInfo.enableThumb = true;
+ makeExif(pExifDst, pThumbSrc, (unsigned int)thumbSize, &mExifInfo, &exifSize, true);
+ }
+#endif
+
+ return exifSize;
+}
+
+void SecCamera::getPostViewConfig(int *width, int *height, int *size)
+{
+ *width = m_snapshot_width;
+ *height = m_snapshot_height;
+ *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+ LOGV("[5B] m_preview_width : %d, mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ m_preview_width, *width, *height, *size);
+}
+
+void SecCamera::getThumbnailConfig(int *width, int *height, int *size)
+{
+ *width = m_jpeg_thumbnail_width;
+ *height = m_jpeg_thumbnail_height;
+ *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+}
+
+int SecCamera::getPostViewOffset(void)
+{
+ return m_postview_offset;
+}
+
+int SecCamera::getSnapshotAndJpeg(SecBuffer *yuv_buf, int index, unsigned char *jpeg_buf,
+ int *output_size)
+{
+ LOGV("%s :", __func__);
+
+ int ret = 0;
+ int i;
+
+#ifdef ZERO_SHUTTER_LAG
+ if (!m_camera_use_ISP){
+ startSnapshot(yuv_buf);
+
+ index = getSnapshot();
+ if (index < 0) {
+ LOGE("ERR(%s): Invalid index!", __func__);
+ return -1;
+ }
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("snapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d",
+ index, m_snapshot_width, m_snapshot_height);
+
+ getCaptureAddr(index, yuv_buf);
+#endif
+
+ if (yuv_buf->virt.extP[0] == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ",
+ __func__, yuv_buf->virt.extP[0]);
+ return UNKNOWN_ERROR;
+ }
+ }
+#else
+ startSnapshot(yuv_buf);
+
+ index = getSnapshot();
+ if (index < 0) {
+ LOGE("ERR(%s): Invalid index!", __func__);
+ return -1;
+ }
+
+#ifndef BOARD_USE_V4L2_ION
+ ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("snapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d",
+ index, m_snapshot_width, m_snapshot_height);
+
+ getCaptureAddr(index, yuv_buf);
+#endif
+
+ if (yuv_buf->virt.extP[0] == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ",
+ __func__, yuv_buf->virt.extP[0]);
+ return UNKNOWN_ERROR;
+ }
+#endif
+
+#ifdef SAMSUNG_EXYNOS4210
+ /* JPEG encode for smdkv310 */
+ if (m_jpeg_fd > 0) {
+ if (api_jpeg_encode_deinit(m_jpeg_fd) != JPEG_OK)
+ LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__);
+ m_jpeg_fd = 0;
+ }
+
+ m_jpeg_fd = api_jpeg_encode_init();
+ LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd);
+
+ if (m_jpeg_fd <= 0) {
+ if (m_jpeg_fd < 0) {
+ m_jpeg_fd = 0;
+ LOGE("ERR(%s):Cannot open a jpeg device file", __func__);
+ return -1;
+ }
+ LOGE("ERR(%s):JPEG device was closed", __func__);
+ return -1;
+ }
+
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) {
+ LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__);
+ return -1;
+ }
+
+ struct jpeg_enc_param enc_param;
+ enum jpeg_frame_format inFormat = YUV_422;
+ enum jpeg_stream_format outFormat = JPEG_422;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ inFormat = YUV_420;
+ outFormat = JPEG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ inFormat = YUV_422;
+ outFormat = JPEG_422;
+ break;
+ }
+
+ // set encode parameters //
+ enc_param.width = m_snapshot_width;
+ enc_param.height = m_snapshot_height;
+ enc_param.in_fmt = inFormat; // YCBCR Only
+ enc_param.out_fmt = outFormat;
+
+ if (m_jpeg_quality >= 90)
+ enc_param.quality = QUALITY_LEVEL_1;
+ else if (m_jpeg_quality >= 80)
+ enc_param.quality = QUALITY_LEVEL_2;
+ else if (m_jpeg_quality >= 70)
+ enc_param.quality = QUALITY_LEVEL_3;
+ else
+ enc_param.quality = QUALITY_LEVEL_4;
+
+ api_jpeg_set_encode_param(&enc_param);
+
+ unsigned int snapshot_size = m_snapshot_width * m_snapshot_height * 2;
+ unsigned char *pInBuf = (unsigned char *)api_jpeg_get_encode_in_buf(m_jpeg_fd, snapshot_size);
+ if (pInBuf == NULL) {
+ LOGE("ERR(%s):JPEG input buffer is NULL!!", __func__);
+ return -1;
+ }
+
+ unsigned char *pOutBuf = (unsigned char *)api_jpeg_get_encode_out_buf(m_jpeg_fd);
+ if (pOutBuf == NULL) {
+ LOGE("ERR(%s):JPEG output buffer is NULL!!", __func__);
+ return -1;
+ }
+
+ memcpy(pInBuf, yuv_buf->virt.extP[0], snapshot_size);
+
+ enum jpeg_ret_type result = api_jpeg_encode_exe(m_jpeg_fd, &enc_param);
+ if (result != JPEG_ENCODE_OK) {
+ LOGE("ERR(%s):encode failed", __func__);
+ return -1;
+ }
+
+ *output_size = enc_param.size;
+ memcpy(jpeg_buf, pOutBuf, *output_size);
+#endif
+
+#ifdef SAMSUNG_EXYNOS4x12
+ /* JPEG encode for smdk4x12 */
+ m_jpeg_fd = jpeghal_enc_init();
+ LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd);
+
+ if (m_jpeg_fd <= 0) {
+ if (m_jpeg_fd < 0) {
+ m_jpeg_fd = 0;
+ LOGE("ERR(%s):Cannot open a jpeg device file", __func__);
+ return -1;
+ }
+ LOGE("ERR(%s):JPEG device was closed", __func__);
+ return -1;
+ }
+
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) {
+ LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__);
+ return -1;
+ }
+
+ struct jpeg_config enc_config;
+ int outFormat;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = V4L2_PIX_FMT_JPEG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ outFormat = V4L2_PIX_FMT_JPEG_422;
+ break;
+ }
+
+ // set encode parameters //
+ enc_config.mode = JPEG_ENCODE;
+
+ if (m_jpeg_quality >= 90)
+ enc_config.enc_qual = QUALITY_LEVEL_1;
+ else if (m_jpeg_quality >= 80)
+ enc_config.enc_qual = QUALITY_LEVEL_2;
+ else if (m_jpeg_quality >= 70)
+ enc_config.enc_qual = QUALITY_LEVEL_3;
+ else
+ enc_config.enc_qual = QUALITY_LEVEL_4;
+
+ if (!m_recording_en) {
+ enc_config.width = m_snapshot_width;
+ enc_config.height = m_snapshot_height;
+ } else {
+ enc_config.width = m_videosnapshot_width;
+ enc_config.height = m_videosnapshot_height;
+ }
+ enc_config.pix.enc_fmt.in_fmt = m_snapshot_v4lformat;
+ enc_config.pix.enc_fmt.out_fmt = outFormat;
+
+ jpeghal_enc_setconfig(m_jpeg_fd, &enc_config);
+
+ ret = jpeghal_s_ctrl(m_jpeg_fd, V4L2_CID_CACHEABLE, 3);
+ CHECK(ret);
+
+ struct jpeg_buf m_jpeg_inbuf;
+#ifdef BOARD_USE_V4L2_ION
+ m_jpeg_inbuf.memory = V4L2_MEMORY_MMAP;
+ m_jpeg_inbuf.num_planes = 1;
+#else
+ m_jpeg_inbuf.start[0] = (void *)fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_PADDR_Y, index);
+ m_jpeg_inbuf.length[0] = m_capture_buf[index].size.extS[0];
+ m_jpeg_inbuf.memory = V4L2_MEMORY_USERPTR;
+ m_jpeg_inbuf.num_planes = 1;
+#endif
+
+ if (jpeghal_set_inbuf(m_jpeg_fd, &m_jpeg_inbuf) < 0) {
+ LOGE("ERR(%s):Fail to JPEG input buffer!!", __func__);
+ return -1;
+ }
+
+ for (i = 0; i < m_jpeg_inbuf.num_planes; i++) {
+ if ((unsigned int)m_jpeg_inbuf.start[i] & (SIZE_4K - 1)) {
+ LOGE("ERR(%s): JPEG start address should be aligned to 4 Kbytes", __func__);
+ return -1;
+ } else if ((unsigned int)enc_config.width & (16 - 1)) {
+ LOGE("ERR(%s): Image width should be multiple of 16", __func__);
+ return -1;
+ }
+ }
+
+ struct jpeg_buf m_jpeg_outbuf;
+ m_jpeg_outbuf.memory = V4L2_MEMORY_MMAP;
+ m_jpeg_outbuf.num_planes = 1;
+
+ if (jpeghal_set_outbuf(m_jpeg_fd, &m_jpeg_outbuf) < 0) {
+ LOGE("ERR(%s):Fail to JPEG output buffer!!", __func__);
+ return -1;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+ memcpy(m_jpeg_inbuf.start[0], yuv_buf->virt.extP[0], m_jpeg_inbuf.length[0]);
+#endif
+
+ if (jpeghal_enc_exe(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) {
+ LOGE("ERR(%s):encode failed", __func__);
+ return -1;
+ }
+
+ ret = jpeghal_g_ctrl(m_jpeg_fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE);
+ if (ret < 0) {
+ LOGE("ERR(%s): jpeghal_g_ctrl fail on V4L2_CID_CAM_JPEG_ENCODEDSIZE", __func__);
+ return -1;
+ } else {
+ *output_size = (unsigned int)ret;
+ }
+
+ memcpy(jpeg_buf, m_jpeg_outbuf.start[0], *output_size);
+
+ if (m_jpeg_fd > 0) {
+ if (jpeghal_deinit(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0)
+ LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__);
+ m_jpeg_fd = 0;
+ }
+#endif
+
+ return 0;
+}
+
+int SecCamera::setVideosnapshotSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_videosnapshot_width = width;
+ m_videosnapshot_height = height;
+
+ return 0;
+}
+
+int SecCamera::getVideosnapshotSize(int *width, int *height, int *frame_size)
+{
+ *width = m_videosnapshot_width;
+ *height = m_videosnapshot_height;
+
+ int frame = 0;
+
+ frame = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+
+ // set it big.
+ if (frame == 0)
+ frame = m_videosnapshot_width * m_videosnapshot_height * BPP;
+
+ *frame_size = frame;
+
+ return 0;
+}
+
+int SecCamera::setSnapshotSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_snapshot_width = width;
+ m_snapshot_height = height;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotSize(int *width, int *height, int *frame_size)
+{
+ *width = m_snapshot_width;
+ *height = m_snapshot_height;
+
+ int frame = 0;
+
+ frame = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+
+ // set it big.
+ if (frame == 0)
+ frame = m_snapshot_width * m_snapshot_height * BPP;
+
+ *frame_size = frame;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotMaxSize(int *width, int *height)
+{
+ *width = m_snapshot_max_width;
+ *height = m_snapshot_max_height;
+
+ return 0;
+}
+
+int SecCamera::setSnapshotPixelFormat(int pixel_format)
+{
+ int v4lpixelformat = pixel_format;
+
+ if (m_snapshot_v4lformat != v4lpixelformat) {
+ m_snapshot_v4lformat = v4lpixelformat;
+ }
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__);
+ else
+ LOGD("SnapshotFormat:UnknownFormat");
+#endif
+ return 0;
+}
+
+int SecCamera::getSnapshotPixelFormat(void)
+{
+ return m_snapshot_v4lformat;
+}
+
+int SecCamera::getCameraId(void)
+{
+ return m_camera_id;
+}
+
+int SecCamera::initSetParams(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, ISO_AUTO) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, METERING_CENTER) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, SATURATION_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, SCENE_MODE_NONE) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, SHARPNESS_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, WHITE_BALANCE_AUTO) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_BANDING, ANTI_BANDING_OFF) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_CONTRAST, IS_CONTRAST_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, IMAGE_EFFECT_NONE) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, IS_BRIGHTNESS_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXPOSURE, IS_EXPOSURE_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__);
+ return -1;
+ }
+/* TODO */
+/* This code is temporary implementation because *
+ * hue value tuning was not complete */
+#ifdef USE_HUE
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_HUE, IS_HUE_DEFAULT) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_HUE", __func__);
+ return -1;
+ }
+#endif
+
+ initParameters(m_camera_use_ISP);
+
+ return 0;
+}
+
+int SecCamera::setAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+
+ m_auto_focus_state = 1;
+
+ return 0;
+}
+
+int SecCamera::setTouchAF(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, FOCUS_MODE_TOUCH) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::getAutoFocusResult(void)
+{
+ int af_result;
+
+ af_result = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT);
+
+ LOGV("%s : returning %d", __func__, af_result);
+
+ return af_result;
+}
+
+int SecCamera::cancelAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+#ifndef BOARD_USE_V4L2
+ if (m_flag_camera_start && m_auto_focus_state) {
+ if (m_params->focus_mode == FOCUS_MODE_AUTO || m_params->focus_mode == FOCUS_MODE_MACRO) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+ }
+ m_auto_focus_state = 0;
+ }
+#endif
+
+ return 0;
+}
+
+int SecCamera::SetRotate(int angle)
+{
+ LOGE("%s(angle(%d))", __func__, angle);
+
+ if (m_angle != angle) {
+ switch (angle) {
+ case -360:
+ case 0:
+ case 360:
+ m_angle = 0;
+ break;
+
+ case -270:
+ case 90:
+ m_angle = 90;
+ break;
+
+ case -180:
+ case 180:
+ m_angle = 180;
+ break;
+
+ case -90:
+ case 270:
+ m_angle = 270;
+ break;
+
+ default:
+ LOGE("ERR(%s):Invalid angle(%d)", __func__, angle);
+ return -1;
+ }
+
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_ROTATION, angle) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_ROTATION", __func__);
+ return -1;
+ }
+ m_angle = angle;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getRotate(void)
+{
+ LOGV("%s : angle(%d)", __func__, m_angle);
+ return m_angle;
+}
+
+int SecCamera::setFrameRate(int frame_rate)
+{
+ LOGV("%s(FrameRate(%d))", __func__, frame_rate);
+
+ if (frame_rate < FRAME_RATE_AUTO || FRAME_RATE_MAX < frame_rate ) {
+ LOGE("ERR(%s):Invalid frame_rate(%d)", __func__, frame_rate);
+ return -1;
+ }
+
+ if (m_params->capture.timeperframe.denominator != frame_rate) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE, frame_rate) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FRAME_RATE", __func__);
+ return -1;
+ }
+ m_params->capture.timeperframe.denominator = frame_rate;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setVerticalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_VFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_VFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setHorizontalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_HFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_HFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setWhiteBalance(int white_balance)
+{
+ LOGV("%s(white_balance(%d))", __func__, white_balance);
+
+ if (white_balance <= WHITE_BALANCE_BASE || WHITE_BALANCE_MAX <= white_balance) {
+ LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance);
+ return -1;
+ }
+
+ if (m_params->white_balance != white_balance) {
+ if (m_flag_camera_create) {
+ LOGE("%s(white_balance(%d))", __func__, white_balance);
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, white_balance) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__);
+ return -1;
+ }
+ m_params->white_balance = white_balance;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getWhiteBalance(void)
+{
+ LOGV("%s : white_balance(%d)", __func__, m_params->white_balance);
+ return m_params->white_balance;
+}
+
+int SecCamera::setBrightness(int brightness)
+{
+ LOGV("%s(brightness(%d))", __func__, brightness);
+
+ if (m_camera_use_ISP) {
+ brightness += IS_BRIGHTNESS_DEFAULT;
+ if (brightness < IS_BRIGHTNESS_MINUS_2 || IS_BRIGHTNESS_PLUS_2 < brightness) {
+ LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness);
+ return -1;
+ }
+ } else {
+ LOGW("WARN(%s):Not supported brightness setting", __func__);
+ return 0;
+ }
+
+ if (m_params->brightness != brightness) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, brightness) < EV_MINUS_4) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ m_params->brightness = brightness;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getBrightness(void)
+{
+ LOGV("%s : brightness(%d)", __func__, m_params->brightness);
+ return m_params->brightness;
+}
+
+int SecCamera::setExposure(int exposure)
+{
+ LOGV("%s(exposure(%d))", __func__, exposure);
+
+ if (m_camera_use_ISP) {
+ exposure += IS_EXPOSURE_DEFAULT;
+ if (exposure < IS_EXPOSURE_MINUS_4 || IS_EXPOSURE_PLUS_4 < exposure) {
+ LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure);
+ return -1;
+ }
+ } else {
+ exposure += EV_DEFAULT;
+ if (exposure < EV_MINUS_4 || EV_PLUS_4 < exposure) {
+ LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure);
+ return -1;
+ }
+ }
+
+ if (m_params->exposure != exposure) {
+ if (m_flag_camera_create) {
+ if (m_camera_use_ISP) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXPOSURE, exposure) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__);
+ return -1;
+ }
+ } else {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BRIGHTNESS, exposure) < EV_MINUS_4) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ }
+ m_params->exposure = exposure;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getExposure(void)
+{
+ LOGV("%s : exposure(%d)", __func__, m_params->exposure);
+ return m_params->exposure;
+}
+
+int SecCamera::setImageEffect(int image_effect)
+{
+ LOGV("%s(image_effect(%d))", __func__, image_effect);
+
+ if (image_effect <= IMAGE_EFFECT_BASE || IMAGE_EFFECT_MAX <= image_effect) {
+ LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect);
+ return -1;
+ }
+
+ if (m_params->effects != image_effect) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, image_effect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__);
+ return -1;
+ }
+ m_params->effects = image_effect;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getImageEffect(void)
+{
+ LOGV("%s : image_effect(%d)", __func__, m_params->effects);
+ return m_params->effects;
+}
+
+int SecCamera::setAntiBanding(int anti_banding)
+{
+ LOGV("%s(anti_banding(%d))", __func__, anti_banding);
+
+ if (anti_banding < ANTI_BANDING_AUTO || ANTI_BANDING_OFF < anti_banding) {
+ LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding);
+ return -1;
+ }
+
+ if (m_params->anti_banding != anti_banding) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_BANDING, anti_banding) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__);
+ return -1;
+ }
+ m_params->anti_banding = anti_banding;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setSceneMode(int scene_mode)
+{
+ LOGV("%s(scene_mode(%d))", __func__, scene_mode);
+
+ if (scene_mode <= SCENE_MODE_BASE || SCENE_MODE_MAX <= scene_mode) {
+ LOGE("ERR(%s):Invalid scene_mode (%d)", __func__, scene_mode);
+ return -1;
+ }
+
+ if (m_params->scene_mode != scene_mode) {
+ if (m_flag_camera_create) {
+ LOGE("%s(scene_mode(%d))", __func__, scene_mode);
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, scene_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__);
+ return -1;
+ }
+ m_params->scene_mode = scene_mode;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSceneMode(void)
+{
+ return m_params->scene_mode;
+}
+
+int SecCamera::setFlashMode(int flash_mode)
+{
+ LOGV("%s(flash_mode(%d))", __func__, flash_mode);
+
+ if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {
+ LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
+ return -1;
+ }
+
+ if (m_params->flash_mode != flash_mode) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);
+ return -1;
+ }
+ m_params->flash_mode = flash_mode;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFlashMode(void)
+{
+ return m_params->flash_mode;
+}
+
+int SecCamera::setAutoExposureLock(int toggle)
+{
+ LOGV("%s(toggle value(%d))", __func__, toggle);
+
+ int aeawb_mode = m_params->aeawb_mode;
+
+ if (m_flag_camera_create) {
+ if (toggle ^ aeawb_mode) {
+ aeawb_mode = aeawb_mode ^ 0x1;
+ m_params->aeawb_mode = aeawb_mode;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK", __func__);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int SecCamera::setAutoWhiteBalanceLock(int toggle)
+{
+ LOGV("%s(toggle value(%d))", __func__, toggle);
+
+ int aeawb_mode = m_params->aeawb_mode;
+
+ if (m_flag_camera_create) {
+ if (toggle ^ (aeawb_mode >> 1)) {
+ aeawb_mode = aeawb_mode ^ (0x1 << 1);
+ m_params->aeawb_mode = aeawb_mode;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK", __func__);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int SecCamera::setISO(int iso_value)
+{
+ LOGV("%s(iso_value(%d))", __func__, iso_value);
+
+ if (iso_value < ISO_AUTO || ISO_MAX <= iso_value) {
+ LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value);
+ return -1;
+ }
+
+ if (m_params->iso != iso_value) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, iso_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__);
+ return -1;
+ }
+ m_params->iso = iso_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getISO(void)
+{
+ return m_params->iso;
+}
+
+int SecCamera::setContrast(int contrast_value)
+{
+ LOGV("%s(contrast_value(%d))", __func__, contrast_value);
+
+ if (m_camera_use_ISP) {
+ if (contrast_value < IS_CONTRAST_AUTO || IS_CONTRAST_MAX <= contrast_value) {
+ LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value);
+ return -1;
+ }
+ } else {
+ if (contrast_value < CONTRAST_MINUS_2 || CONTRAST_MAX <= contrast_value) {
+ LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value);
+ return -1;
+ }
+ }
+
+ if (m_params->contrast != contrast_value) {
+ if (m_flag_camera_create) {
+ if (m_camera_use_ISP) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_CONTRAST, contrast_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ } else {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CONTRAST, contrast_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ }
+ m_params->contrast = contrast_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getContrast(void)
+{
+ return m_params->contrast;
+}
+
+int SecCamera::setSaturation(int saturation_value)
+{
+ LOGV("%s(saturation_value(%d))", __func__, saturation_value);
+
+ saturation_value += SATURATION_DEFAULT;
+ if (saturation_value < SATURATION_MINUS_2 || SATURATION_MAX <= saturation_value) {
+ LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value);
+ return -1;
+ }
+
+ if (m_params->saturation != saturation_value) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, saturation_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__);
+ return -1;
+ }
+ m_params->saturation = saturation_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSaturation(void)
+{
+ return m_params->saturation;
+}
+
+int SecCamera::setSharpness(int sharpness_value)
+{
+ LOGV("%s(sharpness_value(%d))", __func__, sharpness_value);
+
+ sharpness_value += SHARPNESS_DEFAULT;
+ if (sharpness_value < SHARPNESS_MINUS_2 || SHARPNESS_MAX <= sharpness_value) {
+ LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value);
+ return -1;
+ }
+
+ if (m_params->sharpness != sharpness_value) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, sharpness_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__);
+ return -1;
+ }
+ m_params->sharpness = sharpness_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSharpness(void)
+{
+ return m_params->sharpness;
+}
+
+int SecCamera::setHue(int hue_value)
+{
+ LOGV("%s(hue_value(%d))", __func__, hue_value);
+
+/* TODO */
+/* This code is temporary implementation because *
+ * hue value tuning was not complete */
+#ifdef USE_HUE
+ if (m_camera_use_ISP) {
+ hue_value += IS_HUE_DEFAULT;
+ if (hue_value < IS_HUE_MINUS_2 || IS_HUE_MAX <= hue_value) {
+ LOGE("ERR(%s):Invalid hue_value (%d)", __func__, hue_value);
+ return -1;
+ }
+ } else {
+ LOGW("WARN(%s):Not supported hue setting", __func__);
+ return 0;
+ }
+
+ if (m_params->hue != hue_value) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_HUE, hue_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_HUE", __func__);
+ return -1;
+ }
+ m_params->hue = hue_value;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+int SecCamera::getHue(void)
+{
+ return m_params->hue;
+}
+
+int SecCamera::setWDR(int wdr_value)
+{
+ LOGV("%s(wdr_value(%d))", __func__, wdr_value);
+
+ if (m_camera_use_ISP) {
+ if (wdr_value < IS_DRC_BYPASS_DISABLE || IS_DRC_BYPASS_MAX <= wdr_value) {
+ LOGE("ERR(%s):Invalid drc_value (%d)", __func__, wdr_value);
+ return -1;
+ }
+ } else {
+ if (wdr_value < WDR_OFF || WDR_MAX <= wdr_value) {
+ LOGE("ERR(%s):Invalid wdr_value (%d)", __func__, wdr_value);
+ return -1;
+ }
+ }
+
+ if (m_wdr != wdr_value) {
+ if (m_flag_camera_create) {
+ if (m_camera_use_ISP) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_SET_DRC, wdr_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_SET_DRC", __func__);
+ return -1;
+ }
+ } else {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WDR, wdr_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WDR", __func__);
+ return -1;
+ }
+ }
+ m_wdr = wdr_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getWDR(void)
+{
+ return m_wdr;
+}
+
+int SecCamera::setAntiShake(int anti_shake)
+{
+ LOGV("%s(anti_shake(%d))", __func__, anti_shake);
+
+ if (anti_shake < ANTI_SHAKE_OFF || ANTI_SHAKE_MAX <= anti_shake) {
+ LOGE("ERR(%s):Invalid anti_shake (%d)", __func__, anti_shake);
+ return -1;
+ }
+
+ if (m_anti_shake != anti_shake) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_SHAKE, anti_shake) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_SHAKE", __func__);
+ return -1;
+ }
+ m_anti_shake = anti_shake;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getAntiShake(void)
+{
+ return m_anti_shake;
+}
+
+int SecCamera::setMetering(int metering_value)
+{
+ LOGV("%s(metering (%d))", __func__, metering_value);
+
+ if (metering_value <= METERING_BASE || METERING_MAX <= metering_value) {
+ LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value);
+ return -1;
+ }
+
+ if (m_params->metering != metering_value) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, metering_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__);
+ return -1;
+ }
+ m_params->metering = metering_value;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getMetering(void)
+{
+ return m_params->metering;
+}
+
+int SecCamera::setJpegQuality(int jpeg_quality)
+{
+ LOGV("%s(jpeg_quality (%d))", __func__, jpeg_quality);
+
+ if (jpeg_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_quality) {
+ LOGE("ERR(%s):Invalid jpeg_quality (%d)", __func__, jpeg_quality);
+ return -1;
+ }
+
+ if (m_jpeg_quality != jpeg_quality) {
+ m_jpeg_quality = jpeg_quality;
+ if (m_flag_camera_create && !m_camera_use_ISP) {
+ jpeg_quality -= 5;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getJpegQuality(void)
+{
+ return m_jpeg_quality;
+}
+
+int SecCamera::setZoom(int zoom_level)
+{
+ LOGV("%s(zoom_level (%d))", __func__, zoom_level);
+
+ if (zoom_level < ZOOM_LEVEL_0 || ZOOM_LEVEL_MAX <= zoom_level) {
+ LOGE("ERR(%s):Invalid zoom_level (%d)", __func__, zoom_level);
+ return -1;
+ }
+
+ if (m_zoom_level != zoom_level) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ZOOM, zoom_level) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ZOOM", __func__);
+ return -1;
+ }
+ m_zoom_level = zoom_level;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getZoom(void)
+{
+ return m_zoom_level;
+}
+
+int SecCamera::setObjectTracking(int object_tracking)
+{
+ LOGV("%s(object_tracking (%d))", __func__, object_tracking);
+
+ if (object_tracking < OBJECT_TRACKING_OFF || OBJECT_TRACKING_MAX <= object_tracking) {
+ LOGE("ERR(%s):Invalid object_tracking (%d)", __func__, object_tracking);
+ return -1;
+ }
+
+ if (m_object_tracking != object_tracking)
+ m_object_tracking = object_tracking;
+
+ return 0;
+}
+
+int SecCamera::getObjectTracking(void)
+{
+ return m_object_tracking;
+}
+
+int SecCamera::getObjectTrackingStatus(void)
+{
+ int obj_status = 0;
+ obj_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_STATUS);
+ return obj_status;
+}
+
+int SecCamera::setObjectTrackingStartStop(int start_stop)
+{
+ LOGV("%s(object_tracking_start_stop (%d))", __func__, start_stop);
+
+ if (m_object_tracking_start_stop != start_stop) {
+ m_object_tracking_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setTouchAFStartStop(int start_stop)
+{
+ LOGV("%s(touch_af_start_stop (%d))", __func__, start_stop);
+
+ if (m_touch_af_start_stop != start_stop) {
+ m_touch_af_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_TOUCH_AF_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_TOUCH_AF_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setSmartAuto(int smart_auto)
+{
+ LOGV("%s(smart_auto (%d))", __func__, smart_auto);
+
+ if (smart_auto < SMART_AUTO_OFF || SMART_AUTO_MAX <= smart_auto) {
+ LOGE("ERR(%s):Invalid smart_auto (%d)", __func__, smart_auto);
+ return -1;
+ }
+
+ if (m_smart_auto != smart_auto) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO, smart_auto) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SMART_AUTO", __func__);
+ return -1;
+ }
+ m_smart_auto = smart_auto;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSmartAuto(void)
+{
+ return m_smart_auto;
+}
+
+int SecCamera::getAutosceneStatus(void)
+{
+ int autoscene_status = -1;
+
+ if (getSmartAuto() == SMART_AUTO_ON) {
+ autoscene_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO_STATUS);
+
+ if ((autoscene_status < SMART_AUTO_STATUS_AUTO) || (autoscene_status > SMART_AUTO_STATUS_MAX)) {
+ LOGE("ERR(%s):Invalid getAutosceneStatus (%d)", __func__, autoscene_status);
+ return -1;
+ }
+ }
+ return autoscene_status;
+}
+
+int SecCamera::setBeautyShot(int beauty_shot)
+{
+ LOGV("%s(beauty_shot (%d))", __func__, beauty_shot);
+
+ if (beauty_shot < BEAUTY_SHOT_OFF || BEAUTY_SHOT_MAX <= beauty_shot) {
+ LOGE("ERR(%s):Invalid beauty_shot (%d)", __func__, beauty_shot);
+ return -1;
+ }
+
+ if (m_beauty_shot != beauty_shot) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BEAUTY_SHOT, beauty_shot) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BEAUTY_SHOT", __func__);
+ return -1;
+ }
+ m_beauty_shot = beauty_shot;
+ }
+
+ setFaceDetect(FACE_DETECTION_ON_BEAUTY);
+ }
+
+ return 0;
+}
+
+int SecCamera::getBeautyShot(void)
+{
+ return m_beauty_shot;
+}
+
+int SecCamera::setVintageMode(int vintage_mode)
+{
+ LOGV("%s(vintage_mode(%d))", __func__, vintage_mode);
+
+ if (vintage_mode <= VINTAGE_MODE_BASE || VINTAGE_MODE_MAX <= vintage_mode) {
+ LOGE("ERR(%s):Invalid vintage_mode (%d)", __func__, vintage_mode);
+ return -1;
+ }
+
+ if (m_vintage_mode != vintage_mode) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VINTAGE_MODE, vintage_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VINTAGE_MODE", __func__);
+ return -1;
+ }
+ m_vintage_mode = vintage_mode;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getVintageMode(void)
+{
+ return m_vintage_mode;
+}
+
+int SecCamera::setFocusMode(int focus_mode)
+{
+ LOGV("%s(focus_mode(%d))", __func__, focus_mode);
+
+ if (FOCUS_MODE_MAX <= focus_mode) {
+ LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode);
+ return -1;
+ }
+
+ if (m_params->focus_mode != focus_mode) {
+ if (m_flag_camera_create) {
+ if (m_params->focus_mode == FOCUS_MODE_AUTO || m_params->focus_mode == FOCUS_MODE_MACRO) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+ if (!m_camera_use_ISP) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+ }
+ m_params->focus_mode = focus_mode;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFocusMode(void)
+{
+ return m_params->focus_mode;
+}
+
+int SecCamera::setFaceDetect(int face_detect)
+{
+ LOGV("%s(face_detect(%d))", __func__, face_detect);
+ if (m_camera_use_ISP) {
+ if (face_detect < IS_FD_COMMAND_STOP || IS_FD_COMMAND_MAX <= face_detect) {
+ LOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect);
+ return -1;
+ }
+ } else {
+ if (face_detect < FACE_DETECTION_OFF || FACE_DETECTION_MAX <= face_detect) {
+ LOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect);
+ return -1;
+ }
+ }
+
+ if (m_face_detect != face_detect) {
+ if (m_flag_camera_create) {
+ if (m_camera_use_ISP) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, face_detect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CMD_FD", __func__);
+ return -1;
+ }
+ } else {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACE_DETECTION, face_detect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACE_DETECTION", __func__);
+ return -1;
+ }
+ }
+ m_face_detect = face_detect;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFaceDetect(void)
+{
+ return m_face_detect;
+}
+
+int SecCamera::setGPSLatitude(const char *gps_latitude)
+{
+ double conveted_latitude = 0;
+ LOGV("%s(gps_latitude(%s))", __func__, gps_latitude);
+ if (gps_latitude == NULL)
+ m_gps_latitude = 0;
+ else {
+ conveted_latitude = atof(gps_latitude);
+ m_gps_latitude = (long)(conveted_latitude * 10000 / 1);
+ }
+
+ LOGV("%s(m_gps_latitude(%ld))", __func__, m_gps_latitude);
+ return 0;
+}
+
+int SecCamera::setGPSLongitude(const char *gps_longitude)
+{
+ double conveted_longitude = 0;
+ LOGV("%s(gps_longitude(%s))", __func__, gps_longitude);
+ if (gps_longitude == NULL)
+ m_gps_longitude = 0;
+ else {
+ conveted_longitude = atof(gps_longitude);
+ m_gps_longitude = (long)(conveted_longitude * 10000 / 1);
+ }
+
+ LOGV("%s(m_gps_longitude(%ld))", __func__, m_gps_longitude);
+ return 0;
+}
+
+int SecCamera::setGPSAltitude(const char *gps_altitude)
+{
+ double conveted_altitude = 0;
+ LOGV("%s(gps_altitude(%s))", __func__, gps_altitude);
+ if (gps_altitude == NULL)
+ m_gps_altitude = 0;
+ else {
+ conveted_altitude = atof(gps_altitude);
+ m_gps_altitude = (long)(conveted_altitude * 100 / 1);
+ }
+
+ LOGV("%s(m_gps_altitude(%ld))", __func__, m_gps_altitude);
+ return 0;
+}
+
+int SecCamera::setGPSTimeStamp(const char *gps_timestamp)
+{
+ LOGV("%s(gps_timestamp(%s))", __func__, gps_timestamp);
+ if (gps_timestamp == NULL)
+ m_gps_timestamp = 0;
+ else
+ m_gps_timestamp = atol(gps_timestamp);
+
+ LOGV("%s(m_gps_timestamp(%ld))", __func__, m_gps_timestamp);
+ return 0;
+}
+
+int SecCamera::setGPSProcessingMethod(const char *gps_processing_method)
+{
+ LOGV("%s(gps_processing_method(%s))", __func__, gps_processing_method);
+ memset(mExifInfo.gps_processing_method, 0, sizeof(mExifInfo.gps_processing_method));
+ if (gps_processing_method != NULL) {
+ size_t len = strlen(gps_processing_method);
+ if (len > sizeof(mExifInfo.gps_processing_method)) {
+ len = sizeof(mExifInfo.gps_processing_method);
+ }
+ memcpy(mExifInfo.gps_processing_method, gps_processing_method, len);
+ }
+ return 0;
+}
+
+int SecCamera::setFaceDetectLockUnlock(int facedetect_lockunlock)
+{
+ LOGV("%s(facedetect_lockunlock(%d))", __func__, facedetect_lockunlock);
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK, facedetect_lockunlock) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setObjectPosition(int x, int y)
+{
+ LOGV("%s(setObjectPosition(x=%d, y=%d))", __func__, x, y);
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__);
+ return -1;
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_Y, y) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_Y", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setGamma(int gamma)
+{
+ LOGV("%s(gamma(%d))", __func__, gamma);
+
+ if (gamma < GAMMA_OFF || GAMMA_MAX <= gamma) {
+ LOGE("ERR(%s):Invalid gamma (%d)", __func__, gamma);
+ return -1;
+ }
+
+ if (m_video_gamma != gamma) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_GAMMA, gamma) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_GAMMA", __func__);
+ return -1;
+ }
+ m_video_gamma = gamma;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setSlowAE(int slow_ae)
+{
+ LOGV("%s(slow_ae(%d))", __func__, slow_ae);
+
+ if (slow_ae < GAMMA_OFF || GAMMA_MAX <= slow_ae) {
+ LOGE("ERR(%s):Invalid slow_ae (%d)", __func__, slow_ae);
+ return -1;
+ }
+
+ if (m_slow_ae!= slow_ae) {
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_SLOW_AE, slow_ae) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_SLOW_AE", __func__);
+ return -1;
+ }
+ m_slow_ae = slow_ae;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setRecordingSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_recording_width = width;
+ m_recording_height = height;
+
+ return 0;
+}
+
+int SecCamera::getRecordingSize(int *width, int *height)
+{
+ *width = m_recording_width;
+ *height = m_recording_height;
+
+ return 0;
+}
+
+int SecCamera::setExifOrientationInfo(int orientationInfo)
+{
+ LOGV("%s(orientationInfo(%d))", __func__, orientationInfo);
+
+ if (orientationInfo < 0) {
+ LOGE("ERR(%s):Invalid orientationInfo (%d)", __func__, orientationInfo);
+ return -1;
+ }
+ m_exif_orientation = orientationInfo;
+
+ return 0;
+}
+
+int SecCamera::setBatchReflection()
+{
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BATCH_REFLECTION, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BATCH_REFLECTION", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Camcorder fix fps */
+int SecCamera::setSensorMode(int sensor_mode)
+{
+ LOGV("%s(sensor_mode (%d))", __func__, sensor_mode);
+
+ if (sensor_mode < SENSOR_MODE_CAMERA || SENSOR_MODE_MOVIE < sensor_mode) {
+ LOGE("ERR(%s):Invalid sensor mode (%d)", __func__, sensor_mode);
+ return -1;
+ }
+
+ if (m_sensor_mode != sensor_mode)
+ m_sensor_mode = sensor_mode;
+
+ return 0;
+}
+
+/* Shot mode */
+/* SINGLE = 0
+* CONTINUOUS = 1
+* PANORAMA = 2
+* SMILE = 3
+* SELF = 6
+*/
+int SecCamera::setShotMode(int shot_mode)
+{
+ LOGV("%s(shot_mode (%d))", __func__, shot_mode);
+ if (shot_mode < SHOT_MODE_SINGLE || SHOT_MODE_SELF < shot_mode) {
+ LOGE("ERR(%s):Invalid shot_mode (%d)", __func__, shot_mode);
+ return -1;
+ }
+ m_shot_mode = shot_mode;
+
+ return 0;
+}
+
+int SecCamera::setDataLineCheck(int chk_dataline)
+{
+ LOGV("%s(chk_dataline (%d))", __func__, chk_dataline);
+
+ if (chk_dataline < CHK_DATALINE_OFF || CHK_DATALINE_MAX <= chk_dataline) {
+ LOGE("ERR(%s):Invalid chk_dataline (%d)", __func__, chk_dataline);
+ return -1;
+ }
+
+ m_chk_dataline = chk_dataline;
+
+ return 0;
+}
+
+int SecCamera::getDataLineCheck(void)
+{
+ return m_chk_dataline;
+}
+
+int SecCamera::setDataLineCheckStop(void)
+{
+ LOGV("%s", __func__);
+
+ if (m_flag_camera_create) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CHECK_DATALINE_STOP, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CHECK_DATALINE_STOP", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+const __u8* SecCamera::getCameraSensorName(void)
+{
+ LOGV("%s", __func__);
+
+ return fimc_v4l2_enuminput(m_cam_fd, getCameraId());
+}
+
+bool SecCamera::getUseInternalISP(void)
+{
+ LOGV("%s", __func__);
+ int ret = 0;
+
+/*TODO*/
+ if (!strncmp((const char*)getCameraSensorName(), "ISP Camera", 10))
+ return true;
+ else if(!strncmp((const char*)getCameraSensorName(), "S5K3H2", 10))
+ return true;
+ else if(!strncmp((const char*)getCameraSensorName(), "S5K3H7", 10))
+ return true;
+ else if(!strncmp((const char*)getCameraSensorName(), "S5K4E5", 10))
+ return true;
+ else if(!strncmp((const char*)getCameraSensorName(), "S5K6A3", 10))
+ return true;
+ else
+ return false;
+}
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+int SecCamera::getCameraSensorESDStatus(void)
+{
+ LOGV("%s", __func__);
+
+ // 0 : normal operation, 1 : abnormal operation
+ int status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_ESD_INT);
+
+ return status;
+}
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+int SecCamera::setJpegThumbnailSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_jpeg_thumbnail_width = width;
+ m_jpeg_thumbnail_height = height;
+
+ return 0;
+}
+
+int SecCamera::getJpegThumbnailSize(int *width, int *height)
+{
+ if (width)
+ *width = m_jpeg_thumbnail_width;
+ if (height)
+ *height = m_jpeg_thumbnail_height;
+
+ return 0;
+}
+
+int SecCamera::setJpegThumbnailQuality(int jpeg_thumbnail_quality)
+{
+ LOGV("%s(jpeg_thumbnail_quality (%d))", __func__, jpeg_thumbnail_quality);
+
+ if (jpeg_thumbnail_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_thumbnail_quality) {
+ LOGE("ERR(%s):Invalid jpeg_thumbnail_quality (%d)", __func__, jpeg_thumbnail_quality);
+ return -1;
+ }
+
+ if (m_jpeg_thumbnail_quality != jpeg_thumbnail_quality) {
+ m_jpeg_thumbnail_quality = jpeg_thumbnail_quality;
+ }
+
+ return 0;
+}
+
+int SecCamera::getJpegThumbnailQuality(void)
+{
+ return m_jpeg_thumbnail_quality;
+}
+
+void SecCamera::setExifFixedAttribute()
+{
+ char property[PROPERTY_VALUE_MAX];
+
+ //2 0th IFD TIFF Tags
+ //3 Maker
+ property_get("ro.product.brand", property, EXIF_DEF_MAKER);
+ strncpy((char *)mExifInfo.maker, property,
+ sizeof(mExifInfo.maker) - 1);
+ mExifInfo.maker[sizeof(mExifInfo.maker) - 1] = '\0';
+ //3 Model
+ property_get("ro.product.model", property, EXIF_DEF_MODEL);
+ strncpy((char *)mExifInfo.model, property,
+ sizeof(mExifInfo.model) - 1);
+ mExifInfo.model[sizeof(mExifInfo.model) - 1] = '\0';
+ //3 Software
+ property_get("ro.build.id", property, EXIF_DEF_SOFTWARE);
+ strncpy((char *)mExifInfo.software, property,
+ sizeof(mExifInfo.software) - 1);
+ mExifInfo.software[sizeof(mExifInfo.software) - 1] = '\0';
+
+ //3 YCbCr Positioning
+ mExifInfo.ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING;
+
+ //2 0th IFD Exif Private Tags
+ //3 F Number
+ mExifInfo.fnumber.num = EXIF_DEF_FNUMBER_NUM;
+ mExifInfo.fnumber.den = EXIF_DEF_FNUMBER_DEN;
+ //3 Exposure Program
+ mExifInfo.exposure_program = EXIF_DEF_EXPOSURE_PROGRAM;
+ //3 Exif Version
+ memcpy(mExifInfo.exif_version, EXIF_DEF_EXIF_VERSION, sizeof(mExifInfo.exif_version));
+ //3 Aperture
+ uint32_t av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den);
+ mExifInfo.aperture.num = av*EXIF_DEF_APEX_DEN;
+ mExifInfo.aperture.den = EXIF_DEF_APEX_DEN;
+ //3 Maximum lens aperture
+ mExifInfo.max_aperture.num = mExifInfo.aperture.num;
+ mExifInfo.max_aperture.den = mExifInfo.aperture.den;
+ //3 Lens Focal Length
+ if (m_camera_id == CAMERA_ID_BACK)
+ mExifInfo.focal_length.num = BACK_CAMERA_FOCAL_LENGTH;
+ else
+ mExifInfo.focal_length.num = FRONT_CAMERA_FOCAL_LENGTH;
+
+ mExifInfo.focal_length.den = EXIF_DEF_FOCAL_LEN_DEN;
+ //3 User Comments
+ strcpy((char *)mExifInfo.user_comment, EXIF_DEF_USERCOMMENTS);
+ //3 Color Space information
+ mExifInfo.color_space = EXIF_DEF_COLOR_SPACE;
+ //3 Exposure Mode
+ mExifInfo.exposure_mode = EXIF_DEF_EXPOSURE_MODE;
+
+ //2 0th IFD GPS Info Tags
+ unsigned char gps_version[4] = { 0x02, 0x02, 0x00, 0x00 };
+ memcpy(mExifInfo.gps_version_id, gps_version, sizeof(gps_version));
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.compression_scheme = EXIF_DEF_COMPRESSION;
+ mExifInfo.x_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.x_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.y_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.y_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.resolution_unit = EXIF_DEF_RESOLUTION_UNIT;
+}
+
+void SecCamera::setExifChangedAttribute()
+{
+ //2 0th IFD TIFF Tags
+ //3 Width
+ mExifInfo.width = m_snapshot_width;
+ //3 Height
+ mExifInfo.height = m_snapshot_height;
+ //3 Orientation
+ switch (m_exif_orientation) {
+ case 90:
+ mExifInfo.orientation = EXIF_ORIENTATION_90;
+ break;
+ case 180:
+ mExifInfo.orientation = EXIF_ORIENTATION_180;
+ break;
+ case 270:
+ mExifInfo.orientation = EXIF_ORIENTATION_270;
+ break;
+ case 0:
+ default:
+ mExifInfo.orientation = EXIF_ORIENTATION_UP;
+ break;
+ }
+ //3 Date time
+ time_t rawtime;
+ struct tm *timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo);
+
+ //2 0th IFD Exif Private Tags
+ //3 Exposure Time
+ int shutterSpeed = 100;
+ if (m_camera_use_ISP) {
+ shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXIF_SHUTTERSPEED);
+ if (shutterSpeed <= 0) {
+ LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100",
+ __func__, shutterSpeed, m_camera_id);
+ shutterSpeed = 100;
+ }
+ } else {
+ shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_TV);
+ if (shutterSpeed <= 0) {
+ LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100",
+ __func__, shutterSpeed, m_camera_id);
+ shutterSpeed = 100;
+ }
+ }
+
+ /* TODO : external isp is not shuppoting exptime now. */
+ int exptime = 100;
+ if (m_camera_use_ISP) {
+ exptime = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_EXPTIME);
+ if (exptime <= 0) {
+ LOGE("%s: error %d getting exposure time, camera_id = %d, using 100",
+ __func__, exptime, m_camera_id);
+ exptime = 100;
+ }
+ }
+ mExifInfo.exposure_time.num = 1;
+ mExifInfo.exposure_time.den = (uint32_t)exptime;
+
+ /* TODO : Normaly exposure time and shutter speed is same. But we need to */
+ /* calculate exactly value. */
+ shutterSpeed = exptime;
+
+ //3 ISO Speed Rating
+ int iso;
+ if (m_camera_use_ISP)
+ iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXIF_ISO);
+ else
+ iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_ISO);
+ if (iso < 0) {
+ LOGE("%s: error %d getting iso, camera_id = %d, using 100",
+ __func__, iso, m_camera_id);
+ iso = 0;
+ }
+ mExifInfo.iso_speed_rating = iso;
+
+ uint32_t av, tv, bv, sv, ev;
+ if (m_camera_use_ISP) {
+ av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den);
+ tv = APEX_EXPOSURE_TO_SHUTTER((double)mExifInfo.exposure_time.num / mExifInfo.exposure_time.den);
+ sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating);
+ bv = av + tv - sv;
+ ev = m_params->exposure - IS_EXPOSURE_DEFAULT;
+ } else {
+ av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den);
+ tv = shutterSpeed;
+ sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating);
+ bv = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_BV);
+ ev = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_EBV);
+ }
+ LOGD("Shutter speed=1/%d s, iso=%d", shutterSpeed, mExifInfo.iso_speed_rating);
+ LOGD("AV=%d, TV=%d, SV=%d, BV=%d, EV=%d", av, tv, sv, bv, ev);
+
+ //3 Shutter Speed
+ mExifInfo.shutter_speed.num = 1;
+ mExifInfo.shutter_speed.den = shutterSpeed;
+ //3 Brightness
+ mExifInfo.brightness.num = bv*EXIF_DEF_APEX_DEN;
+ mExifInfo.brightness.den = EXIF_DEF_APEX_DEN;
+ //3 Exposure Bias
+ if (m_params->scene_mode == SCENE_MODE_BEACH_SNOW) {
+ mExifInfo.exposure_bias.num = EXIF_DEF_APEX_DEN;
+ mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN;
+ } else {
+ mExifInfo.exposure_bias.num = ev*EXIF_DEF_APEX_DEN;
+ mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN;
+ }
+ //3 Metering Mode
+ switch (m_params->metering) {
+ case METERING_SPOT:
+ mExifInfo.metering_mode = EXIF_METERING_SPOT;
+ break;
+ case METERING_MATRIX:
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ case METERING_CENTER:
+ mExifInfo.metering_mode = EXIF_METERING_CENTER;
+ break;
+ default :
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ }
+
+ //3 Flash
+ int flash = m_params->flash_mode;
+ //int flash = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_FLASH_ONOFF);
+ if (flash < 0)
+ mExifInfo.flash = EXIF_DEF_FLASH;
+ else
+ mExifInfo.flash = flash;
+
+ //3 White Balance
+ if (m_params->white_balance == WHITE_BALANCE_AUTO || m_params->white_balance == IS_AWB_AUTO)
+ mExifInfo.white_balance = EXIF_WB_AUTO;
+ else
+ mExifInfo.white_balance = EXIF_WB_MANUAL;
+ //3 Scene Capture Type
+ switch (m_params->scene_mode) {
+ case SCENE_MODE_PORTRAIT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT;
+ break;
+ case SCENE_MODE_LANDSCAPE:
+ mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE;
+ break;
+ case SCENE_MODE_NIGHTSHOT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT;
+ break;
+ default:
+ mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD;
+ break;
+ }
+
+ //2 0th IFD GPS Info Tags
+ if (m_gps_latitude != 0 && m_gps_longitude != 0) {
+ if (m_gps_latitude > 0)
+ strcpy((char *)mExifInfo.gps_latitude_ref, "N");
+ else
+ strcpy((char *)mExifInfo.gps_latitude_ref, "S");
+
+ if (m_gps_longitude > 0)
+ strcpy((char *)mExifInfo.gps_longitude_ref, "E");
+ else
+ strcpy((char *)mExifInfo.gps_longitude_ref, "W");
+
+ if (m_gps_altitude > 0)
+ mExifInfo.gps_altitude_ref = 0;
+ else
+ mExifInfo.gps_altitude_ref = 1;
+
+ double latitude = fabs(m_gps_latitude / 10000.0);
+ double longitude = fabs(m_gps_longitude / 10000.0);
+ double altitude = fabs(m_gps_altitude / 100.0);
+
+ mExifInfo.gps_latitude[0].num = (uint32_t)latitude;
+ mExifInfo.gps_latitude[0].den = 1;
+ mExifInfo.gps_latitude[1].num = (uint32_t)((latitude - mExifInfo.gps_latitude[0].num) * 60);
+ mExifInfo.gps_latitude[1].den = 1;
+ mExifInfo.gps_latitude[2].num = (uint32_t)((((latitude - mExifInfo.gps_latitude[0].num) * 60)
+ - mExifInfo.gps_latitude[1].num) * 60);
+ mExifInfo.gps_latitude[2].den = 1;
+
+ mExifInfo.gps_longitude[0].num = (uint32_t)longitude;
+ mExifInfo.gps_longitude[0].den = 1;
+ mExifInfo.gps_longitude[1].num = (uint32_t)((longitude - mExifInfo.gps_longitude[0].num) * 60);
+ mExifInfo.gps_longitude[1].den = 1;
+ mExifInfo.gps_longitude[2].num = (uint32_t)((((longitude - mExifInfo.gps_longitude[0].num) * 60)
+ - mExifInfo.gps_longitude[1].num) * 60);
+ mExifInfo.gps_longitude[2].den = 1;
+
+ mExifInfo.gps_altitude.num = (uint32_t)altitude;
+ mExifInfo.gps_altitude.den = 1;
+
+ struct tm tm_data;
+ gmtime_r(&m_gps_timestamp, &tm_data);
+ mExifInfo.gps_timestamp[0].num = tm_data.tm_hour;
+ mExifInfo.gps_timestamp[0].den = 1;
+ mExifInfo.gps_timestamp[1].num = tm_data.tm_min;
+ mExifInfo.gps_timestamp[1].den = 1;
+ mExifInfo.gps_timestamp[2].num = tm_data.tm_sec;
+ mExifInfo.gps_timestamp[2].den = 1;
+ snprintf((char*)mExifInfo.gps_datestamp, sizeof(mExifInfo.gps_datestamp),
+ "%04d:%02d:%02d", tm_data.tm_year + 1900, tm_data.tm_mon + 1, tm_data.tm_mday);
+
+ mExifInfo.enableGps = true;
+ } else {
+ mExifInfo.enableGps = false;
+ }
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.widthThumb = m_jpeg_thumbnail_width;
+ mExifInfo.heightThumb = m_jpeg_thumbnail_height;
+}
+
+int SecCamera::makeExif (unsigned char *exifOut,
+ unsigned char *thumb_buf,
+ unsigned int thumb_size,
+ exif_attribute_t *exifInfo,
+ unsigned int *size,
+ bool useMainbufForThumb)
+{
+ unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset;
+ unsigned int tmp, LongerTagOffest = 0;
+ pApp1Start = pCur = exifOut;
+
+ //2 Exif Identifier Code & TIFF Header
+ pCur += 4; // Skip 4 Byte for APP1 marker and length
+ unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+ memcpy(pCur, ExifIdentifierCode, 6);
+ pCur += 6;
+
+ /* Byte Order - little endian, Offset of IFD - 0x00000008.H */
+ unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
+ memcpy(pCur, TiffHeader, 8);
+ pIfdStart = pCur;
+ pCur += 8;
+
+ //2 0th IFD TIFF Tags
+ if (exifInfo->enableGps)
+ tmp = NUM_0TH_IFD_TIFF;
+ else
+ tmp = NUM_0TH_IFD_TIFF - 1;
+
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT,
+ 1, exifInfo->ycbcr_positioning);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ if (exifInfo->enableGps) {
+ pGpsIfdPtr = pCur;
+ pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer
+ }
+
+ pNextIfdOffset = pCur; // Skip a offset size for next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD Exif Private Tags
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_0TH_IFD_EXIF;
+ memcpy(pCur, &tmp , NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT,
+ 1, exifInfo->exposure_program);
+ writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT,
+ 1, exifInfo->iso_speed_rating);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED,
+ 4, exifInfo->exif_version);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT,
+ 1, exifInfo->metering_mode);
+ writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
+ 1, exifInfo->flash);
+ writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart);
+ char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 };
+ int commentsLen = strlen((char *)exifInfo->user_comment) + 1;
+ memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen);
+ memcpy(exifInfo->user_comment, code, sizeof(code));
+ writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED,
+ commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT,
+ 1, exifInfo->color_space);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG,
+ 1, exifInfo->exposure_mode);
+ writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG,
+ 1, exifInfo->white_balance);
+ writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG,
+ 1, exifInfo->scene_capture_type);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD GPS Info Tags
+ if (exifInfo->enableGps) {
+ writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ if (exifInfo->gps_processing_method[0] == 0) {
+ // don't create GPS_PROCESSING_METHOD tag if there isn't any
+ tmp = NUM_0TH_IFD_GPS - 1;
+ } else {
+ tmp = NUM_0TH_IFD_GPS;
+ }
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE,
+ 4, exifInfo->gps_version_id);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_latitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_longitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE,
+ 1, exifInfo->gps_altitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart);
+ tmp = strlen((char*)exifInfo->gps_processing_method);
+ if (tmp > 0) {
+ if (tmp > 100) {
+ tmp = 100;
+ }
+ static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
+ unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)];
+ memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
+ memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED,
+ tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart);
+ }
+ writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII,
+ 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+ }
+
+ //2 1th IFD TIFF Tags
+
+ unsigned char *thumbBuf = thumb_buf;
+ unsigned int thumbSize = thumb_size;
+
+ if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) {
+ tmp = LongerTagOffest;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_1TH_IFD_TIFF;
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->widthThumb);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->heightThumb);
+ writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT,
+ 1, exifInfo->compression_scheme);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT,
+ 1, exifInfo->resolution_unit);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG,
+ 1, thumbSize);
+
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ memcpy(pIfdStart + LongerTagOffest, thumbBuf, thumbSize);
+ LongerTagOffest += thumbSize;
+ } else {
+ tmp = 0;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+ }
+
+ unsigned char App1Marker[2] = { 0xff, 0xe1 };
+ memcpy(pApp1Start, App1Marker, 2);
+ pApp1Start += 2;
+
+ *size = 10 + LongerTagOffest;
+ tmp = *size - 2; // APP1 Maker isn't counted
+ unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF};
+ memcpy(pApp1Start, size_mm, 2);
+
+ LOGD("makeExif X");
+
+ return 0;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, &value, 4);
+ *pCur += 4;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue)
+{
+ char buf[4] = { 0,};
+
+ memcpy(buf, pValue, count);
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, buf, 4);
+ *pCur += 4;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, count);
+ *offset += count;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, 8 * count);
+ *offset += 8 * count;
+}
+
+status_t SecCamera::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, 255, "dump(%d)\n", fd);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+double SecCamera::jpeg_ratio = 0.7;
+int SecCamera::interleaveDataSize = 5242880;
+int SecCamera::jpegLineLength = 636;
+
+}; // namespace android
diff --git a/exynos4/hal/libcamera/SecCamera.h b/exynos4/hal/libcamera/SecCamera.h
new file mode 100644
index 0000000..fc30fc4
--- /dev/null
+++ b/exynos4/hal/libcamera/SecCamera.h
@@ -0,0 +1,695 @@
+/*
+**
+** 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.
+*/
+
+#ifndef ANDROID_HARDWARE_CAMERA_SEC_H
+#define ANDROID_HARDWARE_CAMERA_SEC_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 <utils/RefBase.h>
+#include <hardware/camera.h>
+#include <videodev2.h>
+#include <videodev2_samsung.h>
+#include "sec_utils_v4l2.h"
+
+#include "SecBuffer.h"
+
+#include <utils/String8.h>
+
+#ifdef SAMSUNG_EXYNOS4210
+#include "jpeg_api.h"
+#endif
+
+#ifdef SAMSUNG_EXYNOS4x12
+#include "jpeg_hal.h"
+#endif
+
+#include "Exif.h"
+namespace android {
+
+//#define ENABLE_ESD_PREVIEW_CHECK
+//#define ZERO_SHUTTER_LAG
+#define VIDEO_SNAPSHOT
+
+#if defined VIDEO_SNAPSHOT
+#define ZERO_SHUTTER_LAG
+#endif
+
+#define USE_FACE_DETECTION
+//#define USE_TOUCH_AF
+
+#if defined(LOG_NDEBUG) && (LOG_NDEBUG == 0)
+#define LOG_CAMERA LOGD
+#define LOG_CAMERA_PREVIEW LOGD
+
+#define LOG_TIME_DEFINE(n) \
+ struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0;
+
+#define LOG_TIME_START(n) \
+ gettimeofday(&time_start_##n, NULL);
+
+#define LOG_TIME_END(n) \
+ gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time_camera(&time_start_##n, &time_stop_##n);
+
+#define LOG_TIME(n) \
+ log_time_##n
+
+#else
+#define LOG_CAMERA(...)
+#define LOG_CAMERA_PREVIEW(...)
+#define LOG_TIME_DEFINE(n)
+#define LOG_TIME_START(n)
+#define LOG_TIME_END(n)
+#define LOG_TIME(n)
+#endif
+
+#define FRM_RATIO(w, h) ((w)*10/(h))
+#define SIZE_4K (1 << 12)
+
+#define JOIN(x, y) JOIN_AGAIN(x, y)
+#define JOIN_AGAIN(x, y) x ## y
+
+#define FRONT_CAM S5K6A3
+#define BACK_CAM M5MO
+
+#if !defined (FRONT_CAM) || !defined(BACK_CAM)
+#error "Please define the Camera module"
+#endif
+
+#define M5MO_PREVIEW_WIDTH 640
+#define M5MO_PREVIEW_HEIGHT 480
+#define M5MO_SNAPSHOT_WIDTH 3264
+#define M5MO_SNAPSHOT_HEIGHT 2448
+
+#define M5MO_THUMBNAIL_WIDTH 320
+#define M5MO_THUMBNAIL_HEIGHT 240
+#define M5MO_THUMBNAIL_BPP 16
+
+#define M5MO_FPS 30
+
+/* focal length of 3.43mm */
+#define M5MO_FOCAL_LENGTH 343
+
+#define S5K6A3_PREVIEW_WIDTH 480
+#define S5K6A3_PREVIEW_HEIGHT 480
+#define S5K6A3_SNAPSHOT_WIDTH 1392
+#define S5K6A3_SNAPSHOT_HEIGHT 1392
+
+#define S5K6A3_THUMBNAIL_WIDTH 160
+#define S5K6A3_THUMBNAIL_HEIGHT 120
+#define S5K6A3_THUMBNAIL_BPP 16
+
+#define S5K6A3_FPS 30
+
+/* focal length of 0.9mm */
+#define S5K6A3_FOCAL_LENGTH 90
+
+#define MAX_BACK_CAMERA_PREVIEW_WIDTH JOIN(BACK_CAM,_PREVIEW_WIDTH)
+#define MAX_BACK_CAMERA_PREVIEW_HEIGHT JOIN(BACK_CAM,_PREVIEW_HEIGHT)
+#define MAX_BACK_CAMERA_SNAPSHOT_WIDTH JOIN(BACK_CAM,_SNAPSHOT_WIDTH)
+#define MAX_BACK_CAMERA_SNAPSHOT_HEIGHT JOIN(BACK_CAM,_SNAPSHOT_HEIGHT)
+
+#define BACK_CAMERA_THUMBNAIL_WIDTH JOIN(BACK_CAM,_THUMBNAIL_WIDTH)
+#define BACK_CAMERA_THUMBNAIL_HEIGHT JOIN(BACK_CAM,_THUMBNAIL_HEIGHT)
+#define BACK_CAMERA_THUMBNAIL_BPP JOIN(BACK_CAM,_THUMBNAIL_BPP)
+
+#define BACK_CAMERA_FPS JOIN(BACK_CAM,_FPS)
+
+#define BACK_CAMERA_FOCAL_LENGTH JOIN(BACK_CAM,_FOCAL_LENGTH)
+
+#define MAX_FRONT_CAMERA_PREVIEW_WIDTH JOIN(FRONT_CAM,_PREVIEW_WIDTH)
+#define MAX_FRONT_CAMERA_PREVIEW_HEIGHT JOIN(FRONT_CAM,_PREVIEW_HEIGHT)
+#define MAX_FRONT_CAMERA_SNAPSHOT_WIDTH JOIN(FRONT_CAM,_SNAPSHOT_WIDTH)
+#define MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT JOIN(FRONT_CAM,_SNAPSHOT_HEIGHT)
+
+#define FRONT_CAMERA_THUMBNAIL_WIDTH JOIN(FRONT_CAM,_THUMBNAIL_WIDTH)
+#define FRONT_CAMERA_THUMBNAIL_HEIGHT JOIN(FRONT_CAM,_THUMBNAIL_HEIGHT)
+#define FRONT_CAMERA_THUMBNAIL_BPP JOIN(FRONT_CAM,_THUMBNAIL_BPP)
+
+#define FRONT_CAMERA_FPS JOIN(FRONT_CAM,_FPS)
+
+#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH)
+
+#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256
+#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192
+
+#ifdef BOARD_USE_V4L2
+#define CAMERA_DEV_NAME "/dev/video1"
+#else
+#define CAMERA_DEV_NAME "/dev/video0"
+#endif
+
+#ifdef SAMSUNG_EXYNOS4210
+#define CAMERA_DEV_NAME3 "/dev/video2"
+#endif
+
+#ifdef SAMSUNG_EXYNOS4x12
+#ifdef BOARD_USE_V4L2
+#define CAMERA_DEV_NAME3 "/dev/video3"
+#else
+#define CAMERA_DEV_NAME3 "/dev/video1"
+#endif
+#ifdef ZERO_SHUTTER_LAG
+#define CAMERA_DEV_NAME2 "/dev/video2"
+#endif
+#endif
+
+#define CAMERA_DEV_NAME_TEMP "/data/videotmp_000"
+#define CAMERA_DEV_NAME2_TEMP "/data/videotemp_002"
+
+
+#define BPP 2
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define MAX_BUFFERS 8
+
+#ifdef ZERO_SHUTTER_LAG
+#define CAP_BUFFERS 8
+#else
+#define CAP_BUFFERS 1
+#endif
+
+#ifdef BOARD_USE_V4L2
+#define MAX_PLANES (3)
+#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+#else
+#define MAX_PLANES (1)
+#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE
+#endif
+
+#ifdef BOARD_USE_V4L2_ION
+#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR
+#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12M
+#define PREVIEW_NUM_PLANE (3)
+#define RECORD_NUM_PLANE (2)
+#else
+#define V4L2_MEMORY_TYPE V4L2_MEMORY_MMAP
+#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12
+#define PREVIEW_NUM_PLANE (1)
+#define RECORD_NUM_PLANE (1)
+#endif
+
+/*
+ * V 4 L 2 F I M C E X T E N S I O N S
+ *
+ */
+#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32)
+#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33)
+#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34)
+#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35)
+#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36)
+#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37)
+
+#define TPATTERN_COLORBAR 1
+#define TPATTERN_HORIZONTAL 2
+#define TPATTERN_VERTICAL 3
+
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U')
+
+/* FOURCC for FIMC specific */
+#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y')
+#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6')
+#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1')
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+/*
+ * U S E R D E F I N E D T Y P E S
+ *
+ */
+#define PREVIEW_MODE 1
+#define CAPTURE_MODE 2
+#define RECORD_MODE 3
+
+struct yuv_fmt_list {
+ const char *name;
+ const char *desc;
+ unsigned int fmt;
+ int depth;
+ int planes;
+};
+
+struct camsensor_date_info {
+ unsigned int year;
+ unsigned int month;
+ unsigned int date;
+};
+
+class SecCamera : public virtual RefBase {
+public:
+
+ enum CAMERA_ID {
+ CAMERA_ID_BACK = 0,
+ CAMERA_ID_FRONT = 1,
+ };
+
+ enum JPEG_QUALITY {
+ JPEG_QUALITY_ECONOMY = 0,
+ JPEG_QUALITY_NORMAL = 50,
+ JPEG_QUALITY_SUPERFINE = 100,
+ JPEG_QUALITY_MAX,
+ };
+
+ enum OBJECT_TRACKING {
+ OBJECT_TRACKING_OFF,
+ OBJECT_TRACKING_ON,
+ OBJECT_TRACKING_MAX,
+ };
+
+ /*VT call*/
+ enum VT_MODE {
+ VT_MODE_OFF,
+ VT_MODE_ON,
+ VT_MODE_MAX,
+ };
+
+ /*Camera sensor mode - Camcorder fix fps*/
+ enum SENSOR_MODE {
+ SENSOR_MODE_CAMERA,
+ SENSOR_MODE_MOVIE,
+ };
+
+ /*Camera Shot mode*/
+ enum SHOT_MODE {
+ SHOT_MODE_SINGLE = 0,
+ SHOT_MODE_CONTINUOUS = 1,
+ SHOT_MODE_PANORAMA = 2,
+ SHOT_MODE_SMILE = 3,
+ SHOT_MODE_SELF = 6,
+ };
+
+ enum CHK_DATALINE {
+ CHK_DATALINE_OFF,
+ CHK_DATALINE_ON,
+ CHK_DATALINE_MAX,
+ };
+
+ enum CAM_MODE {
+ PREVIEW = 0,
+ PICTURE = 1,
+ RECORDING = 2,
+ };
+
+ int m_touch_af_start_stop;
+
+ SecCamera();
+ virtual ~SecCamera();
+
+ static SecCamera* createInstance(void)
+ {
+ static SecCamera singleton;
+ return &singleton;
+ }
+ status_t dump(int fd);
+
+ bool CreateCamera(int index);
+ bool DestroyCamera(void);
+ int getCameraId(void);
+ void initParameters(int index);
+ int setMode(int recording_en);
+
+ int startPreview(void);
+ int stopPreview(void);
+ int getPreviewState(void)
+ {
+ return m_preview_state;
+ }
+ void clearPreviewState(void)
+ {
+ m_preview_state = 0;
+ }
+
+ int startSnapshot(SecBuffer *yuv_buf);
+ int stopSnapshot(void);
+ int getSnapshot(void);
+ int setSnapshotFrame(int index);
+
+ int startRecord(bool recordHint);
+ int stopRecord(void);
+ int setPreviewFrame(int index);
+ int getRecordFrame(void);
+ int releaseRecordFrame(int index);
+ int getRecordAddr(int index, SecBuffer *buffer);
+
+ int getPreview(camera_frame_metadata_t *facedata);
+ int setPreviewSize(int width, int height, int pixel_format);
+ int getPreviewSize(int *width, int *height, int *frame_size);
+ int getPreviewMaxSize(int *width, int *height);
+ int getPreviewPixelFormat(void);
+ int setPreviewImage(int index, unsigned char *buffer, int size);
+
+ int setVideosnapshotSize(int width, int height);
+ int getVideosnapshotSize(int *width, int *height, int *frame_size);
+ int setSnapshotSize(int width, int height);
+ int getSnapshotSize(int *width, int *height, int *frame_size);
+ int getSnapshotMaxSize(int *width, int *height);
+ int setSnapshotPixelFormat(int pixel_format);
+ int getSnapshotPixelFormat(void);
+
+ unsigned char* getJpeg(unsigned char *snapshot_data, int snapshot_size, int *size);
+ unsigned char* yuv2Jpeg(unsigned char *raw_data, int raw_size,
+ int *jpeg_size,
+ int width, int height, int pixel_format);
+
+ int setJpegThumbnailSize(int width, int height);
+ int getJpegThumbnailSize(int *width, int *height);
+
+ int setJpegThumbnailQuality(int jpeg_thumbnail_quality);
+ int getJpegThumbnailQuality(void);
+
+ int initSetParams(void);
+
+ int setAutofocus(void);
+ int setTouchAF(void);
+
+ int SetRotate(int angle);
+ int getRotate(void);
+
+ int setVerticalMirror(void);
+ int setHorizontalMirror(void);
+
+ int setWhiteBalance(int white_balance);
+ int getWhiteBalance(void);
+
+ int setBrightness(int brightness);
+ int getBrightness(void);
+
+ int setExposure(int exposure);
+ int getExposure(void);
+
+ int setImageEffect(int image_effect);
+ int getImageEffect(void);
+
+ int setSceneMode(int scene_mode);
+ int getSceneMode(void);
+
+ int setFlashMode(int flash_mode);
+ int getFlashMode(void);
+
+ int setMetering(int metering_value);
+ int getMetering(void);
+
+ int setAutoExposureLock(int toggle);
+ int setAutoWhiteBalanceLock(int toggle);
+
+ int setISO(int iso_value);
+ int getISO(void);
+
+ int setContrast(int contrast_value);
+ int getContrast(void);
+
+ int setSaturation(int saturation_value);
+ int getSaturation(void);
+
+ int setSharpness(int sharpness_value);
+ int getSharpness(void);
+
+ int setHue(int hue_value);
+ int getHue(void);
+
+ int setWDR(int wdr_value);
+ int getWDR(void);
+
+ int setAntiShake(int anti_shake);
+ int getAntiShake(void);
+
+ int setJpegQuality(int jpeg_qality);
+ int getJpegQuality(void);
+
+ int setZoom(int zoom_level);
+ int getZoom(void);
+
+ int setObjectTracking(int object_tracking);
+ int getObjectTracking(void);
+ int getObjectTrackingStatus(void);
+
+ int setSmartAuto(int smart_auto);
+ int getSmartAuto(void);
+ int getAutosceneStatus(void);
+
+ int setBeautyShot(int beauty_shot);
+ int getBeautyShot(void);
+
+ int setVintageMode(int vintage_mode);
+ int getVintageMode(void);
+
+ int setFocusMode(int focus_mode);
+ int getFocusMode(void);
+
+ int setFaceDetect(int face_detect);
+ int getFaceDetect(void);
+
+ int setGPSLatitude(const char *gps_latitude);
+ int setGPSLongitude(const char *gps_longitude);
+ int setGPSAltitude(const char *gps_altitude);
+ int setGPSTimeStamp(const char *gps_timestamp);
+ int setGPSProcessingMethod(const char *gps_timestamp);
+ int cancelAutofocus(void);
+ int setFaceDetectLockUnlock(int facedetect_lockunlock);
+ int setObjectPosition(int x, int y);
+ int setObjectTrackingStartStop(int start_stop);
+ int setTouchAFStartStop(int start_stop);
+ int setCAFStatus(int on_off);
+ int getAutoFocusResult(void);
+ int setAntiBanding(int anti_banding);
+ int getPostview(void);
+ int setRecordingSize(int width, int height);
+ int getRecordingSize(int *width, int *height);
+ int setGamma(int gamma);
+ int setSlowAE(int slow_ae);
+ int setExifOrientationInfo(int orientationInfo);
+ int setBatchReflection(void);
+ int setSnapshotCmd(void);
+ int endSnapshot(void);
+ int setCameraSensorReset(void);
+ int setSensorMode(int sensor_mode); /* Camcorder fix fps */
+ int setShotMode(int shot_mode); /* Shot mode */
+ int setDataLineCheck(int chk_dataline);
+ int getDataLineCheck(void);
+ int setDataLineCheckStop(void);
+ int setDefultIMEI(int imei);
+ int getDefultIMEI(void);
+ const __u8* getCameraSensorName(void);
+ bool getUseInternalISP(void);
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int getCameraSensorESDStatus(void);
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ int setFrameRate(int frame_rate);
+ unsigned char* getJpeg(int *jpeg_size,
+ int *thumb_size,
+ unsigned int *thumb_addr,
+ unsigned int *phyaddr);
+ int getSnapshotAndJpeg(SecBuffer *yuv_buf,
+ int index,
+ unsigned char *jpeg_buf,
+ int *output_size);
+ int getExif(unsigned char *pExifDst, unsigned char *pThumbSrc, int thumbSize);
+
+ void getPostViewConfig(int*, int*, int*);
+ void getThumbnailConfig(int *width, int *height, int *size);
+
+ int getPostViewOffset(void);
+ int getCameraFd(enum CAM_MODE);
+ int getJpegFd(void);
+ void SetJpgAddr(unsigned char *addr);
+ int getPreviewAddr(int index, SecBuffer *buffer);
+ int getCaptureAddr(int index, SecBuffer *buffer);
+#ifdef BOARD_USE_V4L2_ION
+ void setUserBufferAddr(void *ptr, int index, int mode);
+#endif
+ static void setJpegRatio(double ratio)
+ {
+ if((ratio < 0) || (ratio > 1))
+ return;
+
+ jpeg_ratio = ratio;
+ }
+
+ static double getJpegRatio()
+ {
+ return jpeg_ratio;
+ }
+
+ static void setInterleaveDataSize(int x)
+ {
+ interleaveDataSize = x;
+ }
+
+ static int getInterleaveDataSize()
+ {
+ return interleaveDataSize;
+ }
+
+ static void setJpegLineLength(int x)
+ {
+ jpegLineLength = x;
+ }
+
+ static int getJpegLineLength()
+ {
+ return jpegLineLength;
+ }
+
+private:
+ v4l2_streamparm m_streamparm;
+ struct sec_cam_parm *m_params;
+ int m_flagCreate;
+ int m_preview_state;
+ int m_snapshot_state;
+ int m_camera_id;
+ bool m_camera_use_ISP;
+
+ int m_cam_fd;
+ struct pollfd m_events_c;
+
+ int m_cam_fd2;
+ int m_cap_fd;
+ struct pollfd m_events_c2;
+
+ int m_cam_fd3;
+ int m_rec_fd;
+ struct pollfd m_events_c3;
+ int m_flag_record_start;
+
+ int m_preview_v4lformat;
+ int m_preview_width;
+ int m_preview_height;
+ int m_preview_max_width;
+ int m_preview_max_height;
+
+ int m_snapshot_v4lformat;
+ int m_snapshot_width;
+ int m_snapshot_height;
+ int m_snapshot_max_width;
+ int m_snapshot_max_height;
+
+ int m_num_capbuf;
+ int m_videosnapshot_width;
+ int m_videosnapshot_height;
+
+ int m_angle;
+ int m_anti_banding;
+ int m_wdr;
+ int m_anti_shake;
+ int m_zoom_level;
+ int m_object_tracking;
+ int m_smart_auto;
+ int m_beauty_shot;
+ int m_vintage_mode;
+ int m_face_detect;
+ int m_object_tracking_start_stop;
+ int m_recording_en;
+ bool m_record_hint;
+ int m_recording_width;
+ int m_recording_height;
+ long m_gps_latitude;
+ long m_gps_longitude;
+ long m_gps_altitude;
+ long m_gps_timestamp;
+ int m_sensor_mode; /*Camcorder fix fps */
+ int m_shot_mode; /* Shot mode */
+ int m_exif_orientation;
+ int m_chk_dataline;
+ int m_video_gamma;
+ int m_slow_ae;
+ int m_camera_af_flag;
+ int m_auto_focus_state;
+
+ int m_flag_camera_create;
+ int m_flag_camera_start;
+
+ int m_jpeg_fd;
+ int m_jpeg_thumbnail_width;
+ int m_jpeg_thumbnail_height;
+ int m_jpeg_thumbnail_quality;
+ int m_jpeg_quality;
+
+ int m_postview_offset;
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int m_esd_check_count;
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ exif_attribute_t mExifInfo;
+
+ struct SecBuffer m_capture_buf[CAP_BUFFERS];
+ struct SecBuffer m_buffers_preview[MAX_BUFFERS];
+ struct SecBuffer m_buffers_record[MAX_BUFFERS];
+
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+
+ void setExifChangedAttribute();
+ void setExifFixedAttribute();
+ int makeExif (unsigned char *exifOut,
+ unsigned char *thumb_buf,
+ unsigned int thumb_size,
+ exif_attribute_t *exifInfo,
+ unsigned int *size,
+ bool useMainbufForThumb);
+ void resetCamera();
+
+ static double jpeg_ratio;
+ static int interleaveDataSize;
+ static int jpegLineLength;
+};
+
+extern unsigned long measure_time_camera(struct timeval *start, struct timeval *stop);
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_SEC_H
diff --git a/exynos4/hal/libcamera/SecCameraHWInterface.cpp b/exynos4/hal/libcamera/SecCameraHWInterface.cpp
new file mode 100644
index 0000000..c50ec8d
--- /dev/null
+++ b/exynos4/hal/libcamera/SecCameraHWInterface.cpp
@@ -0,0 +1,3410 @@
+/*
+**
+** 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.
+*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CameraHardwareSec"
+#include <utils/Log.h>
+
+#include "SecCameraHWInterface.h"
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <camera/Camera.h>
+#include <media/stagefright/MetadataBufferType.h>
+
+#define VIDEO_COMMENT_MARKER_H 0xFFBE
+#define VIDEO_COMMENT_MARKER_L 0xFFBF
+#define VIDEO_COMMENT_MARKER_LENGTH 4
+#define JPEG_EOI_MARKER 0xFFD9
+#define HIBYTE(x) (((x) >> 8) & 0xFF)
+#define LOBYTE(x) ((x) & 0xFF)
+
+#define BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR "0.10,0.20,Infinity"
+#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity"
+#define USE_EGL
+
+// This hack does two things:
+// -- it sets preview to NV21 (YUV420SP)
+// -- it sets gralloc to YV12
+//
+// The reason being: the samsung encoder understands only yuv420sp, and gralloc
+// does yv12 and rgb565. So what we do is we break up the interleaved UV in
+// separate V and U planes, which makes preview look good, and enabled the
+// encoder as well.
+//
+// FIXME: Samsung needs to enable support for proper yv12 coming out of the
+// camera, and to fix their video encoder to work with yv12.
+// FIXME: It also seems like either Samsung's YUV420SP (NV21) or img's YV12 has
+// the color planes switched. We need to figure which side is doing it
+// wrong and have the respective party fix it.
+
+namespace android {
+
+struct addrs {
+ uint32_t type; // make sure that this is 4 byte.
+ unsigned int addr_y;
+ unsigned int addr_cbcr;
+ unsigned int buf_index;
+ unsigned int reserved;
+};
+
+struct addrs_cap {
+ unsigned int addr_y;
+ unsigned int width;
+ unsigned int height;
+};
+
+static const int INITIAL_SKIP_FRAME = 3;
+static const int EFFECT_SKIP_FRAME = 1;
+
+gralloc_module_t const* CameraHardwareSec::mGrallocHal;
+
+CameraHardwareSec::CameraHardwareSec(int cameraId, camera_device_t *dev)
+ :
+ mCaptureInProgress(false),
+ mParameters(),
+ mFrameSizeDelta(0),
+ mCameraSensorName(NULL),
+ mUseInternalISP(false),
+ mSkipFrame(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ mMsgEnabled(CAMERA_MSG_RAW_IMAGE),
+ mRecordRunning(false),
+ mPostViewWidth(0),
+ mPostViewHeight(0),
+ mPostViewSize(0),
+ mCapIndex(0),
+ mRecordHint(false),
+ mTouched(0),
+ mHalDevice(dev)
+{
+ LOGV("%s :", __func__);
+ memset(&mCapBuffer, 0, sizeof(struct SecBuffer));
+ int ret = 0;
+
+ mPreviewWindow = NULL;
+ mSecCamera = SecCamera::createInstance();
+
+ mRawHeap = NULL;
+ mPreviewHeap = NULL;
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++)
+ mRecordHeap[i] = NULL;
+
+ if (!mGrallocHal) {
+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal);
+ if (ret)
+ LOGE("ERR(%s):Fail on loading gralloc HAL", __func__);
+ }
+
+ ret = mSecCamera->CreateCamera(cameraId);
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera init", __func__);
+ mSecCamera->DestroyCamera();
+ }
+
+ initDefaultParameters(cameraId);
+
+ mExitAutoFocusThread = false;
+ mExitPreviewThread = false;
+ /* whether the PreviewThread is active in preview or stopped. we
+ * create the thread but it is initially in stopped state.
+ */
+ mPreviewRunning = false;
+ mPreviewStartDeferred = false;
+ mPreviewThread = new PreviewThread(this);
+ mAutoFocusThread = new AutoFocusThread(this);
+ mPictureThread = new PictureThread(this);
+}
+
+int CameraHardwareSec::getCameraId() const
+{
+ return mSecCamera->getCameraId();
+}
+
+void CameraHardwareSec::initDefaultParameters(int cameraId)
+{
+ if (mSecCamera == NULL) {
+ LOGE("ERR(%s):mSecCamera object is NULL", __func__);
+ return;
+ }
+
+ CameraParameters p;
+ CameraParameters ip;
+
+ mCameraSensorName = mSecCamera->getCameraSensorName();
+ if (mCameraSensorName == NULL) {
+ LOGE("ERR(%s):mCameraSensorName is NULL", __func__);
+ return;
+ }
+ LOGV("CameraSensorName: %s", mCameraSensorName);
+
+ int preview_max_width = 0;
+ int preview_max_height = 0;
+ int snapshot_max_width = 0;
+ int snapshot_max_height = 0;
+
+ mCameraID = cameraId;
+ mUseInternalISP = mSecCamera->getUseInternalISP();
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ if (mUseInternalISP) {
+ //3H2
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "720x480,640x384,640x360,640x480,320x240,528x432,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "3248x2436,3216x2144,3200x1920,3072x1728,2592x1944,1920x1080,1440x1080,1280x720,1232x1008,800x480,720x480,640x480");
+ p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+ "1920x1080,1280x720,640x480,176x144");
+ } else {
+ //M5MO
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "3264x2448,1920x1080,1280x720,800x480,720x480,640x480,320x240,528x432,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "3264x2448,3264x1968,2048x1536,2048x1232,800x480,640x480");
+ }
+ } else {
+ if (mUseInternalISP) {
+ //6A3
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "640x480,640x360,480x480,352x288,320x240,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "1392x1392,1280x960,1280x720,880x720,640x480");
+ p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+ "1280x720,640x480,176x144");
+ }
+ }
+
+ p.getSupportedPreviewSizes(mSupportedPreviewSizes);
+
+ String8 parameterString;
+
+ // If these fail, then we are using an invalid cameraId and we'll leave the
+ // sizes at zero to catch the error.
+ if (mSecCamera->getPreviewMaxSize(&preview_max_width,
+ &preview_max_height) < 0)
+ LOGE("getPreviewMaxSize fail (%d / %d)",
+ preview_max_width, preview_max_height);
+ if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width,
+ &snapshot_max_height) < 0)
+ LOGE("getSnapshotMaxSize fail (%d / %d)",
+ snapshot_max_width, snapshot_max_height);
+
+ parameterString = CameraParameters::PIXEL_FORMAT_YUV420P;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::PIXEL_FORMAT_YUV420SP);
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, parameterString);
+ p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P);
+ mFrameSizeDelta = 16;
+ p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420SP);
+ p.setPreviewSize(preview_max_width, preview_max_height);
+
+ p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+ p.setPictureSize(snapshot_max_width, snapshot_max_height);
+ p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // maximum quality
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ CameraParameters::PIXEL_FORMAT_JPEG);
+
+ p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "1280x720");
+
+#ifdef USE_FACE_DETECTION
+ if (mUseInternalISP) {
+ p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, "5");
+ } else {
+ p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, "0");
+ }
+#endif
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FOCUS_MODE_AUTO;
+ /* TODO : sensor will be support this mode */
+ //parameterString.append(",");
+ //parameterString.append(CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO);
+ if (mUseInternalISP) {
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_INFINITY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_MACRO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE);
+ }
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_AUTO);
+ p.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+#ifdef USE_TOUCH_AF
+ if (mUseInternalISP)
+ p.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "1");
+#endif
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "320x240,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "320");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "240");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "7,15,30");
+ p.setPreviewFrameRate(30);
+ } else {
+ p.set(CameraParameters::KEY_FOCUS_MODE, NULL);
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "160x120,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "160");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "120");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ "7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,50,60");
+ p.setPreviewFrameRate(30);
+ }
+
+ parameterString = CameraParameters::EFFECT_NONE;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_MONO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_NEGATIVE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_SEPIA);
+ p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, parameterString.string());
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FLASH_MODE_ON;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_OFF);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_AUTO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_TORCH);
+ p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+
+ /* we have two ranges, 4-30fps for night mode and
+ * 15-30fps for all others
+ */
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "3.43");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(7500,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "7500,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "0.9");
+ }
+ parameterString = CameraParameters::SCENE_MODE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PORTRAIT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_LANDSCAPE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_BEACH);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SNOW);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_FIREWORKS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SPORTS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PARTY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_CANDLELIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_NIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SUNSET);
+ p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_SCENE_MODE,
+ CameraParameters::SCENE_MODE_AUTO);
+
+ parameterString = CameraParameters::WHITE_BALANCE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_INCANDESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_FLUORESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_DAYLIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT);
+ p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
+ parameterString.string());
+
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "100");
+
+ p.set(CameraParameters::KEY_ROTATION, 0);
+ p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO);
+
+ p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE);
+
+ p.set("contrast", 0);
+ p.set("iso", "auto");
+ p.set("metering", "center");
+ p.set("wdr", 0);
+
+ ip.set("chk_dataline", 0);
+ if (cameraId == SecCamera::CAMERA_ID_FRONT) {
+ ip.set("vtmode", 0);
+ ip.set("blur", 0);
+ }
+
+ p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2");
+ p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4");
+
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0");
+ p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "4");
+ p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-4");
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "1");
+
+ p.set("brightness", 0);
+ p.set("brightness-max", 2);
+ p.set("brightness-min", -2);
+
+ p.set("saturation", 0);
+ p.set("saturation-max", 2);
+ p.set("saturation-min", -2);
+
+ p.set("sharpness", 0);
+ p.set("sharpness-max", 2);
+ p.set("sharpness-min", -2);
+
+ p.set("hue", 0);
+ p.set("hue-max", 2);
+ p.set("hue-min", -2);
+
+ parameterString = CameraParameters::ANTIBANDING_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_50HZ);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_60HZ);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_OFF);
+ p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
+ parameterString.string());
+
+ p.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF);
+
+ if (mUseInternalISP) {
+ p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "true");
+ p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, "false");
+ }
+
+ if (mUseInternalISP) {
+ p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "true");
+ p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, "false");
+ }
+
+ p.set(CameraParameters::KEY_RECORDING_HINT, "false");
+
+#ifdef VIDEO_SNAPSHOT
+ if (mUseInternalISP)
+ p.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, "true");
+#endif
+
+ if (!mUseInternalISP) {
+ p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true");
+ p.set(CameraParameters::KEY_MAX_ZOOM, ZOOM_LEVEL_MAX - 1);
+ p.set(CameraParameters::KEY_ZOOM_RATIOS, "31,4.0");
+ }
+
+ mPreviewRunning = false;
+ mParameters = p;
+ mInternalParameters = ip;
+
+ /* make sure mSecCamera has all the settings we do. applications
+ * aren't required to call setParameters themselves (only if they
+ * want to change something.
+ */
+ setParameters(p);
+}
+
+CameraHardwareSec::~CameraHardwareSec()
+{
+ LOGV("%s", __func__);
+ mSecCamera->DestroyCamera();
+}
+
+status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w)
+{
+ int min_bufs;
+
+ mPreviewWindow = w;
+ LOGV("%s: mPreviewWindow %p", __func__, mPreviewWindow);
+
+ if (!w) {
+ LOGE("preview window is NULL!");
+ return OK;
+ }
+
+ mPreviewLock.lock();
+
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGI("stop preview (window change)");
+ stopPreviewInternal();
+ }
+
+ if (w->get_min_undequeued_buffer_count(w, &min_bufs)) {
+ LOGE("%s: could not retrieve min undequeued buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (min_bufs >= BUFFER_COUNT_FOR_GRALLOC) {
+ LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__,
+ min_bufs, BUFFER_COUNT_FOR_GRALLOC - 1);
+ }
+
+ LOGV("%s: setting buffer count to %d", __func__, BUFFER_COUNT_FOR_GRALLOC);
+ if (w->set_buffer_count(w, BUFFER_COUNT_FOR_GRALLOC)) {
+ LOGE("%s: could not set buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ int preview_width;
+ int preview_height;
+ mParameters.getPreviewSize(&preview_width, &preview_height);
+
+ int hal_pixel_format;
+
+ const char *str_preview_format = mParameters.getPreviewFormat();
+ LOGV("%s: preview format %s", __func__, str_preview_format);
+ mFrameSizeDelta = 16;
+
+ hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // default
+
+ if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGB565)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_RGB_565;
+ mFrameSizeDelta = 0;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGBA8888)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mFrameSizeDelta = 0;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420P))
+ hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // HACK
+
+#ifdef USE_EGL
+#ifdef BOARD_USE_V4L2_ION
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_ION)) {
+#else
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN)) {
+#endif
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+#else
+#ifdef BOARD_USE_V4L2_ION
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HWC_HWOVERLAY | GRALLOC_USAGE_HW_ION)) {
+#else
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HW_FIMC1 | GRALLOC_USAGE_HWC_HWOVERLAY)) {
+#endif
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+#endif
+
+ if (w->set_buffers_geometry(w,
+ preview_width, preview_height,
+ hal_pixel_format)) {
+ LOGE("%s: could not set buffers geometry to %s",
+ __func__, str_preview_format);
+ return INVALID_OPERATION;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++)
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) {
+ LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i);
+ return INVALID_OPERATION;
+ }
+#endif
+
+ if (mPreviewRunning && mPreviewStartDeferred) {
+ LOGV("start/resume preview");
+ status_t ret = startPreviewInternal();
+ if (ret == OK) {
+ mPreviewStartDeferred = false;
+ mPreviewCondition.signal();
+ }
+ }
+ mPreviewLock.unlock();
+
+ return OK;
+}
+
+void CameraHardwareSec::setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mGetMemoryCb = get_memory;
+ mCallbackCookie = user;
+}
+
+void CameraHardwareSec::enableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled |= msgType;
+
+ mPreviewLock.lock();
+ if ((msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_VIDEO_FRAME)) &&
+ mPreviewRunning && mPreviewStartDeferred) {
+ LOGV("%s: starting deferred preview", __func__);
+ if (startPreviewInternal() == OK) {
+ mPreviewStartDeferred = false;
+ mPreviewCondition.signal();
+ }
+ }
+ mPreviewLock.unlock();
+
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+void CameraHardwareSec::disableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled &= ~msgType;
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+bool CameraHardwareSec::msgTypeEnabled(int32_t msgType)
+{
+ return (mMsgEnabled & msgType);
+}
+
+void CameraHardwareSec::setSkipFrame(int frame)
+{
+ Mutex::Autolock lock(mSkipFrameLock);
+ if (frame < mSkipFrame)
+ return;
+
+ mSkipFrame = frame;
+}
+
+int CameraHardwareSec::previewThreadWrapper()
+{
+ LOGI("%s: starting", __func__);
+ while (1) {
+ mPreviewLock.lock();
+ while (!mPreviewRunning) {
+ LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__);
+ mSecCamera->stopPreview();
+ /* signal that we're stopping */
+ mPreviewStoppedCondition.signal();
+ mPreviewCondition.wait(mPreviewLock);
+ LOGI("%s: return from wait", __func__);
+ }
+ mPreviewLock.unlock();
+
+ if (mExitPreviewThread) {
+ LOGI("%s: exiting", __func__);
+ mSecCamera->stopPreview();
+ return 0;
+ }
+
+ previewThread();
+ }
+}
+
+int CameraHardwareSec::previewThread()
+{
+ int index;
+ nsecs_t timestamp;
+ SecBuffer previewAddr, recordAddr;
+ static int numArray = 0;
+ void *virAddr[3];
+ camera_frame_metadata_t fdmeta;
+ camera_face_t caface[5];
+
+#ifdef BOARD_USE_V4L2_ION
+ private_handle_t *hnd = NULL;
+#else
+ struct addrs *addrs;
+#endif
+
+ fdmeta.faces = caface;
+ index = mSecCamera->getPreview(&fdmeta);
+
+ mFaceData = &fdmeta;
+
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);
+#ifdef BOARD_USE_V4L2_ION
+ if (mSecCamera->getPreviewState()) {
+ stopPreview();
+ startPreview();
+ mSecCamera->clearPreviewState();
+ }
+#endif
+ return UNKNOWN_ERROR;
+ }
+
+#ifdef ZERO_SHUTTER_LAG
+ if (mUseInternalISP && !mRecordHint) {
+ mCapIndex = mSecCamera->getSnapshot();
+
+ if (mCapIndex >= 0) {
+ if (mSecCamera->setSnapshotFrame(mCapIndex) < 0) {
+ LOGE("%s: Fail qbuf, index(%d)", __func__, mCapIndex);
+ return INVALID_OPERATION;
+ }
+ }
+ }
+#endif
+
+ mSkipFrameLock.lock();
+ if (mSkipFrame > 0) {
+ mSkipFrame--;
+ mSkipFrameLock.unlock();
+ LOGV("%s: index %d skipping frame", __func__, index);
+ if (mSecCamera->setPreviewFrame(index) < 0) {
+ LOGE("%s: Could not qbuff[%d]!!", __func__, index);
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+ }
+ mSkipFrameLock.unlock();
+
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ int width, height, frame_size, offset;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ offset = frame_size * index;
+
+ if (mPreviewWindow && mGrallocHal && mPreviewRunning) {
+#ifdef BOARD_USE_V4L2_ION
+ hnd = (private_handle_t*)*mBufferHandle[index];
+
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ mPreviewHeap = mGetMemoryCb(hnd->fd, frame_size, 1, 0);
+
+ hnd = NULL;
+
+ mGrallocHal->unlock(mGrallocHal, *mBufferHandle[index]);
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[index])) {
+ LOGE("%s: Could not enqueue gralloc buffer[%d]!!", __func__, index);
+ goto callbacks;
+ } else {
+ mBufferHandle[index] = NULL;
+ mStride[index] = NULL;
+ }
+
+ numArray = index;
+#endif
+
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[numArray], &mStride[numArray])) {
+ LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, numArray);
+ goto callbacks;
+ }
+
+ if (!mGrallocHal->lock(mGrallocHal,
+ *mBufferHandle[numArray],
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR,
+ 0, 0, width, height, virAddr)) {
+#ifdef BOARD_USE_V4L2
+ mSecCamera->getPreviewAddr(index, &previewAddr);
+ char *frame = (char *)previewAddr.virt.extP[0];
+#else
+ char *frame = ((char *)mPreviewHeap->data) + offset;
+#endif
+
+#ifdef BOARD_USE_V4L2_ION
+ mSecCamera->setUserBufferAddr(virAddr, index, PREVIEW_MODE);
+#else
+ int total = frame_size + mFrameSizeDelta;
+ int h = 0;
+ char *src = frame;
+
+ /* TODO : Need to fix size of planes for supported color fmt.
+ Currnetly we support only YV12(3 plane) and NV21(2 plane)*/
+ // Y
+ memcpy(virAddr[0],src, width * height);
+ src += width * height;
+
+ if (mPreviewFmtPlane == PREVIEW_FMT_2_PLANE) {
+ memcpy(virAddr[1], src, width * height / 2);
+ } else if (mPreviewFmtPlane == PREVIEW_FMT_3_PLANE) {
+ // U
+ memcpy(virAddr[1], src, width * height / 4);
+ src += width * height / 4;
+
+ // V
+ memcpy(virAddr[2], src, width * height / 4);
+ }
+
+ mGrallocHal->unlock(mGrallocHal, **mBufferHandle);
+#endif
+ }
+ else
+ LOGE("%s: could not obtain gralloc buffer", __func__);
+
+ if (mSecCamera->setPreviewFrame(index) < 0) {
+ LOGE("%s: Fail qbuf, index(%d)", __func__, index);
+ goto callbacks;
+ }
+
+ index = 0;
+#ifndef BOARD_USE_V4L2_ION
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, *mBufferHandle)) {
+ LOGE("Could not enqueue gralloc buffer!");
+ goto callbacks;
+ }
+#endif
+ }
+
+callbacks:
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME && mPreviewRunning)
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie);
+
+#ifdef USE_FACE_DETECTION
+ if (mUseInternalISP && (mMsgEnabled & CAMERA_MSG_PREVIEW_METADATA) && mPreviewRunning)
+ mDataCb(CAMERA_MSG_PREVIEW_METADATA, mFaceDataHeap, 0, mFaceData, mCallbackCookie);
+#endif
+
+ Mutex::Autolock lock(mRecordLock);
+ if (mRecordRunning == true) {
+ int recordingIndex = 0;
+
+ index = mSecCamera->getRecordFrame();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+#ifdef VIDEO_SNAPSHOT
+ if (mUseInternalISP && mRecordHint) {
+ mCapIndex = mSecCamera->getSnapshot();
+
+ if (mSecCamera->setSnapshotFrame(mCapIndex) < 0) {
+ LOGE("%s: Fail qbuf, index(%d)", __func__, mCapIndex);
+ return INVALID_OPERATION;
+ }
+ }
+#endif
+
+#ifdef BOARD_USE_V4L2_ION
+ numArray = index;
+#else
+ recordingIndex = index;
+ mSecCamera->getRecordAddr(index, &recordAddr);
+
+ LOGV("record PhyY(0x%08x) phyC(0x%08x) ", recordAddr.phys.extP[0], recordAddr.phys.extP[1]);
+
+ if (recordAddr.phys.extP[0] == 0xffffffff || recordAddr.phys.extP[1] == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__,
+ recordAddr.phys.extP[0], recordAddr.phys.extP[1]);
+ return UNKNOWN_ERROR;
+ }
+
+ addrs = (struct addrs *)(*mRecordHeap)->data;
+
+ addrs[index].type = kMetadataBufferTypeCameraSource;
+ addrs[index].addr_y = recordAddr.phys.extP[0];
+ addrs[index].addr_cbcr = recordAddr.phys.extP[1];
+ addrs[index].buf_index = index;
+#endif
+
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)
+ mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
+ mRecordHeap[numArray], recordingIndex, mCallbackCookie);
+ else
+ mSecCamera->releaseRecordFrame(index);
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::startPreview()
+{
+ int ret = 0;
+
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mStateLock);
+ if (mCaptureInProgress) {
+ LOGE("%s : capture in progress, not allowed", __func__);
+ return INVALID_OPERATION;
+ }
+
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ // already running
+ LOGE("%s : preview thread already running", __func__);
+ mPreviewLock.unlock();
+ return INVALID_OPERATION;
+ }
+
+ mPreviewRunning = true;
+ mPreviewStartDeferred = false;
+
+ if (!mPreviewWindow &&
+ !(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) &&
+ !(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
+ LOGI("%s : deferring", __func__);
+ mPreviewStartDeferred = true;
+ mPreviewLock.unlock();
+ return NO_ERROR;
+ }
+
+ ret = startPreviewInternal();
+ if (ret == OK)
+ mPreviewCondition.signal();
+
+ mPreviewLock.unlock();
+ return ret;
+}
+
+status_t CameraHardwareSec::startPreviewInternal()
+{
+ LOGV("%s", __func__);
+ int width, height, frame_size;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+ LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))",
+ mSecCamera->getCameraFd(SecCamera::PREVIEW), frame_size + mFrameSizeDelta, width, height);
+
+#ifdef BOARD_USE_V4L2_ION
+#ifdef ZERO_SHUTTER_LAG
+/*TODO*/
+ int mPostViewWidth, mPostViewHeight, mPostViewSize;
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ for(int i = 0; i < CAP_BUFFERS; i++) {
+ mPostviewHeap[i] = new MemoryHeapBaseIon(mPostViewSize);
+ mSecCamera->setUserBufferAddr(mPostviewHeap[i]->base(), i, CAPTURE_MODE);
+ }
+#endif
+ void *vaddr[3];
+
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ if (mBufferHandle[i] == NULL) {
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) {
+ LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i);
+ return INVALID_OPERATION;
+ }
+ }
+ if (mGrallocHal->lock(mGrallocHal,
+ *mBufferHandle[i],
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR,
+ 0, 0, width, height, vaddr)) {
+ LOGE("ERR(%s): Could not get virtual address!!, index = %d", __func__, i);
+ return UNKNOWN_ERROR;
+ }
+ mSecCamera->setUserBufferAddr(vaddr, i, PREVIEW_MODE);
+ }
+#endif
+
+ int ret = mSecCamera->startPreview();
+ LOGV("%s : mSecCamera->startPreview() returned %d", __func__, ret);
+
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startPreview()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ setSkipFrame(INITIAL_SKIP_FRAME);
+
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ for(int i=0; i<BUFFER_COUNT_FOR_ARRAY; i++){
+ if (mRecordHeap[i] != NULL) {
+ mRecordHeap[i]->release(mRecordHeap[i]);
+ mRecordHeap[i] = 0;
+ }
+ }
+
+#ifndef BOARD_USE_V4L2
+ mPreviewHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(SecCamera::PREVIEW),
+ frame_size + mFrameSizeDelta,
+ MAX_BUFFERS,
+ 0); // no cookie
+#endif
+
+ mFaceDataHeap = mGetMemoryCb(-1, 1, 1, 0);
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ mPostViewWidth,mPostViewHeight,mPostViewSize);
+
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopPreviewInternal()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ if (mPreviewRunning) {
+ mPreviewRunning = false;
+ if (!mPreviewStartDeferred) {
+ mPreviewCondition.signal();
+ /* wait until preview thread is stopped */
+ mPreviewStoppedCondition.wait(mPreviewLock);
+
+#ifdef BOARD_USE_V4L2_ION
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ if (mBufferHandle[i] != NULL) {
+ if (0 != mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[i])) {
+ LOGE("%s: Fail to cancel buffer[%d]", __func__, i);
+ } else {
+ mBufferHandle[i] = NULL;
+ mStride[i] = NULL;
+ }
+ }
+ }
+#endif
+ }
+ else
+ LOGV("%s : preview running but deferred, doing nothing", __func__);
+ } else
+ LOGI("%s : preview not running, doing nothing", __func__);
+}
+
+void CameraHardwareSec::stopPreview()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ mPreviewLock.lock();
+ stopPreviewInternal();
+ mPreviewLock.unlock();
+}
+
+bool CameraHardwareSec::previewEnabled()
+{
+ Mutex::Autolock lock(mPreviewLock);
+ LOGV("%s : %d", __func__, mPreviewRunning);
+ return mPreviewRunning;
+}
+
+status_t CameraHardwareSec::startRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ for(int i = 0; i<BUFFER_COUNT_FOR_ARRAY; i++){
+ if (mRecordHeap[i] != NULL) {
+ mRecordHeap[i]->release(mRecordHeap[i]);
+ mRecordHeap[i] = 0;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+ int width, height;
+
+ mSecCamera->getRecordingSize(&width, &height);
+
+ mRecordHeap[i] = mGetMemoryCb(-1, (ALIGN((ALIGN(width, 16) * ALIGN(height, 16)), 2048) + ALIGN((ALIGN(width, 16) * ALIGN(height >> 1, 8)), 2048)), 1, NULL);
+
+ mSecCamera->setUserBufferAddr((void *)(mRecordHeap[i]->data), i, RECORD_MODE);
+#else
+ mRecordHeap[i] = mGetMemoryCb(-1, sizeof(struct addrs), MAX_BUFFERS, NULL);
+#endif
+ if (!mRecordHeap[i]) {
+ LOGE("ERR(%s): Record heap[%d] creation fail", __func__, i);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ LOGV("mRecordHeaps alloc done");
+
+ if (mRecordRunning == false) {
+ if (mSecCamera->startRecord(mRecordHint) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__);
+ return UNKNOWN_ERROR;
+ }
+ mRecordRunning = true;
+ }
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ if (mRecordRunning == true) {
+ if (mSecCamera->stopRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);
+ return;
+ }
+ mRecordRunning = false;
+ }
+}
+
+bool CameraHardwareSec::recordingEnabled()
+{
+ LOGV("%s :", __func__);
+ LOGV("%s : %d", __func__, mPreviewRunning);
+
+ return mRecordRunning;
+}
+
+void CameraHardwareSec::releaseRecordingFrame(const void *opaque)
+{
+#ifdef BOARD_USE_V4L2_ION
+ int i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ if ((char *)mRecordHeap[i]->data == (char *)opaque)
+ break;
+
+ mSecCamera->releaseRecordFrame(i);
+#else
+ struct addrs *addrs = (struct addrs *)opaque;
+ mSecCamera->releaseRecordFrame(addrs->buf_index);
+#endif
+}
+
+int CameraHardwareSec::autoFocusThread()
+{
+ int count =0;
+ int af_status =0 ;
+
+ LOGV("%s : starting", __func__);
+
+ /* block until we're told to start. we don't want to use
+ * a restartable thread and requestExitAndWait() in cancelAutoFocus()
+ * because it would cause deadlock between our callbacks and the
+ * caller of cancelAutoFocus() which both want to grab the same lock
+ * in CameraServices layer.
+ */
+ mFocusLock.lock();
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request0", __func__);
+ return NO_ERROR;
+ }
+ mFocusCondition.wait(mFocusLock);
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request1", __func__);
+ return NO_ERROR;
+ }
+ mFocusLock.unlock();
+
+ /* TODO : Currently only possible auto focus at BACK caemra
+ We need to modify to check that sensor can support auto focus */
+ if (mCameraID == SecCamera::CAMERA_ID_BACK) {
+ LOGV("%s : calling setAutoFocus", __func__);
+ if (mTouched == 0) {
+ if (mSecCamera->setAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ if (mSecCamera->setTouchAF() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ /* TODO */
+ /* This is temperary implementation.
+ When camera support AF blocking mode, this code will be removed
+ Continous AutoFocus is not need to success */
+ const char *focusModeStr = mParameters.get(CameraParameters::KEY_FOCUS_MODE);
+ int isContinousAF = !strncmp(focusModeStr, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, 7);
+ if (mUseInternalISP && !isContinousAF) {
+ int i, err = -1;
+ for (i = 0; i < 400; i++) {
+ usleep(10000);
+
+ af_status = mSecCamera->getAutoFocusResult();
+
+ if ((af_status & 0x2)) {
+ err = 0;
+ break;
+ }
+ }
+ } else {
+ af_status = mSecCamera->getAutoFocusResult();
+ }
+
+ if (af_status == 0x01) {
+ LOGV("%s : AF Cancelled !!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ } else if (af_status == 0x02) {
+ LOGV("%s : AF Success !!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS) {
+ /* CAMERA_MSG_FOCUS only takes a bool. true for
+ * finished and false for failure. cancel is still
+ * considered a true result.
+ */
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ }
+ } else {
+ LOGV("%s : AF Fail !!", __func__);
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+ }
+
+ LOGV("%s : exiting with no error", __func__);
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::autoFocus()
+{
+ LOGV("%s :", __func__);
+ /* signal autoFocusThread to run once */
+ mFocusCondition.signal();
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::cancelAutoFocus()
+{
+ LOGV("%s :", __func__);
+
+ if (mSecCamera->cancelAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+int CameraHardwareSec::save_jpeg( unsigned char *real_jpeg, int jpeg_size)
+{
+ FILE *yuv_fp = NULL;
+ char filename[100], *buffer = NULL;
+
+ /* file create/open, note to "wb" */
+ yuv_fp = fopen("/data/camera_dump.jpeg", "wb");
+ if (yuv_fp == NULL) {
+ LOGE("Save jpeg file open error");
+ return -1;
+ }
+
+ LOGV("[BestIQ] real_jpeg size ========> %d", jpeg_size);
+ buffer = (char *) malloc(jpeg_size);
+ if (buffer == NULL) {
+ LOGE("Save YUV] buffer alloc failed");
+ if (yuv_fp)
+ fclose(yuv_fp);
+
+ return -1;
+ }
+
+ memcpy(buffer, real_jpeg, jpeg_size);
+
+ fflush(stdout);
+
+ fwrite(buffer, 1, jpeg_size, yuv_fp);
+
+ fflush(yuv_fp);
+
+ if (yuv_fp)
+ fclose(yuv_fp);
+ if (buffer)
+ free(buffer);
+
+ return 0;
+}
+
+void CameraHardwareSec::save_postview(const char *fname, uint8_t *buf, uint32_t size)
+{
+ int nw;
+ int cnt = 0;
+ uint32_t written = 0;
+
+ LOGD("opening file [%s]", fname);
+ int fd = open(fname, O_RDWR | O_CREAT);
+ if (fd < 0) {
+ LOGE("failed to create file [%s]: %s", fname, strerror(errno));
+ return;
+ }
+
+ LOGD("writing %d bytes to file [%s]", size, fname);
+ while (written < size) {
+ nw = ::write(fd, buf + written, size - written);
+ if (nw < 0) {
+ LOGE("failed to write to file %d [%s]: %s",written,fname, strerror(errno));
+ break;
+ }
+ written += nw;
+ cnt++;
+ }
+ LOGD("done writing %d bytes to file [%s] in %d passes",size, fname, cnt);
+ ::close(fd);
+}
+
+bool CameraHardwareSec::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHeight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHeight)
+{
+ int32_t step_x, step_y;
+ int32_t iXsrc, iXdst;
+ int32_t x, y, src_y_start_pos, dst_pos, src_pos;
+
+ if (dstWidth % 2 != 0 || dstHeight % 2 != 0) {
+ LOGE("scale_down_yuv422: invalid width, height for scaling");
+ return false;
+ }
+
+ step_x = srcWidth / dstWidth;
+ step_y = srcHeight / dstHeight;
+
+ dst_pos = 0;
+ for (uint32_t y = 0; y < dstHeight; y++) {
+ src_y_start_pos = (y * step_y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < dstWidth; x += 2) {
+ src_pos = src_y_start_pos + (x * (step_x * 2));
+
+ dstBuf[dst_pos++] = srcBuf[src_pos ];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 1];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 2];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 3];
+ }
+ }
+
+ return true;
+}
+
+bool CameraHardwareSec::YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight)
+{
+ int32_t x, y, src_y_start_pos, dst_cbcr_pos, dst_pos, src_pos;
+ unsigned char *srcBufPointer = (unsigned char *)srcBuf;
+ unsigned char *dstBufPointer = (unsigned char *)dstBuf;
+
+ dst_pos = 0;
+ dst_cbcr_pos = srcWidth*srcHeight;
+ for (uint32_t y = 0; y < srcHeight; y++) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 2) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_pos++] = srcBufPointer[src_pos];
+ }
+ }
+ for (uint32_t y = 0; y < srcHeight; y += 2) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 4) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 3];
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 1];
+ }
+ }
+
+ return true;
+}
+
+int CameraHardwareSec::pictureThread()
+{
+ LOGV("%s :", __func__);
+
+ int jpeg_size = 0;
+ int ret = NO_ERROR;
+ unsigned char *jpeg_data = NULL;
+ int postview_offset = 0;
+ unsigned char *postview_data = NULL;
+
+ unsigned char *addr = NULL;
+ int mPostViewWidth, mPostViewHeight, mPostViewSize;
+ int mThumbWidth, mThumbHeight, mThumbSize;
+ int cap_width, cap_height, cap_frame_size;
+
+ int JpegImageSize = 0;
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ mSecCamera->getThumbnailConfig(&mThumbWidth, &mThumbHeight, &mThumbSize);
+ int postviewHeapSize = mPostViewSize;
+ if (!mRecordRunning)
+ mSecCamera->getSnapshotSize(&cap_width, &cap_height, &cap_frame_size);
+ else
+ mSecCamera->getVideosnapshotSize(&cap_width, &cap_height, &cap_frame_size);
+ int mJpegHeapSize;
+ if (!mUseInternalISP)
+ mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio();
+ else
+ mJpegHeapSize = cap_frame_size;
+
+ LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight);
+
+ camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0);
+#ifdef BOARD_USE_V4L2_ION
+#ifdef ZERO_SHUTTER_LAG
+ mThumbnailHeap = new MemoryHeapBaseIon(mThumbSize);
+#else
+ mPostviewHeap[mCapIndex] = new MemoryHeapBaseIon(mPostViewSize);
+ mThumbnailHeap = new MemoryHeapBaseIon(mThumbSize);
+#endif
+#else
+ mThumbnailHeap = new MemoryHeapBase(mThumbSize);
+#endif
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+ int picture_size, picture_width, picture_height;
+ mSecCamera->getSnapshotSize(&picture_width, &picture_height, &picture_size);
+ int picture_format = mSecCamera->getSnapshotPixelFormat();
+
+ unsigned int thumb_addr, phyAddr;
+
+ // Modified the shutter sound timing for Jpeg capture
+ if (!mUseInternalISP) {
+ mSecCamera->setSnapshotCmd();
+
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+
+ jpeg_data = mSecCamera->getJpeg(&JpegImageSize, &mThumbSize, &thumb_addr, &phyAddr);
+ if (jpeg_data == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera->getJpeg()", __func__);
+ ret = UNKNOWN_ERROR;
+ }
+
+ memcpy((unsigned char *)mThumbnailHeap->base(), (unsigned char *)thumb_addr, mThumbSize);
+ memcpy(JpegHeap->data, jpeg_data, JpegImageSize);
+ } else {
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+
+#ifdef ZERO_SHUTTER_LAG
+ mSecCamera->getCaptureAddr(mCapIndex, &mCapBuffer);
+
+ if (mCapBuffer.virt.extP[0] == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ",
+ __func__, mCapBuffer.virt.extP[0]);
+ return UNKNOWN_ERROR;
+ }
+
+ scaleDownYuv422((char *)mCapBuffer.virt.extP[0], cap_width, cap_height,
+ (char *)mThumbnailHeap->base(), mThumbWidth, mThumbHeight);
+#else
+#ifdef BOARD_USE_V4L2_ION
+ mCapBuffer.virt.extP[0] = (char *)mPostviewHeap[mCapIndex]->base();
+#endif
+#endif
+
+ if (mSecCamera->getSnapshotAndJpeg(&mCapBuffer, mCapIndex,
+ (unsigned char*)JpegHeap->data, &JpegImageSize) < 0) {
+ mStateLock.lock();
+ mCaptureInProgress = false;
+ mStateLock.unlock();
+ JpegHeap->release(JpegHeap);
+ return UNKNOWN_ERROR;
+ }
+ LOGI("snapshotandjpeg done");
+
+#ifdef ZERO_SHUTTER_LAG
+ if (!mRecordRunning)
+ stopPreview();
+ memset(&mCapBuffer, 0, sizeof(struct SecBuffer));
+#else
+ scaleDownYuv422((char *)mCapBuffer.virt.extP[0], cap_width, cap_height,
+ (char *)mThumbnailHeap->base(), mThumbWidth, mThumbHeight);
+#endif
+ }
+ }
+
+#ifndef BOARD_USE_V4L2_ION
+ int rawHeapSize = cap_frame_size;
+ LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize);
+#ifdef BOARD_USE_V4L2_ION
+ mRawHeap = mGetMemoryCb(mPostviewHeap[mCapIndex]->getHeapID(), rawHeapSize, 1, 0);
+#else
+ mRawHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(SecCamera::PICTURE), rawHeapSize, 1, 0);
+#endif
+ if (!mRawHeap)
+ LOGE("ERR(%s): Raw heap creation fail", __func__);
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie);
+#endif
+ mStateLock.lock();
+ mCaptureInProgress = false;
+ mStateLock.unlock();
+
+ if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+ camera_memory_t *ExifHeap =
+ mGetMemoryCb(-1, EXIF_FILE_SIZE + mThumbSize, 1, 0);
+
+ int JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data,
+ (unsigned char *)mThumbnailHeap->base(),
+ mThumbSize);
+ LOGV("JpegExifSize=%d", JpegExifSize);
+
+ if (JpegExifSize < 0) {
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+
+ int mJpegHeapSize_out = JpegImageSize + JpegExifSize;
+ camera_memory_t *JpegHeap_out = mGetMemoryCb(-1, mJpegHeapSize_out, 1, 0);
+
+ unsigned char *ExifStart = (unsigned char *)JpegHeap_out->data + 2;
+ unsigned char *ImageStart = ExifStart + JpegExifSize;
+
+ memcpy(JpegHeap_out->data, JpegHeap->data, 2);
+ memcpy(ExifStart, ExifHeap->data, JpegExifSize);
+ memcpy(ImageStart, JpegHeap->data + 2, JpegImageSize - 2);
+
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, JpegHeap_out, 0, NULL, mCallbackCookie);
+
+ if (ExifHeap) {
+ ExifHeap->release(ExifHeap);
+ ExifHeap = 0;
+ }
+
+ if (JpegHeap_out) {
+ JpegHeap_out->release(JpegHeap_out);
+ JpegHeap_out = 0;
+ }
+ }
+
+ LOGV("%s : pictureThread end", __func__);
+
+out:
+ if (JpegHeap) {
+ JpegHeap->release(JpegHeap);
+ JpegHeap = 0;
+ }
+
+ if (mRawHeap) {
+ mRawHeap->release(mRawHeap);
+ mRawHeap = 0;
+ }
+
+ if (!mUseInternalISP && !mRecordRunning)
+ mSecCamera->endSnapshot();
+
+ return ret;
+}
+
+status_t CameraHardwareSec::takePicture()
+{
+ LOGV("%s :", __func__);
+
+#ifdef ZERO_SHUTTER_LAG
+ if (!mUseInternalISP) {
+ stopPreview();
+ }
+#else
+ stopPreview();
+#endif
+
+ Mutex::Autolock lock(mStateLock);
+ if (mCaptureInProgress) {
+ LOGE("%s : capture already in progress", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
+ LOGE("%s : couldn't run picture thread", __func__);
+ return INVALID_OPERATION;
+ }
+ mCaptureInProgress = true;
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::cancelPicture()
+{
+ LOGV("%s", __func__);
+
+ if (mPictureThread.get()) {
+ LOGV("%s: waiting for picture thread to exit", __func__);
+ mPictureThread->requestExitAndWait();
+ LOGV("%s: picture thread has exited", __func__);
+ }
+
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::CheckVideoStartMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckVideoStartMarker() => pBuf is NULL");
+ return false;
+ }
+
+ if (HIBYTE(VIDEO_COMMENT_MARKER_H) == * pBuf && LOBYTE(VIDEO_COMMENT_MARKER_H) == *(pBuf + 1) &&
+ HIBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 2) && LOBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 3))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::CheckEOIMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckEOIMarker() => pBuf is NULL");
+ return false;
+ }
+
+ // EOI marker [FF D9]
+ if (HIBYTE(JPEG_EOI_MARKER) == *pBuf && LOBYTE(JPEG_EOI_MARKER) == *(pBuf + 1))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::FindEOIMarkerInJPEG(unsigned char *pBuf, int dwBufSize, int *pnJPEGsize)
+{
+ if (NULL == pBuf || 0 >= dwBufSize) {
+ LOGE("FindEOIMarkerInJPEG() => There is no contents.");
+ return false;
+ }
+
+ unsigned char *pBufEnd = pBuf + dwBufSize;
+
+ while (pBuf < pBufEnd) {
+ if (CheckEOIMarker(pBuf++))
+ return true;
+
+ (*pnJPEGsize)++;
+ }
+
+ return false;
+}
+
+bool CameraHardwareSec::SplitFrame(unsigned char *pFrame, int dwSize,
+ int dwJPEGLineLength, int dwVideoLineLength, int dwVideoHeight,
+ void *pJPEG, int *pdwJPEGSize,
+ void *pVideo, int *pdwVideoSize)
+{
+ LOGV("===========SplitFrame Start==============");
+
+ if (NULL == pFrame || 0 >= dwSize) {
+ LOGE("There is no contents (pFrame=%p, dwSize=%d", pFrame, dwSize);
+ return false;
+ }
+
+ if (0 == dwJPEGLineLength || 0 == dwVideoLineLength) {
+ LOGE("There in no input information for decoding interleaved jpeg");
+ return false;
+ }
+
+ unsigned char *pSrc = pFrame;
+ unsigned char *pSrcEnd = pFrame + dwSize;
+
+ unsigned char *pJ = (unsigned char *)pJPEG;
+ int dwJSize = 0;
+ unsigned char *pV = (unsigned char *)pVideo;
+ int dwVSize = 0;
+
+ bool bRet = false;
+ bool isFinishJpeg = false;
+
+ while (pSrc < pSrcEnd) {
+ // Check video start marker
+ if (CheckVideoStartMarker(pSrc)) {
+ int copyLength;
+
+ if (pSrc + dwVideoLineLength <= pSrcEnd)
+ copyLength = dwVideoLineLength;
+ else
+ copyLength = pSrcEnd - pSrc - VIDEO_COMMENT_MARKER_LENGTH;
+
+ // Copy video data
+ if (pV) {
+ memcpy(pV, pSrc + VIDEO_COMMENT_MARKER_LENGTH, copyLength);
+ pV += copyLength;
+ dwVSize += copyLength;
+ }
+
+ pSrc += copyLength + VIDEO_COMMENT_MARKER_LENGTH;
+ } else {
+ // Copy pure JPEG data
+ int size = 0;
+ int dwCopyBufLen = dwJPEGLineLength <= pSrcEnd-pSrc ? dwJPEGLineLength : pSrcEnd - pSrc;
+
+ if (FindEOIMarkerInJPEG((unsigned char *)pSrc, dwCopyBufLen, &size)) {
+ isFinishJpeg = true;
+ size += 2; // to count EOF marker size
+ } else {
+ if ((dwCopyBufLen == 1) && (pJPEG < pJ)) {
+ unsigned char checkBuf[2] = { *(pJ - 1), *pSrc };
+
+ if (CheckEOIMarker(checkBuf))
+ isFinishJpeg = true;
+ }
+ size = dwCopyBufLen;
+ }
+
+ memcpy(pJ, pSrc, size);
+
+ dwJSize += size;
+
+ pJ += dwCopyBufLen;
+ pSrc += dwCopyBufLen;
+ }
+ if (isFinishJpeg)
+ break;
+ }
+
+ if (isFinishJpeg) {
+ bRet = true;
+ if (pdwJPEGSize)
+ *pdwJPEGSize = dwJSize;
+ if (pdwVideoSize)
+ *pdwVideoSize = dwVSize;
+ } else {
+ LOGE("DecodeInterleaveJPEG_WithOutDT() => Can not find EOI");
+ bRet = false;
+ if (pdwJPEGSize)
+ *pdwJPEGSize = 0;
+ if (pdwVideoSize)
+ *pdwVideoSize = 0;
+ }
+ LOGV("===========SplitFrame end==============");
+
+ return bRet;
+}
+
+int CameraHardwareSec::decodeInterleaveData(unsigned char *pInterleaveData,
+ int interleaveDataSize,
+ int yuvWidth,
+ int yuvHeight,
+ int *pJpegSize,
+ void *pJpegData,
+ void *pYuvData)
+{
+ if (pInterleaveData == NULL)
+ return false;
+
+ bool ret = true;
+ unsigned int *interleave_ptr = (unsigned int *)pInterleaveData;
+ unsigned char *jpeg_ptr = (unsigned char *)pJpegData;
+ unsigned char *yuv_ptr = (unsigned char *)pYuvData;
+ unsigned char *p;
+ int jpeg_size = 0;
+ int yuv_size = 0;
+
+ int i = 0;
+
+ LOGV("decodeInterleaveData Start~~~");
+ while (i < interleaveDataSize) {
+ if ((*interleave_ptr == 0xFFFFFFFF) || (*interleave_ptr == 0x02FFFFFF) ||
+ (*interleave_ptr == 0xFF02FFFF)) {
+ // Padding Data
+ interleave_ptr++;
+ i += 4;
+ } else if ((*interleave_ptr & 0xFFFF) == 0x05FF) {
+ // Start-code of YUV Data
+ p = (unsigned char *)interleave_ptr;
+ p += 2;
+ i += 2;
+
+ // Extract YUV Data
+ if (pYuvData != NULL) {
+ memcpy(yuv_ptr, p, yuvWidth * 2);
+ yuv_ptr += yuvWidth * 2;
+ yuv_size += yuvWidth * 2;
+ }
+ p += yuvWidth * 2;
+ i += yuvWidth * 2;
+
+ // Check End-code of YUV Data
+ if ((*p == 0xFF) && (*(p + 1) == 0x06)) {
+ interleave_ptr = (unsigned int *)(p + 2);
+ i += 2;
+ } else {
+ ret = false;
+ break;
+ }
+ } else {
+ // Extract JPEG Data
+ if (pJpegData != NULL) {
+ memcpy(jpeg_ptr, interleave_ptr, 4);
+ jpeg_ptr += 4;
+ jpeg_size += 4;
+ }
+ interleave_ptr++;
+ i += 4;
+ }
+ }
+ if (ret) {
+ if (pJpegData != NULL) {
+ // Remove Padding after EOI
+ for (i = 0; i < 3; i++) {
+ if (*(--jpeg_ptr) != 0xFF) {
+ break;
+ }
+ jpeg_size--;
+ }
+ *pJpegSize = jpeg_size;
+
+ }
+ // Check YUV Data Size
+ if (pYuvData != NULL) {
+ if (yuv_size != (yuvWidth * yuvHeight * 2)) {
+ ret = false;
+ }
+ }
+ }
+ LOGV("decodeInterleaveData End~~~");
+ return ret;
+}
+
+status_t CameraHardwareSec::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ const Vector<String16> args;
+
+ if (mSecCamera != 0) {
+ mSecCamera->dump(fd);
+ mParameters.dump(fd, args);
+ mInternalParameters.dump(fd, args);
+ snprintf(buffer, 255, " preview running(%s)\n", mPreviewRunning?"true": "false");
+ result.append(buffer);
+ } else
+ result.append("No camera client yet.\n");
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::isSupportedPreviewSize(const int width,
+ const int height) const
+{
+ unsigned int i;
+
+ for (i = 0; i < mSupportedPreviewSizes.size(); i++) {
+ if (mSupportedPreviewSizes[i].width == width &&
+ mSupportedPreviewSizes[i].height == height)
+ return true;
+ }
+
+ return false;
+}
+
+bool CameraHardwareSec::getVideosnapshotSize(int *width, int *height)
+{
+ unsigned int i;
+ Vector<Size> pictureSizes, videoSizes;
+ int ratio = FRM_RATIO(*width, *height);
+
+ mParameters.getSupportedPictureSizes(pictureSizes);
+ mParameters.getSupportedVideoSizes(videoSizes);
+
+ for (i = 0; i < pictureSizes.size(); i++) {
+ if (FRM_RATIO(pictureSizes[i].width, pictureSizes[i].height) == ratio) {
+ if (mRecordHint) {
+ if (pictureSizes[i].width <= videoSizes[0].width) {
+ *width = pictureSizes[i].width;
+ *height = pictureSizes[i].height;
+ LOGV("%s(width(%d), height(%d))", __func__, *width, *height);
+ return true;
+ }
+ } else {
+ *width = pictureSizes[i].width;
+ *height = pictureSizes[i].height;
+ LOGV("%s(width(%d), height(%d))", __func__, *width, *height);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+status_t CameraHardwareSec::setParameters(const CameraParameters& params)
+{
+ LOGV("%s :", __func__);
+
+ status_t ret = NO_ERROR;
+
+ const char *new_record_hint_str = params.get(CameraParameters::KEY_RECORDING_HINT);
+ const char *curr_record_hint_str = mParameters.get(CameraParameters::KEY_RECORDING_HINT);
+ LOGV("new_record_hint_str: %s", new_record_hint_str);
+
+ if (new_record_hint_str) {
+ if (strncmp(new_record_hint_str, curr_record_hint_str, 5)) {
+ mRecordHint = !strncmp(new_record_hint_str, "true", 4);
+ if (mSecCamera->setMode(mRecordHint) < 0) {
+ LOGE("ERR(%s):fail on mSecCamera->setMode(%d)", __func__, mRecordHint);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_RECORDING_HINT, new_record_hint_str);
+ }
+
+ if (mUseInternalISP) {
+ if (mSecCamera->initSetParams() < 0) {
+ LOGE("ERR(%s):fail on mSecCamera->initSetParams()", __func__);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ }
+ }
+
+ /* if someone calls us while picture thread is running, it could screw
+ * up the sensor quite a bit so return error. we can't wait because
+ * that would cause deadlock with the callbacks
+ */
+ mStateLock.lock();
+ if (mCaptureInProgress) {
+ mStateLock.unlock();
+ LOGE("%s : capture in progress, not allowed", __func__);
+ return UNKNOWN_ERROR;
+ }
+ mStateLock.unlock();
+
+ // preview size
+ int new_preview_width = 0;
+ int new_preview_height = 0;
+ int new_preview_format = 0;
+
+ params.getPreviewSize(&new_preview_width, &new_preview_height);
+
+ if (mUseInternalISP) {
+ int videosnapshot_width = new_preview_width;
+ int videosnapshot_height = new_preview_height;
+
+ if (!getVideosnapshotSize(&videosnapshot_width, &videosnapshot_height)) {
+ LOGE("ERR(%s):fail on getVideosnapshotSize(width(%d), height(%d))",
+ __func__, videosnapshot_width, videosnapshot_height);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (mSecCamera->setVideosnapshotSize(videosnapshot_width, videosnapshot_height) < 0) {
+ LOGE("ERR(%s):fail on mSecCamera->setVideosnapshotSize(width(%d), height(%d))",
+ __func__, videosnapshot_width, videosnapshot_height);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ const char *new_str_preview_format = params.getPreviewFormat();
+ LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s",
+ __func__, new_preview_width, new_preview_height, new_str_preview_format);
+
+ if (0 < new_preview_width && 0 < new_preview_height &&
+ new_str_preview_format != NULL &&
+ isSupportedPreviewSize(new_preview_width, new_preview_height)) {
+
+ mFrameSizeDelta = 16;
+ if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGB565)) {
+ new_preview_format = V4L2_PIX_FMT_RGB565;
+ mFrameSizeDelta = 0;
+ }
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGBA8888)) {
+ new_preview_format = V4L2_PIX_FMT_RGB32;
+ mFrameSizeDelta = 0;
+ }
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ new_preview_format = V4L2_PIX_FMT_NV21;
+ mPreviewFmtPlane = PREVIEW_FMT_2_PLANE;
+ }
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420P)) {
+#ifdef BOARD_USE_V4L2_ION
+ new_preview_format = V4L2_PIX_FMT_YVU420M;
+#else
+ new_preview_format = V4L2_PIX_FMT_YVU420;
+#endif
+ mPreviewFmtPlane = PREVIEW_FMT_3_PLANE;
+ }
+ else if (!strcmp(new_str_preview_format, "yuv420sp_custom"))
+ new_preview_format = V4L2_PIX_FMT_NV12T;
+ else if (!strcmp(new_str_preview_format, "yuv422i"))
+ new_preview_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_preview_format, "yuv422p"))
+ new_preview_format = V4L2_PIX_FMT_YUV422P;
+ else
+ new_preview_format = V4L2_PIX_FMT_NV21; //for 3rd party
+
+ int current_preview_width, current_preview_height, current_frame_size;
+ mSecCamera->getPreviewSize(&current_preview_width,
+ &current_preview_height,
+ &current_frame_size);
+ int current_pixel_format = mSecCamera->getPreviewPixelFormat();
+
+ if (current_preview_width != new_preview_width ||
+ current_preview_height != new_preview_height ||
+ current_pixel_format != new_preview_format) {
+ if (mSecCamera->setPreviewSize(new_preview_width, new_preview_height,
+ new_preview_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setPreviewSize(width(%d), height(%d), format(%d))",
+ __func__, new_preview_width, new_preview_height, new_preview_format);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (mPreviewWindow) {
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGE("ERR(%s): preview is running, cannot change size and format!", __func__);
+ ret = INVALID_OPERATION;
+ }
+ LOGV("%s: mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ LOGV("%s: mPreviewWindow->set_buffers_geometry (%p)", __func__,
+ mPreviewWindow->set_buffers_geometry);
+ mPreviewWindow->set_buffers_geometry(mPreviewWindow,
+ new_preview_width, new_preview_height,
+ V4L2_PIX_2_HAL_PIXEL_FORMAT(new_preview_format));
+ LOGV("%s: DONE mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ }
+ mParameters.setPreviewSize(new_preview_width, new_preview_height);
+ mParameters.setPreviewFormat(new_str_preview_format);
+ }
+ }
+ } else {
+ LOGE("%s: Invalid preview size(%dx%d)",
+ __func__, new_preview_width, new_preview_height);
+
+ ret = INVALID_OPERATION;
+ }
+
+ // picture size
+ int new_picture_width = 0;
+ int new_picture_height = 0;
+
+ params.getPictureSize(&new_picture_width, &new_picture_height);
+ LOGV("%s : new_picture_width x new_picture_height = %dx%d", __func__, new_picture_width, new_picture_height);
+
+ int current_picture_width, current_picture_height, current_picture_size;
+ mSecCamera->getSnapshotSize(&current_picture_width, &current_picture_height, &current_picture_size);
+
+ if (new_picture_width != current_picture_width ||
+ new_picture_height != current_picture_height) {
+ if (mSecCamera->setSnapshotSize(new_picture_width, new_picture_height) < 0) {
+ LOGE("ERR(%s):fail on mSecCamera->setSnapshotSize(width(%d), height(%d))",
+ __func__, new_picture_width, new_picture_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+#ifdef ZERO_SHUTTER_LAG
+ mSecCamera->stopSnapshot();
+ if (mUseInternalISP && !mRecordHint && mPreviewRunning){
+ mSecCamera->startSnapshot(NULL);
+ }
+#endif
+ mParameters.setPictureSize(new_picture_width, new_picture_height);
+ }
+ }
+
+ // picture format
+ const char *new_str_picture_format = params.getPictureFormat();
+ LOGV("%s : new_str_picture_format %s", __func__, new_str_picture_format);
+ if (new_str_picture_format != NULL) {
+ int new_picture_format = 0;
+
+ if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGB565))
+ new_picture_format = V4L2_PIX_FMT_RGB565;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGBA8888))
+ new_picture_format = V4L2_PIX_FMT_RGB32;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_YUV420SP))
+ new_picture_format = V4L2_PIX_FMT_NV21;
+ else if (!strcmp(new_str_picture_format, "yuv420sp_custom"))
+ new_picture_format = V4L2_PIX_FMT_NV12T;
+ else if (!strcmp(new_str_picture_format, "yuv420p"))
+ new_picture_format = V4L2_PIX_FMT_YUV420;
+ else if (!strcmp(new_str_picture_format, "yuv422i"))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "uyv422i_custom")) //Zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, "uyv422i")) //Non-zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_JPEG))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "yuv422p"))
+ new_picture_format = V4L2_PIX_FMT_YUV422P;
+ else
+ new_picture_format = V4L2_PIX_FMT_NV21; //for 3rd party
+
+ if (mSecCamera->setSnapshotPixelFormat(new_picture_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSnapshotPixelFormat(format(%d))", __func__, new_picture_format);
+ ret = UNKNOWN_ERROR;
+ } else
+ mParameters.setPictureFormat(new_str_picture_format);
+ }
+
+ // JPEG image quality
+ int new_jpeg_quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ LOGV("%s : new_jpeg_quality %d", __func__, new_jpeg_quality);
+ /* we ignore bad values */
+ if (new_jpeg_quality >=1 && new_jpeg_quality <= 100) {
+ if (mSecCamera->setJpegQuality(new_jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegQuality(quality(%d))", __func__, new_jpeg_quality);
+ ret = UNKNOWN_ERROR;
+ } else
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, new_jpeg_quality);
+ }
+
+ // JPEG thumbnail size
+ int new_jpeg_thumbnail_width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ int new_jpeg_thumbnail_height= params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if (0 <= new_jpeg_thumbnail_width && 0 <= new_jpeg_thumbnail_height) {
+ if (mSecCamera->setJpegThumbnailSize(new_jpeg_thumbnail_width, new_jpeg_thumbnail_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailSize(width(%d), height(%d))", __func__, new_jpeg_thumbnail_width, new_jpeg_thumbnail_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, new_jpeg_thumbnail_width);
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, new_jpeg_thumbnail_height);
+ }
+ }
+
+ // JPEG thumbnail quality
+ int new_jpeg_thumbnail_quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ LOGV("%s : new_jpeg_thumbnail_quality %d", __func__, new_jpeg_thumbnail_quality);
+ /* we ignore bad values */
+ if (new_jpeg_thumbnail_quality >=1 && new_jpeg_thumbnail_quality <= 100) {
+ if (mSecCamera->setJpegThumbnailQuality(new_jpeg_thumbnail_quality) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailQuality(quality(%d))",
+ __func__, new_jpeg_thumbnail_quality);
+ ret = UNKNOWN_ERROR;
+ } else
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, new_jpeg_thumbnail_quality);
+ }
+
+ // frame rate
+ int new_frame_rate = params.getPreviewFrameRate();
+ /* ignore any fps request, we're determine fps automatically based
+ * on scene mode. don't return an error because it causes CTS failure.
+ */
+ if (mRecordHint) {
+ if (new_frame_rate) {
+ if (mUseInternalISP && (mSecCamera->setFrameRate(new_frame_rate) < 0)){
+ LOGE("ERR(%s):Fail on mSecCamera->setFrameRate(%d)", __func__, new_frame_rate);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPreviewFrameRate(new_frame_rate);
+ }
+ }
+ }
+
+ // rotation
+ int new_rotation = params.getInt(CameraParameters::KEY_ROTATION);
+ LOGV("%s : new_rotation %d", __func__, new_rotation);
+ if (0 <= new_rotation) {
+ LOGV("%s : set orientation:%d", __func__, new_rotation);
+ if (mSecCamera->setExifOrientationInfo(new_rotation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExifOrientationInfo(%d)", __func__, new_rotation);
+ ret = UNKNOWN_ERROR;
+ } else
+ mParameters.set(CameraParameters::KEY_ROTATION, new_rotation);
+ }
+
+ // zoom
+ int new_zoom = params.getInt(CameraParameters::KEY_ZOOM);
+ int current_zoom = mParameters.getInt(CameraParameters::KEY_ZOOM);
+ LOGV("%s : new_zoom %d", __func__, new_zoom);
+ if (0 <= new_zoom) {
+ if (new_zoom != current_zoom) {
+ if (mSecCamera->setZoom(new_zoom) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setZoom(zoom(%d))", __func__, new_zoom);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_ZOOM, new_zoom);
+ }
+ }
+ }
+
+ // brightness
+ int new_brightness = params.getInt("brightness");
+ int max_brightness = params.getInt("brightness-max");
+ int min_brightness = params.getInt("brightness-min");
+ LOGV("%s : new_brightness %d", __func__, new_brightness);
+ if ((min_brightness <= new_brightness) &&
+ (max_brightness >= new_brightness)) {
+ if (mSecCamera->setBrightness(new_brightness) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_brightness);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("brightness", new_brightness);
+ }
+ }
+
+ // saturation
+ int new_saturation = params.getInt("saturation");
+ int max_saturation = params.getInt("saturation-max");
+ int min_saturation = params.getInt("saturation-min");
+ LOGV("%s : new_saturation %d", __func__, new_saturation);
+ if ((min_saturation <= new_saturation) &&
+ (max_saturation >= new_saturation)) {
+ if (mSecCamera->setSaturation(new_saturation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSaturation(saturation(%d))", __func__, new_saturation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("saturation", new_saturation);
+ }
+ }
+
+ // sharpness
+ int new_sharpness = params.getInt("sharpness");
+ int max_sharpness = params.getInt("sharpness-max");
+ int min_sharpness = params.getInt("sharpness-min");
+ LOGV("%s : new_sharpness %d", __func__, new_sharpness);
+ if ((min_sharpness <= new_sharpness) &&
+ (max_sharpness >= new_sharpness)) {
+ if (mSecCamera->setSharpness(new_sharpness) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSharpness(sharpness(%d))", __func__, new_sharpness);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("sharpness", new_sharpness);
+ }
+ }
+
+ // hue
+ int new_hue = params.getInt("hue");
+ int max_hue = params.getInt("hue-max");
+ int min_hue = params.getInt("hue-min");
+ LOGV("%s : new_hue %d", __func__, new_hue);
+ if ((min_hue <= new_hue) &&
+ (max_hue >= new_hue)) {
+ if (mSecCamera->setHue(new_hue) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setHue(hue(%d))", __func__, new_hue);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("hue", new_hue);
+ }
+ }
+
+ // exposure
+ int new_exposure_compensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ int max_exposure_compensation = params.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION);
+ int min_exposure_compensation = params.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION);
+ LOGV("%s : new_exposure_compensation %d", __func__, new_exposure_compensation);
+ if ((min_exposure_compensation <= new_exposure_compensation) &&
+ (max_exposure_compensation >= new_exposure_compensation)) {
+ if (mSecCamera->setExposure(new_exposure_compensation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExposure(exposure(%d))", __func__, new_exposure_compensation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation);
+ }
+ }
+
+ const char *new_AE_lock = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
+ const char *old_AE_lock = mParameters.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
+ if ((new_AE_lock != NULL) && mUseInternalISP && mPreviewRunning) {
+ if (strncmp(new_AE_lock, old_AE_lock, 4)) {
+ int ae_value = !strncmp(new_AE_lock, "true", 4);
+ if (mSecCamera->setAutoExposureLock(ae_value) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExposureLock", __func__);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, new_AE_lock);
+ }
+ }
+ }
+
+ // ISO
+ const char *new_iso_str = params.get("iso");
+ LOGV("%s : new_iso_str %s", __func__, new_iso_str);
+ if (new_iso_str != NULL) {
+ int new_iso = -1;
+
+ if (!strcmp(new_iso_str, "auto")) {
+ new_iso = ISO_AUTO;
+ } else if (!strcmp(new_iso_str, "50")) {
+ new_iso = ISO_50;
+ } else if (!strcmp(new_iso_str, "100")) {
+ new_iso = ISO_100;
+ } else if (!strcmp(new_iso_str, "200")) {
+ new_iso = ISO_200;
+ } else if (!strcmp(new_iso_str, "400")) {
+ new_iso = ISO_400;
+ } else if (!strcmp(new_iso_str, "800")) {
+ new_iso = ISO_800;
+ } else if (!strcmp(new_iso_str, "1600")) {
+ new_iso = ISO_1600;
+ } else {
+ LOGE("ERR(%s):Invalid iso value(%s)", __func__, new_iso_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_iso) {
+ if (mSecCamera->setISO(new_iso) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setISO(iso(%d))", __func__, new_iso);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("iso", new_iso_str);
+ }
+ }
+ }
+
+ // Metering
+ const char *new_metering_str = params.get("metering");
+ LOGV("%s : new_metering_str %s", __func__, new_metering_str);
+ if (new_metering_str != NULL) {
+ int new_metering = -1;
+
+ if (!strcmp(new_metering_str, "center")) {
+ new_metering = METERING_CENTER;
+ } else if (!strcmp(new_metering_str, "spot")) {
+ new_metering = METERING_SPOT;
+ } else if (!strcmp(new_metering_str, "matrix")) {
+ new_metering = METERING_MATRIX;
+ } else {
+ LOGE("ERR(%s):Invalid metering value(%s)", __func__, new_metering_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_metering) {
+ if (mSecCamera->setMetering(new_metering) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setMetering(metering(%d))", __func__, new_metering);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("metering", new_metering_str);
+ }
+ }
+ }
+
+ // AFC
+ const char *new_antibanding_str = params.get(CameraParameters::KEY_ANTIBANDING);
+ LOGV("%s : new_antibanding_str %s", __func__, new_antibanding_str);
+ if (new_antibanding_str != NULL) {
+ int new_antibanding = -1;
+
+ if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_AUTO)) {
+ if (mUseInternalISP)
+ new_antibanding = IS_AFC_AUTO;
+ else
+ new_antibanding = ANTI_BANDING_AUTO;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_50HZ)) {
+ if (mUseInternalISP)
+ new_antibanding = IS_AFC_MANUAL_50HZ;
+ else
+ new_antibanding = ANTI_BANDING_50HZ;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_60HZ)) {
+ if (mUseInternalISP)
+ new_antibanding = IS_AFC_MANUAL_60HZ;
+ else
+ new_antibanding = ANTI_BANDING_60HZ;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_OFF)) {
+ if (mUseInternalISP)
+ new_antibanding = IS_AFC_DISABLE;
+ else
+ new_antibanding = ANTI_BANDING_OFF;
+ } else {
+ LOGE("ERR(%s):Invalid antibanding value(%s)", __func__, new_antibanding_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_antibanding) {
+ if (mSecCamera->setAntiBanding(new_antibanding) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAntiBanding(antibanding(%d))", __func__, new_antibanding);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_ANTIBANDING, new_antibanding_str);
+ }
+ }
+ }
+
+ // scene mode
+ const char *new_scene_mode_str = params.get(CameraParameters::KEY_SCENE_MODE);
+ const char *current_scene_mode_str = mParameters.get(CameraParameters::KEY_SCENE_MODE);
+
+ // fps range
+ int new_min_fps = 0;
+ int new_max_fps = 0;
+ int current_min_fps, current_max_fps;
+ params.getPreviewFpsRange(&new_min_fps, &new_max_fps);
+ mParameters.getPreviewFpsRange(&current_min_fps, &current_max_fps);
+ /* our fps range is determined by the sensor, reject any request
+ * that isn't exactly what we're already at.
+ * but the check is performed when requesting only changing fps range
+ */
+ if (new_scene_mode_str && current_scene_mode_str) {
+ if (!strcmp(new_scene_mode_str, current_scene_mode_str)) {
+ if ((new_min_fps != current_min_fps) || (new_max_fps != current_max_fps)) {
+ LOGW("%s : requested new_min_fps = %d, new_max_fps = %d not allowed",
+ __func__, new_min_fps, new_max_fps);
+ /* TODO : We need policy for fps. */
+ LOGW("%s : current_min_fps = %d, current_max_fps = %d",
+ __func__, current_min_fps, current_max_fps);
+ //ret = UNKNOWN_ERROR;
+ }
+ }
+ } else {
+ /* Check basic validation if scene mode is different */
+ if ((new_min_fps > new_max_fps) ||
+ (new_min_fps < 0) || (new_max_fps < 0))
+ ret = UNKNOWN_ERROR;
+ }
+
+ const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE);
+ const char *new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_MODE);
+ const char *new_white_str = params.get(CameraParameters::KEY_WHITE_BALANCE);
+
+ // fps range is (15000,30000) by default.
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000");
+
+ if ((new_scene_mode_str != NULL) && (current_scene_mode_str != NULL) && strncmp(new_scene_mode_str, current_scene_mode_str, 5)) {
+ int new_scene_mode = -1;
+ if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) {
+ new_scene_mode = SCENE_MODE_NONE;
+ } else {
+ // defaults for non-auto scene modes
+ new_focus_mode_str = CameraParameters::FOCUS_MODE_AUTO;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ new_white_str = CameraParameters::WHITE_BALANCE_AUTO;
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str);
+
+ if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_PORTRAIT)) {
+ new_scene_mode = SCENE_MODE_PORTRAIT;
+ if (mCameraID == SecCamera::CAMERA_ID_BACK)
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_LANDSCAPE)) {
+ new_scene_mode = SCENE_MODE_LANDSCAPE;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SPORTS)) {
+ new_scene_mode = SCENE_MODE_SPORTS;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_PARTY)) {
+ new_scene_mode = SCENE_MODE_PARTY_INDOOR;
+ if (mCameraID == SecCamera::CAMERA_ID_BACK)
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ } else if ((!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_BEACH)) ||
+ (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SNOW))) {
+ new_scene_mode = SCENE_MODE_BEACH_SNOW;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SUNSET)) {
+ new_scene_mode = SCENE_MODE_SUNSET;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_NIGHT)) {
+ new_scene_mode = SCENE_MODE_NIGHTSHOT;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(4000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "4000,30000");
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_FIREWORKS)) {
+ new_scene_mode = SCENE_MODE_FIREWORKS;
+ } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_CANDLELIGHT)) {
+ new_scene_mode = SCENE_MODE_CANDLE_LIGHT;
+ } else {
+ LOGE("%s::unmatched scene_mode(%s)",
+ __func__, new_scene_mode_str); //action, night-portrait, theatre, steadyphoto
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ if (0 <= new_scene_mode) {
+ if (mSecCamera->setSceneMode(new_scene_mode) < 0) {
+ LOGE("%s::mSecCamera->setSceneMode(%d) fail", __func__, new_scene_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_SCENE_MODE, new_scene_mode_str);
+ }
+ }
+ }
+
+ // focus mode
+ /* TODO : currently only posible focus modes at BACK camera */
+ if ((new_focus_mode_str != NULL) && (mCameraID == SecCamera::CAMERA_ID_BACK)) {
+ int new_focus_mode = -1;
+
+ if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_AUTO)) {
+ new_focus_mode = FOCUS_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+ } else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_MACRO)) {
+ new_focus_mode = FOCUS_MODE_MACRO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR);
+ } else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_INFINITY)) {
+ new_focus_mode = FOCUS_MODE_INFINITY;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR);
+ } else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) ||
+ !strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE)) {
+ new_focus_mode = FOCUS_MODE_CONTINOUS;
+ } else {
+ /* TODO */
+ /* This is temperary implementation.
+ When camera support all AF mode, this code will be changing */
+ LOGE("%s::unmatched focus_mode(%s)", __func__, new_focus_mode_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_focus_mode) {
+ if (mSecCamera->setFocusMode(new_focus_mode) < 0) {
+ LOGE("%s::mSecCamera->setFocusMode(%d) fail", __func__, new_focus_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE, new_focus_mode_str);
+ }
+ }
+ }
+
+ // flash..
+ if (new_flash_mode_str != NULL) {
+ int new_flash_mode = -1;
+
+ if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_OFF))
+ new_flash_mode = FLASH_MODE_OFF;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_AUTO))
+ new_flash_mode = FLASH_MODE_AUTO;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_ON))
+ new_flash_mode = FLASH_MODE_ON;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_TORCH))
+ new_flash_mode = FLASH_MODE_TORCH;
+ else {
+ LOGE("%s::unmatched flash_mode(%s)", __func__, new_flash_mode_str); //red-eye
+ ret = UNKNOWN_ERROR;
+ }
+ if (0 <= new_flash_mode) {
+ if (mSecCamera->setFlashMode(new_flash_mode) < 0) {
+ LOGE("%s::mSecCamera->setFlashMode(%d) fail", __func__, new_flash_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FLASH_MODE, new_flash_mode_str);
+ }
+ }
+ }
+
+ // whitebalance
+ LOGV("%s : new_white_str %s", __func__, new_white_str);
+ if ((new_scene_mode_str != NULL) && !strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) {
+ if (new_white_str != NULL) {
+ int new_white = -1;
+
+ if (!strcmp(new_white_str, CameraParameters::WHITE_BALANCE_AUTO)) {
+ new_white = WHITE_BALANCE_AUTO;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_DAYLIGHT)) {
+ new_white = WHITE_BALANCE_SUNNY;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT)) {
+ new_white = WHITE_BALANCE_CLOUDY;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_FLUORESCENT)) {
+ new_white = WHITE_BALANCE_FLUORESCENT;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_INCANDESCENT)) {
+ new_white = WHITE_BALANCE_TUNGSTEN;
+ } else {
+ LOGE("ERR(%s):Invalid white balance(%s)", __func__, new_white_str); //twilight, shade, warm_flourescent
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_white) {
+ if (mSecCamera->setWhiteBalance(new_white) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWhiteBalance(white(%d))", __func__, new_white);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str);
+ }
+ }
+ }
+ }
+
+ const char *new_AWB_lock = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
+ const char *old_AWB_lock = mParameters.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
+ if (new_AWB_lock != NULL && mUseInternalISP && mPreviewRunning) {
+ if (strncmp(new_AWB_lock, old_AWB_lock, 4)) {
+ int awb_value = !strncmp(new_AWB_lock, "true", 4);
+ if (mSecCamera->setAutoWhiteBalanceLock(awb_value) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setoAutoWhiteBalanceLock()", __func__);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, new_AWB_lock);
+ }
+ }
+ }
+
+ const char *new_touch_rect_str = params.get(CameraParameters::KEY_FOCUS_AREAS);
+ LOGV("Touched rect is '%s'", new_touch_rect_str);
+
+ if (new_touch_rect_str != NULL) {
+ int left = 0, top = 0, right = 0, bottom = 0, touched = 0;
+ int objx, objy;
+
+ char *end;
+ char delim = ',';
+ left = (int)strtol(new_touch_rect_str+1, &end, 10);
+ if (*end != delim) {
+ LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str);
+ return -1;
+ }
+ top = (int)strtol(end+1, &end, 10);
+ if (*end != delim) {
+ LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str);
+ return -1;
+ }
+ right = (int)strtol(end+1, &end, 10);
+ if (*end != delim) {
+ LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str);
+ return -1;
+ }
+ bottom = (int)strtol(end+1, &end, 10);
+ if (*end != delim) {
+ LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str);
+ return -1;
+ }
+ touched = (int)strtol(end+1, &end, 10);
+ if (*end != ')') {
+ LOGE("Cannot find ')' in str=%s", new_touch_rect_str);
+ return -1;
+ }
+
+ /* TODO : Converting axis and Calcurating center of rect. Because driver need (x, y) point. */
+ objx = (int)((1023 * (left + 1000)) / 2000) + 97;
+ objy = (int)((1023 * (top + 1000)) / 2000) + 128;
+
+ mTouched = touched;
+ mSecCamera->setObjectPosition(objx, objy);
+ }
+
+ // image effect
+ const char *new_image_effect_str = params.get(CameraParameters::KEY_EFFECT);
+ if (new_image_effect_str != NULL) {
+
+ int new_image_effect = -1;
+
+ if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NONE)) {
+ new_image_effect = IMAGE_EFFECT_NONE;
+ } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO)) {
+ new_image_effect = IMAGE_EFFECT_BNW;
+ } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA)) {
+ new_image_effect = IMAGE_EFFECT_SEPIA;
+ } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_AQUA))
+ new_image_effect = IMAGE_EFFECT_AQUA;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NEGATIVE)) {
+ new_image_effect = IMAGE_EFFECT_NEGATIVE;
+ } else {
+ //posterize, whiteboard, blackboard, solarize
+ LOGE("ERR(%s):Invalid effect(%s)", __func__, new_image_effect_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (new_image_effect >= 0) {
+ if (mSecCamera->setImageEffect(new_image_effect) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setImageEffect(effect(%d))", __func__, new_image_effect);
+ ret = UNKNOWN_ERROR;
+ } else {
+ const char *old_image_effect_str = mParameters.get(CameraParameters::KEY_EFFECT);
+
+ if (old_image_effect_str) {
+ if (strcmp(old_image_effect_str, new_image_effect_str)) {
+ setSkipFrame(EFFECT_SKIP_FRAME);
+ }
+ }
+
+ mParameters.set(CameraParameters::KEY_EFFECT, new_image_effect_str);
+ }
+ }
+ }
+
+ //contrast
+ const char *new_contrast_str = params.get("contrast");
+ LOGV("%s : new_contrast_str %s", __func__, new_contrast_str);
+ if (new_contrast_str != NULL) {
+ int new_contrast = -1;
+
+ if (!strcmp(new_contrast_str, "auto")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_AUTO;
+ else
+ LOGW("WARN(%s):Invalid contrast value (%s)", __func__, new_contrast_str);
+ } else if (!strcmp(new_contrast_str, "-2")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_MINUS_2;
+ else
+ new_contrast = CONTRAST_MINUS_2;
+ } else if (!strcmp(new_contrast_str, "-1")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_MINUS_1;
+ else
+ new_contrast = CONTRAST_MINUS_1;
+ } else if (!strcmp(new_contrast_str, "0")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_DEFAULT;
+ else
+ new_contrast = CONTRAST_DEFAULT;
+ } else if (!strcmp(new_contrast_str, "1")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_PLUS_1;
+ else
+ new_contrast = CONTRAST_PLUS_1;
+ } else if (!strcmp(new_contrast_str, "2")) {
+ if (mUseInternalISP)
+ new_contrast = IS_CONTRAST_PLUS_2;
+ else
+ new_contrast = CONTRAST_PLUS_2;
+ } else {
+ LOGE("ERR(%s):Invalid contrast value(%s)", __func__, new_contrast_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_contrast) {
+ if (mSecCamera->setContrast(new_contrast) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setContrast(contrast(%d))", __func__, new_contrast);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("contrast", new_contrast_str);
+ }
+ }
+ }
+
+ //WDR
+ int new_wdr = params.getInt("wdr");
+ LOGV("%s : new_wdr %d", __func__, new_wdr);
+
+ if (0 <= new_wdr) {
+ if (mSecCamera->setWDR(new_wdr) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_wdr);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //anti shake
+ int new_anti_shake = mInternalParameters.getInt("anti-shake");
+
+ if (0 <= new_anti_shake) {
+ if (mSecCamera->setAntiShake(new_anti_shake) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_anti_shake);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // gps latitude
+ const char *new_gps_latitude_str = params.get(CameraParameters::KEY_GPS_LATITUDE);
+ if (mSecCamera->setGPSLatitude(new_gps_latitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSLatitude(%s) fail", __func__, new_gps_latitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_latitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE, new_gps_latitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_LATITUDE);
+ }
+ }
+
+ // gps longitude
+ const char *new_gps_longitude_str = params.get(CameraParameters::KEY_GPS_LONGITUDE);
+
+ if (mSecCamera->setGPSLongitude(new_gps_longitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSLongitude(%s) fail", __func__, new_gps_longitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_longitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, new_gps_longitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE);
+ }
+ }
+
+ // gps altitude
+ const char *new_gps_altitude_str = params.get(CameraParameters::KEY_GPS_ALTITUDE);
+
+ if (mSecCamera->setGPSAltitude(new_gps_altitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSAltitude(%s) fail", __func__, new_gps_altitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_altitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, new_gps_altitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE);
+ }
+ }
+
+ // gps timestamp
+ const char *new_gps_timestamp_str = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
+
+ if (mSecCamera->setGPSTimeStamp(new_gps_timestamp_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSTimeStamp(%s) fail", __func__, new_gps_timestamp_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_timestamp_str) {
+ mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, new_gps_timestamp_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP);
+ }
+ }
+
+ // gps processing method
+ const char *new_gps_processing_method_str = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+
+ if (mSecCamera->setGPSProcessingMethod(new_gps_processing_method_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSProcessingMethod(%s) fail", __func__, new_gps_processing_method_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_processing_method_str) {
+ mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, new_gps_processing_method_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ }
+ }
+
+ // Recording size
+ /* TODO */
+ /* GED application don't set different recording size before recording button is pushed */
+ int new_recording_width = 0;
+ int new_recording_height = 0;
+ params.getVideoSize(&new_recording_width, &new_recording_height);
+ LOGV("new_recording_width (%d) new_recording_height (%d)",
+ new_recording_width, new_recording_height);
+
+ int current_recording_width, current_recording_height;
+ mParameters.getVideoSize(&current_recording_width, &current_recording_height);
+ LOGV("current_recording_width (%d) current_recording_height (%d)",
+ current_recording_width, current_recording_height);
+
+ if (current_recording_width != new_recording_width ||
+ current_recording_height != new_recording_height) {
+ if (0 < new_recording_width && 0 < new_recording_height) {
+ if (mSecCamera->setRecordingSize(new_recording_width, new_recording_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))",
+ __func__, new_recording_width, new_recording_height);
+ ret = UNKNOWN_ERROR;
+ }
+ mParameters.setVideoSize(new_recording_width, new_recording_height);
+ }
+ }
+
+ //gamma
+ const char *new_gamma_str = mInternalParameters.get("video_recording_gamma");
+
+ if (new_gamma_str != NULL) {
+ int new_gamma = -1;
+ if (!strcmp(new_gamma_str, "off"))
+ new_gamma = GAMMA_OFF;
+ else if (!strcmp(new_gamma_str, "on"))
+ new_gamma = GAMMA_ON;
+ else {
+ LOGE("%s::unmatched gamma(%s)", __func__, new_gamma_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_gamma) {
+ if (mSecCamera->setGamma(new_gamma) < 0) {
+ LOGE("%s::mSecCamera->setGamma(%d) fail", __func__, new_gamma);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ //slow ae
+ const char *new_slow_ae_str = mInternalParameters.get("slow_ae");
+
+ if (new_slow_ae_str != NULL) {
+ int new_slow_ae = -1;
+
+ if (!strcmp(new_slow_ae_str, "off"))
+ new_slow_ae = SLOW_AE_OFF;
+ else if (!strcmp(new_slow_ae_str, "on"))
+ new_slow_ae = SLOW_AE_ON;
+ else {
+ LOGE("%s::unmatched slow_ae(%s)", __func__, new_slow_ae_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_slow_ae) {
+ if (mSecCamera->setSlowAE(new_slow_ae) < 0) {
+ LOGE("%s::mSecCamera->setSlowAE(%d) fail", __func__, new_slow_ae);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ /*Camcorder fix fps*/
+ int new_sensor_mode = mInternalParameters.getInt("cam_mode");
+
+ if (0 <= new_sensor_mode) {
+ if (mSecCamera->setSensorMode(new_sensor_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSensorMode(%d)", __func__, new_sensor_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_sensor_mode=0;
+ }
+
+ /*Shot mode*/
+ int new_shot_mode = mInternalParameters.getInt("shot_mode");
+
+ if (0 <= new_shot_mode) {
+ if (mSecCamera->setShotMode(new_shot_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setShotMode(%d)", __func__, new_shot_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_shot_mode=0;
+ }
+
+ // chk_dataline
+ int new_dataline = mInternalParameters.getInt("chk_dataline");
+
+ if (0 <= new_dataline) {
+ if (mSecCamera->setDataLineCheck(new_dataline) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setDataLineCheck(%d)", __func__, new_dataline);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ LOGV("%s return ret = %d", __func__, ret);
+
+ return ret;
+}
+
+CameraParameters CameraHardwareSec::getParameters() const
+{
+ LOGV("%s :", __func__);
+ return mParameters;
+}
+
+status_t CameraHardwareSec::sendCommand(int32_t command, int32_t arg1, int32_t arg2)
+{
+ /* TODO */
+ /* CAMERA_CMD_START_FACE_DETECTION and CAMERA_CMD_STOP_FACE_DETECTION
+ for Face Detection */
+ if(command == CAMERA_CMD_START_FACE_DETECTION) {
+ if (mSecCamera->setFaceDetect(FACE_DETECTION_ON) < 0) {
+ LOGE("ERR(%s): Fail on mSecCamera->startFaceDetection()");
+ return BAD_VALUE;
+ } else {
+ return NO_ERROR;
+ }
+ }
+ if(command == CAMERA_CMD_STOP_FACE_DETECTION) {
+ if (mSecCamera->setFaceDetect(FACE_DETECTION_OFF) < 0) {
+ LOGE("ERR(%s): Fail on mSecCamera->stopFaceDetection()");
+ return BAD_VALUE;
+ } else {
+ return NO_ERROR;
+ }
+ }
+
+ return BAD_VALUE;
+}
+
+void CameraHardwareSec::release()
+{
+ LOGV("%s", __func__);
+
+ /* shut down any threads we have that might be running. do it here
+ * instead of the destructor. we're guaranteed to be on another thread
+ * than the ones below. if we used the destructor, since the threads
+ * have a reference to this object, we could wind up trying to wait
+ * for ourself to exit, which is a deadlock.
+ */
+ if (mPreviewThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable or running. signal it so it wakes
+ * up and can exit.
+ */
+ mPreviewThread->requestExit();
+ mExitPreviewThread = true;
+ mPreviewRunning = true; /* let it run so it can exit */
+ mPreviewCondition.signal();
+ mPreviewThread->requestExitAndWait();
+ mPreviewThread.clear();
+ }
+ if (mAutoFocusThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable. signal it so it wakes up and can exit.
+ */
+ mFocusLock.lock();
+ mAutoFocusThread->requestExit();
+ mExitAutoFocusThread = true;
+ mFocusCondition.signal();
+ mFocusLock.unlock();
+ mAutoFocusThread->requestExitAndWait();
+ mAutoFocusThread.clear();
+ }
+ if (mPictureThread != NULL) {
+ mPictureThread->requestExitAndWait();
+ mPictureThread.clear();
+ }
+
+ if (mRawHeap) {
+ mRawHeap->release(mRawHeap);
+ mRawHeap = 0;
+ }
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) {
+ if (mRecordHeap[i]) {
+ mRecordHeap[i]->release(mRecordHeap[i]);
+ mRecordHeap[i] = 0;
+ }
+ }
+
+ /* close after all the heaps are cleared since those
+ * could have dup'd our file descriptor.
+ */
+ mSecCamera->DestroyCamera();
+}
+
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 90, /* orientation */
+ },
+ {
+ CAMERA_FACING_FRONT,
+ 90, /* orientation */
+ }
+};
+
+status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable)
+{
+ // FIXME:
+ // metadata buffer mode can be turned on or off.
+ // Samsung needs to fix this.
+ if (!enable) {
+ LOGE("Non-metadata buffer mode is not supported!");
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+/** Close this device */
+
+static camera_device_t *g_cam_device;
+
+static int HAL_camera_device_close(struct hw_device_t* device)
+{
+ LOGI("%s", __func__);
+ if (device) {
+ camera_device_t *cam_device = (camera_device_t *)device;
+ delete static_cast<CameraHardwareSec *>(cam_device->priv);
+ free(cam_device);
+ g_cam_device = 0;
+ }
+ return 0;
+}
+
+static inline CameraHardwareSec *obj(struct camera_device *dev)
+{
+ return reinterpret_cast<CameraHardwareSec *>(dev->priv);
+}
+
+/** Set the preview_stream_ops to which preview frames are sent */
+static int HAL_camera_device_set_preview_window(struct camera_device *dev,
+ struct preview_stream_ops *buf)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->setPreviewWindow(buf);
+}
+
+/** Set the notification and data callbacks */
+static void HAL_camera_device_set_callbacks(struct camera_device *dev,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void* user)
+{
+ LOGV("%s", __func__);
+ obj(dev)->setCallbacks(notify_cb, data_cb, data_cb_timestamp,
+ get_memory,
+ user);
+}
+
+/**
+ * The following three functions all take a msg_type, which is a bitmask of
+ * the messages defined in include/ui/Camera.h
+ */
+
+/**
+ * Enable a message, or set of messages.
+ */
+static void HAL_camera_device_enable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->enableMsgType(msg_type);
+}
+
+/**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera
+ * HAL should not rely on its client to call releaseRecordingFrame() to
+ * release video recording frames sent out by the cameral HAL before and
+ * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL
+ * clients must not modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+static void HAL_camera_device_disable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->disableMsgType(msg_type);
+}
+
+/**
+ * Query whether a message, or a set of messages, is enabled. Note that
+ * this is operates as an AND, if any of the messages queried are off, this
+ * will return false.
+ */
+static int HAL_camera_device_msg_type_enabled(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->msgTypeEnabled(msg_type);
+}
+
+/**
+ * Start preview mode.
+ */
+static int HAL_camera_device_start_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startPreview();
+}
+
+/**
+ * Stop a previously started preview.
+ */
+static void HAL_camera_device_stop_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopPreview();
+}
+
+/**
+ * Returns true if preview is enabled.
+ */
+static int HAL_camera_device_preview_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->previewEnabled();
+}
+
+/**
+ * Request the camera HAL to store meta data or real YUV data in the video
+ * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If
+ * it is not called, the default camera HAL behavior is to store real YUV
+ * data in the video buffers.
+ *
+ * This method should be called before startRecording() in order to be
+ * effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the receiver of
+ * the video buffers to interpret the contents and to find the actual frame
+ * data with the help of the meta data in the buffer. How this is done is
+ * outside of the scope of this method.
+ *
+ * Some camera HALs may not support storing meta data in the video buffers,
+ * but all camera HALs should support storing real YUV data in the video
+ * buffers. If the camera HAL does not support storing the meta data in the
+ * video buffers when it is requested to do do, INVALID_OPERATION must be
+ * returned. It is very useful for the camera HAL to pass meta data rather
+ * than the actual frame data directly to the video encoder, since the
+ * amount of the uncompressed frame data can be very large if video size is
+ * large.
+ *
+ * @param enable if true to instruct the camera HAL to store
+ * meta data in the video buffers; false to instruct
+ * the camera HAL to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+static int HAL_camera_device_store_meta_data_in_buffers(struct camera_device *dev, int enable)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->storeMetaDataInBuffers(enable);
+}
+
+/**
+ * Start record mode. When a record image is available, a
+ * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding
+ * frame. Every record frame must be released by a camera HAL client via
+ * releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames,
+ * and the client must not modify/access any video recording frames.
+ */
+static int HAL_camera_device_start_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startRecording();
+}
+
+/**
+ * Stop a previously started recording.
+ */
+static void HAL_camera_device_stop_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopRecording();
+}
+
+/**
+ * Returns true if recording is enabled.
+ */
+static int HAL_camera_device_recording_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->recordingEnabled();
+}
+
+/**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera HAL client's responsibility to release video recording
+ * frames sent out by the camera HAL before the camera HAL receives a call
+ * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames.
+ */
+static void HAL_camera_device_release_recording_frame(struct camera_device *dev,
+ const void *opaque)
+{
+ LOGV("%s", __func__);
+ obj(dev)->releaseRecordingFrame(opaque);
+}
+
+/**
+ * Start auto focus, the notification callback routine is called with
+ * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be
+ * called again if another auto focus is needed.
+ */
+static int HAL_camera_device_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->autoFocus();
+}
+
+/**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress or
+ * not, this function will return the focus position to the default. If
+ * the camera does not support auto-focus, this is a no-op.
+ */
+static int HAL_camera_device_cancel_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelAutoFocus();
+}
+
+/**
+ * Take a picture.
+ */
+static int HAL_camera_device_take_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->takePicture();
+}
+
+/**
+ * Cancel a picture that was started with takePicture. Calling this method
+ * when no picture is being taken is a no-op.
+ */
+static int HAL_camera_device_cancel_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelPicture();
+}
+
+/**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+static int HAL_camera_device_set_parameters(struct camera_device *dev,
+ const char *parms)
+{
+ LOGV("%s", __func__);
+ String8 str(parms);
+ CameraParameters p(str);
+ return obj(dev)->setParameters(p);
+}
+
+/** Return the camera parameters. */
+char *HAL_camera_device_get_parameters(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ String8 str;
+ CameraParameters parms = obj(dev)->getParameters();
+ str = parms.flatten();
+ return strdup(str.string());
+}
+
+static void HAL_camera_device_put_parameters(struct camera_device *dev, char *parms)
+{
+ LOGV("%s", __func__);
+ free(parms);
+}
+
+/**
+ * Send command to camera driver.
+ */
+static int HAL_camera_device_send_command(struct camera_device *dev,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->sendCommand(cmd, arg1, arg2);
+}
+
+/**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+static void HAL_camera_device_release(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->release();
+}
+
+/**
+ * Dump state of the camera hardware
+ */
+static int HAL_camera_device_dump(struct camera_device *dev, int fd)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->dump(fd);
+}
+
+static int HAL_getNumberOfCameras()
+{
+ LOGV("%s", __func__);
+
+ int cam_fd;
+ static struct v4l2_input input;
+
+ cam_fd = open(CAMERA_DEV_NAME, O_RDONLY);
+ if (cam_fd < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME, strerror(errno));
+ return -1;
+ }
+
+ input.index = 0;
+ while (ioctl(cam_fd, VIDIOC_ENUMINPUT, &input) == 0) {
+ LOGI("Name of input channel[%d] is %s", input.index, input.name);
+ input.index++;
+ }
+
+ close(cam_fd);
+
+ return --input.index;
+}
+
+static int HAL_getCameraInfo(int cameraId, struct camera_info *cameraInfo)
+{
+ LOGV("%s", __func__);
+ memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+ return 0;
+}
+
+#define SET_METHOD(m) m : HAL_camera_device_##m
+
+static camera_device_ops_t camera_device_ops = {
+ SET_METHOD(set_preview_window),
+ SET_METHOD(set_callbacks),
+ SET_METHOD(enable_msg_type),
+ SET_METHOD(disable_msg_type),
+ SET_METHOD(msg_type_enabled),
+ SET_METHOD(start_preview),
+ SET_METHOD(stop_preview),
+ SET_METHOD(preview_enabled),
+ SET_METHOD(store_meta_data_in_buffers),
+ SET_METHOD(start_recording),
+ SET_METHOD(stop_recording),
+ SET_METHOD(recording_enabled),
+ SET_METHOD(release_recording_frame),
+ SET_METHOD(auto_focus),
+ SET_METHOD(cancel_auto_focus),
+ SET_METHOD(take_picture),
+ SET_METHOD(cancel_picture),
+ SET_METHOD(set_parameters),
+ SET_METHOD(get_parameters),
+ SET_METHOD(put_parameters),
+ SET_METHOD(send_command),
+ SET_METHOD(release),
+ SET_METHOD(dump),
+};
+
+#undef SET_METHOD
+
+static int HAL_camera_device_open(const struct hw_module_t* module,
+ const char *id,
+ struct hw_device_t** device)
+{
+ LOGV("%s", __func__);
+
+ int cameraId = atoi(id);
+ if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) {
+ LOGE("Invalid camera ID %s", id);
+ return -EINVAL;
+ }
+
+ if (g_cam_device) {
+ if (obj(g_cam_device)->getCameraId() == cameraId) {
+ LOGV("returning existing camera ID %s", id);
+ goto done;
+ } else {
+ LOGE("Cannot open camera %d. camera %d is already running!",
+ cameraId, obj(g_cam_device)->getCameraId());
+ return -ENOSYS;
+ }
+ }
+
+ g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t));
+ if (!g_cam_device)
+ return -ENOMEM;
+
+ g_cam_device->common.tag = HARDWARE_DEVICE_TAG;
+ g_cam_device->common.version = 1;
+ g_cam_device->common.module = const_cast<hw_module_t *>(module);
+ g_cam_device->common.close = HAL_camera_device_close;
+
+ g_cam_device->ops = &camera_device_ops;
+
+ LOGI("%s: open camera %s", __func__, id);
+
+ g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device);
+
+done:
+ *device = (hw_device_t *)g_cam_device;
+ LOGI("%s: opened camera %s (%p)", __func__, id, *device);
+ return 0;
+}
+
+static hw_module_methods_t camera_module_methods = {
+ open : HAL_camera_device_open
+};
+
+extern "C" {
+ struct camera_module HAL_MODULE_INFO_SYM = {
+ common : {
+ tag : HARDWARE_MODULE_TAG,
+ version_major : 1,
+ version_minor : 0,
+ id : CAMERA_HARDWARE_MODULE_ID,
+ name : "orion camera HAL",
+ author : "Samsung Corporation",
+ methods : &camera_module_methods,
+ },
+ get_number_of_cameras : HAL_getNumberOfCameras,
+ get_camera_info : HAL_getCameraInfo
+ };
+}
+
+}; // namespace android
diff --git a/exynos4/hal/libcamera/SecCameraHWInterface.h b/exynos4/hal/libcamera/SecCameraHWInterface.h
new file mode 100644
index 0000000..321eb15
--- /dev/null
+++ b/exynos4/hal/libcamera/SecCameraHWInterface.h
@@ -0,0 +1,242 @@
+/*
+**
+** 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.
+*/
+
+#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H
+
+#include "SecCamera.h"
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <hardware/camera.h>
+#include <hardware/gralloc.h>
+#include <camera/CameraParameters.h>
+#ifdef BOARD_USE_V4L2_ION
+#include <binder/MemoryHeapBaseIon.h>
+#include "gralloc_priv.h"
+
+#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS + 4)
+#define BUFFER_COUNT_FOR_ARRAY (MAX_BUFFERS)
+#else
+#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS)
+#define BUFFER_COUNT_FOR_ARRAY (1)
+#endif
+
+namespace android {
+ class CameraHardwareSec : public virtual RefBase {
+public:
+ virtual void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ virtual void enableMsgType(int32_t msgType);
+ virtual void disableMsgType(int32_t msgType);
+ virtual bool msgTypeEnabled(int32_t msgType);
+
+ virtual status_t startPreview();
+ virtual void stopPreview();
+ virtual bool previewEnabled();
+
+ virtual status_t startRecording();
+ virtual void stopRecording();
+ virtual bool recordingEnabled();
+ virtual void releaseRecordingFrame(const void *opaque);
+
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t takePicture();
+ virtual status_t cancelPicture();
+ virtual status_t dump(int fd) const;
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual CameraParameters getParameters() const;
+ virtual status_t sendCommand(int32_t command, int32_t arg1, int32_t arg2);
+ virtual status_t setPreviewWindow(preview_stream_ops *w);
+ virtual status_t storeMetaDataInBuffers(bool enable);
+ virtual void release();
+
+ inline int getCameraId() const;
+
+ CameraHardwareSec(int cameraId, camera_device_t *dev);
+ virtual ~CameraHardwareSec();
+private:
+ status_t startPreviewInternal();
+ void stopPreviewInternal();
+
+ class PreviewThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PreviewThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop() {
+ mHardware->previewThreadWrapper();
+ return false;
+ }
+ };
+
+ class PictureThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PictureThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual bool threadLoop() {
+ mHardware->pictureThread();
+ return false;
+ }
+ };
+
+ class AutoFocusThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ AutoFocusThread(CameraHardwareSec *hw): Thread(false), mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraAutoFocusThread", PRIORITY_DEFAULT);
+ }
+ virtual bool threadLoop() {
+ mHardware->autoFocusThread();
+ return true;
+ }
+ };
+
+ void initDefaultParameters(int cameraId);
+ void initHeapLocked();
+
+ sp<PreviewThread> mPreviewThread;
+ int previewThread();
+ int previewThreadWrapper();
+
+ sp<AutoFocusThread> mAutoFocusThread;
+ int autoFocusThread();
+
+ sp<PictureThread> mPictureThread;
+ int pictureThread();
+ bool mCaptureInProgress;
+
+ int save_jpeg(unsigned char *real_jpeg, int jpeg_size);
+ void save_postview(const char *fname, uint8_t *buf,
+ uint32_t size);
+ int decodeInterleaveData(unsigned char *pInterleaveData,
+ int interleaveDataSize,
+ int yuvWidth,
+ int yuvHeight,
+ int *pJpegSize,
+ void *pJpegData,
+ void *pYuvData);
+ bool YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight);
+ bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth,
+ uint32_t srcHight, char *dstBuf,
+ uint32_t dstWidth, uint32_t dstHight);
+
+ bool CheckVideoStartMarker(unsigned char *pBuf);
+ bool CheckEOIMarker(unsigned char *pBuf);
+ bool FindEOIMarkerInJPEG(unsigned char *pBuf,
+ int dwBufSize, int *pnJPEGsize);
+ bool SplitFrame(unsigned char *pFrame, int dwSize,
+ int dwJPEGLineLength, int dwVideoLineLength,
+ int dwVideoHeight, void *pJPEG,
+ int *pdwJPEGSize, void *pVideo,
+ int *pdwVideoSize);
+ void setSkipFrame(int frame);
+ bool isSupportedPreviewSize(const int width,
+ const int height) const;
+ bool getVideosnapshotSize(int *width, int *height);
+ /* used by auto focus thread to block until it's told to run */
+ mutable Mutex mFocusLock;
+ mutable Condition mFocusCondition;
+ bool mExitAutoFocusThread;
+ int mTouched;
+
+ /* used by preview thread to block until it's told to run */
+ mutable Mutex mPreviewLock;
+ mutable Condition mPreviewCondition;
+ mutable Condition mPreviewStoppedCondition;
+ bool mPreviewRunning;
+ bool mPreviewStartDeferred;
+ bool mExitPreviewThread;
+
+ preview_stream_ops *mPreviewWindow;
+
+ /* used to guard threading state */
+ mutable Mutex mStateLock;
+
+ enum PREVIEW_FMT {
+ PREVIEW_FMT_1_PLANE = 0,
+ PREVIEW_FMT_2_PLANE,
+ PREVIEW_FMT_3_PLANE,
+ };
+
+ int mPreviewFmtPlane;
+
+ CameraParameters mParameters;
+ CameraParameters mInternalParameters;
+
+ int mFrameSizeDelta;
+ camera_memory_t *mPreviewHeap;
+ camera_memory_t *mRawHeap;
+ sp<MemoryHeapBase> mPostviewHeap[CAP_BUFFERS];
+ sp<MemoryHeapBase> mThumbnailHeap;
+ camera_memory_t *mRecordHeap[BUFFER_COUNT_FOR_ARRAY];
+
+ camera_frame_metadata_t *mFaceData;
+ camera_memory_t *mFaceDataHeap;
+
+ buffer_handle_t *mBufferHandle[BUFFER_COUNT_FOR_ARRAY];
+ int mStride[BUFFER_COUNT_FOR_ARRAY];
+
+
+ SecCamera *mSecCamera;
+ const __u8 *mCameraSensorName;
+ bool mUseInternalISP;
+
+ mutable Mutex mSkipFrameLock;
+ int mSkipFrame;
+
+ camera_notify_callback mNotifyCb;
+ camera_data_callback mDataCb;
+ camera_data_timestamp_callback mDataCbTimestamp;
+ camera_request_memory mGetMemoryCb;
+ void *mCallbackCookie;
+
+ int32_t mMsgEnabled;
+
+ bool mRecordRunning;
+ bool mRecordHint;
+ mutable Mutex mRecordLock;
+ int mPostViewWidth;
+ int mPostViewHeight;
+ int mPostViewSize;
+ struct SecBuffer mCapBuffer;
+ int mCapIndex;
+ int mCameraID;
+
+ Vector<Size> mSupportedPreviewSizes;
+
+ camera_device_t *mHalDevice;
+ static gralloc_module_t const* mGrallocHal;
+};
+
+}; // namespace android
+
+#endif
diff --git a/exynos4/hal/libfimc/Android.mk b/exynos4/hal/libfimc/Android.mk
new file mode 100644
index 0000000..624d39e
--- /dev/null
+++ b/exynos4/hal/libfimc/Android.mk
@@ -0,0 +1,55 @@
+# 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)),)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog libutils libcutils
+ifeq ($(BOARD_SUPPORT_SYSMMU),true)
+LOCAL_SHARED_LIBRARIES+= libMali
+endif
+
+ifeq ($(BOARD_SUPPORT_SYSMMU),true)
+LOCAL_CFLAGS+=-DBOARD_SUPPORT_SYSMMU
+endif
+
+ifeq ($(TARGET_SOC),exynos4210)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+ifeq ($(BOARD_USE_V4L2),true)
+LOCAL_CFLAGS += -DBOARD_USE_V4L2
+endif
+
+LOCAL_CFLAGS += \
+ -DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include \
+ framework/base/include
+
+LOCAL_SRC_FILES := SecFimc.cpp
+
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE := libfimc
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libfimc/SecFimc.cpp b/exynos4/hal/libfimc/SecFimc.cpp
new file mode 100644
index 0000000..ab744a2
--- /dev/null
+++ b/exynos4/hal/libfimc/SecFimc.cpp
@@ -0,0 +1,1701 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file SecFimc.cpp
+ * \brief source file for Fimc HAL MODULE
+ * \author Hyunkyung, Kim(hk310.kim@samsung.com)
+ * \date 2010/10/13
+ *
+ * <b>Revision History: </b>
+ * - 2010/10/13 : Hyunkyung, Kim(hk310.kim@samsung.com) \n
+ * Initial version
+ *
+ * - 2011/11/15 : Sunmi, Lee(carrotsm.lee@samsung.com) \n
+ * Adjust V4L2 architecture \n
+ */
+
+#define LOG_TAG "libfimc"
+#include <cutils/log.h>
+
+#include "SecFimc.h"
+
+#define FIMC2_DEV_NAME "/dev/video2"
+
+//#define DEBUG_LIB_FIMC
+
+#ifdef BOARD_USE_V4L2
+#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
+#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+#define V4L2_ROTATE V4L2_CID_ROTATE
+#else
+#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT
+#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE
+#define V4L2_ROTATE V4L2_CID_ROTATION
+#endif
+
+#define V4L2_BUF_TYPE_SRC V4L2_BUF_TYPE_OUTPUT
+#define V4L2_MEMORY_TYPE_SRC V4L2_MEMORY_USERPTR
+#ifdef BOARD_USE_V4L2
+#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_CAPTURE
+#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_MMAP
+#else
+#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_VIDEO_OVERLAY
+#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_USERPTR
+#endif
+
+struct yuv_fmt_list yuv_list[] = {
+ { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 },
+#ifdef BOARD_USE_V4L2
+ { "V4L2_PIX_FMT_NV12M", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12M, 12, 2 },
+ { "V4L2_PIX_FMT_NV12MT", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12MT, 12, 2 },
+#endif
+ { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 },
+ { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 },
+ { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 },
+ { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 },
+#ifdef BOARD_USE_V4L2
+ { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 },
+#endif
+ { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 },
+ { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 },
+ { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 },
+ { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 },
+ { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 },
+ { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 },
+ { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 },
+ { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 },
+ { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 },
+ { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 },
+};
+
+#ifdef BOARD_USE_V4L2
+void dump_pixfmt_mp(struct v4l2_pix_format_mplane *pix_mp)
+{
+ LOGI("w: %d", pix_mp->width);
+ LOGI("h: %d", pix_mp->height);
+ LOGI("color: %x", pix_mp->colorspace);
+
+ switch (pix_mp->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ LOGI ("YUYV");
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ LOGI ("UYVY");
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ LOGI ("RGB565");
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ LOGI ("RGB565X");
+ break;
+ default:
+ LOGI("not supported");
+ }
+}
+#endif
+
+void dump_pixfmt(struct v4l2_pix_format *pix)
+{
+ LOGI("w: %d", pix->width);
+ LOGI("h: %d", pix->height);
+ LOGI("color: %x", pix->colorspace);
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ LOGI ("YUYV");
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ LOGI ("UYVY");
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ LOGI ("RGB565");
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ LOGI ("RGB565X");
+ break;
+ default:
+ LOGI("not supported");
+ }
+}
+
+void dump_crop(struct v4l2_crop *crop)
+{
+ LOGI("crop l: %d", crop->c.left);
+ LOGI("crop t: %d", crop->c.top);
+ LOGI("crop w: %d", crop->c.width);
+ LOGI("crop h: %d", crop->c.height);
+}
+
+void dump_window(struct v4l2_window *win)
+{
+ LOGI("window l: %d", win->w.left);
+ LOGI("window t: %d", win->w.top);
+ LOGI("window w: %d", win->w.width);
+ LOGI("window h: %d", win->w.height);
+}
+
+void v4l2_overlay_dump_state(int fd)
+{
+ struct v4l2_format format;
+ struct v4l2_crop crop;
+
+ format.type = V4L2_BUF_TYPE_OUTPUT;
+ if (ioctl(fd, VIDIOC_G_FMT, &format) < 0)
+ return;
+
+ LOGI("dumping driver state:");
+#ifdef BOARD_USE_V4L2
+ dump_pixfmt_mp(&format.fmt.pix_mp);
+#else
+ dump_pixfmt(&format.fmt.pix);
+#endif
+
+ crop.type = format.type;
+ if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
+ return;
+
+ LOGI("input window(crop):");
+ dump_crop(&crop);
+
+ crop.type = V4L2_BUF_TYPE_CAPTURE;
+ if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
+ return;
+
+ LOGI("output crop:");
+ dump_crop(&crop);
+
+}
+
+int fimc_v4l2_query_buf(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_plane)
+{
+ struct v4l2_buffer buf;
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[MAX_PLANES];
+ for (int i = 0; i < MAX_PLANES; i++)
+ memset(&planes[i], 0, sizeof(struct v4l2_plane));
+#endif
+
+ if (MAX_DST_BUFFERS <= buf_index || MAX_PLANES <= num_plane) {
+ LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane);
+ return -1;
+ }
+
+ buf.type = type;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = buf_index;
+#ifdef BOARD_USE_V4L2
+ buf.m.planes = planes;
+ buf.length = num_plane;
+#endif
+
+ if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
+ LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
+ return -1;
+ }
+
+#ifdef BOARD_USE_V4L2
+ for (int i = 0; i < num_plane; i++) {
+ secBuf->phys.extP[i] = (unsigned int)buf.m.planes[i].cookie;
+ secBuf->size.extS[i] = buf.m.planes[i].length;
+
+ 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]);
+ LOGE("%s::paddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->phys.extP[i]);
+ return -1;
+ }
+ }
+#else
+ secBuf->size.s = buf.length;
+
+ if ((secBuf->virt.p = (char *)mmap(0, buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset)) < 0) {
+ LOGE("%s::mmap failed", __func__);
+ return -1;
+ }
+ LOGI("%s::buffers[%d] vaddr = 0x%x", __func__, buf_index, (unsigned int)secBuf->virt.p);
+#endif
+
+ return 0;
+}
+
+int fimc_v4l2_req_buf(int fd, unsigned int num_bufs, enum v4l2_buf_type type, enum v4l2_memory memory)
+{
+ 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;
+ }
+
+#ifdef DEBUG_LIB_FIMC
+ LOGI("%d buffers allocated %d requested", reqbuf.count, 4);
+#endif
+
+ if (reqbuf.count < num_bufs) {
+ LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
+ __func__, reqbuf.count, num_bufs);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_s_ctrl(int fd, int id, int value)
+{
+ 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 fimc_v4l2_set_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, s5p_fimc_img_info *img_info, unsigned int addr)
+{
+ struct v4l2_framebuffer fbuf;
+ struct v4l2_format fmt;
+ struct v4l2_crop crop;
+ struct fimc_buf fimc_dst_buf;
+ struct v4l2_control vc;
+
+ 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 = img_info->full_width;
+ fmt.fmt.pix.height = img_info->full_height;
+ fmt.fmt.pix.pixelformat = img_info->color_space;
+ fmt.fmt.pix.field = field;
+ break;
+#ifdef BOARD_USE_V4L2
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ fmt.fmt.pix_mp.width = img_info->full_width;
+ fmt.fmt.pix_mp.height = img_info->full_height;
+ fmt.fmt.pix_mp.pixelformat = img_info->color_space;
+ fmt.fmt.pix_mp.field = field;
+ fmt.fmt.pix_mp.num_planes = img_info->planes;
+ break;
+#endif
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (ioctl(fd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_G_FBUF failed", __func__);
+ return -1;
+ }
+
+ fbuf.base = (void *)addr;
+ fbuf.fmt.width = img_info->full_width;
+ fbuf.fmt.height = img_info->full_height;
+ fbuf.fmt.pixelformat = img_info->color_space;
+
+ if (ioctl(fd, VIDIOC_S_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_S_FBUF (w=%d, h=%d, color=%d) failed",
+ __func__,
+ img_info->full_width,
+ img_info->full_height,
+ img_info->color_space);
+ return -1;
+ }
+
+ fimc_dst_buf.base[0] = (unsigned int)img_info->buf_addr_phy_rgb_y;
+ fimc_dst_buf.base[1] = (unsigned int)img_info->buf_addr_phy_cb;
+ fimc_dst_buf.base[2] = (unsigned int)img_info->buf_addr_phy_cr;
+
+ vc.id = V4L2_CID_DST_INFO;
+ vc.value = (unsigned int)&fimc_dst_buf.base[0];
+
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, vc.id, vc.value);
+ return -1;
+ }
+
+ fmt.fmt.win.w.left = img_info->start_x;
+ fmt.fmt.win.w.top = img_info->start_y;
+ fmt.fmt.win.w.width = img_info->width;
+ fmt.fmt.win.w.height = img_info->height;
+ break;
+ default:
+ LOGE("invalid buffer type");
+ return -1;
+ break;
+ }
+
+ if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ crop.type = type;
+ crop.c.left = img_info->start_x;
+ crop.c.top = img_info->start_y;
+ crop.c.width = img_info->width;
+ crop.c.height = img_info->height;
+
+ if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+ LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
+ __func__,
+ img_info->start_x,
+ img_info->start_y,
+ img_info->width,
+ img_info->height);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
+{
+ if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
+ LOGE("%s::VIDIOC_STREAMON failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_queue(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int index, int num_plane)
+{
+ struct v4l2_buffer buf;
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[MAX_PLANES];
+ for (int i = 0; i < MAX_PLANES; i++)
+ memset(&planes[i], 0, sizeof(struct v4l2_plane));
+#else
+ struct fimc_buf fimcbuf;
+#endif
+
+ buf.type = type;
+ buf.memory = memory;
+ buf.length = num_plane;
+ buf.index = index;
+#ifdef BOARD_USE_V4L2
+ buf.m.planes = planes;
+
+ for (unsigned int i = 0; i < buf.length; i++) {
+ buf.m.planes[i].length = secBuf->size.extS[i];
+ buf.m.planes[i].m.userptr = (unsigned long)secBuf->phys.extP[i];
+ }
+#else
+ for (int i = 0; i < 3 ; i++) {
+ fimcbuf.base[i] = secBuf->phys.extP[i];
+ fimcbuf.length[i] = secBuf->size.extS[i];
+ }
+
+ buf.m.userptr = (unsigned long)(&fimcbuf);
+ //buf.m.userptr = secBuf->phys.p;
+#endif
+
+ if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
+ LOGE("%s::VIDIOC_QBUF failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_dequeue(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *index, int num_plane)
+{
+ struct v4l2_buffer buf;
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+#ifdef BOARD_USE_V4L2
+ struct v4l2_plane planes[MAX_PLANES];
+ for (int i = 0; i < MAX_PLANES; i++)
+ memset(&planes[i], 0, sizeof(struct v4l2_plane));
+#endif
+
+ buf.type = type;
+ buf.memory = memory;
+ buf.length = num_plane;
+#ifdef BOARD_USE_V4L2
+ buf.m.planes = planes;
+#endif
+ if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
+ LOGE("%s::VIDIOC_DQBUF failed", __func__);
+ return -1;
+ }
+ *index = buf.index;
+
+ return 0;
+}
+
+int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
+{
+ if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
+ LOGE("%s::VIDIOC_STREAMOFF failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = 0;
+ req.type = type;
+ req.memory = memory;
+
+ if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
+ LOGE("%s::VIDIOC_REQBUFS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int multipleOfN(int number, int N)
+{
+ int result = number;
+ switch (N) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ result = (number - (number & (N-1)));
+ break;
+ default:
+ result = number - (number % N);
+ break;
+ }
+ return result;
+}
+
+extern "C" SecFimc* create_instance()
+{
+ return new SecFimc;
+}
+
+extern "C" void destroy_instance(SecFimc* handle)
+{
+ if (handle != NULL)
+ delete handle;
+}
+
+SecFimc::SecFimc()
+: mFlagCreate(false)
+{
+ memset(&mFimcCap, 0, sizeof(struct v4l2_capability));
+ memset(&mS5pFimc, 0, sizeof(s5p_fimc_t));
+
+ mRotVal = 0;
+ mRealDev = -1;
+ mNumOfBuf = 0;
+ mHwVersion = 0;
+ mGlobalAlpha = 0x0;
+ mFlagStreamOn = false;
+ mFlagSetSrcParam = false;
+ mFlagSetDstParam = false;
+ mFlagGlobalAlpha = false;
+ mFlagLocalAlpha = false;
+ mFlagColorKey = false;
+ mFimcMode = 0;
+ mFd = 0;
+ mDev = 0;
+ mColorKey = 0x0;
+}
+
+SecFimc::~SecFimc()
+{
+ if (mFlagCreate == true) {
+ LOGE("%s::this is not Destroyed fail", __func__);
+ if (destroy() == false)
+ LOGE("%s::destroy failed", __func__);
+ }
+}
+
+bool SecFimc::create(enum DEV dev, enum MODE mode, int numOfBuf)
+{
+ if (mFlagCreate == true) {
+ LOGE("%s::Already Created fail", __func__);
+ return false;
+ }
+
+ char node[20];
+ struct v4l2_format fmt;
+ struct v4l2_control vc;
+ SecBuffer zeroBuf;
+
+ mDev = dev;
+ mRealDev = dev;
+
+ switch (mode) {
+ case MODE_SINGLE_BUF:
+ mFimcMode = FIMC_OVLY_NONE_SINGLE_BUF;
+ break;
+ case MODE_MULTI_BUF:
+ mFimcMode = FIMC_OVLY_NONE_MULTI_BUF;
+ break;
+ case MODE_DMA_AUTO:
+ mFimcMode = FIMC_OVLY_DMA_AUTO;
+ break;
+ default:
+ LOGE("%s::Invalid mode(%d) fail", __func__, mode);
+ mFimcMode = FIMC_OVLY_NOT_FIXED;
+ goto err;
+ break;
+ }
+
+ mNumOfBuf = numOfBuf;
+
+ for (int i = 0; i < MAX_DST_BUFFERS; i++)
+ mDstBuffer[i] = zeroBuf;
+
+#ifdef BOARD_USE_V4L2
+ switch(mDev) {
+ case DEV_0:
+ mRealDev = 0;
+ break;
+ case DEV_1:
+ mRealDev = 2;
+ break;
+ case DEV_2:
+ mRealDev = 4;
+ break;
+ case DEV_3:
+ mRealDev = 5;
+ break;
+ default:
+ LOGE("%s::invalid mDev(%d)", __func__, mDev);
+ goto err;
+ break;
+ }
+#endif
+
+ sprintf(node, "%s%d", PFX_NODE_FIMC, (int)mRealDev);
+
+ mFd = open(node, O_RDWR);
+ if (mFd < 0) {
+ LOGE("%s::open(%s) failed", __func__, node);
+ mFd = 0;
+ goto err;
+ }
+
+ /* check capability */
+ if (ioctl(mFd, VIDIOC_QUERYCAP, &mFimcCap) < 0) {
+ LOGE("%s::VIDIOC_QUERYCAP failed", __func__);
+ goto err;
+ }
+
+ if (!(mFimcCap.capabilities & V4L2_CAP_STREAMING)) {
+ LOGE("%s::%s has no streaming support", __func__, node);
+ goto err;
+ }
+
+#ifdef BOARD_USE_V4L2
+ if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
+ LOGE("%s::%s is no video output mplane", __func__, node);
+ goto err;
+ }
+
+ if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
+ LOGE("%s::%s is no video capture mplane", __func__, node);
+ goto err;
+ }
+#else
+ if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ LOGE("%s::%s is no video output", __func__, node);
+ goto err;
+ }
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_G_FMT failed", __func__);
+ goto err;
+ }
+
+ vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR;
+ vc.value = 0;
+ if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) {
+ LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR", __func__);
+ goto err;
+ }
+
+ mDstBuffer[0].phys.p = (unsigned int)vc.value;
+
+ mS5pFimc.out_buf.phys_addr = (void *)mDstBuffer[0].phys.p;
+
+ vc.id = V4L2_CID_FIMC_VERSION;
+ vc.value = 0;
+ if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) {
+ LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_FIMC_VERSION failed, FIMC version is set with default", __func__);
+ vc.value = 0x43;
+ }
+
+ mHwVersion = vc.value;
+
+ vc.id = V4L2_CID_OVLY_MODE;
+ vc.value = mFimcMode;
+ if (ioctl(mFd, VIDIOC_S_CTRL, &vc) < 0) {
+ LOGE("%s::VIDIOC_S_CTRL - V4L2_CID_OVLY_MODE failed", __func__);
+ goto err;
+ }
+#endif
+
+ mFlagCreate = true;
+
+ return true;
+
+err :
+ if (0 < mFd)
+ close(mFd);
+ mFd = 0;
+
+ return false;
+}
+
+bool SecFimc::destroy()
+{
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Already Destroyed fail", __func__);
+ return false;
+ }
+
+ if (mFlagStreamOn == true) {
+ if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
+ return false;
+ }
+#ifdef BOARD_USE_V4L2
+ if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_DST) < 0) {
+ LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
+ return false;
+ }
+#endif
+ mFlagStreamOn = false;
+ }
+
+ if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_clr_buf()[src] failed", __func__);
+ return false;
+ }
+
+#ifdef BOARD_USE_V4L2
+ if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
+ LOGE("%s::fimc_v4l2_clr_buf()[dst] failed", __func__);
+ return false;
+ }
+#endif
+ if (mS5pFimc.out_buf.phys_addr != NULL) {
+ mS5pFimc.out_buf.phys_addr = NULL;
+ mS5pFimc.out_buf.length = 0;
+ }
+
+ if (0 < mFd)
+ close(mFd);
+ mFd = 0;
+
+ mFlagCreate = false;
+
+ return true;
+}
+
+bool SecFimc::flagCreate(void)
+{
+ return mFlagCreate;
+}
+
+int SecFimc::getFd(void)
+{
+ return mFd;
+}
+
+SecBuffer * SecFimc::getMemAddr(int index)
+{
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ return &mDstBuffer[index];
+}
+
+int SecFimc::getHWVersion(void)
+{
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ return mHwVersion;
+}
+
+bool SecFimc::setSrcParams(unsigned int width, unsigned int height,
+ unsigned int cropX, unsigned int cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int colorFormat,
+ bool forceChange)
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
+ if (v4l2ColorFormat < 0) {
+ LOGE("%s::not supported color format", __func__);
+ return false;
+ }
+
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+ unsigned int fimcWidth = *cropWidth;
+ unsigned int fimcHeight = *cropHeight;
+ int src_planes = m_getYuvPlanes(v4l2ColorFormat);
+
+ m_checkSrcSize(width, height,
+ cropX, cropY,
+ &fimcWidth, &fimcHeight,
+ v4l2ColorFormat,
+ false);
+
+ if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
+ if (forceChange == true) {
+#ifdef DEBUG_LIB_FIMC
+ LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
+ *cropWidth, *cropHeight, fimcWidth, fimcHeight);
+#endif
+ } else {
+ LOGE("%s::invalid source params", __func__);
+ return false;
+ }
+ }
+
+ if ( (params->src.full_width == width)
+ && (params->src.full_height == height)
+ && (params->src.start_x == cropX)
+ && (params->src.start_y == cropY)
+ && (params->src.width == fimcWidth)
+ && (params->src.height == fimcHeight)
+ && (params->src.color_space == (unsigned int)v4l2ColorFormat))
+ return true;
+
+ params->src.full_width = width;
+ params->src.full_height = height;
+ params->src.start_x = cropX;
+ params->src.start_y = cropY;
+ params->src.width = fimcWidth;
+ params->src.height = fimcHeight;
+ params->src.color_space = v4l2ColorFormat;
+ src_planes = (src_planes == -1) ? 1 : src_planes;
+
+ if (mFlagSetSrcParam == true) {
+ if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_clr_buf_src() failed", __func__);
+ return false;
+ }
+ }
+
+ if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_SRC, V4L2_FIELD_NONE, &(params->src), 0) < 0) {
+ LOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__);
+ return false;
+ }
+
+ if (fimc_v4l2_req_buf(mFd, 1, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__);
+ return false;
+ }
+
+ *cropWidth = fimcWidth;
+ *cropHeight = fimcHeight;
+
+ mFlagSetSrcParam = true;
+ return true;
+}
+
+bool SecFimc::getSrcParams(unsigned int *width, unsigned int *height,
+ unsigned int *cropX, unsigned int *cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int *colorFormat)
+{
+ struct v4l2_format fmt;
+ struct v4l2_crop crop;
+
+ fmt.type = V4L2_BUF_TYPE_SRC;
+
+ if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
+ return false;
+ }
+
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+ *colorFormat = fmt.fmt.pix.pixelformat;
+ break;
+#ifdef BOARD_USE_V4L2
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ *width = fmt.fmt.pix_mp.width;
+ *height = fmt.fmt.pix_mp.height;
+ *colorFormat = fmt.fmt.pix_mp.pixelformat;
+ break;
+#endif
+ default:
+ LOGE("%s::Invalid buffer type", __func__);
+ return false;
+ break;
+ }
+
+ crop.type = V4L2_BUF_TYPE_SRC;
+ if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) {
+ LOGE("%s::VIDIOC_G_CROP failed", __func__);
+ return false;
+ }
+
+ *cropX = crop.c.left;
+ *cropY = crop.c.top;
+ *cropWidth = crop.c.width;
+ *cropHeight = crop.c.height;
+
+ return true;
+}
+
+bool SecFimc::setSrcAddr(unsigned int physYAddr,
+ unsigned int physCbAddr,
+ unsigned int physCrAddr,
+ int colorFormat)
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+ int src_planes = m_getYuvPlanes(params->src.color_space);
+ int src_bpp = m_getYuvBpp(params->src.color_space);
+ unsigned int frame_size = params->src.full_width * params->src.full_height;
+ src_planes = (src_planes == -1) ? 1 : src_planes;
+
+ mSrcBuffer.phys.extP[0] = physYAddr;
+
+ if (colorFormat == HAL_PIXEL_FORMAT_YV12) {
+ mSrcBuffer.phys.extP[1] = physCrAddr;
+ mSrcBuffer.phys.extP[2] = physCbAddr;
+ } else {
+ mSrcBuffer.phys.extP[1] = physCbAddr;
+ mSrcBuffer.phys.extP[2] = physCrAddr;
+ }
+
+ if (2 <= src_planes && mSrcBuffer.phys.extP[1] == 0)
+ mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[0] + frame_size;
+
+ if (3 == src_planes && mSrcBuffer.phys.extP[2] == 0) {
+ if (colorFormat == HAL_PIXEL_FORMAT_YV12) {
+ if (12 == src_bpp)
+ mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 2);
+ else
+ mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 1);
+ } else {
+ if (12 == src_bpp)
+ mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 2);
+ else
+ mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 1);
+ }
+ }
+
+ return true;
+}
+
+bool SecFimc::setDstParams(unsigned int width, unsigned int height,
+ unsigned int cropX, unsigned int cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int colorFormat,
+ bool forceChange)
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
+ if (v4l2ColorFormat < 0) {
+ LOGE("%s::not supported color format", __func__);
+ return false;
+ }
+
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+ unsigned int fimcWidth = *cropWidth;
+ unsigned int fimcHeight = *cropHeight;
+ int dst_planes = m_getYuvPlanes(v4l2ColorFormat);
+
+ m_checkDstSize(width, height,
+ cropX, cropY,
+ &fimcWidth, &fimcHeight,
+ v4l2ColorFormat,
+ mRotVal,
+ true);
+
+ if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
+ if (forceChange == true) {
+#ifdef DEBUG_LIB_FIMC
+ LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
+ *cropWidth, *cropHeight, fimcWidth, fimcHeight);
+#endif
+ } else {
+ LOGE("%s::Invalid destination params", __func__);
+ return false;
+ }
+ }
+
+ if (90 == mRotVal || 270 == mRotVal) {
+ params->dst.full_width = height;
+ params->dst.full_height = width;
+
+ if (90 == mRotVal) {
+ params->dst.start_x = cropY;
+ params->dst.start_y = width - (cropX + fimcWidth);
+ } else {
+ params->dst.start_x = height - (cropY + fimcHeight);
+ params->dst.start_y = cropX;
+ }
+
+ params->dst.width = fimcHeight;
+ params->dst.height = fimcWidth;
+
+ if (0x50 != mHwVersion)
+ params->dst.start_y += (fimcWidth - params->dst.height);
+
+ } else {
+ params->dst.full_width = width;
+ params->dst.full_height = height;
+
+ if (180 == mRotVal) {
+ params->dst.start_x = width - (cropX + fimcWidth);
+ params->dst.start_y = height - (cropY + fimcHeight);
+ } else {
+ params->dst.start_x = cropX;
+ params->dst.start_y = cropY;
+ }
+
+ params->dst.width = fimcWidth;
+ params->dst.height = fimcHeight;
+ }
+ params->dst.color_space = v4l2ColorFormat;
+ dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+
+#ifdef BOARD_USE_V4L2
+ if (mFlagSetDstParam == true) {
+ if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
+ LOGE("%s::fimc_v4l2_clr_buf_dst() failed", __func__);
+ return false;
+ }
+ }
+#endif
+
+ if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) {
+ LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
+ return false;
+ }
+
+ if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) {
+ LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
+ return false;
+ }
+
+#ifdef BOARD_USE_V4L2
+ if (fimc_v4l2_req_buf(mFd, mNumOfBuf, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
+ LOGE("%s::fimc_v4l2_req_buf()[dst] failed", __func__);
+ return false;
+ }
+
+ for (int i = 0; i < mNumOfBuf; i++) {
+ if (fimc_v4l2_query_buf(mFd, &(mDstBuffer[i]),
+ V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) {
+ LOGE("%s::fimc_v4l2_query_buf() failed", __func__);
+ }
+ }
+#endif
+
+ *cropWidth = fimcWidth;
+ *cropHeight = fimcHeight;
+
+ mFlagSetDstParam = true;
+ return true;
+}
+
+bool SecFimc::getDstParams(unsigned int *width, unsigned int *height,
+ unsigned int *cropX, unsigned int *cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int *colorFormat)
+{
+ struct v4l2_framebuffer fbuf;
+ struct v4l2_format fmt;
+ struct v4l2_crop crop;
+
+ fmt.type = V4L2_BUF_TYPE_DST;
+ if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
+ return false;
+ }
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+ *colorFormat = fmt.fmt.pix.pixelformat;
+ break;
+#ifdef BOARD_USE_V4L2
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ *width = fmt.fmt.pix_mp.width;
+ *height = fmt.fmt.pix_mp.height;
+ *colorFormat = fmt.fmt.pix_mp.pixelformat;
+ break;
+#endif
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ *cropX = fmt.fmt.win.w.left;
+ *cropY = fmt.fmt.win.w.top;
+ *cropWidth = fmt.fmt.win.w.width;
+ *cropHeight = fmt.fmt.win.w.height;
+
+ if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_G_FBUF failed", __func__);
+ return false;
+ }
+
+ *width = fbuf.fmt.width;
+ *height = fbuf.fmt.height;
+ *colorFormat = fbuf.fmt.pixelformat;
+ break;
+ default:
+ LOGE("%s::Invalid buffer type", __func__);
+ return false;
+ break;
+ }
+
+ if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+
+ crop.type = V4L2_BUF_TYPE_DST;
+ if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) {
+ LOGE("%s::VIDIOC_G_CROP(crop.type : %d) failed", __func__, crop.type);
+ return false;
+ }
+
+ *cropX = crop.c.left;
+ *cropY = crop.c.top;
+ *cropWidth = crop.c.width;
+ *cropHeight = crop.c.height;
+ }
+
+ return true;
+}
+
+bool SecFimc::setDstAddr(unsigned int physYAddr, unsigned int physCbAddr, unsigned int physCrAddr, int buf_index)
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ mS5pFimc.out_buf.phys_addr = (void *)physYAddr;
+
+ mDstBuffer[buf_index].phys.extP[0] = physYAddr;
+ mDstBuffer[buf_index].phys.extP[1] = physCbAddr;
+ mDstBuffer[buf_index].phys.extP[2] = physCrAddr;
+
+#ifdef BOARD_USE_V4L2
+ if (physYAddr != 0)
+ mS5pFimc.use_ext_out_mem = 1;
+#else
+ params->dst.buf_addr_phy_rgb_y = physYAddr;
+ params->dst.buf_addr_phy_cb = physCbAddr;
+ params->dst.buf_addr_phy_cr = physCrAddr;
+
+ if ((physYAddr != 0)
+ && ((unsigned int)mS5pFimc.out_buf.phys_addr != mDstBuffer[0].phys.p))
+ mS5pFimc.use_ext_out_mem = 1;
+
+ if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) {
+ LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
+ return false;
+ }
+
+ if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) {
+ LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+bool SecFimc::setRotVal(unsigned int rotVal)
+{
+ struct v4l2_control vc;
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, rotVal) < 0) {
+ LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE) failed", __func__);
+ return false;
+ }
+
+ mRotVal = rotVal;
+ return true;
+}
+
+bool SecFimc::setGlobalAlpha(bool enable, int alpha)
+{
+ struct v4l2_framebuffer fbuf;
+ struct v4l2_format fmt;
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ if (mFlagStreamOn == true) {
+ LOGE("%s::mFlagStreamOn == true", __func__);
+ return false;
+ }
+
+ if (mFlagGlobalAlpha == enable && mGlobalAlpha == alpha)
+ return true;
+
+ memset(&fbuf, 0, sizeof(fbuf));
+
+ if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_G_FBUF failed", __func__);
+ return false;
+ }
+
+ if (enable)
+ fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ else
+ fbuf.flags &= ~V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+
+ if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_S_FBUF failed", __func__);
+ return false;
+ }
+
+ if (enable) {
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+
+ if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_G_FMT failed", __func__);
+ return false;
+ }
+
+ fmt.fmt.win.global_alpha = alpha & 0xFF;
+ if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_S_FMT failed", __func__);
+ return false;
+ }
+ }
+
+ mFlagGlobalAlpha = enable;
+ mGlobalAlpha = alpha;
+
+ return true;
+
+}
+
+bool SecFimc::setLocalAlpha(bool enable)
+{
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ if (mFlagStreamOn == true) {
+ LOGE("%s::mFlagStreamOn == true", __func__);
+ return false;
+ }
+
+ if (mFlagLocalAlpha == enable)
+ return true;
+
+ return true;
+}
+
+bool SecFimc::setColorKey(bool enable, int colorKey)
+{
+ struct v4l2_framebuffer fbuf;
+ struct v4l2_format fmt;
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ if (mFlagStreamOn == true) {
+ LOGE("%s::mFlagStreamOn == true", __func__);
+ return false;
+ }
+
+ if (mFlagColorKey == enable && mColorKey == colorKey)
+ return true;
+
+ memset(&fbuf, 0, sizeof(fbuf));
+
+ if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_G_FBUF failed", __func__);
+ return false;
+ }
+
+ if (enable)
+ fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+ else
+ fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
+
+ if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) {
+ LOGE("%s::VIDIOC_S_FBUF failed", __func__);
+ return false;
+ }
+
+ if (enable) {
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+
+ if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::VIDIOC_G_FMT failed", __func__);
+ return false;
+ }
+
+ fmt.fmt.win.chromakey = colorKey & 0xFFFFFF;
+
+ if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0)
+ LOGE("%s::VIDIOC_S_FMT failed", __func__);
+ }
+ mFlagColorKey = enable;
+ mColorKey = colorKey;
+ return true;
+}
+
+bool SecFimc::draw(int src_index, int dst_index)
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+ if (mFlagCreate == false) {
+ LOGE("%s::Not yet created", __func__);
+ return false;
+ }
+
+ if (mFlagSetSrcParam == false) {
+ LOGE("%s::mFlagSetSrcParam == false fail", __func__);
+ return false;
+ }
+
+ if (mFlagSetDstParam == false) {
+ LOGE("%s::mFlagSetDstParam == false fail", __func__);
+ return false;
+ }
+
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+ bool flagStreamOn = false;
+ int src_planes = m_getYuvPlanes(params->src.color_space);
+ int dst_planes = m_getYuvPlanes(params->dst.color_space);
+ src_planes = (src_planes == -1) ? 1 : src_planes;
+ dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+
+#ifdef BOARD_USE_V4L2
+ if (mFlagStreamOn == false) {
+ if (m_streamOn() == false) {
+ LOGE("%s::m_streamOn failed", __func__);
+ return false;
+ }
+ mFlagStreamOn = true;
+ }
+ if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, &dst_index, dst_planes) < 0) {
+ LOGE("%s::fimc_v4l2_dequeue[dst](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
+ return false;
+ }
+
+ if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
+ LOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
+ return false;
+ }
+
+ if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) {
+ LOGE("%s::fimc_v4l2_queue[src](index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
+ return false;
+ }
+
+ if (fimc_v4l2_queue(mFd, &(mDstBuffer[dst_index]), V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, dst_index, dst_planes) < 0) {
+ LOGE("%s::fimc_v4l2_queue[dst](index : %d) (mNumOfBuf : %d) failed", __func__, dst_index, mNumOfBuf);
+ return false;
+ }
+#else
+ if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
+ goto err;
+ }
+
+ flagStreamOn = true;
+
+ if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) {
+ LOGE("%s::fimc_v4l2_queue(index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
+ goto err;
+ }
+
+ if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
+ LOGE("%s::fimc_v4l2_dequeue (mNumOfBuf : %d) failed", __func__, mNumOfBuf);
+ goto err;
+ }
+#endif
+
+err :
+#ifndef BOARD_USE_V4L2
+ if (flagStreamOn == true) {
+ if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
+
+bool SecFimc::m_streamOn()
+{
+#ifdef DEBUG_LIB_FIMC
+ LOGD("%s", __func__);
+#endif
+
+#ifdef BOARD_USE_V4L2
+ s5p_fimc_params_t *params = &(mS5pFimc.params);
+ int src_planes = m_getYuvPlanes(params->src.color_space);
+ int dst_planes = m_getYuvPlanes(params->dst.color_space);
+ src_planes = (src_planes == -1) ? 1 : src_planes;
+ dst_planes = (dst_planes == -1) ? 1 : dst_planes;
+
+ if (params->src.color_space == V4L2_PIX_FMT_RGB32) {
+ mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 4;
+
+ } else if ( (params->src.color_space == V4L2_PIX_FMT_NV12MT)
+ || (params->src.color_space == V4L2_PIX_FMT_NV12M)) {
+ mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width;
+ mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 2;
+ } else if ( (params->src.color_space == V4L2_PIX_FMT_YUV420)
+ || (params->src.color_space == V4L2_PIX_FMT_YUV420M)) {
+ mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width;
+ mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 4;
+ mSrcBuffer.size.extS[2] = params->src.full_height * params->src.full_width / 4;
+ } else {
+ mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 2;
+ }
+
+ if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, 0, src_planes) < 0) {
+ LOGE("%s::fimc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, 0, 1);
+ return false;
+ }
+
+ for (int i = 0; i < mNumOfBuf; i++) {
+ if (fimc_v4l2_queue(mFd, &(mDstBuffer[i]),
+ V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) {
+ LOGE("%s::fimc_v4l2_queue(index : %d) (mDstBufNum : %d) failed", __func__, i, mNumOfBuf);
+ return false;
+ }
+ }
+#endif
+ if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
+ LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
+ return false;
+ }
+
+#ifdef BOARD_USE_V4L2
+ if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_DST) < 0) {
+ LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool SecFimc::m_checkSrcSize(unsigned int width, unsigned int height,
+ unsigned int cropX, unsigned int cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int colorFormat,
+ bool forceChange)
+{
+ bool ret = true;
+
+ if (8 <= height && *cropHeight < 8) {
+ if (forceChange)
+ *cropHeight = 8;
+ ret = false;
+ }
+
+ if (16 <= width && *cropWidth < 16) {
+ if (forceChange)
+ *cropWidth = 16;
+ ret = false;
+ }
+
+ if (0x50 == mHwVersion) {
+ if (colorFormat == V4L2_PIX_FMT_YUV422P) {
+ if (*cropHeight % 2 != 0) {
+ if (forceChange)
+ *cropHeight = multipleOfN(*cropHeight, 2);
+ ret = false;
+ }
+ if (*cropWidth % 2 != 0) {
+ if (forceChange)
+ *cropWidth = multipleOfN(*cropWidth, 2);
+ ret = false;
+ }
+ }
+ } else {
+ if (height < 8)
+ return false;
+
+ if (width % 16 != 0)
+ return false;
+
+ if (*cropWidth % 16 != 0) {
+ if (forceChange)
+ *cropWidth = multipleOfN(*cropWidth, 16);
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+bool SecFimc::m_checkDstSize(unsigned int width, unsigned int height,
+ unsigned int cropX, unsigned int cropY,
+ unsigned int *cropWidth, unsigned int *cropHeight,
+ int colorFormat, int rotVal, bool forceChange)
+{
+ bool ret = true;
+ unsigned int rotWidth;
+ unsigned int rotHeight;
+ unsigned int *rotCropWidth;
+ unsigned int *rotCropHeight;
+
+ if (rotVal == 90 || rotVal == 270) {
+ rotWidth = height;
+ rotHeight = width;
+ rotCropWidth = cropHeight;
+ rotCropHeight = cropWidth;
+ } else {
+ rotWidth = width;
+ rotHeight = height;
+ rotCropWidth = cropWidth;
+ rotCropHeight = cropHeight;
+ }
+
+ if (rotHeight < 8)
+ return false;
+
+ if (rotWidth % 8 != 0)
+ return false;
+
+ switch (colorFormat) {
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+#ifdef BOARD_USE_V4L2
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12MT:
+ case V4L2_PIX_FMT_YUV420M:
+#endif
+ case V4L2_PIX_FMT_YUV420:
+ if (*rotCropHeight % 2 != 0) {
+ if (forceChange)
+ *rotCropHeight = multipleOfN(*rotCropHeight, 2);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+int SecFimc::m_widthOfFimc(int v4l2ColorFormat, int width)
+{
+ int newWidth = width;
+
+ if (0x50 == mHwVersion) {
+ switch (v4l2ColorFormat) {
+ /* 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:
+#ifdef BOARD_USE_V4L2
+ case V4L2_PIX_FMT_NV12MT:
+ case V4L2_PIX_FMT_YUV420M:
+#endif
+ case V4L2_PIX_FMT_YUV420:
+
+ newWidth = multipleOfN(width, 2);
+ break;
+ default :
+ break;
+ }
+ } else {
+ switch (v4l2ColorFormat) {
+ case V4L2_PIX_FMT_RGB565:
+ newWidth = multipleOfN(width, 8);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ newWidth = multipleOfN(width, 4);
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ newWidth = multipleOfN(width, 4);
+ break;
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ newWidth = multipleOfN(width, 8);
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ newWidth = multipleOfN(width, 16);
+ break;
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+#ifdef BOARD_USE_V4L2
+ case V4L2_PIX_FMT_NV12MT:
+#endif
+ newWidth = multipleOfN(width, 8);
+ break;
+#ifdef BOARD_USE_V4L2
+ case V4L2_PIX_FMT_YUV420M:
+#endif
+ case V4L2_PIX_FMT_YUV420:
+ newWidth = multipleOfN(width, 16);
+ break;
+ default :
+ break;
+ }
+ }
+ return newWidth;
+}
+
+int SecFimc::m_heightOfFimc(int v4l2ColorFormat, int height)
+{
+ int newHeight = height;
+
+ switch (v4l2ColorFormat) {
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+#ifdef BOARD_USE_V4L2
+ case V4L2_PIX_FMT_NV12MT:
+ case V4L2_PIX_FMT_YUV420M:
+#endif
+ case V4L2_PIX_FMT_YUV420:
+ newHeight = multipleOfN(height, 2);
+ break;
+ default :
+ break;
+ }
+ return newHeight;
+}
+
+int SecFimc::m_getYuvBpp(unsigned int fmt)
+{
+ int i, sel = -1;
+
+ for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+ if (yuv_list[i].fmt == fmt) {
+ sel = i;
+ break;
+ }
+ }
+
+ if (sel == -1)
+ return sel;
+ else
+ return yuv_list[sel].bpp;
+}
+
+int SecFimc::m_getYuvPlanes(unsigned int fmt)
+{
+ int i, sel = -1;
+
+ for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+ if (yuv_list[i].fmt == fmt) {
+ sel = i;
+ break;
+ }
+ }
+
+ if (sel == -1)
+ return sel;
+ else
+ return yuv_list[sel].planes;
+}
diff --git a/exynos4/hal/libfimg/Android.mk b/exynos4/hal/libfimg3x/Android.mk
index 0d607e2..c60274d 100644
--- a/exynos4/hal/libfimg/Android.mk
+++ b/exynos4/hal/libfimg3x/Android.mk
@@ -1,18 +1,22 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_C_INCLUDES += \
- $(BOARD_HAL_PATH)/include \
+ifeq ($(BOARD_USES_FIMGAPI),true)
-LOCAL_SRC_FILES := \
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES:= \
FimgApi.cpp \
FimgC210.cpp
LOCAL_SHARED_LIBRARIES:= liblog libutils libbinder
-LOCAL_MODULE_TAGS := eng
-LOCAL_MODULE := libfimg
+LOCAL_MODULE:= libfimg
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libfimg/FimgApi.cpp b/exynos4/hal/libfimg3x/FimgApi.cpp
index b4c5890..b4c5890 100644
--- a/exynos4/hal/libfimg/FimgApi.cpp
+++ b/exynos4/hal/libfimg3x/FimgApi.cpp
diff --git a/exynos4/hal/libfimg/FimgApi.h b/exynos4/hal/libfimg3x/FimgApi.h
index 3daac3d..3daac3d 100644
--- a/exynos4/hal/libfimg/FimgApi.h
+++ b/exynos4/hal/libfimg3x/FimgApi.h
diff --git a/exynos4/hal/libfimg/FimgC210.cpp b/exynos4/hal/libfimg3x/FimgC210.cpp
index 129acae..129acae 100644
--- a/exynos4/hal/libfimg/FimgC210.cpp
+++ b/exynos4/hal/libfimg3x/FimgC210.cpp
diff --git a/exynos4/hal/libfimg/FimgC210.h b/exynos4/hal/libfimg3x/FimgC210.h
index 7aa9a9a..7aa9a9a 100644
--- a/exynos4/hal/libfimg/FimgC210.h
+++ b/exynos4/hal/libfimg3x/FimgC210.h
diff --git a/exynos4/hal/libfimg4x/Android.mk b/exynos4/hal/libfimg4x/Android.mk
new file mode 100644
index 0000000..f42da3f
--- /dev/null
+++ b/exynos4/hal/libfimg4x/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifeq ($(BOARD_USES_FIMGAPI),true)
+
+#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
+LOCAL_C_INCLUDES += external/skia/include/core
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES:= \
+ FimgApi.cpp \
+ FimgExynos4.cpp
+
+LOCAL_SHARED_LIBRARIES:= liblog libutils libbinder
+
+LOCAL_MODULE:= libfimg
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libfimg4x/FimgApi.cpp b/exynos4/hal/libfimg4x/FimgApi.cpp
new file mode 100644
index 0000000..ff11b8d
--- /dev/null
+++ b/exynos4/hal/libfimg4x/FimgApi.cpp
@@ -0,0 +1,376 @@
+/*
+**
+** Copyright 2009 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 "SKIA"
+#include <utils/Log.h>
+
+#include "FimgApi.h"
+
+struct blit_op_table optbl[] = {
+ { (int)BLIT_OP_SOLID_FILL, "FILL" },
+ { (int)BLIT_OP_CLR, "CLR" },
+ { (int)BLIT_OP_SRC, "SRC" },
+ { (int)BLIT_OP_DST, "DST" },
+ { (int)BLIT_OP_SRC_OVER, "SRC_OVER" },
+ { (int)BLIT_OP_DST_OVER, "DST_OVER" },
+ { (int)BLIT_OP_SRC_IN, "SRC_IN" },
+ { (int)BLIT_OP_DST_IN, "DST_IN" },
+ { (int)BLIT_OP_SRC_OUT, "SRC_OUT" },
+ { (int)BLIT_OP_DST_OUT, "DST_OUT" },
+ { (int)BLIT_OP_SRC_ATOP, "SRC_ATOP" },
+ { (int)BLIT_OP_DST_ATOP, "DST_ATOP" },
+ { (int)BLIT_OP_XOR, "XOR" },
+ { (int)BLIT_OP_ADD, "ADD" },
+ { (int)BLIT_OP_MULTIPLY, "MULTIPLY" },
+ { (int)BLIT_OP_SCREEN, "SCREEN" },
+ { (int)BLIT_OP_DARKEN, "DARKEN" },
+ { (int)BLIT_OP_LIGHTEN, "LIGHTEN" },
+ { (int)BLIT_OP_DISJ_SRC_OVER, "DISJ_SRC_OVER" },
+ { (int)BLIT_OP_DISJ_DST_OVER, "DISJ_DST_OVER" },
+ { (int)BLIT_OP_DISJ_SRC_IN, "DISJ_SRC_IN" },
+ { (int)BLIT_OP_DISJ_DST_IN, "DISJ_DST_IN" },
+ { (int)BLIT_OP_DISJ_SRC_OUT, "DISJ_SRC_OUT" },
+ { (int)BLIT_OP_DISJ_DST_OUT, "DISJ_DST_OUT" },
+ { (int)BLIT_OP_DISJ_SRC_ATOP, "DISJ_SRC_ATOP" },
+ { (int)BLIT_OP_DISJ_DST_ATOP, "DISJ_DST_ATOP" },
+ { (int)BLIT_OP_DISJ_XOR, "DISJ_XOR" },
+ { (int)BLIT_OP_CONJ_SRC_OVER, "CONJ_SRC_OVER" },
+ { (int)BLIT_OP_CONJ_DST_OVER, "CONJ_DST_OVER" },
+ { (int)BLIT_OP_CONJ_SRC_IN, "CONJ_SRC_IN" },
+ { (int)BLIT_OP_CONJ_DST_IN, "CONJ_DST_IN" },
+ { (int)BLIT_OP_CONJ_SRC_OUT, "CONJ_SRC_OUT" },
+ { (int)BLIT_OP_CONJ_DST_OUT, "CONJ_DST_OUT" },
+ { (int)BLIT_OP_CONJ_SRC_ATOP, "CONJ_SRC_ATOP" },
+ { (int)BLIT_OP_CONJ_DST_ATOP, "CONJ_DST_ATOP" },
+ { (int)BLIT_OP_CONJ_XOR, "CONJ_XOR" },
+ { (int)BLIT_OP_USER_COEFF, "USER_COEFF" },
+ { (int)BLIT_OP_END, "" },
+};
+
+#ifndef REAL_DEBUG
+ void VOID_FUNC(const char *format, ...)
+ {}
+#endif
+
+FimgApi::FimgApi()
+{
+ m_flagCreate = false;
+}
+
+FimgApi::~FimgApi()
+{
+ if (m_flagCreate == true)
+ PRINT("%s::this is not Destroyed fail\n", __func__);
+}
+
+bool FimgApi::Create(void)
+{
+ bool ret = false;
+
+ if (t_Lock() == false) {
+ PRINT("%s::t_Lock() fail\n", __func__);
+ goto CREATE_DONE;
+ }
+
+ if (m_flagCreate == true) {
+ PRINT("%s::Already Created fail\n", __func__);
+ goto CREATE_DONE;
+ }
+
+ if (t_Create() == false) {
+ PRINT("%s::t_Create() fail\n", __func__);
+ goto CREATE_DONE;
+ }
+
+ m_flagCreate = true;
+
+ ret = true;
+
+CREATE_DONE :
+
+ t_UnLock();
+
+ return ret;
+}
+
+bool FimgApi::Destroy(void)
+{
+ bool ret = false;
+
+ if (t_Lock() == false) {
+ PRINT("%s::t_Lock() fail\n", __func__);
+ goto DESTROY_DONE;
+ }
+
+ if (m_flagCreate == false) {
+ PRINT("%s::Already Destroyed fail\n", __func__);
+ goto DESTROY_DONE;
+ }
+
+ if (t_Destroy() == false) {
+ PRINT("%s::t_Destroy() fail\n", __func__);
+ goto DESTROY_DONE;
+ }
+
+ m_flagCreate = false;
+
+ ret = true;
+
+DESTROY_DONE :
+
+ t_UnLock();
+
+ return ret;
+}
+
+bool FimgApi::Stretch(struct fimg2d_blit *cmd)
+{
+ bool ret = false;
+
+ if (t_Lock() == false) {
+ PRINT("%s::t_Lock() fail\n", __func__);
+ goto STRETCH_DONE;
+ }
+
+ if (m_flagCreate == false) {
+ PRINT("%s::This is not Created fail\n", __func__);
+ goto STRETCH_DONE;
+ }
+
+ if (t_Stretch(cmd) == false) {
+ goto STRETCH_DONE;
+ }
+
+ ret = true;
+
+STRETCH_DONE :
+
+ t_UnLock();
+
+ return ret;
+}
+
+bool FimgApi::Sync(void)
+{
+ bool ret = false;
+
+ if (m_flagCreate == false) {
+ PRINT("%s::This is not Created fail\n", __func__);
+ goto SYNC_DONE;
+ }
+
+ if (t_Sync() == false)
+ goto SYNC_DONE;
+
+ ret = true;
+
+SYNC_DONE :
+
+ return ret;
+}
+
+bool FimgApi::t_Create(void)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+bool FimgApi::t_Destroy(void)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+bool FimgApi::t_Stretch(struct fimg2d_blit *cmd)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+bool FimgApi::t_Sync(void)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+bool FimgApi::t_Lock(void)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+bool FimgApi::t_UnLock(void)
+{
+ PRINT("%s::This is empty virtual function fail\n", __func__);
+ return false;
+}
+
+//---------------------------------------------------------------------------//
+// extern function
+//---------------------------------------------------------------------------//
+extern "C" int stretchFimgApi(struct fimg2d_blit *cmd)
+{
+ FimgApi * fimgApi = createFimgApi();
+
+ if (fimgApi == NULL) {
+ PRINT("%s::createFimgApi() fail\n", __func__);
+ return -1;
+ }
+
+ if (fimgApi->Stretch(cmd) == false) {
+ if (fimgApi != NULL)
+ destroyFimgApi(fimgApi);
+
+ return -1;
+ }
+
+ if (fimgApi != NULL)
+ destroyFimgApi(fimgApi);
+
+ return 0;
+}
+
+extern "C" int SyncFimgApi(void)
+{
+ FimgApi * fimgApi = createFimgApi();
+ if (fimgApi == NULL) {
+ PRINT("%s::createFimgApi() fail\n", __func__);
+ return -1;
+ }
+
+ if (fimgApi->Sync() == false) {
+ if (fimgApi != NULL)
+ destroyFimgApi(fimgApi);
+
+ return -1;
+ }
+
+ if (fimgApi != NULL)
+ destroyFimgApi(fimgApi);
+
+ return 0;
+}
+
+void printDataBlit(char *title, struct fimg2d_blit *cmd)
+{
+ LOGI("%s\n", title);
+
+ LOGI(" sequence_no. = %u\n", cmd->seq_no);
+ LOGI(" blit_op = %d(%s)\n", cmd->op, optbl[cmd->op].str);
+ LOGI(" fill_color = %X\n", cmd->solid_color);
+ LOGI(" global_alpha = %u\n", (unsigned int)cmd->g_alpha);
+ LOGI(" PREMULT = %s\n", cmd->premult == PREMULTIPLIED ? "PREMULTIPLIED" : "NON-PREMULTIPLIED");
+ LOGI(" do_dither = %s\n", cmd->dither == true ? "dither" : "no-dither");
+
+ printDataBlitRotate(cmd->rotate);
+
+ printDataBlitScale(cmd->scaling);
+
+ printDataBlitImage("SRC", cmd->src);
+ printDataBlitImage("DST", cmd->dst);
+ printDataBlitImage("MSK", cmd->msk);
+
+ printDataBlitRect("SRC", cmd->src_rect);
+ printDataBlitRect("DST", cmd->dst_rect);
+ printDataBlitRect("MSK", cmd->msk_rect);
+
+ printDataBlitClip(cmd->clipping);
+}
+
+void printDataBlitImage(char *title, struct fimg2d_image *image)
+{
+ if (NULL != image) {
+ LOGI(" Image_%s\n", title);
+ LOGI(" addr = %X\n", image->addr.start);
+ LOGI(" size = %u\n", image->addr.size);
+ LOGI(" (width, height) = (%d, %d)\n", image->width, image->height);
+ LOGI(" format = %d\n", image->fmt);
+ } else
+ LOGI(" Image_%s : NULL\n", title);
+}
+
+void printDataBlitRect(char *title, struct fimg2d_rect *rect)
+{
+ if (NULL != rect) {
+ LOGI(" RECT_%s\n", title);
+ LOGI(" (x1, y1) = (%d, %d)\n", rect->x1, rect->y1);
+ LOGI(" (x2, y2) = (%d, %d)\n", rect->x2, rect->y2);
+ LOGI(" (width, height) = (%d, %d)\n", rect->x2 - rect->x1, rect->y2 - rect->y1);
+ } else
+ LOGI(" RECT_%s : NULL\n", title);
+}
+
+void printDataBlitRotate(enum rotation rotate)
+{
+ LOGI(" ROTATE : %d\n", rotate);
+}
+
+void printDataBlitClip(struct fimg2d_clip *clip)
+{
+ if (NULL != clip) {
+ LOGI(" CLIP\n");
+ LOGI(" clip %s\n", clip->enable == true ? "enabled" : "disabled");
+ LOGI(" (x1, y1) = (%d, %d)\n", clip->x1, clip->y1);
+ LOGI(" (x2, y2) = (%d, %d)\n", clip->x2, clip->y2);
+ LOGI(" (width, hight) = (%d, %d)\n", clip->x2 - clip->x1, clip->y2 - clip->y1);
+ } else
+ LOGI(" CLIP : NULL\n");
+}
+
+void printDataBlitScale(struct fimg2d_scale *scaling)
+{
+ if (NULL != scaling) {
+ LOGI(" SCALING\n");
+ LOGI(" scale_mode : %s\n", scaling->mode == 0 ?
+ "NO_SCALING" :
+ (scaling->mode == 1 ? "SCALING_NEAREST" : "SCALING_BILINEAR"));
+ LOGI(" scaling_factor_unit : %s\n", scaling->factor == 0 ? "PERCENT" : "PIXEL");
+
+ if (scaling->factor == 0)
+ LOGI(" scaling_factor : (scale_w, scale_y) = (%d, %d)\n", scaling->scale_w, scaling->scale_h);
+ else {
+ LOGI(" src : (src_w, src_h) = (%d, %d)\n", scaling->src_w, scaling->src_h);
+ LOGI(" dst : (dst_w, dst_h) = (%d, %d)\n", scaling->dst_w, scaling->dst_h);
+ LOGI(" scaling_factor : (scale_w, scale_y) = (%3.2f, %3.2f)\n", (double)scaling->dst_w / scaling->src_w, (double)scaling->dst_h / scaling->src_h);
+ }
+ } else
+ LOGI(" SCALING : NULL(NO SCALE MODE)\n");
+
+}
+
+void printDataMatrix(int matrixType)
+{
+ LOGI(" MATRIX\n");
+
+ if (matrixType & SkMatrix::kIdentity_Mask)
+ LOGI(" Matrix_type : Identity_Mask\n");
+
+ if (matrixType & SkMatrix::kTranslate_Mask)
+ LOGI(" Matrix_type : Translate_Mask(the matrix has translation)\n");
+
+ if (matrixType & SkMatrix::kScale_Mask)
+ LOGI(" Matrix_type : Scale_Mask(the matrix has X or Y scale)\n");
+
+ if (matrixType & SkMatrix::kAffine_Mask)
+ LOGI(" Matrix_type : Affine_Mask(the matrix skews or rotates)\n");
+
+ if (matrixType & SkMatrix::kPerspective_Mask)
+ LOGI(" Matrix_type : Perspective_Mask(the matrix is in perspective)\n");
+}
diff --git a/exynos4/hal/libfimg4x/FimgApi.h b/exynos4/hal/libfimg4x/FimgApi.h
new file mode 100644
index 0000000..a2c9eac
--- /dev/null
+++ b/exynos4/hal/libfimg4x/FimgApi.h
@@ -0,0 +1,114 @@
+/*
+**
+** Copyright 2009 Samsung Electronics Co, Ltd.
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
+**
+*/
+
+#ifndef FIMG_API_H
+#define FIMG_API_H
+
+#include <utils/Log.h>
+#include "SkMatrix.h"
+#include "sec_g2d_4x.h"
+
+#define REAL_DEBUG
+#define ANDROID_LOG
+
+#if defined(REAL_DEBUG)
+#ifdef ANDROID_LOG
+#define PRINT LOGE
+#define PRINTD LOGD
+#else
+#define PRINT printf
+#define PRINTD printf
+#endif
+#else
+void VOID_FUNC(const char *format, ...);
+
+#define PRINT VOID_FUNC
+#define PRINTD VOID_FUNC
+#endif
+
+#ifdef __cplusplus
+
+struct blit_op_table {
+ int op;
+ const char *str;
+};
+
+extern struct blit_op_table optbl[];
+
+class FimgApi
+{
+public:
+#endif
+
+#ifdef __cplusplus
+private :
+ bool m_flagCreate;
+
+protected :
+ FimgApi();
+ FimgApi(const FimgApi& rhs) {}
+ virtual ~FimgApi();
+
+public:
+ bool Create(void);
+ bool Destroy(void);
+ inline bool FlagCreate(void) { return m_flagCreate; }
+ bool Stretch(struct fimg2d_blit *cmd);
+ bool Sync(void);
+
+protected:
+ virtual bool t_Create(void);
+ virtual bool t_Destroy(void);
+ virtual bool t_Stretch(struct fimg2d_blit *cmd);
+ virtual bool t_Sync(void);
+ virtual bool t_Lock(void);
+ virtual bool t_UnLock(void);
+
+};
+#endif
+
+#ifdef __cplusplus
+extern "C"
+#endif
+struct FimgApi *createFimgApi();
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void destroyFimgApi(FimgApi *ptrFimgApi);
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int stretchFimgApi(struct fimg2d_blit *cmd);
+#ifdef __cplusplus
+extern "C"
+#endif
+int SyncFimgApi(void);
+
+void printDataBlit(char *title, struct fimg2d_blit *cmd);
+void printDataBlitRotate(enum rotation rotate);
+void printDataBlitImage(char *title, struct fimg2d_image *image);
+void printDataBlitRect(char *title, struct fimg2d_rect *rect);
+void printDataBlitClip(struct fimg2d_clip *clip);
+void printDataBlitScale(struct fimg2d_scale *scaling);
+void printDataMatrix(int matrixType);
+
+#endif //FIMG_API_H
diff --git a/exynos4/hal/libfimg4x/FimgExynos4.cpp b/exynos4/hal/libfimg4x/FimgExynos4.cpp
new file mode 100644
index 0000000..f9a7f1e
--- /dev/null
+++ b/exynos4/hal/libfimg4x/FimgExynos4.cpp
@@ -0,0 +1,302 @@
+/*
+**
+** Copyright 2009 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 "FimgExynos4"
+#include <utils/Log.h>
+
+#include "FimgExynos4.h"
+
+namespace android
+{
+Mutex FimgV4x::m_instanceLock;
+unsigned FimgV4x::m_curFimgV4xIndex = 0;
+int FimgV4x::m_numOfInstance = 0;
+FimgApi * FimgV4x::m_ptrFimgApiList[NUMBER_FIMG_LIST] = {NULL, };
+
+//---------------------------------------------------------------------------//
+
+FimgV4x::FimgV4x()
+ : m_g2dFd(0),
+ m_g2dVirtAddr(NULL),
+ m_g2dSize(0),
+ m_g2dSrcVirtAddr(NULL),
+ m_g2dSrcSize(0),
+ m_g2dDstVirtAddr(NULL),
+ m_g2dDstSize(0)
+{
+ memset(&(m_g2dPoll), 0, sizeof(struct pollfd));
+ m_lock = new Mutex(Mutex::SHARED, "FimgV4x");
+}
+
+FimgV4x::~FimgV4x()
+{
+ delete m_lock;
+}
+
+FimgApi *FimgV4x::CreateInstance()
+{
+ Mutex::Autolock autolock(m_instanceLock);
+
+ FimgApi *ptrFimg = NULL;
+
+ for(unsigned int i = m_curFimgV4xIndex; i < NUMBER_FIMG_LIST; i++) {
+ if (m_ptrFimgApiList[i] == NULL)
+ m_ptrFimgApiList[i] = new FimgV4x;
+
+ if (m_ptrFimgApiList[i]->FlagCreate() == false) {
+ if (m_ptrFimgApiList[i]->Create() == false) {
+ PRINT("%s::Create(%d) fail\n", __func__, i);
+ goto CreateInstance_End;
+ }
+ else
+ m_numOfInstance++;
+ }
+
+ if (i < NUMBER_FIMG_LIST - 1)
+ m_curFimgV4xIndex = i + 1;
+ else
+ m_curFimgV4xIndex = 0;
+
+ ptrFimg = m_ptrFimgApiList[i];
+ goto CreateInstance_End;
+ }
+
+CreateInstance_End :
+
+ return ptrFimg;
+}
+
+void FimgV4x::DestroyInstance(FimgApi * ptrFimgApi)
+{
+ Mutex::Autolock autolock(m_instanceLock);
+
+ for(int i = 0; i < NUMBER_FIMG_LIST; i++) {
+ if (m_ptrFimgApiList[i] != NULL && m_ptrFimgApiList[i] == ptrFimgApi) {
+ if (m_ptrFimgApiList[i]->FlagCreate() == true && m_ptrFimgApiList[i]->Destroy() == false) {
+ PRINT("%s::Destroy() fail\n", __func__);
+ } else {
+ FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i];
+ delete tempFimgV4x;
+ m_ptrFimgApiList[i] = NULL;
+
+ m_numOfInstance--;
+ }
+
+ break;
+ }
+ }
+}
+
+void FimgV4x::DestroyAllInstance(void)
+{
+ Mutex::Autolock autolock(m_instanceLock);
+
+ for(int i = 0; i < NUMBER_FIMG_LIST; i++) {
+ if (m_ptrFimgApiList[i] != NULL) {
+ if (m_ptrFimgApiList[i]->FlagCreate() == true
+ && m_ptrFimgApiList[i]->Destroy() == false) {
+ PRINT("%s::Destroy() fail\n", __func__);
+ } else {
+ FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i];
+ delete tempFimgV4x;
+ m_ptrFimgApiList[i] = NULL;
+ }
+ }
+ }
+}
+
+bool FimgV4x::t_Create(void)
+{
+ bool ret = true;
+
+ if (m_CreateG2D() == false) {
+ PRINT("%s::m_CreateG2D() fail \n", __func__);
+
+ if (m_DestroyG2D() == false)
+ PRINT("%s::m_DestroyG2D() fail \n", __func__);
+
+ ret = false;
+ }
+
+ return ret;
+}
+
+bool FimgV4x::t_Destroy(void)
+{
+ bool ret = true;
+
+ if (m_DestroyG2D() == false) {
+ PRINT("%s::m_DestroyG2D() fail \n", __func__);
+ ret = false;
+ }
+
+ return ret;
+}
+
+bool FimgV4x::t_Stretch(struct fimg2d_blit *cmd)
+{
+#ifdef CHECK_FIMGV4x_PERFORMANCE
+#define NUM_OF_STEP (10)
+ StopWatch stopWatch("CHECK_FIMGV4x_PERFORMANCE");
+ const char *stopWatchName[NUM_OF_STEP];
+ nsecs_t stopWatchTime[NUM_OF_STEP];
+ int stopWatchIndex = 0;
+#endif // CHECK_FIMGV4x_PERFORMANCE
+
+ if (m_DoG2D(cmd) == false) {
+ goto STRETCH_FAIL;
+ }
+
+#ifdef G2D_NONE_BLOCKING_MODE
+ if (m_PollG2D(&m_g2dPoll) == false)
+ {
+ PRINT("%s::m_PollG2D() fail\n", __func__);
+ goto STRETCH_FAIL;
+ }
+#endif
+
+ #ifdef CHECK_FIMGV4x_PERFORMANCE
+ m_PrintFimgV4xPerformance(src, dst, stopWatchIndex, stopWatchName, stopWatchTime);
+ #endif // CHECK_FIMGV4x_PERFORMANCE
+
+ return true;
+
+STRETCH_FAIL:
+ return false;
+
+}
+
+bool FimgV4x::t_Sync(void)
+{
+ if (m_PollG2D(&m_g2dPoll) == false)
+ {
+ PRINT("%s::m_PollG2D() fail\n", __func__);
+ goto SYNC_FAIL;
+ }
+ return true;
+
+SYNC_FAIL:
+ return false;
+
+}
+
+bool FimgV4x::t_Lock(void)
+{
+ m_lock->lock();
+ return true;
+}
+
+bool FimgV4x::t_UnLock(void)
+{
+ m_lock->unlock();
+ return true;
+}
+
+bool FimgV4x::m_CreateG2D(void)
+{
+ void * mmap_base;
+
+ if (m_g2dFd != 0) {
+ PRINT("%s::m_g2dFd(%d) is not 0 fail\n", __func__, m_g2dFd);
+ return false;
+ }
+
+#ifdef G2D_NONE_BLOCKING_MODE
+ m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR | O_NONBLOCK);
+#else
+ m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR);
+#endif
+ if (m_g2dFd < 0) {
+ PRINT("%s::open(%s) fail(%s)\n", __func__, SEC_G2D_DEV_NAME, strerror(errno));
+ m_g2dFd = 0;
+ return false;
+ }
+
+ memset(&m_g2dPoll, 0, sizeof(m_g2dPoll));
+ m_g2dPoll.fd = m_g2dFd;
+ m_g2dPoll.events = POLLOUT | POLLERR;
+
+ return true;
+}
+
+bool FimgV4x::m_DestroyG2D(void)
+{
+ if (m_g2dVirtAddr != NULL) {
+ munmap(m_g2dVirtAddr, m_g2dSize);
+ m_g2dVirtAddr = NULL;
+ m_g2dSize = 0;
+ }
+
+ if (0 < m_g2dFd) {
+ close(m_g2dFd);
+ }
+ m_g2dFd = 0;
+
+ return true;
+}
+
+bool FimgV4x::m_DoG2D(struct fimg2d_blit *cmd)
+{
+
+ if (ioctl(m_g2dFd, FIMG2D_BITBLT_BLIT, cmd) < 0)
+ return false;
+
+ return true;
+}
+
+inline bool FimgV4x::m_PollG2D(struct pollfd * events)
+{
+#define G2D_POLL_TIME (1000)
+
+ int ret;
+
+ ret = poll(events, 1, G2D_POLL_TIME);
+
+ if (ret < 0) {
+ PRINT("%s::poll fail \n", __func__);
+ return false;
+ }
+ else if (ret == 0) {
+ PRINT("%s::No data in %d milli secs..\n", __func__, G2D_POLL_TIME);
+ return false;
+ }
+
+ return true;
+}
+
+//---------------------------------------------------------------------------//
+// extern function
+//---------------------------------------------------------------------------//
+extern "C" struct FimgApi * createFimgApi()
+{
+ if (fimgApiAutoFreeThread == 0)
+ fimgApiAutoFreeThread = new FimgApiAutoFreeThread();
+ else
+ fimgApiAutoFreeThread->SetOneMoreSleep();
+
+ return FimgV4x::CreateInstance();
+}
+
+extern "C" void destroyFimgApi(FimgApi * ptrFimgApi)
+{
+ // Dont' call DestroyInstance.
+}
+
+}; // namespace android
diff --git a/exynos4/hal/libfimg4x/FimgExynos4.h b/exynos4/hal/libfimg4x/FimgExynos4.h
new file mode 100644
index 0000000..2a7c42f
--- /dev/null
+++ b/exynos4/hal/libfimg4x/FimgExynos4.h
@@ -0,0 +1,169 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2009 Samsung Electronics Co, Ltd. All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
+**
+*/
+
+#ifndef FIMG_EXYNOS4_H
+#define FIMG_EXYNOS4_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/android_pmem.h>
+#include <utils/threads.h>
+#include <utils/StopWatch.h>
+
+#include "FimgApi.h"
+
+#include "sec_g2d_4x.h"
+
+namespace android
+{
+
+#define NUMBER_FIMG_LIST (1) // kcoolsw : because of pmem
+#define GET_RECT_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel))
+#define GET_REAL_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel))
+#define GET_START_ADDR(rect) (rect->virt_addr + ((rect->y * rect->full_w) * rect->bytes_per_pixel))
+#define SLEEP_TIME (3000000) // 3 sec
+
+//---------------------------------------------------------------------------//
+// class FimgV4x : public FimgBase
+//---------------------------------------------------------------------------//
+class FimgV4x : public FimgApi
+{
+private :
+ int m_g2dFd;
+
+ unsigned char *m_g2dVirtAddr;
+ unsigned int m_g2dSize;
+ unsigned char *m_g2dSrcVirtAddr;
+ unsigned int m_g2dSrcSize;
+ unsigned char *m_g2dDstVirtAddr;
+ unsigned int m_g2dDstSize;
+ struct pollfd m_g2dPoll;
+
+ Mutex *m_lock;
+
+ static Mutex m_instanceLock;
+ static unsigned m_curFimgV4xIndex;
+ static int m_numOfInstance;
+
+ static FimgApi *m_ptrFimgApiList[NUMBER_FIMG_LIST];
+
+protected :
+ FimgV4x();
+ virtual ~FimgV4x();
+
+public:
+ static FimgApi *CreateInstance();
+ static void DestroyInstance(FimgApi *ptrFimgApi);
+ static void DestroyAllInstance(void);
+
+protected:
+ virtual bool t_Create(void);
+ virtual bool t_Destroy(void);
+ virtual bool t_Stretch(struct fimg2d_blit *cmd);
+ virtual bool t_Sync(void);
+ virtual bool t_Lock(void);
+ virtual bool t_UnLock(void);
+
+private:
+ bool m_CreateG2D(void);
+ bool m_DestroyG2D(void);
+
+ bool m_DoG2D(struct fimg2d_blit *cmd);
+
+ inline bool m_PollG2D(struct pollfd *events);
+
+ inline int m_ColorFormatFimgApi2FimgHw(int colorFormat);
+};
+
+class FimgApiAutoFreeThread;
+
+static sp<FimgApiAutoFreeThread> fimgApiAutoFreeThread = 0;
+
+class FimgApiAutoFreeThread : public Thread
+{
+private:
+ bool mOneMoreSleep;
+ bool mDestroyed;
+
+public:
+ FimgApiAutoFreeThread(void):
+ Thread(false),
+ mOneMoreSleep(true),
+ mDestroyed(false)
+ { }
+ ~FimgApiAutoFreeThread(void)
+ {
+ if (mDestroyed == false)
+ {
+ FimgV4x::DestroyAllInstance();
+ mDestroyed = true;
+ }
+ }
+
+ virtual void onFirstRef()
+ {
+ run("FimgApiAutoFreeThread", PRIORITY_BACKGROUND);
+ }
+
+ virtual bool threadLoop()
+ {
+
+ if (mOneMoreSleep == true)
+ {
+ mOneMoreSleep = false;
+ usleep(SLEEP_TIME);
+
+ return true;
+ }
+ else
+ {
+ if (mDestroyed == false)
+ {
+ FimgV4x::DestroyAllInstance();
+ mDestroyed = true;
+ }
+
+ fimgApiAutoFreeThread = 0;
+
+ return false;
+ }
+ }
+
+ void SetOneMoreSleep(void)
+ {
+ mOneMoreSleep = true;
+ }
+};
+
+}; // namespace android
+
+#endif // FIMG_EXYNOS4_H
diff --git a/exynos4/hal/libfimg4x/sec_g2d_4x.h b/exynos4/hal/libfimg4x/sec_g2d_4x.h
new file mode 100644
index 0000000..b9ddbb2
--- /dev/null
+++ b/exynos4/hal/libfimg4x/sec_g2d_4x.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2011, Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __SEC_G2D_4X_H
+#define __SEC_G2D_4X_H __FILE__
+
+#define SEC_G2D_DEV_NAME "/dev/fimg2d"
+
+/* ioctl commands */
+#define FIMG2D_IOCTL_MAGIC 'F'
+#define FIMG2D_BITBLT_BLIT _IOWR(FIMG2D_IOCTL_MAGIC, 0, struct fimg2d_blit)
+#define FIMG2D_BITBLT_SYNC _IO(FIMG2D_IOCTL_MAGIC, 1)
+#define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version)
+
+#define G2D_ALPHA_VALUE_MAX (255)
+
+enum addr_space {
+ ADDR_UNKNOWN,
+ ADDR_PHYS,
+ ADDR_KERN,
+ ADDR_USER,
+ ADDR_DEVICE,
+};
+
+/**
+ * DO NOT CHANGE THIS ORDER
+ */
+enum pixel_order {
+ AX_RGB = 0,
+ RGB_AX,
+ AX_BGR,
+ BGR_AX,
+ ARGB_ORDER_END,
+
+ P1_CRY1CBY0,
+ P1_CBY1CRY0,
+ P1_Y1CRY0CB,
+ P1_Y1CBY0CR,
+ P1_ORDER_END,
+
+ P2_CRCB,
+ P2_CBCR,
+ P2_ORDER_END,
+};
+
+/**
+ * DO NOT CHANGE THIS ORDER
+ */
+enum color_format {
+ CF_XRGB_8888 = 0,
+ CF_ARGB_8888,
+ CF_RGB_565,
+ CF_XRGB_1555,
+ CF_ARGB_1555,
+ CF_XRGB_4444,
+ CF_ARGB_4444,
+ CF_RGB_888,
+ CF_YCBCR_444,
+ CF_YCBCR_422,
+ CF_YCBCR_420,
+ CF_A8,
+ CF_L8,
+ SRC_DST_FORMAT_END,
+
+ CF_MSK_1BIT,
+ CF_MSK_4BIT,
+ CF_MSK_8BIT,
+ CF_MSK_16BIT_565,
+ CF_MSK_16BIT_1555,
+ CF_MSK_16BIT_4444,
+ CF_MSK_32BIT_8888,
+ MSK_FORMAT_END,
+};
+
+enum rotation {
+ ORIGIN,
+ ROT_90, /* clockwise */
+ ROT_180,
+ ROT_270,
+ XFLIP, /* x-axis flip */
+ YFLIP, /* y-axis flip */
+};
+
+/**
+ * @NO_REPEAT: no effect
+ * @REPEAT_NORMAL: repeat horizontally and vertically
+ * @REPEAT_PAD: pad with pad color
+ * @REPEAT_REFLECT: reflect horizontally and vertically
+ * @REPEAT_CLAMP: pad with edge color of original image
+ *
+ * DO NOT CHANGE THIS ORDER
+ */
+enum repeat {
+ NO_REPEAT = 0,
+ REPEAT_NORMAL, /* default setting */
+ REPEAT_PAD,
+ REPEAT_REFLECT, REPEAT_MIRROR = REPEAT_REFLECT,
+ REPEAT_CLAMP,
+};
+
+enum scaling {
+ NO_SCALING,
+ SCALING_NEAREST,
+ SCALING_BILINEAR,
+};
+
+/**
+ * @SCALING_PERCENTAGE: percentage of width, height
+ * @SCALING_PIXELS: coordinate of src, dest
+ */
+enum scaling_factor {
+ SCALING_PERCENTAGE,
+ SCALING_PIXELS,
+};
+
+/**
+ * premultiplied alpha
+ */
+enum premultiplied {
+ PREMULTIPLIED,
+ NON_PREMULTIPLIED,
+};
+
+/**
+ * @TRANSP: discard bluescreen color
+ * @BLUSCR: replace bluescreen color with background color
+ */
+enum bluescreen {
+ OPAQUE,
+ TRANSP,
+ BLUSCR,
+};
+
+/**
+ * DO NOT CHANGE THIS ORDER
+ */
+enum blit_op {
+ BLIT_OP_SOLID_FILL = 0,
+
+ BLIT_OP_CLR,
+ BLIT_OP_SRC, BLIT_OP_SRC_COPY = BLIT_OP_SRC,
+ BLIT_OP_DST,
+ BLIT_OP_SRC_OVER,
+ BLIT_OP_DST_OVER, BLIT_OP_OVER_REV = BLIT_OP_DST_OVER,
+ BLIT_OP_SRC_IN,
+ BLIT_OP_DST_IN, BLIT_OP_IN_REV = BLIT_OP_DST_IN,
+ BLIT_OP_SRC_OUT,
+ BLIT_OP_DST_OUT, BLIT_OP_OUT_REV = BLIT_OP_DST_OUT,
+ BLIT_OP_SRC_ATOP,
+ BLIT_OP_DST_ATOP, BLIT_OP_ATOP_REV = BLIT_OP_DST_ATOP,
+ BLIT_OP_XOR,
+
+ BLIT_OP_ADD,
+ BLIT_OP_MULTIPLY,
+ BLIT_OP_SCREEN,
+ BLIT_OP_DARKEN,
+ BLIT_OP_LIGHTEN,
+
+ BLIT_OP_DISJ_SRC_OVER,
+ BLIT_OP_DISJ_DST_OVER, BLIT_OP_SATURATE = BLIT_OP_DISJ_DST_OVER,
+ BLIT_OP_DISJ_SRC_IN,
+ BLIT_OP_DISJ_DST_IN, BLIT_OP_DISJ_IN_REV = BLIT_OP_DISJ_DST_IN,
+ BLIT_OP_DISJ_SRC_OUT,
+ BLIT_OP_DISJ_DST_OUT, BLIT_OP_DISJ_OUT_REV = BLIT_OP_DISJ_DST_OUT,
+ BLIT_OP_DISJ_SRC_ATOP,
+ BLIT_OP_DISJ_DST_ATOP, BLIT_OP_DISJ_ATOP_REV = BLIT_OP_DISJ_DST_ATOP,
+ BLIT_OP_DISJ_XOR,
+
+ BLIT_OP_CONJ_SRC_OVER,
+ BLIT_OP_CONJ_DST_OVER, BLIT_OP_CONJ_OVER_REV = BLIT_OP_CONJ_DST_OVER,
+ BLIT_OP_CONJ_SRC_IN,
+ BLIT_OP_CONJ_DST_IN, BLIT_OP_CONJ_IN_REV = BLIT_OP_CONJ_DST_IN,
+ BLIT_OP_CONJ_SRC_OUT,
+ BLIT_OP_CONJ_DST_OUT, BLIT_OP_CONJ_OUT_REV = BLIT_OP_CONJ_DST_OUT,
+ BLIT_OP_CONJ_SRC_ATOP,
+ BLIT_OP_CONJ_DST_ATOP, BLIT_OP_CONJ_ATOP_REV = BLIT_OP_CONJ_DST_ATOP,
+ BLIT_OP_CONJ_XOR,
+
+ /* Add new operation type here */
+
+ /* user select coefficient manually */
+ BLIT_OP_USER_COEFF,
+
+ /* end of blit operation */
+ BLIT_OP_END,
+
+ /* driver not supporting format */
+ BLIT_OP_NOT_SUPPORTED
+};
+
+#define MAX_FIMG2D_BLIT_OP (int)BLIT_OP_END
+
+struct fimg2d_version {
+ unsigned int hw;
+ unsigned int sw;
+};
+
+/**
+ * @start: start address or unique id of image
+ * @size: whole length of allocated image
+ * @cacheable: memory is cacheable
+ * @pinnable: memory is pinnable. currently not supported.
+ */
+struct fimg2d_addr {
+ enum addr_space type;
+ unsigned long start;
+ size_t size;
+ int cacheable;
+ int pinnable;
+};
+
+struct fimg2d_rect {
+ int x1;
+ int y1;
+ int x2; /* x1 + width */
+ int y2; /* y1 + height */
+};
+
+/**
+ * if factor is percentage, scale_w and scale_h are valid
+ * if factor is pixels, src_w, src_h, dst_w, dst_h are valid
+ */
+struct fimg2d_scale {
+ enum scaling mode;
+ enum scaling_factor factor;
+
+ /* percentage */
+ int scale_w;
+ int scale_h;
+
+ /* pixels */
+ int src_w, src_h;
+ int dst_w, dst_h;
+};
+
+/**
+ * coordinate from start address(0,0) of image
+ */
+struct fimg2d_clip {
+ bool enable;
+ int x1;
+ int y1;
+ int x2; /* x1 + width */
+ int y2; /* y1 + height */
+};
+
+struct fimg2d_repeat {
+ enum repeat mode;
+ unsigned long pad_color;
+};
+
+/**
+ * @bg_color: bg_color is valid only if bluescreen mode is BLUSCR.
+ */
+struct fimg2d_bluscr {
+ enum bluescreen mode;
+ unsigned long bs_color;
+ unsigned long bg_color;
+};
+
+/**
+ * @plane2: address info for CbCr in YCbCr 2plane mode
+ */
+struct fimg2d_image {
+ struct fimg2d_addr addr;
+ struct fimg2d_addr plane2;
+ int width;
+ int height;
+ int stride;
+ enum pixel_order order;
+ enum color_format fmt;
+};
+
+struct fimg2d_param {
+ enum blit_op op;
+ unsigned long fillcolor;
+ unsigned char g_alpha;
+ enum premultiplied premult;
+ bool dither;
+ enum rotation rotate;
+ struct fimg2d_scale *scaling;
+ struct fimg2d_repeat *repeat;
+ struct fimg2d_bluscr *bluscr;
+ struct fimg2d_clip *clipping;
+};
+
+/**
+ * @g_alpha: 0xff is opaque, 0x0 is transparnet
+ * @seq_no: used for debugging
+ */
+struct fimg2d_blit {
+ enum blit_op op;
+
+ enum premultiplied premult;
+ unsigned char g_alpha;
+ bool dither;
+ enum rotation rotate;
+ struct fimg2d_scale *scaling;
+ struct fimg2d_repeat *repeat;
+ struct fimg2d_bluscr *bluscr;
+ struct fimg2d_clip *clipping;
+
+ unsigned long solid_color;
+ struct fimg2d_image *src;
+ struct fimg2d_image *dst;
+ struct fimg2d_image *msk;
+
+ struct fimg2d_rect *src_rect;
+ struct fimg2d_rect *dst_rect;
+ struct fimg2d_rect *msk_rect;
+
+ unsigned int seq_no;
+};
+#endif /* __SEC_G2D_4X_H__ */
diff --git a/exynos4/hal/libgralloc_ump/Android.mk b/exynos4/hal/libgralloc_ump/Android.mk
new file mode 100644
index 0000000..20584a4
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/Android.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2010 ARM Limited. All rights reserved.
+#
+# Portions of this code have been modified from the original.
+# These modifications are:
+# * The build configuration for the Gralloc module
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libUMP libGLESv1_CM libion
+
+# Include the UMP header files
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES := \
+ gralloc_module.cpp \
+ alloc_device.cpp \
+ framebuffer_device.cpp
+
+LOCAL_MODULE_TAGS := eng
+#LOCAL_MODULE := gralloc.default
+LOCAL_MODULE := gralloc.$(TARGET_DEVICE)
+LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -DGRALLOC_32_BITS -DSTANDARD_LINUX_SCREEN
+#LOCAL_CFLAGS+= -DMALI_VSYNC_EVENT_REPORT_ENABLE
+
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS_CACHE_UMP
+
+ifeq ($(TARGET_SOC),exynos4210)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos4/hal/libgralloc_ump/alloc_device.cpp b/exynos4/hal/libgralloc_ump/alloc_device.cpp
new file mode 100644
index 0000000..982f1b8
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/alloc_device.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * gralloc_alloc_buffer()
+ * * gralloc_alloc_framebuffer_locked()
+ * * gralloc_alloc_framebuffer()
+ * * alloc_device_alloc()
+ * * alloc_device_free()
+ * * alloc_device_close()
+ * * alloc_device_open()
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include "sec_format.h"
+
+#include "gralloc_priv.h"
+#include "gralloc_helper.h"
+#include "framebuffer_device.h"
+
+#include "ump.h"
+#include "ump_ref_drv.h"
+
+/*****************************************************************************/
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#include <pixelflinger/format.h>
+#endif
+
+#include "videodev2.h"
+#include "s5p_fimc.h"
+
+#ifdef SAMSUNG_EXYNOS4x12
+#define PFX_NODE_FIMC1 "/dev/video3"
+#endif
+#ifdef SAMSUNG_EXYNOS4210
+#define PFX_NODE_FIMC1 "/dev/video1"
+#endif
+
+#ifndef OMX_COLOR_FormatYUV420Planar
+#define OMX_COLOR_FormatYUV420Planar 0x13
+#endif
+
+#ifndef OMX_COLOR_FormatYUV420SemiPlanar
+#define OMX_COLOR_FormatYUV420SemiPlanar 0x15
+#endif
+
+bool ion_dev_open = true;
+static pthread_mutex_t l_surface= PTHREAD_MUTEX_INITIALIZER;
+static int buffer_offset = 0;
+static int gfd = 0;
+
+#ifdef USE_PARTIAL_FLUSH
+extern struct private_handle_rect *rect_list;
+extern private_handle_rect *find_rect(int secure_id);
+extern private_handle_rect *find_last_rect(int secure_id);
+extern int release_rect(int secure_id);
+#endif
+
+#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
+
+static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage,
+ buffer_handle_t* pHandle, int w, int h,
+ int format, int bpp, int stride_raw, int stride)
+{
+ ump_handle ump_mem_handle;
+ void *cpu_ptr;
+ ump_secure_id ump_id;
+
+ size = round_up_to_page_size(size);
+ if (usage & GRALLOC_USAGE_HW_FIMC1) {
+ int dev_fd=0;
+ char node[20];
+ int ret;
+ int paddr=0;
+ int offset=0;
+
+ struct v4l2_control vc;
+ sprintf(node, "%s", PFX_NODE_FIMC1);
+
+ if (gfd == 0) {
+ gfd = open(node, O_RDWR);
+
+ if (gfd < 0) {
+ LOGE("%s:: %s Post processor open error\n", __func__, node);
+ return false;
+ }
+ }
+
+ vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR;
+ vc.value = 0;
+ ret = ioctl(gfd, VIDIOC_G_CTRL, &vc);
+ if (ret < 0) {
+ LOGE("Error in video VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR (%d)\n", ret);
+ return false;
+ }
+ paddr = (unsigned int)vc.value;
+
+ if ((buffer_offset + size) >= FIMC1_RESERVED_SIZE * 1024)
+ buffer_offset = 0;
+
+ paddr += buffer_offset;
+ private_handle_t* hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_IOCTL, size, 0,
+ private_handle_t::LOCK_STATE_MAPPED, 0, 0);
+
+ *pHandle = hnd;
+ hnd->format = format;
+ hnd->usage = usage;
+ hnd->width = w;
+ hnd->height = h;
+ hnd->bpp = bpp;
+ hnd->paddr = paddr;
+ hnd->offset = buffer_offset;
+ hnd->stride = stride;
+ hnd->fd = gfd;
+ hnd->uoffset = (EXYNOS4_ALIGN((EXYNOS4_ALIGN(hnd->width, 16) * EXYNOS4_ALIGN(hnd->height, 16)), 4096));
+ hnd->voffset = (EXYNOS4_ALIGN((EXYNOS4_ALIGN((hnd->width >> 1), 16) * EXYNOS4_ALIGN((hnd->height >> 1), 16)), 4096));
+ buffer_offset += size;
+
+ return 0;
+ } else {
+ ion_buffer ion_fd = 0;
+ unsigned int ion_flags = 0;
+ int priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_UMP;
+
+ if (usage & GRALLOC_USAGE_HW_ION) {
+ if (!ion_dev_open) {
+ LOGE("ERROR, failed to open ion");
+ return -1;
+ }
+
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ ion_flags = ION_HEAP_EXYNOS_MASK;
+ ion_fd = ion_alloc(m->ion_client, size, 0, ion_flags);
+
+ if (ion_fd < 0) {
+ LOGE("Failed to ion_alloc");
+ return -1;
+ }
+
+ cpu_ptr = ion_map(ion_fd, size, 0);
+
+ if (NULL == cpu_ptr) {
+ LOGE("Failed to ion_map");
+ ion_free(ion_fd);
+ return -1;
+ }
+
+ ump_mem_handle = ump_ref_drv_ion_import(ion_fd, UMP_REF_DRV_CONSTRAINT_NONE);
+
+ if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) {
+ priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_ION;
+ } else {
+ LOGE("gralloc_alloc_buffer() failed to import ION memory");
+ ion_unmap(cpu_ptr, size);
+ ion_free(ion_fd);
+ return -1;
+ }
+ }
+#ifdef SAMSUNG_EXYNOS_CACHE_UMP
+ else if ((usage&GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
+ ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_USE_CACHE);
+ else
+ ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_NONE);
+#else
+ else
+ ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_NONE);
+#endif
+ if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) {
+ if (!(usage & GRALLOC_USAGE_HW_ION))
+ cpu_ptr = ump_mapped_pointer_get(ump_mem_handle);
+ if (NULL != cpu_ptr) {
+ ump_id = ump_secure_id_get(ump_mem_handle);
+ if (UMP_INVALID_SECURE_ID != ump_id) {
+ private_handle_t* hnd;
+ hnd = new private_handle_t(priv_alloc_flag, size, (int)cpu_ptr,
+ private_handle_t::LOCK_STATE_MAPPED, ump_id, ump_mem_handle, ion_fd, 0, 0);
+ if (NULL != hnd) {
+ *pHandle = hnd;
+#ifdef USE_PARTIAL_FLUSH
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+ private_handle_rect *psRect;
+ private_handle_rect *psFRect;
+ psRect = (private_handle_rect *)calloc(1, sizeof(private_handle_rect));
+ psRect->handle = (int)hnd->ump_id;
+ psRect->stride = (int)hnd->stride_raw;
+ psFRect = find_last_rect((int)hnd->ump_id);
+ psFRect->next = psRect;
+ }
+#endif
+ hnd->format = format;
+ hnd->usage = usage;
+ hnd->width = w;
+ hnd->height = h;
+ hnd->bpp = bpp;
+ hnd->stride = stride;
+ hnd->uoffset = ((EXYNOS4_ALIGN(hnd->width, 16) * EXYNOS4_ALIGN(hnd->height, 16)));
+ hnd->voffset = ((EXYNOS4_ALIGN((hnd->width >> 1), 16) * EXYNOS4_ALIGN((hnd->height >> 1), 16)));
+ return 0;
+ } else {
+ LOGE("gralloc_alloc_buffer() failed to allocate handle");
+ }
+ } else {
+ LOGE("gralloc_alloc_buffer() failed to retrieve valid secure id");
+ }
+
+ ump_mapped_pointer_release(ump_mem_handle);
+ } else {
+ LOGE("gralloc_alloc_buffer() failed to map UMP memory");
+ }
+
+ ump_reference_release(ump_mem_handle);
+ } else {
+ LOGE("gralloc_alloc_buffer() failed to allcoate UMP memory");
+ }
+ }
+ return -1;
+}
+
+static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage,
+ buffer_handle_t* pHandle, int w, int h,
+ int format, int bpp)
+{
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ /* allocate the framebuffer */
+ if (m->framebuffer == NULL) {
+ /* initialize the framebuffer, the framebuffer is mapped once and forever. */
+ int err = init_frame_buffer_locked(m);
+ if (err < 0)
+ return err;
+ }
+
+ const uint32_t bufferMask = m->bufferMask;
+ const uint32_t numBuffers = m->numBuffers;
+ const size_t bufferSize = m->finfo.line_length * m->info.yres;
+ if (numBuffers == 1) {
+ /*
+ * If we have only one buffer, we never use page-flipping. Instead,
+ * we return a regular buffer which will be memcpy'ed to the main
+ * screen when post is called.
+ */
+ int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
+ LOGE("fallback to single buffering");
+ return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle, w, h, format, bpp, 0, 0);
+ }
+
+ if (bufferMask >= ((1LU<<numBuffers)-1))
+ return -ENOMEM;
+
+ int vaddr = m->framebuffer->base;
+ /* find a free slot */
+ for (uint32_t i = 0; i < numBuffers; i++) {
+ if ((bufferMask & (1LU<<i)) == 0) {
+ m->bufferMask |= (1LU<<i);
+ break;
+ }
+ vaddr += bufferSize;
+ }
+
+ /*
+ * The entire framebuffer memory is already mapped,
+ * now create a buffer object for parts of this memory
+ */
+ private_handle_t* hnd = new private_handle_t
+ (private_handle_t::PRIV_FLAGS_FRAMEBUFFER, size, vaddr,
+ 0, dup(m->framebuffer->fd), vaddr - m->framebuffer->base);
+
+ hnd->format = format;
+ hnd->usage = usage;
+ hnd->width = w;
+ hnd->height = h;
+ hnd->bpp = bpp;
+
+ *pHandle = hnd;
+
+ return 0;
+}
+
+static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage,
+ buffer_handle_t* pHandle, int w, int h,
+ int format, int bpp)
+{
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ pthread_mutex_lock(&m->lock);
+ int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle, w, h, format, bpp);
+ pthread_mutex_unlock(&m->lock);
+ return err;
+}
+
+static int alloc_device_alloc(alloc_device_t* dev, int w, int h, int format,
+ int usage, buffer_handle_t* pHandle, int* pStride)
+{
+ if (!pHandle || !pStride)
+ return -EINVAL;
+
+ size_t size = 0;
+ size_t stride = 0;
+ size_t stride_raw = 0;
+
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP ||
+ format == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
+ format == HAL_PIXEL_FORMAT_YCbCr_422_SP ||
+ format == HAL_PIXEL_FORMAT_YCbCr_420_P ||
+ format == HAL_PIXEL_FORMAT_YV12 ||
+ format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP ||
+ format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED ||
+ format == GGL_PIXEL_FORMAT_L_8 ||
+ format == OMX_COLOR_FormatYUV420Planar ||
+ format == OMX_COLOR_FormatYUV420SemiPlanar) {
+ /* FIXME: there is no way to return the vstride */
+ int vstride;
+ stride = (w + 15) & ~15;
+ vstride = (h + 15) & ~15;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ size = stride * vstride * 2;
+ if(usage & GRALLOC_USAGE_HW_FIMC1)
+ size += PAGE_SIZE * 2;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ size = (stride * vstride) + (w/2 * h/2) * 2;
+ break;
+ case GGL_PIXEL_FORMAT_L_8:
+ size = (stride * vstride);
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ int align = 8;
+ int bpp = 0;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ bpp = 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ bpp = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ size_t bpr = (w*bpp + (align-1)) & ~(align-1);
+ size = bpr * h;
+ stride = bpr / bpp;
+ stride_raw = bpr;
+ }
+
+ int err;
+ pthread_mutex_lock(&l_surface);
+ if (usage & GRALLOC_USAGE_HW_FB)
+ err = gralloc_alloc_framebuffer(dev, size, usage, pHandle, w, h, format, 32);
+ else
+ err = gralloc_alloc_buffer(dev, size, usage, pHandle, w, h, format, 0, (int)stride_raw, (int)stride);
+
+ pthread_mutex_unlock(&l_surface);
+
+ if (err < 0)
+ return err;
+
+ *pStride = stride;
+ return 0;
+}
+
+static int alloc_device_free(alloc_device_t* dev, buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ pthread_mutex_lock(&l_surface);
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ /* free this buffer */
+ const size_t bufferSize = m->finfo.line_length * m->info.yres;
+ int index = (hnd->base - m->framebuffer->base) / bufferSize;
+ m->bufferMask &= ~(1<<index);
+ close(hnd->fd);
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+#ifdef USE_PARTIAL_FLUSH
+ if (!release_rect((int)hnd->ump_id))
+ LOGE("secure id: 0x%x, release error",(int)hnd->ump_id);
+#endif
+ ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+#ifdef USE_PARTIAL_FLUSH
+ if (!release_rect((int)hnd->ump_id))
+ LOGE("secure id: 0x%x, release error",(int)hnd->ump_id);
+#endif
+ ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+
+ ion_unmap((void*)hnd->base, hnd->size);
+ ion_free(hnd->fd);
+ }
+ pthread_mutex_unlock(&l_surface);
+ delete hnd;
+
+ return 0;
+}
+
+static int alloc_device_close(struct hw_device_t *device)
+{
+ alloc_device_t* dev = reinterpret_cast<alloc_device_t*>(device);
+ if (dev) {
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ if (ion_dev_open)
+ ion_client_destroy(m->ion_client);
+ delete dev;
+ ump_close();
+ }
+ return 0;
+}
+
+int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
+{
+ alloc_device_t *dev;
+
+ dev = new alloc_device_t;
+ if (NULL == dev)
+ return -1;
+
+ dev->common.module = const_cast<hw_module_t*>(module);
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+ m->ion_client = ion_client_create();
+ ump_result ump_res = ump_open();
+ if (0 > m->ion_client)
+ ion_dev_open = false;
+ if (UMP_OK != ump_res) {
+ LOGE("UMP open failed ump_res %d", ump_res);
+ delete dev;
+ return -1;
+ }
+
+ /* initialize our state here */
+ memset(dev, 0, sizeof(*dev));
+
+ /* initialize the procs */
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = const_cast<hw_module_t*>(module);
+ dev->common.close = alloc_device_close;
+ dev->alloc = alloc_device_alloc;
+ dev->free = alloc_device_free;
+
+ *device = &dev->common;
+
+ return 0;
+}
diff --git a/exynos4/hal/libgralloc_ump/alloc_device.h b/exynos4/hal/libgralloc_ump/alloc_device.h
new file mode 100644
index 0000000..4609787
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/alloc_device.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * alloc_device_open()
+ *
+ * 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.
+ */
+
+#include <hardware/hardware.h>
+
+// Create an alloc device
+int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device);
diff --git a/exynos4/hal/libgralloc_ump/framebuffer_device.cpp b/exynos4/hal/libgralloc_ump/framebuffer_device.cpp
new file mode 100644
index 0000000..9413112
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/framebuffer_device.cpp
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * enums
+ * * fb_set_swap_interval()
+ * * fb_post()
+ * * init_frame_buffer_locked()
+ * * init_frame_buffer()
+ * * fb_close()
+ * * framebuffer_device_open()
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <stdlib.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <GLES/gl.h>
+
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+#include "gralloc_vsync_report.h"
+#endif
+
+#include "gralloc_priv.h"
+#include "gralloc_helper.h"
+
+#include "linux/fb.h"
+
+/* numbers of buffers for page flipping */
+#define NUM_BUFFERS 2
+
+enum {
+ PAGE_FLIP = 0x00000001,
+};
+
+static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval)
+{
+ if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
+ return -EINVAL;
+
+ /* Currently not implemented */
+ return 0;
+}
+
+static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
+{
+ if (private_handle_t::validate(buffer) < 0)
+ return -EINVAL;
+
+ private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+
+ if (m->currentBuffer) {
+ m->base.unlock(&m->base, m->currentBuffer);
+ m->currentBuffer = 0;
+ }
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
+ 0, 0, m->info.xres, m->info.yres, NULL);
+
+ const size_t offset = hnd->base - m->framebuffer->base;
+ int interrupt;
+ m->info.activate = FB_ACTIVATE_VBL;
+ m->info.yoffset = offset / m->finfo.line_length;
+
+#ifdef STANDARD_LINUX_SCREEN
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int)
+ if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1) {
+ LOGE("FBIOPAN_DISPLAY failed");
+ m->base.unlock(&m->base, buffer);
+ return 0;
+ }
+
+ if (m->enableVSync) {
+ /* enable VSYNC */
+ interrupt = 1;
+ if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) {
+ LOGE("S3CFB_SET_VSYNC_INT enable failed");
+ return 0;
+ }
+ /* wait for VSYNC */
+
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);
+#endif
+ int crtc;
+ crtc = 0;
+ if (ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) {
+ LOGE("FBIO_WAITFORVSYNC failed");
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
+#endif
+ return 0;
+ }
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
+#endif
+ // disable VSYNC
+ interrupt = 0;
+ if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) {
+ LOGE("S3CFB_SET_VSYNC_INT disable failed");
+ return 0;
+ }
+#else
+ /*Standard Android way*/
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);
+#endif
+ if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+ LOGE("FBIOPUT_VSCREENINFO failed");
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
+#endif
+ m->base.unlock(&m->base, buffer);
+ return -errno;
+ }
+#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
+ gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
+#endif
+#endif
+ }
+ m->currentBuffer = buffer;
+ } else {
+ /*
+ * If we can't do the page_flip, just copy the buffer to the front
+ * FIXME: use copybit HAL instead of memcpy
+ */
+ void* fb_vaddr;
+ void* buffer_vaddr;
+
+ m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY,
+ 0, 0, m->info.xres, m->info.yres, &fb_vaddr);
+
+ m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY,
+ 0, 0, m->info.xres, m->info.yres, &buffer_vaddr);
+
+ memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
+
+ m->base.unlock(&m->base, buffer);
+ m->base.unlock(&m->base, m->framebuffer);
+ }
+ return 0;
+}
+
+int init_frame_buffer_locked(struct private_module_t* module)
+{
+ /* Nothing to do, already initialized */
+ if (module->framebuffer)
+ return 0;
+
+ char const * const device_template[] = {
+ "/dev/graphics/fb%u",
+ "/dev/fb%u",
+ NULL
+ };
+
+ 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)
+ return -errno;
+
+ struct fb_fix_screeninfo finfo;
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+ return -errno;
+
+ struct fb_var_screeninfo info;
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+ return -errno;
+
+ info.reserved[0] = 0;
+ info.reserved[1] = 0;
+ info.reserved[2] = 0;
+ info.xoffset = 0;
+ info.yoffset = 0;
+ info.activate = FB_ACTIVATE_NOW;
+
+#ifdef GRALLOC_16_BITS
+ /*
+ * Explicitly request 5/6/5
+ */
+ info.bits_per_pixel = 16;
+ info.red.offset = 11;
+ info.red.length = 5;
+ info.green.offset = 5;
+ info.green.length = 6;
+ info.blue.offset = 0;
+ info.blue.length = 5;
+ info.transp.offset = 0;
+ info.transp.length = 0;
+#else
+ /*
+ * Explicitly request 8/8/8
+ */
+ info.bits_per_pixel = 32;
+ info.red.offset = 16;
+ info.red.length = 8;
+ info.green.offset = 8;
+ info.green.length = 8;
+ info.blue.offset = 0;
+ info.blue.length = 8;
+ info.transp.offset = 0;
+ info.transp.length = 0;
+#endif
+
+ /*
+ * Request NUM_BUFFERS screens (at lest 2 for page flipping)
+ */
+ info.yres_virtual = info.yres * NUM_BUFFERS;
+
+ uint32_t flags = PAGE_FLIP;
+ if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
+ info.yres_virtual = info.yres;
+ flags &= ~PAGE_FLIP;
+ LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
+ }
+
+ if (info.yres_virtual < info.yres * 2) {
+ // we need at least 2 for page-flipping
+ info.yres_virtual = info.yres;
+ flags &= ~PAGE_FLIP;
+ LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+ info.yres_virtual, info.yres * 2);
+ }
+
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+ return -errno;
+
+ int refreshRate = 1000000000000000LLU /
+ (
+ uint64_t( info.upper_margin + info.lower_margin + info.yres )
+ * ( info.left_margin + info.right_margin + info.xres )
+ * info.pixclock
+ );
+
+ if (refreshRate == 0)
+ refreshRate = 60 * 1000; /* 60 Hz */
+
+ if (int(info.width) <= 0 || int(info.height) <= 0) {
+ /* the driver doesn't return that information. default to 160 dpi */
+ info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
+ info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+ }
+
+ float xdpi = (info.xres * 25.4f) / info.width;
+ float ydpi = (info.yres * 25.4f) / info.height;
+ float fps = refreshRate / 1000.0f;
+
+ LOGI("using (fd=%d)\n"
+ "id = %s\n"
+ "xres = %d px\n"
+ "yres = %d px\n"
+ "xres_virtual = %d px\n"
+ "yres_virtual = %d px\n"
+ "bpp = %d\n"
+ "r = %2u:%u\n"
+ "g = %2u:%u\n"
+ "b = %2u:%u\n",
+ fd,
+ finfo.id,
+ info.xres,
+ info.yres,
+ info.xres_virtual,
+ info.yres_virtual,
+ info.bits_per_pixel,
+ info.red.offset, info.red.length,
+ info.green.offset, info.green.length,
+ info.blue.offset, info.blue.length);
+
+ LOGI("width = %d mm (%f dpi)\n"
+ "height = %d mm (%f dpi)\n"
+ "refresh rate = %.2f Hz\n",
+ info.width, xdpi,
+ info.height, ydpi,
+ fps);
+
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+ return -errno;
+
+ if (finfo.smem_len <= 0)
+ return -errno;
+
+ module->flags = flags;
+ module->info = info;
+ module->finfo = finfo;
+ module->xdpi = xdpi;
+ module->ydpi = ydpi;
+ module->fps = fps;
+
+ char value[32];
+ property_get("debug.gralloc.vsync", value, "1");
+ module->enableVSync = atoi(value);
+ /*
+ * map the framebuffer
+ */
+ size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
+ void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (vaddr == MAP_FAILED) {
+ LOGE("Error mapping the framebuffer (%s)", strerror(errno));
+ return -errno;
+ }
+
+ memset(vaddr, 0, fbSize);
+
+ /*
+ * Create a "fake" buffer object for the entire frame buffer memory,
+ * and store it in the module
+ */
+ module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
+ fbSize, intptr_t(vaddr), 0, dup(fd), 0);
+
+ module->numBuffers = info.yres_virtual / info.yres;
+ module->bufferMask = 0;
+
+ return 0;
+}
+
+int enableScreen(struct framebuffer_device_t* dev, int enable)
+{
+ private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
+
+ if (enable == 1) {
+ if (ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+ LOGE("%s: FBIOBLANK failed : (%d:%s)",
+ __func__, m->framebuffer->fd, strerror(errno));
+ return -EINVAL;
+ }
+ } else if (enable == 0) {
+ if (ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+ LOGE("%s: FBIOBLANK failed : (%d:%s)",
+ __func__, m->framebuffer->fd, strerror(errno));
+ return -EINVAL;
+ }
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
+static int init_frame_buffer(struct private_module_t* module)
+{
+ pthread_mutex_lock(&module->lock);
+ int err = init_frame_buffer_locked(module);
+ pthread_mutex_unlock(&module->lock);
+ return err;
+}
+
+static int fb_close(struct hw_device_t *device)
+{
+ framebuffer_device_t* dev = reinterpret_cast<framebuffer_device_t*>(device);
+ if (dev) {
+ ump_close();
+ delete dev;
+ }
+ return 0;
+}
+
+int compositionComplete(struct framebuffer_device_t* dev)
+{
+#ifndef HWC_HWOVERLAY
+ unsigned char pixels[4];
+ /* By doing a readpixel here we force the GL driver to start rendering
+ all the drawcalls up to this point, and to wait for the rendering to be complete.
+ Readpixel() also reads a dummy pixel, but this is not used. We only use this
+ function here to flush the render pipeline. */
+ glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ /* The rendering of the backbuffer is now completed.
+ When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done
+ synchronously in the same thread, and not asynchronoulsy in a background thread later.
+ The SurfaceFlinger requires this behaviour since it releases the lock on all the
+ SourceBuffers (Layers) after the compositionComplete() function returns.
+ However this "bad" behaviour by SurfaceFlinger should not affect performance,
+ since the Applications that render the SourceBuffers (Layers) still get the
+ full renderpipeline using asynchronouls rendering. So they perform at maximum speed,
+ and because of their complexity compared to the Surface flinger jobs, the Surface flinger
+ is normally faster even if it does everyhing synchronous and serial.
+ */
+#endif
+ return 0;
+}
+
+int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
+{
+ int status = -EINVAL;
+
+ alloc_device_t* gralloc_device;
+ status = gralloc_open(module, &gralloc_device);
+ if (status < 0)
+ return status;
+
+ private_module_t* m = (private_module_t*)module;
+ status = init_frame_buffer(m);
+ if (status < 0) {
+ gralloc_close(gralloc_device);
+ return status;
+ }
+
+ /* initialize our state here */
+ framebuffer_device_t *dev = new framebuffer_device_t;
+ memset(dev, 0, sizeof(*dev));
+
+ /* initialize the procs */
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = const_cast<hw_module_t*>(module);
+ dev->common.close = fb_close;
+ dev->setSwapInterval = fb_set_swap_interval;
+ dev->post = fb_post;
+ dev->setUpdateRect = 0;
+ dev->compositionComplete = &compositionComplete;
+ dev->enableScreen = &enableScreen;
+
+ int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
+ const_cast<uint32_t&>(dev->flags) = 0;
+ const_cast<uint32_t&>(dev->width) = m->info.xres;
+ const_cast<uint32_t&>(dev->height) = m->info.yres;
+ const_cast<int&>(dev->stride) = stride;
+#ifdef GRALLOC_16_BITS
+ const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
+#else
+ const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888;
+#endif
+ const_cast<float&>(dev->xdpi) = m->xdpi;
+ const_cast<float&>(dev->ydpi) = m->ydpi;
+ const_cast<float&>(dev->fps) = m->fps;
+ const_cast<int&>(dev->minSwapInterval) = 1;
+ const_cast<int&>(dev->maxSwapInterval) = 1;
+ *device = &dev->common;
+ status = 0;
+
+ return status;
+}
diff --git a/exynos4/hal/libgralloc_ump/framebuffer_device.h b/exynos4/hal/libgralloc_ump/framebuffer_device.h
new file mode 100644
index 0000000..efcf1c3
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/framebuffer_device.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * framebuffer_device_open()
+ * * init_frame_buffer_locked()
+ *
+ * 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.
+ */
+
+#include <hardware/hardware.h>
+
+// Create a framebuffer device
+int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device);
+
+// Initialize the framebuffer (must keep module lock before calling
+int init_frame_buffer_locked(struct private_module_t* module); \ No newline at end of file
diff --git a/exynos4/hal/libgralloc_ump/gr.h b/exynos4/hal/libgralloc_ump/gr.h
new file mode 100644
index 0000000..3a43aa7
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/gr.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GR_H_
+#define GR_H_
+
+#include <stdint.h>
+#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
+# include <asm/page.h>
+#else
+# include <sys/user.h>
+#endif
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <cutils/native_handle.h>
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+inline size_t roundUpToPageSize(size_t x) {
+ return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+int mapFrameBufferLocked(struct private_module_t* module);
+int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+
+/*****************************************************************************/
+
+class Locker {
+ pthread_mutex_t mutex;
+public:
+ class Autolock {
+ Locker& locker;
+ public:
+ inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
+ inline ~Autolock() { locker.unlock(); }
+ };
+ inline Locker() { pthread_mutex_init(&mutex, 0); }
+ inline ~Locker() { pthread_mutex_destroy(&mutex); }
+ inline void lock() { pthread_mutex_lock(&mutex); }
+ inline void unlock() { pthread_mutex_unlock(&mutex); }
+};
+
+#endif /* GR_H_ */
diff --git a/exynos4/hal/libgralloc_ump/gralloc_helper.h b/exynos4/hal/libgralloc_ump/gralloc_helper.h
new file mode 100644
index 0000000..21a5135
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/gralloc_helper.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * round_up_to_page_size()
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_HELPER_H_
+#define GRALLOC_HELPER_H_
+
+#include <sys/mman.h>
+
+inline size_t round_up_to_page_size(size_t x)
+{
+ return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+#endif /* GRALLOC_HELPER_H_ */
diff --git a/exynos4/hal/libgralloc_ump/gralloc_module.cpp b/exynos4/hal/libgralloc_ump/gralloc_module.cpp
new file mode 100644
index 0000000..fb8fc43
--- /dev/null
+++ b/exynos4/hal/libgralloc_ump/gralloc_module.cpp
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * Portions of this code have been modified from the original.
+ * These modifications are:
+ * * includes
+ * * enums
+ * * gralloc_device_open()
+ * * gralloc_register_buffer()
+ * * gralloc_unregister_buffer()
+ * * gralloc_lock()
+ * * gralloc_unlock()
+ * * gralloc_module_methods
+ * * HAL_MODULE_INFO_SYM
+ *
+ * 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.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+
+#include <sys/mman.h>
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <fcntl.h>
+
+#include "gralloc_priv.h"
+#include "alloc_device.h"
+#include "framebuffer_device.h"
+
+#include "ump.h"
+#include "ump_ref_drv.h"
+#include "s5p_fimc.h"
+#include "exynos_mem.h"
+static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
+
+static int s_ump_is_open = 0;
+static int gMemfd = 0;
+#define PFX_NODE_MEM "/dev/exynos-mem"
+
+/* we need this for now because pmem cannot mmap at an offset */
+#define PMEM_HACK 1
+#ifdef USE_PARTIAL_FLUSH
+struct private_handle_rect *rect_list;
+
+private_handle_rect *find_rect(int secure_id)
+{
+ private_handle_rect *psRect;
+
+ for (psRect = rect_list; psRect; psRect = psRect->next)
+ if (psRect->handle == secure_id)
+ break;
+ if (!psRect)
+ return NULL;
+
+ return psRect;
+}
+
+private_handle_rect *find_last_rect(int secure_id)
+{
+ private_handle_rect *psRect;
+ private_handle_rect *psFRect;
+
+ if (rect_list == NULL) {
+ rect_list = (private_handle_rect *)calloc(1, sizeof(private_handle_rect));
+ return rect_list;
+ }
+
+ for (psRect = rect_list; psRect; psRect = psRect->next) {
+ if (psRect->handle == secure_id)
+ return psFRect;
+ psFRect = psRect;
+ }
+ return psFRect;
+}
+
+int release_rect(int secure_id)
+{
+ private_handle_rect *psRect;
+ private_handle_rect *psTRect;
+
+ for (psRect = rect_list; psRect; psRect = psRect->next) {
+ if (psRect->next) {
+ if (psRect->next->handle == secure_id) {
+ if (psRect->next->next)
+ psTRect = psRect->next->next;
+ else
+ psTRect = NULL;
+
+ free(psRect->next);
+ psRect->next = psTRect;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static int gralloc_map(gralloc_module_t const* module,
+ buffer_handle_t handle, void** vaddr)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) {
+ size_t size = FIMC1_RESERVED_SIZE * 1024;
+ void *mappedAddress = mmap(0, size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, gMemfd, (hnd->paddr - hnd->offset));
+ if (mappedAddress == MAP_FAILED) {
+ LOGE("Could not mmap %s fd(%d)", strerror(errno),hnd->fd);
+ return -errno;
+ }
+ hnd->base = intptr_t(mappedAddress) + hnd->offset;
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+ size_t size = hnd->size;
+ hnd->ion_client = ion_client_create();
+ void *mappedAddress = ion_map(hnd->fd, size, 0);
+
+ if (mappedAddress == MAP_FAILED) {
+ LOGE("Could not ion_map %s fd(%d)", strerror(errno), hnd->fd);
+ return -errno;
+ }
+
+ hnd->base = intptr_t(mappedAddress) + hnd->offset;
+ } else {
+ size_t size = hnd->size;
+#if PMEM_HACK
+ size += hnd->offset;
+#endif
+ void *mappedAddress = mmap(0, size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
+ if (mappedAddress == MAP_FAILED) {
+ LOGE("Could not mmap %s fd(%d)", strerror(errno),hnd->fd);
+ return -errno;
+ }
+ hnd->base = intptr_t(mappedAddress) + hnd->offset;
+ }
+ }
+ *vaddr = (void*)hnd->base;
+ return 0;
+}
+
+static int gralloc_unmap(gralloc_module_t const* module,
+ buffer_handle_t handle)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) {
+ void* base = (void*)(intptr_t(hnd->base) - hnd->offset);
+ size_t size = FIMC1_RESERVED_SIZE * 1024;
+ if (munmap(base, size) < 0)
+ LOGE("Could not unmap %s", strerror(errno));
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+ void* base = (void*)hnd->base;
+ size_t size = hnd->size;
+ if (ion_unmap(base, size) < 0)
+ LOGE("Could not ion_unmap %s", strerror(errno));
+ ion_client_destroy(hnd->ion_client);
+ } else {
+ void* base = (void*)hnd->base;
+ size_t size = hnd->size;
+#if PMEM_HACK
+ base = (void*)(intptr_t(base) - hnd->offset);
+ size += hnd->offset;
+#endif
+ if (munmap(base, size) < 0)
+ LOGE("Could not unmap %s", strerror(errno));
+ }
+ }
+ hnd->base = 0;
+ return 0;
+}
+
+static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)
+{
+ int status = -EINVAL;
+
+ if (!strcmp(name, GRALLOC_HARDWARE_GPU0))
+ status = alloc_device_open(module, name, device);
+ else if (!strcmp(name, GRALLOC_HARDWARE_FB0))
+ status = framebuffer_device_open(module, name, device);
+
+ return status;
+}
+
+static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle)
+{
+ int err = 0;
+ int retval = -EINVAL;
+ void *vaddr;
+ if (private_handle_t::validate(handle) < 0) {
+ LOGE("Registering invalid buffer, returning error");
+ return -EINVAL;
+ }
+
+ /* if this handle was created in this process, then we keep it as is. */
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+#ifdef USE_PARTIAL_FLUSH
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+ private_handle_rect *psRect;
+ private_handle_rect *psFRect;
+ psRect = (private_handle_rect *)calloc(1, sizeof(private_handle_rect));
+ psRect->handle = (int)hnd->ump_id;
+ psRect->stride = (int)hnd->stride;
+ psFRect = find_last_rect((int)hnd->ump_id);
+ psFRect->next = psRect;
+ }
+#endif
+ if (hnd->pid == getpid())
+ return 0;
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+ err = gralloc_map(module, handle, &vaddr);
+
+ pthread_mutex_lock(&s_map_lock);
+
+ if (!s_ump_is_open) {
+ ump_result res = ump_open(); /* TODO: Fix a ump_close() somewhere??? */
+ if (res != UMP_OK) {
+ pthread_mutex_unlock(&s_map_lock);
+ LOGE("Failed to open UMP library");
+ return retval;
+ }
+ s_ump_is_open = 1;
+ }
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+ hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id);
+ if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle) {
+ hnd->base = (int)ump_mapped_pointer_get((ump_handle)hnd->ump_mem_handle);
+ if (0 != hnd->base) {
+ hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
+ hnd->writeOwner = 0;
+ hnd->lockState = 0;
+
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ } else {
+ LOGE("Failed to map UMP handle");
+ }
+
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+ } else {
+ LOGE("Failed to create UMP handle");
+ }
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) {
+ void* vaddr = NULL;
+
+ if (gMemfd == 0) {
+ gMemfd = open(PFX_NODE_MEM, O_RDWR);
+ if (gMemfd < 0) {
+ LOGE("%s:: %s exynos-mem open error\n", __func__, PFX_NODE_MEM);
+ return false;
+ }
+ }
+
+ gralloc_map(module, handle, &vaddr);
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+ hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id);
+ if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle) {
+ vaddr = (void*)ump_mapped_pointer_get((ump_handle)hnd->ump_mem_handle);
+ if (0 != vaddr) {
+ hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
+ hnd->writeOwner = 0;
+ hnd->lockState = 0;
+
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ } else {
+ LOGE("Failed to map UMP handle");
+ }
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+ } else {
+ LOGE("Failed to create UMP handle");
+ }
+ } else {
+ LOGE("registering non-UMP buffer not supported");
+ }
+
+ pthread_mutex_unlock(&s_map_lock);
+ return retval;
+}
+
+static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0) {
+ LOGE("unregistering invalid buffer, returning error");
+ return -EINVAL;
+ }
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+#ifdef USE_PARTIAL_FLUSH
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP)
+ if (!release_rect((int)hnd->ump_id))
+ LOGE("secureID: 0x%x, release error", (int)hnd->ump_id);
+#endif
+ LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
+ "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState);
+
+ /* never unmap buffers that were created in this process */
+ if (hnd->pid != getpid()) {
+ pthread_mutex_lock(&s_map_lock);
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+ ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
+ hnd->base = 0;
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+ hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE;
+ hnd->lockState = 0;
+ hnd->writeOwner = 0;
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) {
+ if(hnd->base != 0)
+ gralloc_unmap(module, handle);
+
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+ ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
+ ump_reference_release((ump_handle)hnd->ump_mem_handle);
+ if (hnd->base)
+ gralloc_unmap(module, handle);
+
+ hnd->base = 0;
+ hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE;
+ hnd->lockState = 0;
+ hnd->writeOwner = 0;
+ } else {
+ LOGE("unregistering non-UMP buffer not supported");
+ }
+
+ pthread_mutex_unlock(&s_map_lock);
+ }
+
+ return 0;
+}
+
+static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle,
+ int usage, int l, int t, int w, int h, void** vaddr)
+{
+ int err = 0;
+ if (private_handle_t::validate(handle) < 0) {
+ LOGE("Locking invalid buffer, returning error");
+ return -EINVAL;
+ }
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+#ifdef SAMSUNG_EXYNOS_CACHE_UMP
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+#ifdef USE_PARTIAL_FLUSH
+ private_handle_rect *psRect;
+ psRect = find_rect((int)hnd->ump_id);
+ psRect->l = l;
+ psRect->t = t;
+ psRect->w = w;
+ psRect->h= h;
+ psRect->locked = 1;
+#endif
+ }
+#endif
+ if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
+ *vaddr = (void*)hnd->base;
+
+ if (usage & GRALLOC_USAGE_YUV_ADDR) {
+ vaddr[0] = (void*)hnd->base;
+ vaddr[1] = (void*)(hnd->base + hnd->uoffset);
+ vaddr[2] = (void*)(hnd->base + hnd->uoffset + hnd->voffset);
+ }
+ return err;
+}
+
+static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0) {
+ LOGE("Unlocking invalid buffer, returning error");
+ return -EINVAL;
+ }
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+#ifdef SAMSUNG_EXYNOS_CACHE_UMP
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) {
+#ifdef USE_PARTIAL_FLUSH
+ private_handle_rect *psRect;
+ psRect = find_rect((int)hnd->ump_id);
+ ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN,
+ (void *)(hnd->base + (psRect->stride * psRect->t)), psRect->stride * psRect->h );
+ return 0;
+#endif
+ ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, NULL, 0);
+ }
+#endif
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+ ion_msync(hnd->ion_client, hnd->fd, IMSYNC_DEV_TO_RW | IMSYNC_SYNC_FOR_DEV, hnd->size, hnd->offset);
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) {
+ int ret;
+ exynos_mem_flush_range mem;
+ mem.start = hnd->paddr;
+ mem.length = hnd->size;
+
+ ret = ioctl(gMemfd, EXYNOS_MEM_PADDR_CACHE_FLUSH, &mem);
+ if (ret < 0) {
+ LOGE("Error in exynos-mem : EXYNOS_MEM_PADDR_CACHE_FLUSH (%d)\n", ret);
+ return false;
+ }
+ }
+
+ return 0;
+}
+
+static int gralloc_getphys(gralloc_module_t const* module, buffer_handle_t handle, void** paddr)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+ paddr[0] = (void*)hnd->paddr;
+ paddr[1] = (void*)(hnd->paddr + hnd->uoffset);
+ paddr[2] = (void*)(hnd->paddr + hnd->uoffset + hnd->voffset);
+ return 0;
+}
+
+/* There is one global instance of the module */
+static struct hw_module_methods_t gralloc_module_methods =
+{
+ open: gralloc_device_open
+};
+
+struct private_module_t HAL_MODULE_INFO_SYM =
+{
+ base:
+ {
+ common:
+ {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: GRALLOC_HARDWARE_MODULE_ID,
+ name: "Graphics Memory Allocator Module",
+ author: "ARM Ltd.",
+ methods: &gralloc_module_methods,
+ dso: NULL,
+ reserved : {0,},
+ },
+ registerBuffer: gralloc_register_buffer,
+ unregisterBuffer: gralloc_unregister_buffer,
+ lock: gralloc_lock,
+ unlock: gralloc_unlock,
+ getphys: gralloc_getphys,
+ perform: NULL,
+ reserved_proc: {0,},
+ },
+ framebuffer: NULL,
+ flags: 0,
+ numBuffers: 0,
+ bufferMask: 0,
+ lock: PTHREAD_MUTEX_INITIALIZER,
+ currentBuffer: NULL,
+ ion_client: -1,
+};
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/liblights/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk
index 995bd02..9a4b721 100644
--- a/exynos4/hal/liblights/Android.mk
+++ b/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk
@@ -1,5 +1,4 @@
-# Copyright (C) 2011 The Android Open Source Project
-# Copyright (C) 2011 The CyanogenMod Project
+# 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.
@@ -13,21 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+ifeq ($(BOARD_USES_HDMI),true)
+
LOCAL_PATH:= $(call my-dir)
-# HAL module implemenation, not prelinked and stored in
-# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := lights.c
+LOCAL_MODULE_TAGS := eng
LOCAL_PRELINK_MODULE := false
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-
LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := libcec.c
-LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
-
-LOCAL_MODULE_TAGS := optional
+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/libsensors/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk
index 15c29a2..38891be 100644
--- a/exynos4/hal/libsensors/Android.mk
+++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk
@@ -12,34 +12,34 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+ifeq ($(BOARD_USES_HDMI),true)
-LOCAL_PATH := $(call my-dir)
-
-ifneq ($(TARGET_SIMULATOR),true)
-
-# HAL module implemenation, not prelinked, and stored in
-# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.product.board>.so
+LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE := sensors.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := eng
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := libddc.c
-LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/../../../include
-LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\"
-LOCAL_SRC_FILES := \
- sensors.cpp \
- SensorBase.cpp \
- LightSensor.cpp \
- ProximitySensor.cpp \
- AkmSensor.cpp \
- GyroSensor.cpp \
- InputEventReader.cpp
+ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_7)
+LOCAL_CFLAGS += -DDDC_CH_I2C_7
+endif
-LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
-LOCAL_PRELINK_MODULE := false
+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 # !TARGET_SIMULATOR
+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/libump/ump.mak b/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk
index e417313..602ae4d 100644
--- a/exynos4/hal/libump/ump.mak
+++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk
@@ -1,34 +1,34 @@
+# Copyright (C) 2008 The Android Open Source Project
#
-# Copyright (C) 2011 ARM Limited. All rights reserved.
-#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
+# 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 ($(UMP_NO_UMP),1)
+ifeq ($(BOARD_USES_HDMI),true)
-UMP_SRCS = \
- $(UMP_DIR)/arch_999_no_ump/ump_frontend.c \
- $(UMP_DIR)/arch_999_no_ump/ump_ref_drv.c
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
-else
+LOCAL_MODULE_TAGS := eng
-UMP_SRCS = \
- $(UMP_DIR)/arch_011_udd/ump_frontend.c \
- $(UMP_DIR)/arch_011_udd/ump_ref_drv.c \
- $(UMP_DIR)/arch_011_udd/ump_arch.c \
- $(UMP_DIR)/os/$(UDD_OS)/ump_uku.c \
- $(UMP_DIR)/os/$(UDD_OS)/ump_osu_memory.c \
- $(UMP_DIR)/os/$(UDD_OS)/ump_osu_locks.c
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := liblog libddc
+LOCAL_SRC_FILES := libedid.c
-endif
+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_ */
diff --git a/exynos4/hal/libhwcomposer/Android.mk b/exynos4/hal/libhwcomposer/Android.mk
new file mode 100644
index 0000000..902a72f
--- /dev/null
+++ b/exynos4/hal/libhwcomposer/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.
+
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
+
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL \
+ libGLESv1_CM
+
+ifeq ($(BOARD_USE_V4L2_ION),true)
+LOCAL_SHARED_LIBRARIES += libion
+endif
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES := SecHWCLog.cpp SecHWCUtils.cpp SecHWC.cpp
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libfimg
+
+ifeq ($(TARGET_SOC),exynos4210)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210
+endif
+
+ifeq ($(TARGET_SOC),exynos4x12)
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12
+endif
+
+ifeq ($(BOARD_USES_HDMI),true)
+LOCAL_C_INCLUDES += \
+ $(TARGET_HAL_PATH)/libhwcomposer \
+ $(TARGET_HAL_PATH)/include \
+ $(TARGET_HAL_PATH)/libhdmi/libhdmiservice
+
+LOCAL_SHARED_LIBRARIES += libhdmiclient libTVOut
+
+LOCAL_CFLAGS += -DBOARD_USES_HDMI
+LOCAL_CFLAGS += -DBOARD_HDMI_STD=$(BOARD_HDMI_STD)
+LOCAL_CFLAGS += -DVIDEO_DUAL_DISPLAY
+
+ifeq ($(BOARD_USES_HDMI_SUBTITLES),true)
+ LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES
+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
+endif
+
+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 := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos4/hal/libhwcomposer/SecHWC.cpp b/exynos4/hal/libhwcomposer/SecHWC.cpp
new file mode 100644
index 0000000..d2f3ecc
--- /dev/null
+++ b/exynos4/hal/libhwcomposer/SecHWC.cpp
@@ -0,0 +1,957 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie Oh (jung-min.oh@samsung.com)
+ * @date 2011-03-11
+ *
+ */
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <EGL/egl.h>
+
+#include "SecHWCUtils.h"
+
+#include "gralloc_priv.h"
+#ifdef HWC_HWOVERLAY
+#include <GLES/gl.h>
+#endif
+#if defined(BOARD_USES_HDMI)
+#include "SecHdmiClient.h"
+#include "SecTVOutService.h"
+
+#include "SecHdmi.h"
+
+//#define CHECK_EGL_FPS
+#ifdef CHECK_EGL_FPS
+extern void check_fps();
+#endif
+
+static int lcd_width, lcd_height;
+static int prev_usage = 0;
+
+#define CHECK_TIME_DEBUG 0
+#define SUPPORT_AUTO_UI_ROTATE
+#endif
+int testRenderNum =0;
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device);
+
+static struct hw_module_methods_t hwc_module_methods = {
+ open: hwc_device_open
+};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: HWC_HARDWARE_MODULE_ID,
+ name: "Samsung S5PC21X hwcomposer module",
+ author: "SAMSUNG",
+ methods: &hwc_module_methods,
+ }
+};
+
+/*****************************************************************************/
+
+static void dump_layer(hwc_layer_t const* l) {
+ LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
+ "{%d,%d,%d,%d}, {%d,%d,%d,%d}",
+ l->compositionType, l->flags, l->handle, l->transform, l->blending,
+ l->sourceCrop.left,
+ l->sourceCrop.top,
+ l->sourceCrop.right,
+ l->sourceCrop.bottom,
+ l->displayFrame.left,
+ l->displayFrame.top,
+ l->displayFrame.right,
+ l->displayFrame.bottom);
+}
+
+void calculate_rect(struct hwc_win_info_t *win, hwc_layer_t *cur,
+ sec_rect *rect)
+{
+ rect->x = cur->displayFrame.left;
+ rect->y = cur->displayFrame.top;
+ rect->w = cur->displayFrame.right - cur->displayFrame.left;
+ rect->h = cur->displayFrame.bottom - cur->displayFrame.top;
+
+ if (rect->x < 0) {
+ if (rect->w + rect->x > win->lcd_info.xres)
+ rect->w = win->lcd_info.xres;
+ else
+ rect->w = rect->w + rect->x;
+ rect->x = 0;
+ } else {
+ if (rect->w + rect->x > win->lcd_info.xres)
+ rect->w = win->lcd_info.xres - rect->x;
+ }
+ if (rect->y < 0) {
+ if (rect->h + rect->y > win->lcd_info.yres)
+ rect->h = win->lcd_info.yres;
+ else
+ rect->h = rect->h + rect->y;
+ rect->y = 0;
+ } else {
+ if (rect->h + rect->y > win->lcd_info.yres)
+ rect->h = win->lcd_info.yres - rect->y;
+ }
+}
+
+static int set_src_dst_img_rect(hwc_layer_t *cur,
+ struct hwc_win_info_t *win,
+ struct sec_img *src_img,
+ struct sec_img *dst_img,
+ struct sec_rect *src_rect,
+ struct sec_rect *dst_rect,
+ int win_idx)
+{
+ private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
+ sec_rect rect;
+
+ /* 1. Set src_img from prev_handle */
+ src_img->f_w = prev_handle->width;
+ src_img->f_h = prev_handle->height;
+ src_img->w = prev_handle->width;
+ src_img->h = prev_handle->height;
+ src_img->format = prev_handle->format;
+ src_img->base = (uint32_t)prev_handle->base;
+ src_img->offset = prev_handle->offset;
+ src_img->mem_id = prev_handle->fd;
+ src_img->paddr = prev_handle->paddr;
+ src_img->usage = prev_handle->usage;
+ src_img->uoffset = prev_handle->uoffset;
+ src_img->voffset = prev_handle->voffset;
+
+ src_img->mem_type = HWC_VIRT_MEM_TYPE;
+
+ switch (src_img->format) {
+ case HAL_PIXEL_FORMAT_YV12: /* To support video editor */
+ case HAL_PIXEL_FORMAT_YCbCr_420_P: /* To support SW codec */
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
+ src_img->f_w = (src_img->f_w + 15) & ~15;
+ src_img->f_h = (src_img->f_h + 1) & ~1;
+ break;
+ default:
+ src_img->f_w = src_img->w;
+ src_img->f_h = src_img->h;
+ break;
+ }
+
+ /* 2. Set dst_img from window(lcd) */
+ calculate_rect(win, cur, &rect);
+ dst_img->f_w = win->lcd_info.xres;
+ dst_img->f_h = win->lcd_info.yres;
+ dst_img->w = rect.w;
+ dst_img->h = rect.h;
+
+ switch (win->lcd_info.bits_per_pixel) {
+ case 32:
+ dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
+ break;
+ default:
+ dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
+ break;
+ }
+
+ dst_img->base = win->addr[win->buf_index];
+ dst_img->offset = 0;
+ dst_img->mem_id = 0;
+ dst_img->mem_type = HWC_PHYS_MEM_TYPE;
+
+ /* 3. Set src_rect(crop rect) */
+ if (cur->displayFrame.left < 0) {
+ src_rect->x =
+ (0 - cur->displayFrame.left)
+ *(src_img->w)
+ /(cur->displayFrame.right - cur->displayFrame.left + 1);
+ if (cur->displayFrame.right + 1 > win->lcd_info.xres) {
+ src_rect->w =
+ (cur->sourceCrop.right - cur->sourceCrop.left + 1) -
+ src_rect->x -
+ (cur->displayFrame.right - win->lcd_info.xres)
+ *(src_img->w)
+ /(cur->displayFrame.right - cur->displayFrame.left + 1);
+ } else {
+ src_rect->w =
+ (cur->sourceCrop.right - cur->sourceCrop.left + 1) -
+ src_rect->x;
+ }
+ } else {
+ src_rect->x = cur->sourceCrop.left;
+ if (cur->displayFrame.right + 1 > win->lcd_info.xres) {
+ src_rect->w =
+ (cur->sourceCrop.right - cur->sourceCrop.left + 1) -
+ src_rect->x -
+ (cur->displayFrame.right - win->lcd_info.xres)
+ *(src_img->w)
+ /(cur->displayFrame.right - cur->displayFrame.left + 1);
+ } else {
+ src_rect->w =
+ (cur->sourceCrop.right - cur->sourceCrop.left + 1);
+ }
+ }
+ if (cur->displayFrame.top < 0) {
+ src_rect->y =
+ (0 - cur->displayFrame.top)
+ *(src_img->h)
+ /(cur->displayFrame.bottom - cur->displayFrame.top + 1);
+ if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) {
+ src_rect->h =
+ (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) -
+ src_rect->y -
+ (cur->displayFrame.bottom - win->lcd_info.yres)
+ *(src_img->h)
+ /(cur->displayFrame.bottom - cur->displayFrame.top + 1);
+ } else {
+ src_rect->h =
+ (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) -
+ src_rect->y;
+ }
+ } else {
+ src_rect->y = cur->sourceCrop.top;
+ if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) {
+ src_rect->h =
+ (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) -
+ src_rect->y -
+ (cur->displayFrame.bottom - win->lcd_info.yres)
+ *(src_img->h)
+ /(cur->displayFrame.bottom - cur->displayFrame.top + 1);
+ } else {
+ src_rect->h =
+ (cur->sourceCrop.bottom - cur->sourceCrop.top + 1);
+ }
+ }
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "crop information()::"
+ "sourceCrop left(%d),top(%d),right(%d),bottom(%d),"
+ "src_rect x(%d),y(%d),w(%d),h(%d),"
+ "prev_handle w(%d),h(%d)",
+ cur->sourceCrop.left,
+ cur->sourceCrop.top,
+ cur->sourceCrop.right,
+ cur->sourceCrop.bottom,
+ src_rect->x, src_rect->y, src_rect->w, src_rect->h,
+ prev_handle->width, prev_handle->height);
+
+ src_rect->x = SEC_MAX(src_rect->x, 0);
+ src_rect->y = SEC_MAX(src_rect->y, 0);
+ src_rect->w = SEC_MAX(src_rect->w, 0);
+ src_rect->w = SEC_MIN(src_rect->w, prev_handle->width);
+ src_rect->h = SEC_MAX(src_rect->h, 0);
+ src_rect->h = SEC_MIN(src_rect->h, prev_handle->height);
+
+ /* 4. Set dst_rect(fb or lcd)
+ * fimc dst image will be stored from left top corner
+ */
+ dst_rect->x = 0;
+ dst_rect->y = 0;
+ dst_rect->w = win->rect_info.w;
+ dst_rect->h = win->rect_info.h;
+
+ /* Summery */
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "set_src_dst_img_rect()::"
+ "SRC w(%d),h(%d),f_w(%d),f_h(%d),fmt(0x%x),"
+ "base(0x%x),offset(%d),paddr(0x%X),mem_id(%d),mem_type(%d)=>\r\n"
+ " DST w(%d),h(%d),f(0x%x),base(0x%x),"
+ "offset(%d),mem_id(%d),mem_type(%d),"
+ "rot(%d),win_idx(%d)"
+ " SRC_RECT x(%d),y(%d),w(%d),h(%d)=>"
+ "DST_RECT x(%d),y(%d),w(%d),h(%d)",
+ src_img->w, src_img->h, src_img->f_w, src_img->f_h, src_img->format,
+ src_img->base, src_img->offset, src_img->paddr, src_img->mem_id, src_img->mem_type,
+ dst_img->w, dst_img->h, dst_img->format, dst_img->base,
+ dst_img->offset, dst_img->mem_id, dst_img->mem_type,
+ cur->transform, win_idx,
+ src_rect->x, src_rect->y, src_rect->w, src_rect->h,
+ dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
+
+ return 0;
+}
+
+static int get_hwc_compos_decision(hwc_layer_t* cur, int iter, int win_cnt)
+{
+ if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s::is_skip_layer %d cur->handle %x ",
+ __func__, cur->flags & HWC_SKIP_LAYER, cur->handle);
+
+ return HWC_FRAMEBUFFER;
+ }
+
+ private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
+ int compositionType = HWC_FRAMEBUFFER;
+
+ if (iter == 0) {
+ /* check here....if we have any resolution constraints */
+ if (((cur->sourceCrop.right - cur->sourceCrop.left + 1) < 16) ||
+ ((cur->sourceCrop.bottom - cur->sourceCrop.top + 1) < 8))
+ return compositionType;
+
+ if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
+ (cur->transform == HAL_TRANSFORM_ROT_270)) {
+ if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 4) ||
+ ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 8))
+ return compositionType;
+ } else if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 8) ||
+ ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 4)) {
+ return compositionType;
+ }
+
+ switch (prev_handle->format) {
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ compositionType = HWC_OVERLAY;
+ break;
+ case HAL_PIXEL_FORMAT_YV12: /* YCrCb_420_P */
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ if ((prev_handle->usage & GRALLOC_USAGE_HWC_HWOVERLAY) &&
+ (cur->blending == HWC_BLENDING_NONE))
+ compositionType = HWC_OVERLAY;
+ else
+ compositionType = HWC_FRAMEBUFFER;
+ break;
+ default:
+ compositionType = HWC_FRAMEBUFFER;
+ break;
+ }
+ }
+
+#ifdef SUB_TITLES_HWC
+ else if ((win_cnt > 0) &&
+ (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) {
+ switch (prev_handle->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ compositionType = HWC_OVERLAY;
+ break;
+ default:
+ compositionType = HWC_FRAMEBUFFER;
+ break;
+ }
+
+ SEC_HWC_Log(HWC_LOG_DEBUG, "2nd iter###%s:: compositionType %d bpp %d"
+ " format %x src[%d %d %d %d] dst[%d %d %d %d] srcImg[%d %d]",
+ __func__, compositionType, prev_handle->bpp,
+ prev_handle->format,
+ cur->sourceCrop.left, cur->sourceCrop.right,
+ cur->sourceCrop.top, cur->sourceCrop.bottom,
+ cur->displayFrame.left, cur->displayFrame.right,
+ cur->displayFrame.top, cur->displayFrame.bottom,
+ prev_handle->width, prev_handle->height);
+ }
+#endif
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "%s::compositionType(%d)=>0:FB,1:OVERLAY \r\n"
+ " format(0x%x),magic(0x%x),flags(%d),size(%d),offset(%d)"
+ "b_addr(0x%x),usage(%d),w(%d),h(%d),bpp(%d)",
+ "get_hwc_compos_decision()", compositionType,
+ prev_handle->format, prev_handle->magic, prev_handle->flags,
+ prev_handle->size, prev_handle->offset, prev_handle->base,
+ prev_handle->usage, prev_handle->width, prev_handle->height,
+ prev_handle->bpp);
+
+ return compositionType;
+}
+
+static void reset_win_rect_info(hwc_win_info_t *win)
+{
+ win->rect_info.x = 0;
+ win->rect_info.y = 0;
+ win->rect_info.w = 0;
+ win->rect_info.h = 0;
+ return;
+}
+
+
+static int assign_overlay_window(struct hwc_context_t *ctx, hwc_layer_t *cur,
+ int win_idx, int layer_idx)
+{
+ struct hwc_win_info_t *win;
+ sec_rect rect;
+ int ret = 0;
+
+ if (NUM_OF_WIN <= win_idx)
+ return -1;
+
+ win = &ctx->win[win_idx];
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "%s:: left(%d),top(%d),right(%d),bottom(%d),transform(%d)"
+ "lcd_info.xres(%d),lcd_info.yres(%d)",
+ "++assign_overlay_window()",
+ cur->displayFrame.left, cur->displayFrame.top,
+ cur->displayFrame.right, cur->displayFrame.bottom, cur->transform,
+ win->lcd_info.xres, win->lcd_info.yres);
+
+ calculate_rect(win, cur, &rect);
+
+ if ((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
+ (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
+ win->rect_info.x = rect.x;
+ win->rect_info.y = rect.y;
+ win->rect_info.w = rect.w;
+ win->rect_info.h = rect.h;
+ //turnoff the window and set the window position with new conf...
+ if (window_set_pos(win) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
+ __func__, strerror(errno));
+ ret = -1;
+ }
+ ctx->layer_prev_buf[win_idx] = 0;
+ }
+
+ win->layer_index = layer_idx;
+ win->status = HWC_WIN_RESERVED;
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d\n",
+ "--assign_overlay_window()",
+ win->rect_info.x, win->rect_info.y, win->rect_info.w,
+ win->rect_info.h, win->layer_index, win_idx );
+
+ return 0;
+}
+
+static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
+{
+ struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
+ int overlay_win_cnt = 0;
+ int compositionType = 0;
+ int ret;
+
+ //if geometry is not changed, there is no need to do any work here
+ if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
+ return 0;
+
+ //all the windows are free here....
+ for (int i = 0 ; i < NUM_OF_WIN; i++) {
+ ctx->win[i].status = HWC_WIN_FREE;
+ ctx->win[i].buf_index = 0;
+ }
+
+ ctx->num_of_hwc_layer = 0;
+ ctx->num_of_fb_layer = 0;
+ ctx->num_2d_blit_layer = 0;
+
+ for (int i = 0; i < list->numHwLayers ; i++) {
+ hwc_layer_t* cur = &list->hwLayers[i];
+
+ if (overlay_win_cnt < NUM_OF_WIN) {
+ compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt);
+
+ if (compositionType == HWC_FRAMEBUFFER) {
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ } else {
+ ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
+ if (ret != 0) {
+ LOGE("assign_overlay_window fail, change to frambuffer");
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ continue;
+ }
+
+ cur->compositionType = HWC_OVERLAY;
+ cur->hints = HWC_HINT_CLEAR_FB;
+ overlay_win_cnt++;
+ ctx->num_of_hwc_layer++;
+ }
+ } else {
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ }
+ }
+
+#ifdef SUB_TITLES_HWC
+ for (int i = 0; i < list->numHwLayers ; i++) {
+ if (overlay_win_cnt < NUM_OF_WIN) {
+ hwc_layer_t* cur = &list->hwLayers[i];
+ if (get_hwc_compos_decision(cur, 1, overlay_win_cnt) == HWC_OVERLAY) {
+ ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
+ if (ret == 0) {
+ cur->compositionType = HWC_OVERLAY;
+ cur->hints = HWC_HINT_CLEAR_FB;
+ overlay_win_cnt++;
+ ctx->num_of_hwc_layer++;
+ ctx->num_of_fb_layer--;
+ ctx->num_2d_blit_layer = 1;
+ }
+ }
+ }
+ else
+ break;
+ }
+#endif
+
+#if defined(BOARD_USES_HDMI)
+ android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
+ mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer);
+#endif
+
+ if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
+ __func__, list->numHwLayers, ctx->num_of_fb_layer,
+ ctx->num_of_hwc_layer);
+
+ if (overlay_win_cnt < NUM_OF_WIN) {
+ //turn off the free windows
+ for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
+ window_hide(&ctx->win[i]);
+ reset_win_rect_info(&ctx->win[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int hwc_set(hwc_composer_device_t *dev,
+ hwc_display_t dpy,
+ hwc_surface_t sur,
+ hwc_layer_list_t* list)
+{
+ struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
+ int skipped_window_mask = 0;
+ hwc_layer_t* cur;
+ struct hwc_win_info_t *win;
+ int ret;
+ int pmem_phyaddr;
+ static int egl_check;
+ int egl_run = 0;
+ struct sec_img src_img;
+ struct sec_img dst_img;
+ struct sec_rect src_work_rect;
+ struct sec_rect dst_work_rect;
+
+ memset(&src_img, 0, sizeof(src_img));
+ memset(&dst_img, 0, sizeof(dst_img));
+ memset(&src_work_rect, 0, sizeof(src_work_rect));
+ memset(&dst_work_rect, 0, sizeof(dst_work_rect));
+
+#if defined(BOARD_USES_HDMI)
+ int skip_hdmi_rendering = 0;
+ int rotVal = 0;
+#endif
+
+ if (!list) {
+ //turn off the all windows
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ window_hide(&ctx->win[i]);
+ reset_win_rect_info(&ctx->win[i]);
+ ctx->win[i].status = HWC_WIN_FREE;
+ }
+ ctx->num_of_hwc_layer = 0;
+
+ if (sur == NULL && dpy == NULL)
+ return HWC_EGL_ERROR;
+ }
+
+ if(ctx->num_of_hwc_layer > NUM_OF_WIN)
+ ctx->num_of_hwc_layer = NUM_OF_WIN;
+
+ //compose hardware layers here
+ for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) {
+ win = &ctx->win[i];
+ if (win->status == HWC_WIN_RESERVED) {
+ cur = &list->hwLayers[win->layer_index];
+
+ if (cur->compositionType == HWC_OVERLAY) {
+ if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) {
+ /*
+ * In android platform, all the graphic buffer are at least
+ * double buffered (2 or more) this buffer is already rendered.
+ * It is the redundant src buffer for FIMC rendering.
+ */
+ LOGD("SKIP FIMC rendering for Layer%d", win->layer_index);
+#if defined(BOARD_USES_HDMI)
+ skip_hdmi_rendering = 1;
+#endif
+ continue;
+ }
+ ctx->layer_prev_buf[i] = (uint32_t)cur->handle;
+ // initialize the src & dist context for fimc
+ set_src_dst_img_rect(cur, win, &src_img, &dst_img,
+ &src_work_rect, &dst_work_rect, i);
+
+ ret = runFimc(ctx,
+ &src_img, &src_work_rect,
+ &dst_img, &dst_work_rect,
+ cur->transform);
+
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n",
+ __func__, ret);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+
+ window_pan_display(win);
+
+ win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
+ if (win->power_state == 0)
+ window_show(win);
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s:: error : layer %d compositionType should have been"
+ " HWC_OVERLAY ", __func__, win->layer_index);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have "
+ "been HWC_WIN_RESERVED by now... ", __func__);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+ }
+
+#ifdef SUB_TITLES_HWC
+ if (ctx->num_2d_blit_layer) {
+ g2d_rect srcRect;
+ g2d_rect dstRect;
+
+ win = &ctx->win[ctx->num_of_hwc_layer - 1];
+ cur = &list->hwLayers[win->layer_index];
+ set_src_dst_g2d_rect(cur, win, &srcRect, &dstRect);
+ ret = runG2d(ctx, &srcRect, &dstRect,
+ cur->transform);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::runG2d fail : ret=%d\n",
+ __func__, ret);
+ skipped_window_mask |= (1 << (ctx->num_of_hwc_layer - 1));
+ goto g2d_error;
+ }
+
+ window_pan_display(win);
+
+ win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
+ if (win->power_state == 0)
+ window_show(win);
+ }
+
+g2d_error:
+#endif
+
+ if (skipped_window_mask) {
+ //turn off the free windows
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (skipped_window_mask & (1 << i)) {
+ window_hide(&ctx->win[i]);
+ reset_win_rect_info(&ctx->win[i]);
+ }
+ }
+ }
+
+ if (0 < ctx->num_of_fb_layer) {
+#ifdef CHECK_EGL_FPS
+ check_fps();
+#endif
+#ifdef HWC_HWOVERLAY
+ unsigned char pixels[4];
+ glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+#endif
+ egl_check = 1;
+ egl_run = 1;
+ } else {
+ if (egl_check == 1) {
+ egl_check = 0;
+ egl_run = 1;
+ }
+ }
+
+ if (egl_run == 1) {
+ EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
+ if (!sucess)
+ return HWC_EGL_ERROR;
+ }
+
+#if defined(BOARD_USES_HDMI)
+ android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
+
+ if (skip_hdmi_rendering == 1)
+ return 0;
+
+ if (list == NULL) {
+ // Don't display unnecessary image
+ mHdmiClient->setHdmiEnable(0);
+ return 0;
+ } else {
+ mHdmiClient->setHdmiEnable(1);
+ }
+
+#ifdef SUPPORT_AUTO_UI_ROTATE
+ cur = &list->hwLayers[0];
+
+ if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270)
+ mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
+ else
+ mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
+#endif
+
+ // To support S3D video playback (automatic TV mode change to 3D mode)
+ if (ctx->num_of_hwc_layer == 1) {
+ if (src_img.usage != prev_usage)
+ mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60
+
+ if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
+ (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL))
+ mHdmiClient->setHdmiResolution(7209601); // V4L2_STD_TVOUT_720P_60_SBS_HALF
+ else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
+ (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL))
+ mHdmiClient->setHdmiResolution(1080924); // V4L2_STD_TVOUT_1080P_24_TB
+
+ prev_usage = src_img.usage;
+ } else {
+ if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
+ (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) ||
+ (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
+ (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL))
+ mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60
+
+ prev_usage = 0;
+ }
+
+ if (ctx->num_of_hwc_layer == 1) {
+ if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
+ (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
+ ADDRS * addr = (ADDRS *)(src_img.base);
+
+ mHdmiClient->blit2Hdmi(src_img.w, src_img.h,
+ src_img.format,
+ (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr,
+ 0, 0,
+ android::SecHdmiClient::HDMI_MODE_VIDEO,
+ ctx->num_of_hwc_layer);
+ } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
+ (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
+ (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
+ (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
+ mHdmiClient->blit2Hdmi(src_img.w, src_img.h,
+ src_img.format,
+ (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
+ (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
+ (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
+ 0, 0,
+ android::SecHdmiClient::HDMI_MODE_VIDEO,
+ ctx->num_of_hwc_layer);
+ } else {
+ LOGE("%s: Unsupported format = %d", __func__, src_img.format);
+ }
+ }
+#endif
+ return 0;
+}
+
+static int hwc_device_close(struct hw_device_t *dev)
+{
+ struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
+ int ret = 0;
+ int i;
+ if (ctx) {
+ if (destroyFimc(&ctx->fimc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__);
+ ret = -1;
+ }
+#ifdef SUB_TITLES_HWC
+ if (destroyG2d(&ctx->g2d) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__);
+ ret = -1;
+ }
+#endif
+ if (destroyMem(&ctx->s3c_mem) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyMem fail", __func__);
+ ret = -1;
+ }
+
+#ifdef USE_HW_PMEM
+ if (destroyPmem(&ctx->sec_pmem) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyPmem fail", __func__);
+ ret = -1;
+ }
+#endif
+ for (i = 0; i < NUM_OF_WIN; i++) {
+ if (window_close(&ctx->win[i]) < 0)
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
+ }
+
+ free(ctx);
+ }
+ return ret;
+}
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device)
+{
+ int status = 0;
+ struct hwc_win_info_t *win;
+
+ if (strcmp(name, HWC_HARDWARE_COMPOSER))
+ return -EINVAL;
+
+ struct hwc_context_t *dev;
+ dev = (hwc_context_t*)malloc(sizeof(*dev));
+
+ /* initialize our state here */
+ memset(dev, 0, sizeof(*dev));
+
+ /* initialize the procs */
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = hwc_device_close;
+
+ dev->device.prepare = hwc_prepare;
+ dev->device.set = hwc_set;
+
+ *device = &dev->device.common;
+
+ //initializing
+ memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
+ memset(&(dev->s3c_mem), 0, sizeof(struct s3c_mem_t));
+#ifdef USE_HW_PMEM
+ memset(&(dev->sec_pmem), 0, sizeof(sec_pmem_t));
+#endif
+ /* open WIN0 & WIN1 here */
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (window_open(&(dev->win[i]), i) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s:: Failed to open window %d device ", __func__, i);
+ status = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (window_get_global_lcd_info(dev->win[0].fd, &dev->lcd_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s::window_get_global_lcd_info is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+#if defined(BOARD_USES_HDMI)
+ lcd_width = dev->lcd_info.xres;
+ lcd_height = dev->lcd_info.yres;
+#endif
+
+ /* initialize the window context */
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ win = &dev->win[i];
+ memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
+ memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
+
+ win->rect_info.x = 0;
+ win->rect_info.y = 0;
+ win->rect_info.w = win->var_info.xres;
+ win->rect_info.h = win->var_info.yres;
+
+ if (window_set_pos(win) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+ if (window_get_info(win, i) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+ }
+
+#ifdef USE_HW_PMEM
+ if (createPmem(&dev->sec_pmem, PMEM_SIZE) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::initPmem(%d) fail", __func__, PMEM_SIZE);
+ }
+#endif
+
+ if (createMem(&dev->s3c_mem, 0, 0) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::createMem() fail (size=0)", __func__);
+ status = -EINVAL;
+ goto err;
+ }
+
+ //create PP
+ if (createFimc(&dev->fimc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__);
+ status = -EINVAL;
+ goto err;
+ }
+
+#ifdef SUB_TITLES_HWC
+ if (createG2d(&dev->g2d) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::createG2d() fail", __func__);
+ status = -EINVAL;
+ goto err;
+ }
+#endif
+
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__);
+
+ return 0;
+
+err:
+ if (destroyFimc(&dev->fimc) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__);
+#ifdef SUB_TITLES_HWC
+ if (destroyG2d(&dev->g2d) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__);
+#endif
+ if (destroyMem(&dev->s3c_mem) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyMem() fail", __func__);
+
+#ifdef USE_HW_PMEM
+ if (destroyPmem(&dev->sec_pmem) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyPmem() fail", __func__);
+#endif
+
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (window_close(&dev->win[i]) < 0)
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
+ }
+
+ return status;
+}
diff --git a/exynos4/hal/libhwcomposer/SecHWCLog.cpp b/exynos4/hal/libhwcomposer/SecHWCLog.cpp
new file mode 100644
index 0000000..6ad4283
--- /dev/null
+++ b/exynos4/hal/libhwcomposer/SecHWCLog.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie Oh (jung-min.oh@samsung.com)
+ * @date 2011-03-11
+ *
+ */
+
+#include <utils/Log.h>
+
+#include "SecHWCUtils.h"
+
+void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...)
+{
+ va_list argptr;
+
+ va_start(argptr, msg);
+
+ switch (logLevel) {
+ case HWC_LOG_DEBUG:
+ __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr);
+ break;
+ case HWC_LOG_WARNING:
+ __android_log_vprint(ANDROID_LOG_WARN, tag, msg, argptr);
+ break;
+ case HWC_LOG_ERROR:
+ __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, argptr);
+ break;
+ default:
+ __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr);
+ }
+
+ va_end(argptr);
+}
diff --git a/exynos4/hal/libhwcomposer/SecHWCUtils.cpp b/exynos4/hal/libhwcomposer/SecHWCUtils.cpp
new file mode 100644
index 0000000..5214e40
--- /dev/null
+++ b/exynos4/hal/libhwcomposer/SecHWCUtils.cpp
@@ -0,0 +1,2077 @@
+/*
+ * 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.
+ */
+
+/*
+ * Revision History:
+ * - 2011/03/11 : Rama, Meka(v.meka@samsung.com)
+ * Initial version
+ *
+ * - 2011/12/07 : Jeonghee, Kim(jhhhh.kim@samsung.com)
+ * Add V4L2_PIX_FMT_YUV420M V4L2_PIX_FMT_NV12M
+ *
+ */
+
+#include "SecHWCUtils.h"
+
+#ifdef BOARD_USE_V4L2_ION
+#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
+#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+#else
+#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT
+#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE
+#endif
+
+#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
+
+//#define CHECK_FPS
+#ifdef CHECK_FPS
+#include <sys/time.h>
+#include <unistd.h>
+#define CHK_FRAME_CNT 30
+
+void check_fps()
+{
+ static struct timeval tick, tick_old;
+ static int total = 0;
+ static int cnt = 0;
+ int FPS;
+ cnt++;
+ gettimeofday(&tick, NULL);
+ if (cnt > 10) {
+ if (tick.tv_sec > tick_old.tv_sec)
+ total += ((tick.tv_usec/1000) + (tick.tv_sec - tick_old.tv_sec)*1000 - (tick_old.tv_usec/1000));
+ else
+ total += ((tick.tv_usec - tick_old.tv_usec)/1000);
+
+ memcpy(&tick_old, &tick, sizeof(timeval));
+ if (cnt == (10 + CHK_FRAME_CNT)) {
+ FPS = 1000*CHK_FRAME_CNT/total;
+ LOGE("[FPS]:%d\n", FPS);
+ total = 0;
+ cnt = 10;
+ }
+ } else {
+ memcpy(&tick_old, &tick, sizeof(timeval));
+ total = 0;
+ }
+}
+#endif
+
+struct yuv_fmt_list yuv_list[] = {
+ { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 },
+ { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 },
+ { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 },
+ { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 },
+ { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 },
+ { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 },
+#ifdef BOARD_USE_V4L2_ION
+ { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 },
+ { "V4L2_PIX_FMT_NV12M", "YUV420/2P", V4L2_PIX_FMT_NV12M, 12, 2 },
+#endif
+ { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 },
+ { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 },
+ { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 },
+ { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 },
+ { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 },
+ { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 },
+ { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 },
+ { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 },
+ { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 },
+};
+
+int window_open(struct hwc_win_info_t *win, int id)
+{
+ int fd = 0;
+ char name[64];
+ int vsync = 1;
+ int real_id = id;
+
+ char const * const device_template = "/dev/graphics/fb%u";
+ // window & FB maping
+ // fb0 -> win-id : 2
+ // fb1 -> win-id : 3
+ // fb2 -> win-id : 4
+ // fb3 -> win-id : 0
+ // fb4 -> win_id : 1
+ // it is pre assumed that ...win0 or win1 is used here..
+
+ switch (id) {
+ case 0:
+#ifdef BOARD_USE_V4L2_ION
+ real_id = 2;
+#else
+ real_id = 3;
+#endif
+ break;
+ case 1:
+#ifdef BOARD_USE_V4L2_ION
+ real_id = 1;
+#else
+ real_id = 4;
+#endif
+ break;
+ default:
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::id(%d) is weird", __func__, id);
+ goto error;
+}
+
+// 0/10
+// snprintf(name, 64, device_template, id + 3);
+// 5/10
+// snprintf(name, 64, device_template, id + 0);
+// 0/10
+// snprintf(name, 64, device_template, id + 1);
+ snprintf(name, 64, device_template, real_id);
+
+ win->fd = open(name, O_RDWR);
+ if (win->fd <= 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Failed to open window device (%s) : %s",
+ __func__, strerror(errno), name);
+ goto error;
+ }
+
+#ifdef ENABLE_FIMD_VSYNC
+ if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
+ goto error;
+ }
+#endif
+
+ return 0;
+
+error:
+ if (0 < win->fd)
+ close(win->fd);
+ win->fd = 0;
+
+ return -1;
+}
+
+int window_close(struct hwc_win_info_t *win)
+{
+ int ret = 0;
+
+ if (0 < win->fd) {
+
+#ifdef BOARD_USE_V4L2_ION
+ ion_unmap((void *)win->addr[0], ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE));
+ ion_free(win->ion_fd);
+#endif
+
+#ifdef ENABLE_FIMD_VSYNC
+ int vsync = 0;
+ if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
+#endif
+ ret = close(win->fd);
+ }
+ win->fd = 0;
+
+ return ret;
+}
+
+int window_set_pos(struct hwc_win_info_t *win)
+{
+ struct s3cfb_user_window window;
+
+ //before changing the screen configuration...powerdown the window
+ if (window_hide(win) != 0)
+ return -1;
+
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: x(%d), y(%d)",
+ __func__, win->rect_info.x, win->rect_info.y);
+
+ win->var_info.xres_virtual = (win->lcd_info.xres + 15) & ~ 15;
+ win->var_info.yres_virtual = win->lcd_info.yres * NUM_OF_WIN_BUF;
+ win->var_info.xres = win->rect_info.w;
+ win->var_info.yres = win->rect_info.h;
+
+ win->var_info.activate &= ~FB_ACTIVATE_MASK;
+ win->var_info.activate |= FB_ACTIVATE_FORCE;
+
+ if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPUT_VSCREENINFO(%d, %d) fail",
+ __func__, win->rect_info.w, win->rect_info.h);
+ return -1;
+ }
+
+ window.x = win->rect_info.x;
+ window.y = win->rect_info.y;
+
+ if (ioctl(win->fd, S3CFB_WIN_POSITION, &window) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_WIN_POSITION(%d, %d) fail",
+ __func__, window.x, window.y);
+ return -1;
+ }
+
+ return 0;
+}
+
+int window_get_info(struct hwc_win_info_t *win, int win_num)
+{
+ int temp_size = 0;
+
+ if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_FSCREENINFO failed : %s",
+ strerror(errno));
+ goto error;
+ }
+
+ win->size = win->fix_info.line_length * win->var_info.yres;
+
+#ifdef BOARD_USE_V4L2_ION
+ struct s3c_fb_user_ion_client ion_handle;
+ void *ion_start_addr;
+
+ if (ioctl(win->fd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Get fb ion client is failed\n");
+ return -1;
+ }
+
+ win->ion_fd = ion_handle.fd;
+ ion_start_addr = ion_map(win->ion_fd, ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE), 0);
+#endif
+
+ for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
+ temp_size = win->size * j;
+#ifdef BOARD_USE_V4L2_ION
+ win->addr[j] = (uint32_t)ion_start_addr + temp_size;
+#else
+ win->addr[j] = win->fix_info.smem_start + temp_size;
+#endif
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s::win-%d add[%d] %x ",
+ __func__, win_num, j, win->addr[j]);
+ }
+ return 0;
+
+error:
+ win->fix_info.smem_start = 0;
+
+ return -1;
+}
+
+int window_pan_display(struct hwc_win_info_t *win)
+{
+ struct fb_var_screeninfo *lcd_info = &(win->lcd_info);
+
+#ifdef ENABLE_FIMD_VSYNC
+#ifdef BOARD_USE_V4L2_ION
+ int fimd_num = 0;
+ if (ioctl(win->fd, FBIO_WAITFORVSYNC, &fimd_num) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)",
+ __func__, strerror(errno));
+#else
+ if (ioctl(win->fd, FBIO_WAITFORVSYNC, 0) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)",
+ __func__, strerror(errno));
+#endif
+#endif
+
+ lcd_info->yoffset = lcd_info->yres * win->buf_index;
+
+ if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)",
+ __func__,
+ lcd_info->yres,
+ win->buf_index, lcd_info->yres_virtual,
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int window_show(struct hwc_win_info_t *win)
+{
+ if (win->power_state == 0) {
+ if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
+ __func__, win->fd, strerror(errno));
+ return -1;
+ }
+ win->power_state = 1;
+ }
+ return 0;
+}
+
+int window_hide(struct hwc_win_info_t *win)
+{
+ if (win->power_state == 1) {
+ if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
+ __func__, win->fd, strerror(errno));
+ return -1;
+ }
+ win->power_state = 0;
+ }
+ return 0;
+}
+
+int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info)
+{
+ if (ioctl(fd, FBIOGET_VSCREENINFO, lcd_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_VSCREENINFO failed : %s",
+ strerror(errno));
+ return -1;
+ }
+
+ SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: Default LCD x(%d),y(%d)",
+ __func__, lcd_info->xres, lcd_info->yres);
+ return 0;
+}
+
+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;
+
+#ifdef BOARD_USE_V4L2_ION
+ /* You MUST initialize structure for v4l2 */
+ memset(&fmt, 0, sizeof(fmt));
+ memset(&cropcap, 0, sizeof(cropcap));
+ memset(&crop, 0, sizeof(crop));
+ memset(&req, 0, sizeof(req));
+
+ /* To set size & format for source image (DMA-INPUT) */
+ fmt.fmt.pix_mp.num_planes = src->planes;
+ fmt.fmt.pix_mp.width = src->full_width;
+ fmt.fmt.pix_mp.height = src->full_height;
+ fmt.fmt.pix_mp.pixelformat = src->color_space;
+ fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
+#else
+ 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;
+#endif
+ fmt.type = V4L2_BUF_TYPE_OUTPUT;
+
+ if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::VIDIOC_S_FMT failed : errno=%d (%s)"
+ " : fd=%d\n", __func__, errno, strerror(errno), fd);
+ return -1;
+ }
+
+ /* crop input size */
+ crop.type = V4L2_BUF_TYPE_OUTPUT;
+ crop.c.width = src->width;
+ crop.c.height = src->height;
+#ifdef BOARD_USE_V4L2_ION
+ crop.c.left = src->start_x;
+ crop.c.top = src->start_y;
+#else
+ 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;
+ }
+
+#endif
+
+ if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP :"
+ "crop.c.left : (%d), crop.c.top : (%d), crop.c.width : (%d), crop.c.height : (%d)",
+ __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+ return -1;
+ }
+
+ /* input buffer type */
+ req.count = 1;
+ req.memory = V4L2_MEMORY_USERPTR;
+ req.type = V4L2_BUF_TYPE_OUTPUT;
+
+ if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst,
+ int rotation, int hflip, int vflip, unsigned int addr)
+{
+ struct v4l2_format sFormat;
+ struct v4l2_control vc;
+ struct v4l2_framebuffer fbuf;
+#ifdef BOARD_USE_V4L2_ION
+ struct v4l2_crop crop;
+ struct v4l2_requestbuffers req;
+#endif
+ int ret;
+
+#ifdef BOARD_USE_V4L2_ION
+ /* You MUST initialize structure for v4l2 */
+ memset(&sFormat, 0, sizeof(sFormat));
+ memset(&vc, 0, sizeof(vc));
+ memset(&fbuf, 0, sizeof(fbuf));
+ memset(&crop, 0, sizeof(crop));
+ memset(&req, 0, sizeof(req));
+#endif
+
+ /* set rotation configuration */
+#ifdef BOARD_USE_V4L2_ION
+ vc.id = V4L2_CID_ROTATE;
+#else
+ vc.id = V4L2_CID_ROTATION;
+#endif
+ vc.value = rotation;
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s::Error in video VIDIOC_S_CTRL - rotation (%d)"
+ "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_HFLIP;
+ vc.value = hflip;
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s::Error in video VIDIOC_S_CTRL - hflip (%d)"
+ "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_VFLIP;
+ vc.value = vflip;
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%s::Error in video VIDIOC_S_CTRL - vflip (%d)"
+ "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
+ return -1;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+ /* set destination */
+ sFormat.type = V4L2_BUF_TYPE_CAPTURE;
+ sFormat.fmt.pix_mp.width = dst->full_width;
+ sFormat.fmt.pix_mp.height = dst->full_height;
+ sFormat.fmt.pix_mp.pixelformat = dst->color_space;
+ sFormat.fmt.pix_mp.num_planes = dst->planes;
+ sFormat.fmt.pix.field = V4L2_FIELD_ANY;
+
+ ret = ioctl(fd, VIDIOC_S_FMT, &sFormat);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret);
+ return -1;
+ }
+
+ /* set destination window */
+ crop.type = V4L2_BUF_TYPE_CAPTURE;
+ crop.c.left = dst->start_x;
+ crop.c.top = dst->start_y;
+ crop.c.width = dst->width;
+ crop.c.height = dst->height;
+
+ ret = ioctl(fd, VIDIOC_S_CROP, &crop);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP (%d)", __func__, ret);
+ return -1;
+ }
+
+ /* input buffer type */
+ req.count = 1;
+ req.type = V4L2_BUF_TYPE_CAPTURE;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ ret = ioctl (fd, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS (%d)", __func__, ret);
+ return -1;
+ }
+#else
+ /* set size, format & address for destination image (DMA-OUTPUT) */
+ ret = ioctl(fd, VIDIOC_G_FBUF, &fbuf);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FBUF (%d)", __func__, ret);
+ return -1;
+ }
+
+ fbuf.base = (void *)addr;
+ fbuf.fmt.width = dst->full_width;
+ fbuf.fmt.height = dst->full_height;
+ fbuf.fmt.pixelformat = dst->color_space;
+
+ ret = ioctl(fd, VIDIOC_S_FBUF, &fbuf);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FBUF (%d)", __func__, ret);
+ return -1;
+ }
+
+ /* set destination window */
+ sFormat.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ sFormat.fmt.win.w.left = dst->start_x;
+ sFormat.fmt.win.w.top = dst->start_y;
+ sFormat.fmt.win.w.width = dst->width;
+ sFormat.fmt.win.w.height = dst->height;
+
+ ret = ioctl(fd, VIDIOC_S_FMT, &sFormat);
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret);
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
+{
+ if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMON\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type, int index)
+{
+#ifdef BOARD_USE_V4L2_ION
+ struct v4l2_plane plane[3];
+ int i;
+#endif
+ struct v4l2_buffer buf;
+ int ret;
+
+#ifdef BOARD_USE_V4L2_ION
+ buf.length = fimc_buf->planes;
+#else
+ buf.length = 0;
+ buf.m.userptr = (unsigned long)fimc_buf;
+#endif
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.index = index;
+ buf.type = type;
+
+#ifdef BOARD_USE_V4L2_ION
+ if (buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+ buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ for (i = 0; i < buf.length; i++) {
+ plane[i].m.userptr = fimc_buf->base[i];
+ plane[i].length = fimc_buf->size[i];
+ }
+ }
+ buf.m.planes = plane;
+#endif
+
+ ret = ioctl(fd, VIDIOC_QBUF, &buf);
+ if (0 > ret) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_QBUF : (%d)", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_dequeue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type)
+{
+ struct v4l2_buffer buf;
+#ifdef BOARD_USE_V4L2_ION
+ struct v4l2_plane plane[3];
+#endif
+
+#ifdef BOARD_USE_V4L2_ION
+ buf.m.planes = plane;
+ buf.length = fimc_buf->planes;
+#endif
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.type = type;
+
+ if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_DQBUF\n");
+ return -1;
+ }
+
+ return buf.index;
+}
+
+int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
+{
+ if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMOFF\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = 0;
+ req.memory = V4L2_MEMORY_USERPTR;
+ req.type = type;
+
+ if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_REQBUFS");
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_S_ctrl(int fd)
+{
+ struct v4l2_control vc;
+
+ vc.id = V4L2_CID_CACHEABLE;
+ vc.value = 1;
+
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_S_CTRL");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_src_buf, struct fimc_buf *fimc_dst_buf)
+{
+#ifdef CHECK_FPS
+ check_fps();
+#endif
+
+#ifdef BOARD_USE_V4L2_ION
+ if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()");
+ return -1;
+ }
+
+ if (fimc_v4l2_queue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE, 0) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_queue()");
+ return -2;
+ }
+
+ if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()");
+ return -3;
+ }
+
+ if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_CAPTURE) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_on()");
+ return -4;
+ }
+#else
+ if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()");
+ return -5;
+ }
+
+ if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()");
+ goto STREAM_OFF;
+ }
+#endif
+ if (fimc_v4l2_dequeue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_dequeue()");
+ return -6;
+ }
+#ifdef BOARD_USE_V4L2_ION
+ if (fimc_v4l2_dequeue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_dequeue()");
+ return -7;
+ }
+#endif
+STREAM_OFF:
+ if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_off()");
+ return -8;
+ }
+#ifdef BOARD_USE_V4L2_ION
+ if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_CAPTURE) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_off()");
+ return -9;
+ }
+#endif
+ if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_clr_buf()");
+ return -10;
+ }
+#ifdef BOARD_USE_V4L2_ION
+ if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_CAPTURE)< 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_clr_buf()");
+ return -11;
+ }
+#endif
+ return 0;
+}
+
+static int memcpy_rect(void *dst, void *src, int fullW, int fullH, int realW, int realH, int format)
+{
+ unsigned char *srcCb, *srcCr;
+ unsigned char *dstCb, *dstCr;
+ unsigned char *srcY, *dstY;
+ int srcCbOffset, srcCrOffset;
+ int dstCbOffset, dstFrameOffset, dstCrOffset;
+ int cbFullW, cbRealW, cbFullH, cbRealH;
+ int ySrcFW, ySrcFH, ySrcRW, ySrcRH;
+ int planes;
+ int i;
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "++memcpy_rect()::"
+ "dst(0x%x),src(0x%x),f.w(%d),f.h(%d),r.w(%d),r.h(%d),format(0x%x)",
+ (unsigned int)dst, (unsigned int)src, fullW, fullH, realW, realH, format);
+
+// Set dst Y, Cb, Cr address for FIMC
+ {
+ cbFullW = fullW >> 1;
+ cbRealW = realW >> 1;
+ cbFullH = fullH >> 1;
+ cbRealH = realH >> 1;
+ dstFrameOffset = fullW * fullH;
+ dstCrOffset = cbFullW * cbFullH;
+ dstY = (unsigned char *)dst;
+ dstCb = (unsigned char *)dst + dstFrameOffset;
+ dstCr = (unsigned char *)dstCb + dstCrOffset;
+ }
+
+// Get src Y, Cb, Cr address for source buffer.
+// Each address is aligned by 16's multiple for GPU both width and height.
+ {
+ ySrcFW = fullW;
+ ySrcFH = fullH;
+ ySrcRW = realW;
+ ySrcRH = realH;
+ srcCbOffset = EXYNOS4_ALIGN(ySrcRW,16)* EXYNOS4_ALIGN(ySrcRH,16);
+ srcCrOffset = EXYNOS4_ALIGN(cbRealW,16)* EXYNOS4_ALIGN(cbRealH,16);
+ srcY = (unsigned char *)src;
+ srcCb = (unsigned char *)src + srcCbOffset;
+ srcCr = (unsigned char *)srcCb + srcCrOffset;
+ }
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "--memcpy_rect()::\n"
+ "dstY(0x%x),dstCb(0x%x),dstCr(0x%x) \n"
+ "srcY(0x%x),srcCb(0x%x),srcCr(0x%x) \n"
+ "cbRealW(%d),cbRealH(%d)",
+ (unsigned int)dstY,(unsigned int)dstCb,(unsigned int)dstCr,
+ (unsigned int)srcY,(unsigned int)srcCb,(unsigned int)srcCr,
+ cbRealW, cbRealH);
+
+ if (format == HAL_PIXEL_FORMAT_YV12) { //YV12(Y,Cr,Cv)
+ planes = 3;
+//This is code for VE, deleted temporory by SSONG 2011.09.22
+// This will be enabled later.
+/*
+ //as defined in hardware.h, cb & cr full_width should be aligned to 16. ALIGN(y_stride/2, 16).
+ ////Alignment is hard coded to 16.
+ ////for example...check frameworks/media/libvideoeditor/lvpp/VideoEditorTools.cpp file for UV stride cal
+ cbSrcFW = (cbSrcFW + 15) & (~15);
+ srcCbOffset = ySrcFW * fullH;
+ srcCrOffset = srcCbOffset + ((cbSrcFW * fullH) >> 1);
+ srcY = (unsigned char *)src;
+ srcCb = (unsigned char *)src + srcCbOffset;
+ srcCr = (unsigned char *)src + srcCrOffset;
+*/
+ } else if ((format == HAL_PIXEL_FORMAT_YCbCr_420_P)) {
+ planes = 3;
+ } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ planes = 2;
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR, "use default memcpy instead of memcpy_rect");
+ return -1;
+ }
+//#define CHECK_PERF
+#ifdef CHECK_PERF
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+ for (i = 0; i < realH; i++)
+ memcpy(dstY + fullW * i, srcY + ySrcFW * i, ySrcRW);
+ if (planes == 2) {
+ for (i = 0; i < cbRealH; i++)
+ memcpy(dstCb + ySrcFW * i, srcCb + ySrcFW * i, ySrcRW);
+ } else if (planes == 3) {
+ for (i = 0; i < cbRealH; i++)
+ memcpy(dstCb + cbFullW * i, srcCb + cbFullW * i, cbRealW);
+ for (i = 0; i < cbRealH; i++)
+ memcpy(dstCr + cbFullW * i, srcCr + cbFullW * i, cbRealW);
+ }
+#ifdef CHECK_PERF
+ gettimeofday(&end, NULL);
+ SEC_HWC_Log(HWC_LOG_ERROR, "[COPY]=%d,",(end.tv_sec - start.tv_sec)*1000+(end.tv_usec - start.tv_usec)/1000);
+#endif
+
+ return 0;
+}
+
+/*****************************************************************************/
+static int get_src_phys_addr(struct hwc_context_t *ctx,
+ sec_img *src_img, sec_rect *src_rect)
+{
+ s5p_fimc_t *fimc = &ctx->fimc;
+ struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0];
+ struct s3c_mem_dma_param s3c_mem_dma;
+#ifdef USE_HW_PMEM
+ sec_pmem_alloc_t *pm_alloc = &ctx->sec_pmem.sec_pmem_alloc[0];
+#endif
+
+ unsigned int src_virt_addr = 0;
+ unsigned int src_phys_addr = 0;
+ unsigned int src_frame_size = 0;
+
+ struct pmem_region region;
+ ADDRS * addr;
+
+ // error check routine
+ if (0 == src_img->base && !(src_img->usage & GRALLOC_USAGE_HW_FIMC1)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src image base\n", __func__);
+ return 0;
+ }
+
+ switch (src_img->mem_type) {
+ case HWC_PHYS_MEM_TYPE:
+ src_phys_addr = src_img->base + src_img->offset;
+ break;
+
+ case HWC_VIRT_MEM_TYPE:
+ case HWC_UNKNOWN_MEM_TYPE:
+ switch (src_img->format) {
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
+ addr = (ADDRS *)(src_img->base);
+ fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
+ fimc->params.src.buf_addr_phy_cb = addr->addr_cbcr;
+
+ src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
+ if (0 == src_phys_addr) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
+ "(format=CUSTOM_YCbCr/YCrCb_420_SP Y-addr=0x%x "
+ "CbCr-Addr=0x%x)",
+ __func__, fimc->params.src.buf_addr_phy_rgb_y,
+ fimc->params.src.buf_addr_phy_cb);
+ return 0;
+ }
+ break;
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
+ addr = (ADDRS *)(src_img->base + src_img->offset);
+ fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
+ src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
+ if (0 == src_phys_addr) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
+ "(format=CUSTOM_YCbCr/CbYCrY_422_I Y-addr=0x%x)",
+ __func__, fimc->params.src.buf_addr_phy_rgb_y);
+ return 0;
+ }
+ break;
+ default:
+#ifdef BOARD_USE_V4L2_ION
+ fimc->params.src.buf_addr_phy_rgb_y = src_img->base;
+ fimc->params.src.buf_addr_phy_cb = src_img->base + src_img->uoffset;
+ fimc->params.src.buf_addr_phy_cr = src_img->base + src_img->uoffset + src_img->voffset;
+ src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
+ break;
+#endif
+ if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
+ fimc->params.src.buf_addr_phy_rgb_y = src_img->paddr;
+ fimc->params.src.buf_addr_phy_cb = src_img->paddr + src_img->uoffset;
+ fimc->params.src.buf_addr_phy_cr = src_img->paddr + src_img->uoffset + src_img->voffset;
+ src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
+ break;
+ }
+ // copy
+ src_frame_size = FRAME_SIZE(src_img->format, src_img->w, src_img->h);
+ if (src_frame_size == 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FRAME_SIZE fail", __func__);
+ return 0;
+ }
+
+#ifdef USE_HW_PMEM
+ if (0 <= checkPmem(&ctx->sec_pmem, 0, src_frame_size)) {
+ src_virt_addr = pm_alloc->virt_addr;
+ src_phys_addr = pm_alloc->phys_addr;
+ pm_alloc->size = src_frame_size;
+ } else
+#endif
+ if (0 <= checkMem(&ctx->s3c_mem, 0, src_frame_size)) {
+ src_virt_addr = ptr_mem_alloc->vir_addr;
+ src_phys_addr = ptr_mem_alloc->phy_addr;
+ ptr_mem_alloc->size = src_frame_size;
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::check_mem fail", __func__);
+ return 0;
+ }
+ if ((src_img->format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
+ (src_img->format == HAL_PIXEL_FORMAT_YV12) ||
+ (src_img->format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
+ (src_img->format == HAL_PIXEL_FORMAT_YCrCb_420_SP)) {
+ if (memcpy_rect((void *)src_virt_addr, (void*)((unsigned int)src_img->base),
+ src_img->f_w, src_img->f_h, src_rect->w, src_rect->h, src_img->format) != 0)
+ return 0;
+ } else {
+ memcpy((void *)src_virt_addr, (void*)((unsigned int)src_img->base), src_frame_size);
+ }
+
+#ifdef USE_HW_PMEM
+ if (pm_alloc->size == src_frame_size) {
+ region.offset = 0;
+ region.len = src_frame_size;
+ if (ioctl(ctx->sec_pmem.pmem_master_fd, PMEM_CACHE_FLUSH, &region) < 0)
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::pmem cache flush fail ", __func__);
+ }
+#endif
+ break;
+ }
+ }
+
+ return src_phys_addr;
+}
+
+static int get_dst_phys_addr(struct hwc_context_t *ctx, sec_img *dst_img,
+ sec_rect *dst_rect, int *dst_memcpy_flag)
+{
+ unsigned int dst_phys_addr = 0;
+
+ if (HWC_PHYS_MEM_TYPE == dst_img->mem_type && 0 != dst_img->base)
+ dst_phys_addr = dst_img->base;
+ else
+ dst_phys_addr = dst_img->base;
+
+ return dst_phys_addr;
+}
+
+static inline int rotateValueHAL2PP(unsigned char transform)
+{
+ int rotate_flag = transform & 0x7;
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_ROT_90: return 90;
+ case HAL_TRANSFORM_ROT_180: return 180;
+ case HAL_TRANSFORM_ROT_270: return 270;
+ case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: return 90;
+ case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: return 90;
+ case HAL_TRANSFORM_FLIP_H: return 0;
+ case HAL_TRANSFORM_FLIP_V: return 0;
+ }
+ return 0;
+}
+
+static inline int hflipValueHAL2PP(unsigned char transform)
+{
+ int flip_flag = transform & 0x7;
+ switch (flip_flag) {
+ case HAL_TRANSFORM_FLIP_H:
+ case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
+ return 1;
+ case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_180:
+ case HAL_TRANSFORM_ROT_270:
+ case HAL_TRANSFORM_FLIP_V:
+ break;
+ }
+ return 0;
+}
+
+static inline int vflipValueHAL2PP(unsigned char transform)
+{
+ int flip_flag = transform & 0x7;
+ switch (flip_flag) {
+ case HAL_TRANSFORM_FLIP_V:
+ case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
+ return 1;
+ case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_180:
+ case HAL_TRANSFORM_ROT_270:
+ case HAL_TRANSFORM_FLIP_H:
+ break;
+ }
+ return 0;
+}
+
+static inline int multipleOf2(int number)
+{
+ if (number % 2 == 1)
+ return (number - 1);
+ else
+ return number;
+}
+
+static inline int multipleOf4(int number)
+{
+ int remain_number = number % 4;
+
+ if (remain_number != 0)
+ return (number - remain_number);
+ else
+ return number;
+}
+
+static inline int multipleOf8(int number)
+{
+ int remain_number = number % 8;
+
+ if (remain_number != 0)
+ return (number - remain_number);
+ else
+ return number;
+}
+
+static inline int multipleOf16(int number)
+{
+ int remain_number = number % 16;
+
+ if (remain_number != 0)
+ return (number - remain_number);
+ else
+ return number;
+}
+
+static inline int widthOfPP(unsigned int ver, int pp_color_format, int number)
+{
+#ifdef BOARD_USE_V4L2_ION
+ if (1) {
+#else
+ if (0x50 <= ver) {
+#endif
+ 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 multipleOf2(number);
+
+ default :
+ return number;
+ }
+ } else {
+ switch (pp_color_format) {
+ case V4L2_PIX_FMT_RGB565:
+ return multipleOf8(number);
+
+ case V4L2_PIX_FMT_RGB32:
+ return multipleOf4(number);
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ return multipleOf4(number);
+
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ return multipleOf8(number);
+
+ case V4L2_PIX_FMT_YUV422P:
+ return multipleOf16(number);
+
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ return multipleOf8(number);
+
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOf16(number);
+
+ 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 multipleOf2(number);
+
+ default :
+ return number;
+ break;
+ }
+ return number;
+}
+
+static unsigned int get_yuv_bpp(unsigned int fmt)
+{
+ int i, sel = -1;
+
+ for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+ if (yuv_list[i].fmt == fmt) {
+ sel = i;
+ break;
+ }
+ }
+
+ if (sel == -1)
+ return sel;
+ else
+ return yuv_list[sel].bpp;
+}
+
+static unsigned int get_yuv_planes(unsigned int fmt)
+{
+ int i, sel = -1;
+
+ for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
+ if (yuv_list[i].fmt == fmt) {
+ sel = i;
+ break;
+ }
+ }
+
+ if (sel == -1)
+ return sel;
+ else
+ return yuv_list[sel].planes;
+}
+
+static int runcFimcCore(struct hwc_context_t *ctx,
+ unsigned int src_phys_addr, 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_t * fimc = &ctx->fimc;
+ s5p_fimc_params_t * params = &(fimc->params);
+
+ struct fimc_buf fimc_src_buf;
+ int src_bpp, src_planes;
+
+#ifdef BOARD_USE_V4L2_ION
+ struct fimc_buf fimc_dst_buf;
+ int dst_bpp, dst_planes;
+ unsigned int src_frame_size = 0;
+ unsigned int dst_frame_size = 0;
+#endif
+ unsigned int frame_size = 0;
+
+ bool src_cbcr_order = true;
+ int rotate_value = rotateValueHAL2PP(transform);
+ int hflip = hflipValueHAL2PP(transform);
+ int vflip = vflipValueHAL2PP(transform);
+
+ /* 1. param(fimc config)->src information
+ * - src_img,src_rect => s_fw,s_fh,s_w,s_h,s_x,s_y
+ */
+ params->src.full_width = src_img->f_w;
+ params->src.full_height = src_img->f_h;
+ params->src.width = src_rect->w;
+ params->src.height = src_rect->h;
+ params->src.start_x = src_rect->x;
+ params->src.start_y = src_rect->y;
+ params->src.color_space = src_color_space;
+ params->src.buf_addr_phy_rgb_y = src_phys_addr;
+
+#ifdef BOARD_USE_V4L2_ION
+ params->dst.full_width = dst_img->f_w;
+ params->dst.full_height = dst_img->f_h;
+ params->dst.width = widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+ params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
+ params->dst.start_x = dst_rect->x;
+ params->dst.start_y = dst_rect->y;
+ params->dst.color_space = dst_color_space;
+ params->dst.buf_addr_phy_rgb_y = dst_phys_addr;
+#endif
+
+ /* check src minimum */
+ if (src_rect->w < 16 || src_rect->h < 8) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%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;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+#else
+ /* 2. param(fimc config)->dst information
+ * - dst_img,dst_rect,rot => d_fw,d_fh,d_w,d_h,d_x,d_y
+ */
+ switch (rotate_value) {
+ case 0:
+ params->dst.full_width = dst_img->f_w;
+ params->dst.full_height = dst_img->f_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->f_h;
+ params->dst.full_height = dst_img->f_w;
+
+ params->dst.start_x = dst_rect->y;
+ params->dst.start_y = dst_img->f_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->f_w;
+ params->dst.full_height = dst_img->f_h;
+
+ params->dst.start_x = dst_img->f_w - (dst_rect->x + dst_rect->w);
+ params->dst.start_y = dst_img->f_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->f_h;
+ params->dst.full_height = dst_img->f_w;
+
+ params->dst.start_x = dst_img->f_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;
+#endif
+
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "runcFimcCore()::"
+ "SRC f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)=>"
+ "DST f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)",
+ params->src.full_width, params->src.full_height,
+ params->src.start_x, params->src.start_y,
+ params->src.width, params->src.height,
+ params->dst.full_width, params->dst.full_height,
+ params->dst.start_x, params->dst.start_y,
+ params->dst.width, params->dst.height);
+
+ /* check dst minimum */
+ if (dst_rect->w < 8 || dst_rect->h < 4) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%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))) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "%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;
+ }
+
+ /* 3. Set configuration related to destination (DMA-OUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+#ifdef BOARD_USE_V4L2_ION
+ switch (dst_img->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ dst_planes = 1;
+ dst_bpp = 32;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ dst_planes = 1;
+ dst_bpp = 16;
+ break;
+ }
+
+ dst_frame_size = params->dst.width * params->dst.height ;
+ params->dst.planes = dst_planes;
+
+ if (dst_planes == 1) {
+ fimc_dst_buf.base[0] = params->dst.buf_addr_phy_rgb_y;
+ if (dst_bpp == 32)
+ fimc_dst_buf.size[0] = dst_frame_size * 4;
+ else if (dst_bpp == 16)
+ fimc_dst_buf.size[0] = dst_frame_size * 2;
+ }
+#endif
+
+ if (fimc_v4l2_set_dst(fimc->dev_fd, &params->dst, rotate_value, hflip, vflip, dst_phys_addr) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_dst is failed\n");
+ return -1;
+ }
+
+ /* 4. Set configuration related to source (DMA-INPUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+#ifndef BOARD_USE_V4L2_ION
+ if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, &params->src) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n");
+ return -1;
+ }
+#endif
+
+ /* 5. Set input dma address (Y/RGB, Cb, Cr)
+ * - zero copy : mfc, camera
+ * - memcpy to pmem : SW dec(420P), video editor(YV12)
+ */
+ switch (src_img->format) {
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
+ /* for video contents 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;
+
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_YV12:
+ default:
+ if (src_img->format == HAL_PIXEL_FORMAT_YV12)
+ src_cbcr_order = false;
+
+#ifdef BOARD_USE_V4L2_ION
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ if (src_cbcr_order == true) {
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cr;
+ } else {
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cr;
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cb;
+ }
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n",
+ fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]);
+ src_frame_size = params->src.full_width * params->src.full_height;
+ fimc_src_buf.size[0] = src_frame_size;
+ fimc_src_buf.size[1] = src_frame_size >> 2;
+ fimc_src_buf.size[2] = src_frame_size >> 2;
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "runFimcCore - Y_length=%d, U_length=%d, V_length=%d\n",
+ fimc_src_buf.size[0], fimc_src_buf.size[1],fimc_src_buf.size[2]);
+ src_planes = get_yuv_planes(src_color_space);
+
+ break;
+#endif
+
+ if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ if (src_cbcr_order == true) {
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cr;
+ }
+ else {
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cb;
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cr;
+ }
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n",
+ fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]);
+ break;
+ }
+
+ /* set source Y image */
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ /* set source Cb,Cr images for 2 or 3 planes */
+ src_bpp = get_yuv_bpp(src_color_space);
+ src_planes = get_yuv_planes(src_color_space);
+ if (2 == src_planes) { /* 2 planes */
+ frame_size = params->src.full_width * params->src.full_height;
+ params->src.buf_addr_phy_cb =
+ params->src.buf_addr_phy_rgb_y + frame_size;
+ /* CbCr */
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ } else if (3 == src_planes) { /* 3 planes */
+ frame_size = params->src.full_width * params->src.full_height;
+ params->src.buf_addr_phy_cb =
+ params->src.buf_addr_phy_rgb_y + frame_size;
+ if (12 == src_bpp)
+ params->src.buf_addr_phy_cr =
+ params->src.buf_addr_phy_cb + (frame_size >> 2);
+ else
+ params->src.buf_addr_phy_cr =
+ params->src.buf_addr_phy_cb + (frame_size >> 1);
+ /* Cb, Cr */
+ if (src_cbcr_order == true) {
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cr;
+ }
+ else {
+ fimc_src_buf.base[2] = params->src.buf_addr_phy_cb;
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cr;
+ }
+ }
+ break;
+ }
+
+ /* 6. Run FIMC
+ * - stream on => queue => dequeue => stream off => clear buf
+ */
+#ifdef BOARD_USE_V4L2_ION
+ int ret = 0;
+ params->src.planes = src_planes;
+
+ if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, &params->src) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n");
+ return -1;
+ }
+
+ fimc_src_buf.planes = src_planes;
+ fimc_dst_buf.planes = dst_planes;
+
+ ret = fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, &fimc_dst_buf);
+
+ if (ret < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR,"fimc_handle_oneshot = %d\n",ret);
+ if (ret == -2) {
+ fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT);
+ } else if (ret == -3) {
+ fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT);
+ fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_CAPTURE);
+ }
+ return ret;
+ }
+#else
+ if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, NULL) < 0) {
+ fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT);
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+#ifdef SUB_TITLES_HWC
+int createG2d(sec_g2d_t *g2d)
+{
+ g2d->dev_fd = open(SEC_G2D_DEV_NAME, O_RDWR);
+
+ if (g2d->dev_fd <= 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::G2d open error (%d)", __func__, errno);
+ goto err;
+ }
+
+ return 0;
+err:
+ if (0 < g2d->dev_fd)
+ close(g2d->dev_fd);
+ g2d->dev_fd =0;
+
+ return -1;
+}
+
+int destroyG2d(sec_g2d_t *g2d)
+{
+ // close
+ if (0 < g2d->dev_fd)
+ close(g2d->dev_fd);
+ g2d->dev_fd = 0;
+
+ return 0;
+}
+#endif
+
+int createFimc(s5p_fimc_t *fimc)
+{
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+ struct v4l2_control vc;
+
+ // open device file
+ if (fimc->dev_fd <= 0)
+ fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR);
+
+ if (fimc->dev_fd <= 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Post processor open error (%d)",
+ __func__, errno);
+ goto err;
+ }
+
+ // check capability
+ if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "VIDIOC_QUERYCAP failed");
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%d has no streaming support", fimc->dev_fd);
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%d is no video output", fimc->dev_fd);
+ goto err;
+ }
+
+ /*
+ * malloc fimc_outinfo structure
+ */
+ fmt.type = V4L2_BUF_TYPE_OUTPUT;
+ if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FMT", __func__);
+ goto err;
+ }
+
+#ifdef BOARD_USE_V4L2_ION
+#else
+ vc.id = V4L2_CID_FIMC_VERSION;
+ vc.value = 0;
+
+ if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_CTRL", __func__);
+ goto err;
+ }
+ fimc->hw_ver = vc.value;
+#endif
+
+ return 0;
+
+err:
+ if (0 < fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd =0;
+
+ return -1;
+}
+
+int destroyFimc(s5p_fimc_t *fimc)
+{
+ if (fimc->out_buf.virt_addr != NULL) {
+ fimc->out_buf.virt_addr = NULL;
+ fimc->out_buf.length = 0;
+ }
+
+ // close
+ if (0 < fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd = 0;
+
+ return 0;
+}
+
+int runFimc(struct hwc_context_t *ctx,
+ struct sec_img *src_img, struct sec_rect *src_rect,
+ struct sec_img *dst_img, struct sec_rect *dst_rect,
+ uint32_t transform)
+{
+ s5p_fimc_t * fimc = &ctx->fimc;
+
+ unsigned int src_phys_addr = 0;
+ unsigned int dst_phys_addr = 0;
+ int rotate_value = 0;
+ int flag_force_memcpy = 0;
+ int32_t src_color_space;
+ int32_t dst_color_space;
+
+ /* 1. source address and size */
+ src_phys_addr = get_src_phys_addr(ctx, src_img, src_rect);
+ if (0 == src_phys_addr)
+ return -1;
+
+ /* 2. destination address and size */
+ dst_phys_addr = get_dst_phys_addr(ctx, dst_img, dst_rect, &flag_force_memcpy);
+ if (0 == dst_phys_addr)
+ return -2;
+
+ /* 3. check whether fimc supports the src format */
+ src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
+ if (0 > src_color_space)
+ return -3;
+ dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
+ if (0 > dst_color_space)
+ return -4;
+
+ /* 4. FIMC: src_rect of src_img => dst_rect of dst_img */
+ if (runcFimcCore(ctx, src_phys_addr, 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;
+
+ if (flag_force_memcpy == 1) {
+#ifdef USE_HW_PMEM
+ if (0 != ctx->sec_pmem.sec_pmem_alloc[1].size) {
+ struct s3c_mem_dma_param s3c_mem_dma;
+
+ s3c_mem_dma.src_addr =
+ (unsigned long)(ctx->sec_pmem.sec_pmem_alloc[1].virt_addr);
+ s3c_mem_dma.size = ctx->sec_pmem.sec_pmem_alloc[1].size;
+
+ ioctl(ctx->s3c_mem.fd, S3C_MEM_CACHE_INVAL, &s3c_mem_dma);
+
+ memcpy((void*)((unsigned int)dst_img->base),
+ (void *)(ctx->sec_pmem.sec_pmem_alloc[1].virt_addr),
+ ctx->sec_pmem.sec_pmem_alloc[1].size);
+ } else
+#endif
+ {
+ struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[1];
+ struct s3c_mem_dma_param s3c_mem_dma;
+
+ s3c_mem_dma.src_addr = (unsigned long)ptr_mem_alloc->vir_addr;
+ s3c_mem_dma.size = ptr_mem_alloc->size;
+
+ ioctl(ctx->s3c_mem.fd, S3C_MEM_CACHE_INVAL, &s3c_mem_dma);
+
+ memcpy((void*)((unsigned int)dst_img->base),
+ (void *)ptr_mem_alloc->vir_addr, ptr_mem_alloc->size);
+ }
+ }
+
+ return 0;
+}
+
+#ifdef SUB_TITLES_HWC
+static int get_g2d_src_phys_addr(struct hwc_context_t *ctx, g2d_rect *src_rect)
+{
+ sec_g2d_t *g2d = &ctx->g2d;
+ struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0];
+#ifdef USE_HW_PMEM
+ sec_pmem_alloc_t *pm_alloc = &ctx->sec_pmem.sec_pmem_alloc[0];
+#endif
+
+ unsigned int src_virt_addr = 0;
+ unsigned int src_phys_addr = 0;
+ unsigned int src_frame_size = 0;
+
+ struct pmem_region region;
+
+ // error check routine
+ if (0 == src_rect->virt_addr) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src address\n", __func__);
+ return 0;
+ }
+
+ src_frame_size = FRAME_SIZE(src_rect->color_format,
+ src_rect->full_w, src_rect->full_h);
+ if (src_frame_size == 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::FRAME_SIZE fail", __func__);
+ return 0;
+ }
+
+#ifdef USE_HW_PMEM
+ if (0 <= checkPmem(&ctx->sec_pmem, 0, src_frame_size)) {
+ src_virt_addr = pm_alloc->virt_addr;
+ src_phys_addr = pm_alloc->phys_addr;
+ pm_alloc->size = src_frame_size;
+ } else
+#endif
+ if (0 <= checkMem(&ctx->s3c_mem, 0, src_frame_size)) {
+ src_virt_addr = ptr_mem_alloc->vir_addr;
+ src_phys_addr = ptr_mem_alloc->phy_addr;
+ ptr_mem_alloc->size = src_frame_size;
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::check_mem fail", __func__);
+ return 0;
+ }
+ memcpy((void *)src_virt_addr, (void*)((unsigned int)src_rect->virt_addr), src_frame_size);
+
+ return src_phys_addr;
+}
+
+int get_HAL_2_G2D_FORMAT(int format)
+{
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888: return G2D_ABGR_8888;
+ case HAL_PIXEL_FORMAT_RGBX_8888: return G2D_XBGR_8888;
+ case HAL_PIXEL_FORMAT_BGRA_8888: return G2D_ARGB_8888;
+ case HAL_PIXEL_FORMAT_RGB_888: return G2D_PACKED_BGR_888;
+ case HAL_PIXEL_FORMAT_RGB_565: return G2D_RGB_565;
+ case HAL_PIXEL_FORMAT_RGBA_5551: return G2D_RGBA_5551;
+ case HAL_PIXEL_FORMAT_RGBA_4444: return G2D_RGBA_4444;
+ default:
+ return -1;
+ }
+}
+
+static inline int rotateValueHAL2G2D(unsigned char transform)
+{
+ int rotate_flag = transform & 0x7;
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_ROT_90: return G2D_ROT_90;
+ case HAL_TRANSFORM_ROT_180: return G2D_ROT_180;
+ case HAL_TRANSFORM_ROT_270: return G2D_ROT_270;
+ default:
+ return G2D_ROT_0;
+ }
+}
+
+int runG2d(struct hwc_context_t *ctx, g2d_rect *src_rect, g2d_rect *dst_rect,
+ uint32_t transform)
+{
+ sec_g2d_t * g2d = &ctx->g2d;
+ g2d_flag flag = {G2D_ROT_0, G2D_ALPHA_BLENDING_OPAQUE, 0, 0, 0, 0, 0, 0};
+ int rotate_value = 0;
+
+ // 1 : source address and size
+ src_rect->phys_addr = get_g2d_src_phys_addr(ctx, src_rect);
+ if (0 == src_rect->phys_addr)
+ return -1;
+
+ // 2 : destination address and size
+ if (0 == dst_rect->phys_addr)
+ return -2;
+
+ // check whether g2d supports the src format
+ src_rect->color_format = get_HAL_2_G2D_FORMAT(src_rect->color_format);
+ if (0 > src_rect->color_format)
+ return -3;
+
+ dst_rect->color_format = get_HAL_2_G2D_FORMAT(dst_rect->color_format);
+ if (0 > dst_rect->color_format)
+ return -4;
+
+ flag.rotate_val = rotateValueHAL2G2D(transform);
+
+ // scale and rotate and alpha with FIMG
+ if(stretchSecFimg(src_rect, dst_rect, &flag) < 0)
+ return -5;
+
+ return 0;
+}
+#endif
+
+int createMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size)
+{
+ struct s3c_mem_alloc *ptr_mem_alloc;
+ struct s3c_mem_alloc mem_alloc_info;
+
+ if (index >= NUM_OF_MEM_OBJ) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)",
+ __func__, index, NUM_OF_MEM_OBJ);
+ goto err;
+ }
+
+ ptr_mem_alloc = &mem->mem_alloc[index];
+
+ if (mem->fd <= 0) {
+ mem->fd = open(S3C_MEM_DEV_NAME, O_RDWR);
+ if (mem->fd <= 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)",
+ __func__, S3C_MEM_DEV_NAME, strerror(errno));
+ goto err;
+ }
+ }
+
+ // kcoolsw : what the hell of this line??
+ if (0 == size)
+ return 0;
+
+ mem_alloc_info.size = size;
+
+ if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail",
+ __func__, mem_alloc_info.size);
+ goto err;
+ }
+
+ ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr;
+ ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr;
+ ptr_mem_alloc->size = mem_alloc_info.size;
+
+ return 0;
+
+err:
+ if (0 < mem->fd)
+ close(mem->fd);
+ mem->fd = 0;
+
+ return 0;
+}
+
+int destroyMem(struct s3c_mem_t *mem)
+{
+ int i;
+ struct s3c_mem_alloc *ptr_mem_alloc;
+
+ if (mem->fd <= 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalied fd(%d) fail", __func__, mem->fd);
+ return -1;
+ }
+
+ for (i = 0; i < NUM_OF_MEM_OBJ; i++) {
+ ptr_mem_alloc = &mem->mem_alloc[i];
+
+ if (0 != ptr_mem_alloc->vir_addr) {
+ if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__);
+ return -1;
+ }
+
+ ptr_mem_alloc->phy_addr = 0;
+ ptr_mem_alloc->vir_addr = 0;
+ ptr_mem_alloc->size = 0;
+ }
+ }
+
+ close(mem->fd);
+ mem->fd = 0;
+
+ return 0;
+}
+
+int checkMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size)
+{
+ int ret;
+ struct s3c_mem_alloc *ptr_mem_alloc;
+ struct s3c_mem_alloc mem_alloc_info;
+
+ if (index >= NUM_OF_MEM_OBJ) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)", __func__,
+ index, NUM_OF_MEM_OBJ);
+ return -1;
+ }
+
+ if (mem->fd <= 0) {
+ ret = createMem(mem, index, size);
+ return ret;
+ }
+
+ ptr_mem_alloc = &mem->mem_alloc[index];
+
+ if (ptr_mem_alloc->size < (int)size) {
+ if (0 < ptr_mem_alloc->size) {
+ // free allocated mem
+ if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__);
+ return -1;
+ }
+ }
+
+ // allocate mem with requested size
+ mem_alloc_info.size = size;
+ if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail",
+ __func__, mem_alloc_info.size);
+ return -1;
+ }
+
+ ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr;
+ ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr;
+ ptr_mem_alloc->size = mem_alloc_info.size;
+ }
+
+ return 0;
+}
+
+#ifdef USE_HW_PMEM
+int createPmem(sec_pmem_t *pm, unsigned int buf_size)
+{
+ int master_fd, err = 0, i;
+ void *base;
+ unsigned int phys_base;
+ size_t size, sub_size[NUM_OF_MEM_OBJ];
+ struct pmem_region region;
+
+ master_fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0);
+ if (master_fd < 0) {
+ pm->pmem_master_fd = -1;
+ if (EACCES == errno) {
+ return 0;
+ } else {
+ SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)",
+ __func__, PMEM_DEVICE_DEV_NAME, strerror(errno));
+ return -errno;
+ }
+ }
+
+ if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, &region) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_TOTAL_SIZE failed, default mode");
+ size = 8<<20; // 8 MiB
+ } else {
+ size = region.len;
+ }
+
+ base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0);
+ if (base == MAP_FAILED) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "[%s] mmap failed : %d (%s)", __func__,
+ errno, strerror(errno));
+ base = 0;
+ close(master_fd);
+ master_fd = -1;
+ return -errno;
+ }
+
+ if (ioctl(master_fd, PMEM_GET_PHYS, &region) < 0) {
+ SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_PHYS failed, limp mode");
+ region.offset = 0;
+ }
+
+ pm->pmem_master_fd = master_fd;
+ pm->pmem_master_base = base;
+ pm->pmem_total_size = size;
+ //pm->pmem_master_phys_base = region.offset;
+ phys_base = region.offset;
+
+ // sec_pmem_alloc[0] for temporary buffer for source
+ sub_size[0] = buf_size;
+ sub_size[0] = roundUpToPageSize(sub_size[0]);
+
+ for (i = 0; i < NUM_OF_MEM_OBJ; i++) {
+ sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[i]);
+ int fd, ret;
+ int offset = i ? sub_size[i-1] : 0;
+ struct pmem_region sub = { offset, sub_size[i] };
+
+ // create the "sub-heap"
+ if (0 > (fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0))) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "[%s][index=%d] open failed (%dL) : %d (%s)",
+ __func__, i, __LINE__, errno, strerror(errno));
+ return -errno;
+ }
+
+ // connect to it
+ if (0 != (ret = ioctl(fd, PMEM_CONNECT, pm->pmem_master_fd))) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "[%s][index=%d] ioctl(PMEM_CONNECT) failed : %d (%s)",
+ __func__, i, errno, strerror(errno));
+ close(fd);
+ return -errno;
+ }
+
+ // make it available to the client process
+ if (0 != (ret = ioctl(fd, PMEM_MAP, &sub))) {
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "[%s][index=%d] ioctl(PMEM_MAP) failed : %d (%s)",
+ __func__, i, errno, strerror(errno));
+ close(fd);
+ return -errno;
+ }
+
+ pm_alloc->fd = fd;
+ pm_alloc->total_size = sub_size[i];
+ pm_alloc->offset = offset;
+ pm_alloc->virt_addr = (unsigned int)base + (unsigned int)offset;
+ pm_alloc->phys_addr = (unsigned int)phys_base + (unsigned int)offset;
+
+#if defined (PMEM_DEBUG)
+ SEC_HWC_Log(HWC_LOG_DEBUG, "[%s] pm_alloc[%d] fd=%d total_size=%d "
+ "offset=0x%x virt_addr=0x%x phys_addr=0x%x",
+ __func__, i, pm_alloc->fd, pm_alloc->total_size,
+ pm_alloc->offset, pm_alloc->virt_addr, pm_alloc->phys_addr);
+#endif
+ }
+
+ return err;
+}
+
+int destroyPmem(sec_pmem_t *pm)
+{
+ int i, err;
+
+ for (i=0; i<NUM_OF_MEM_OBJ; i++) {
+ sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[i]);
+
+ if (0 <= pm_alloc->fd) {
+ struct pmem_region sub = { pm_alloc->offset, pm_alloc->total_size };
+
+ if (0 > (err = ioctl(pm_alloc->fd, PMEM_UNMAP, &sub)))
+ SEC_HWC_Log(HWC_LOG_ERROR,
+ "[%s][index=%d] ioctl(PMEM_UNMAP) failed : %d (%s)",
+ __func__, i, errno, strerror(errno));
+#if defined (PMEM_DEBUG)
+ else
+ SEC_HWC_Log(HWC_LOG_DEBUG,
+ "[%s] pm_alloc[%d] unmap fd=%d total_size=%d offset=0x%x",
+ __func__, i, pm_alloc->fd, pm_alloc->total_size,
+ pm_alloc->offset);
+#endif
+ close(pm_alloc->fd);
+
+ pm_alloc->fd = -1;
+ pm_alloc->total_size = 0;
+ pm_alloc->offset = 0;
+ pm_alloc->virt_addr = 0;
+ pm_alloc->phys_addr = 0;
+ }
+ }
+
+ if (0 <= pm->pmem_master_fd) {
+ munmap(pm->pmem_master_base, pm->pmem_total_size);
+ close(pm->pmem_master_fd);
+ pm->pmem_master_fd = -1;
+ }
+
+ pm->pmem_master_base = 0;
+ pm->pmem_total_size = 0;
+
+ return 0;
+}
+
+int checkPmem(sec_pmem_t *pm, unsigned int index, unsigned int requested_size)
+{
+ sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[index]);
+
+ if (0 < pm_alloc->virt_addr &&
+ requested_size <= (unsigned int)(pm_alloc->total_size))
+ return 0;
+
+ pm_alloc->size = 0;
+ return -1;
+}
+
+#endif
diff --git a/exynos4/hal/libhwcomposer/SecHWCUtils.h b/exynos4/hal/libhwcomposer/SecHWCUtils.h
new file mode 100644
index 0000000..005b694
--- /dev/null
+++ b/exynos4/hal/libhwcomposer/SecHWCUtils.h
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie, Oh (jung-min.oh@samsung.com)
+ * @date 2011-03-11
+ *
+ */
+
+#ifndef ANDROID_SEC_HWC_UTILS_H_
+#define ANDROID_SEC_HWC_UTILS_H_
+
+#include <stdlib.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <cutils/log.h>
+
+#ifdef BOARD_USE_V4L2_ION
+#include <ion.h>
+#include "s5p_fimc_v4l2.h"
+#include "sec_utils_v4l2.h"
+#else
+#include <linux/videodev.h>
+#include "s5p_fimc.h"
+#include "sec_utils.h"
+#endif
+
+#include <linux/android_pmem.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <hardware/gralloc.h>
+
+#include "linux/fb.h"
+
+#include "s3c_lcd.h"
+#include "s3c_mem.h"
+#include "sec_format.h"
+
+//#define HWC_DEBUG
+#if defined(BOARD_USES_FIMGAPI)
+#include "sec_g2d.h"
+//#define SUB_TITLES_HWC
+#endif
+
+#define NUM_OF_WIN (2)
+#define NUM_OF_WIN_BUF (2)
+#define NUM_OF_MEM_OBJ (1)
+
+#if (NUM_OF_WIN_BUF < 2)
+ #define ENABLE_FIMD_VSYNC
+#endif
+
+#define MAX_RESIZING_RATIO_LIMIT (63)
+
+#ifdef SAMSUNG_EXYNOS4x12
+#ifdef BOARD_USE_V4L2_ION
+#define PP_DEVICE_DEV_NAME "/dev/video4"
+#else
+#define PP_DEVICE_DEV_NAME "/dev/video3"
+#endif
+#endif
+
+#ifdef SAMSUNG_EXYNOS4210
+#define PP_DEVICE_DEV_NAME "/dev/video1"
+#endif
+
+#define S3C_MEM_DEV_NAME "/dev/s3c-mem"
+#define PMEM_DEVICE_DEV_NAME "/dev/pmem_gpu1"
+
+#ifdef BOARD_USE_V4L2_ION
+#undef USE_HW_PMEM
+#else
+#define USE_HW_PMEM
+#endif
+
+#define PMEM_SIZE (1920 * 1280 * 2)
+
+struct sec_rect {
+ int32_t x;
+ int32_t y;
+ int32_t w;
+ int32_t h;
+};
+
+struct sec_img {
+ uint32_t f_w;
+ uint32_t f_h;
+ uint32_t w;
+ uint32_t h;
+ uint32_t format;
+ uint32_t base;
+ uint32_t offset;
+ uint32_t paddr;
+ uint32_t uoffset;
+ uint32_t voffset;
+ int usage;
+ 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);
+}
+
+struct s3c_mem_t {
+ int fd;
+ struct s3c_mem_alloc mem_alloc[NUM_OF_MEM_OBJ];
+};
+
+#ifdef USE_HW_PMEM
+typedef struct __sec_pmem_alloc {
+ int fd;
+ int total_size;
+ int offset;
+ int size;
+ unsigned int virt_addr;
+ unsigned int phys_addr;
+} sec_pmem_alloc_t;
+
+typedef struct __sec_pmem {
+ int pmem_master_fd;
+ void *pmem_master_base;
+ int pmem_total_size;
+ sec_pmem_alloc_t sec_pmem_alloc[NUM_OF_MEM_OBJ];
+} sec_pmem_t;
+
+inline size_t roundUpToPageSize(size_t x)
+{
+ return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+#endif
+
+struct hwc_win_info_t {
+ int fd;
+ int size;
+ sec_rect rect_info;
+ uint32_t addr[NUM_OF_WIN_BUF];
+ int buf_index;
+
+ int power_state;
+ int blending;
+ int layer_index;
+ int status;
+ int vsync;
+#ifdef BOARD_USE_V4L2_ION
+ int ion_fd;
+#endif
+
+ struct fb_fix_screeninfo fix_info;
+ struct fb_var_screeninfo var_info;
+ struct fb_var_screeninfo lcd_info;
+};
+
+enum {
+ HWC_WIN_FREE = 0,
+ HWC_WIN_RESERVED,
+};
+
+enum {
+ HWC_UNKNOWN_MEM_TYPE = 0,
+ HWC_PHYS_MEM_TYPE,
+ HWC_VIRT_MEM_TYPE,
+};
+
+struct hwc_context_t {
+ hwc_composer_device_t device;
+
+ /* our private state goes below here */
+ struct hwc_win_info_t win[NUM_OF_WIN];
+ struct fb_var_screeninfo lcd_info;
+ s5p_fimc_t fimc;
+#ifdef SUB_TITLES_HWC
+ sec_g2d_t g2d;
+#endif
+ struct s3c_mem_t s3c_mem;
+#ifdef USE_HW_PMEM
+ sec_pmem_t sec_pmem;
+#endif
+ int num_of_fb_layer;
+ int num_of_hwc_layer;
+ int num_2d_blit_layer;
+ uint32_t layer_prev_buf[NUM_OF_WIN];
+};
+
+typedef enum _LOG_LEVEL {
+ HWC_LOG_DEBUG,
+ HWC_LOG_WARNING,
+ HWC_LOG_ERROR,
+} HWC_LOG_LEVEL;
+
+#define SEC_HWC_LOG_TAG "SECHWC_LOG"
+
+#ifdef HWC_DEBUG
+#define SEC_HWC_Log(a, ...) ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__))
+#else
+#define SEC_HWC_Log(a, ...) \
+ do { \
+ if (a == HWC_LOG_ERROR) \
+ ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__)); \
+ } while (0)
+#endif
+
+extern void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...);
+
+/* copied from gralloc module ..*/
+typedef struct {
+ native_handle_t base;
+
+ /* These fields can be sent cross process. They are also valid
+ * to duplicate within the same process.
+ *
+ * A table is stored within psPrivateData on gralloc_module_t (this
+ * is obviously per-process) which maps stamps to a mapped
+ * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock
+ * count associated with it, satisfying the requirements of the
+ * Android API. This also prevents us from leaking maps/allocations.
+ *
+ * This table has entries inserted either by alloc()
+ * (alloc_device_t) or map() (gralloc_module_t). Entries are removed
+ * by free() (alloc_device_t) and unmap() (gralloc_module_t).
+ *
+ * As a special case for framebuffer_device_t, framebuffer_open()
+ * will add and framebuffer_close() will remove from this table.
+ */
+
+#define IMG_NATIVE_HANDLE_NUMFDS 1
+ /* The `fd' field is used to "export" a meminfo to another process.
+ * Therefore, it is allocated by alloc_device_t, and consumed by
+ * gralloc_module_t. The framebuffer_device_t does not need a handle,
+ * and the special value IMG_FRAMEBUFFER_FD is used instead.
+ */
+ int fd;
+
+#if 1
+ int format;
+ int magic;
+ int flags;
+ int size;
+ int offset;
+ int base_addr;
+#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(uint64_t) / sizeof(int)) + 4 + 6)
+#else
+#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(IMG_UINT64) / sizeof(int)) + 4)
+#endif
+ /* A KERNEL unique identifier for any exported kernel meminfo. Each
+ * exported kernel meminfo will have a unique stamp, but note that in
+ * userspace, several meminfos across multiple processes could have
+ * the same stamp. As the native_handle can be dup(2)'d, there could be
+ * multiple handles with the same stamp but different file descriptors.
+ */
+ uint64_t ui64Stamp;
+
+ /* We could live without this, but it lets us perform some additional
+ * validation on the client side. Normally, we'd have no visibility
+ * of the allocated usage, just the lock usage.
+ */
+ int usage;
+
+ /* In order to do efficient cache flushes we need the buffer dimensions
+ * and format. These are available on the android_native_buffer_t,
+ * but the platform doesn't pass them down to the graphics HAL.
+ *
+ * TODO: Ideally the platform would be modified to not require this.
+ */
+ int width;
+ int height;
+ int bpp;
+}
+__attribute__((aligned(sizeof(int)),packed)) sec_native_handle_t;
+
+int window_open (struct hwc_win_info_t *win, int id);
+int window_close (struct hwc_win_info_t *win);
+int window_set_pos (struct hwc_win_info_t *win);
+int window_get_info (struct hwc_win_info_t *win, int win_num);
+int window_pan_display(struct hwc_win_info_t *win);
+int window_show (struct hwc_win_info_t *win);
+int window_hide (struct hwc_win_info_t *win);
+int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info);
+
+int createFimc (s5p_fimc_t *fimc);
+int destroyFimc(s5p_fimc_t *fimc);
+int runFimc(struct hwc_context_t *ctx,
+ struct sec_img *src_img, struct sec_rect *src_rect,
+ struct sec_img *dst_img, struct sec_rect *dst_rect,
+ uint32_t transform);
+
+#ifdef SUB_TITLES_HWC
+int runG2d(struct hwc_context_t *ctx,
+ g2d_rect *src_rect, g2d_rect *dst_rect,
+ uint32_t transform);
+
+int destroyG2d(sec_g2d_t *g2d);
+int createG2d(sec_g2d_t *g2d);
+#endif
+
+int createMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size);
+int destroyMem(struct s3c_mem_t *mem);
+int checkMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size);
+
+#ifdef USE_HW_PMEM
+int createPmem (sec_pmem_t *pm, unsigned int size);
+int destroyPmem(sec_pmem_t *pm);
+int checkPmem (sec_pmem_t *pm, unsigned int index, unsigned int size);
+#endif
+
+#endif /* ANDROID_SEC_HWC_UTILS_H_*/
diff --git a/exynos4/hal/libhwconverter/Android.mk b/exynos4/hal/libhwconverter/Android.mk
index ecda03b..c1ded53 100644
--- a/exynos4/hal/libhwconverter/Android.mk
+++ b/exynos4/hal/libhwconverter/Android.mk
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),)
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -21,10 +23,13 @@ LOCAL_SHARED_LIBRARIES := liblog libutils libcutils libfimc
LOCAL_SRC_FILES := HardwareConverter.cpp
LOCAL_C_INCLUDES := \
- $(TOP)/$(BOARD_HAL_PATH)/include \
- $(TOP)/$(BOARD_HMM_PATH)/openmax/sec_omx/include/khronos \
- $(TOP)/$(BOARD_HMM_PATH)/openmax/sec_omx/include/sec
+ $(LOCAL_PATH)/../include \
+ $(TOP)/$(TARGET_HAL_PATH)/include \
+ $(TOP)/$(TARGET_OMX_PATH)/include/khronos \
+ $(TOP)/$(TARGET_OMX_PATH)/include/sec
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libhwconverter
include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/exynos4/hal/libhwconverter/HardwareConverter.cpp b/exynos4/hal/libhwconverter/HardwareConverter.cpp
index 3a66767..9ff6e55 100644
--- a/exynos4/hal/libhwconverter/HardwareConverter.cpp
+++ b/exynos4/hal/libhwconverter/HardwareConverter.cpp
@@ -15,7 +15,6 @@
*/
#include <utils/Log.h>
-
#include "SEC_OMX_Def.h"
#include "SecFimc.h"
#include "HardwareConverter.h"
@@ -25,7 +24,7 @@ HardwareConverter::HardwareConverter()
SecFimc* handle_fimc = new SecFimc();
mSecFimc = (void *)handle_fimc;
- if (handle_fimc->create(SecFimc::DEV_2, SecFimc::MODE_MULTI_BUF, 1) == false)
+ if (handle_fimc->create(SecFimc::DEV_0, SecFimc::MODE_MULTI_BUF, 1) == false)
bHWconvert_flag = 0;
else
bHWconvert_flag = 1;
diff --git a/exynos4/hal/libhwjpeg/Android.mk b/exynos4/hal/libhwjpeg/Android.mk
new file mode 100644
index 0000000..21a99fb
--- /dev/null
+++ b/exynos4/hal/libhwjpeg/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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH) \
+ $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES:= \
+ jpeg_hal_unit.c \
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+
+LOCAL_STATIC_LIBRARIES := \
+
+LOCAL_MODULE:= libhwjpeg
+
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos4/hal/libhwjpeg/jpeg_hal_unit.c b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c
new file mode 100644
index 0000000..a0b4224
--- /dev/null
+++ b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c
@@ -0,0 +1,572 @@
+/*
+ * 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_TAG "libhwjpeg"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/poll.h>
+
+#include <cutils/log.h>
+
+#include "jpeg_hal.h"
+
+#ifdef JPEG_PERF_MEAS
+unsigned long measure_time(struct timeval *start, struct timeval *stop)
+{
+ unsigned long sec, usec, time;
+
+ sec = stop->tv_sec - start->tv_sec;
+
+ if (stop->tv_usec >= start->tv_usec) {
+ usec = stop->tv_usec - start->tv_usec;
+ } else {
+ usec = stop->tv_usec + 1000000 - start->tv_usec;
+ sec--;
+ }
+
+ time = (sec * 1000000) + usec;
+
+ return time;
+}
+#endif
+
+static int jpeg_v4l2_querycap(int fd)
+{
+ struct v4l2_capability cap;
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING))
+ LOGE("[%s]: does not support streaming", __func__);
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))
+ LOGE("[%s]: does not support output", __func__);
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ LOGE("[%s]: does not support capture", __func__);
+
+ return ret;
+}
+
+static int jpeg_v4l2_s_jpegcomp(int fd, int quality)
+{
+ struct v4l2_jpegcompression arg;
+ int ret = 0;
+
+ arg.quality = quality;
+
+ ret = ioctl(fd, VIDIOC_S_JPEGCOMP, &arg);
+
+ return ret;
+}
+
+static int jpeg_v4l2_s_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config)
+{
+ struct v4l2_format fmt;
+ int ret = 0;
+
+ fmt.type = type;
+ fmt.fmt.pix_mp.width = config->width;
+ fmt.fmt.pix_mp.height = config->height;
+ fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
+ fmt.fmt.pix_mp.num_planes = config->num_planes;
+
+ if (config->mode == JPEG_ENCODE)
+ fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG;
+
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (config->mode == JPEG_ENCODE) {
+ fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.in_fmt;
+ } else {
+ fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.in_fmt;
+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = config->sizeJpeg;
+ }
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ if (config->mode == JPEG_ENCODE) {
+ fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.out_fmt;
+ } else {
+ fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.out_fmt;
+ fmt.fmt.pix_mp.width = config->scaled_width;
+ fmt.fmt.pix_mp.height = config->scaled_height;
+ }
+ break;
+ default:
+ LOGE("[%s]: invalid v4l2 buf type", __func__);
+ return -1;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
+
+ return ret;
+}
+
+static int jpeg_v4l2_g_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config)
+{
+ struct v4l2_format fmt;
+ int ret = 0;
+
+ fmt.type = type;
+ ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
+ if (ret < 0)
+ return -1;
+
+ config->width = fmt.fmt.pix_mp.width;
+ config->height = fmt.fmt.pix_mp.height;
+
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (config->mode == JPEG_ENCODE)
+ config->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+ else
+ config->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ if (config->mode == JPEG_ENCODE)
+ config->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+ else
+ config->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+ break;
+ default:
+ LOGE("[%s]: invalid v4l2 buf type", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: input G_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0)
+ LOGE("[%s]: output G_FMT failed", __func__);
+
+ return ret;
+}
+
+static int jpeg_v4l2_reqbufs(int fd, int buf_cnt, struct jpeg_buf *buf)
+{
+ struct v4l2_requestbuffers req;
+ int ret = 0;
+
+ memset(&req, 0, sizeof(req));
+
+ req.type = buf->buf_type;
+ req.memory = buf->memory;
+
+ req.count = buf_cnt;
+
+ ret = ioctl(fd, VIDIOC_REQBUFS, &req);
+
+ return ret;
+}
+
+static int jpeg_v4l2_querybuf(int fd, struct jpeg_buf *buf)
+{
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+ int i;
+ int ret = 0;
+
+ memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+ v4l2_buf.index = 0;
+ v4l2_buf.type = buf->buf_type;
+ v4l2_buf.memory = buf->memory;
+ v4l2_buf.length = buf->num_planes;
+ v4l2_buf.m.planes = plane;
+
+ ret = ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: VIDIOC_QUERYBUF failed", __func__, ret);
+ return ret;
+ }
+
+ for (i= 0; i < buf->num_planes; i++) {
+ buf->length[i] = v4l2_buf.m.planes[i].length;
+ buf->start[i] = (char *) mmap(0, buf->length[i],
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ v4l2_buf.m.planes[i].m.mem_offset);
+
+ //LOGI("[%s]: buf.start[%d] = %p, length = %d", __func__, 0, buf->start[0], buf->length[0]);
+ if (buf->start[0] == MAP_FAILED) {
+ LOGE("[%s]: mmap failed", __func__);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_qbuf(int fd, struct jpeg_buf *buf)
+{
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+ int i;
+ int ret = 0;
+
+ memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer));
+ memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+ v4l2_buf.index = 0;
+ v4l2_buf.type = buf->buf_type;
+ v4l2_buf.memory = buf->memory;
+ v4l2_buf.length = buf->num_planes;
+ v4l2_buf.m.planes = plane;
+
+ if (buf->memory == V4L2_MEMORY_USERPTR) {
+ for (i = 0; i < buf->num_planes; i++) {
+ v4l2_buf.m.planes[i].m.userptr = (unsigned long)buf->start[i];
+ v4l2_buf.m.planes[i].length = buf->length[i];
+ }
+ }
+
+ ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d] QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory)
+{
+ struct v4l2_buffer buf;
+ int ret = 0;
+
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+ buf.type = type;
+ buf.memory = memory;
+
+ ret = ioctl(fd, VIDIOC_DQBUF, &buf);
+ if (ret < 0) {
+ LOGE("[%s:%d] DQBUF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_streamon(int fd, enum v4l2_buf_type type)
+{
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("[%s:%d] STREAMON failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_streamoff(int fd, enum v4l2_buf_type type)
+{
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("[%s:%d] STREAMOFF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_dec_init()
+{
+ int fd;
+ int ret = 0;
+
+ fd = open(JPEG_DEC_NODE, O_RDWR, 0);
+
+ if (fd < 0) {
+ LOGE("[%s]: JPEG dec open failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_querycap(fd);
+ if (ret < 0) {
+ LOGE("[%s]: QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ return fd;
+}
+
+int jpeghal_enc_init()
+{
+ int fd;
+ int ret = 0;
+
+ fd = open(JPEG_ENC_NODE, O_RDWR, 0);
+ if (fd < 0) {
+ LOGE("[%s]: JPEG enc open failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_querycap(fd);
+ if (ret < 0) {
+ LOGE("[%s]: QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ return fd;
+}
+
+int jpeghal_dec_setconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ config->mode = JPEG_DECODE;
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: decoder input S_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: decoder output S_FMT failed", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_dec_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ jpeghal_getconfig(fd, config);
+
+ return ret;
+}
+
+int jpeghal_enc_setconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_s_jpegcomp(fd, config->enc_qual);
+ if (ret < 0) {
+ LOGE("[%s]: S_JPEGCOMP failed", __func__);
+ return -1;
+ }
+
+ config->mode = JPEG_ENCODE;
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: encoder input S_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: encoder output S_FMT failed", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_enc_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ jpeghal_getconfig(fd, config);
+
+ return ret;
+}
+
+int jpeghal_set_inbuf(int fd, struct jpeg_buf *buf)
+{
+ int ret = 0;
+
+ buf->buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+ ret = jpeg_v4l2_reqbufs(fd, 1, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input REQBUFS failed", __func__, ret);
+ return -1;
+ }
+
+ if (buf->memory == V4L2_MEMORY_MMAP) {
+ ret = jpeg_v4l2_querybuf(fd, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input QUERYBUF failed", __func__, ret);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+int jpeghal_set_outbuf(int fd, struct jpeg_buf *buf)
+{
+ int ret = 0;
+
+ buf->buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ ret = jpeg_v4l2_reqbufs(fd, 1, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output REQBUFS failed", __func__, ret);
+ return -1;
+ }
+
+ if (buf->memory == V4L2_MEMORY_MMAP) {
+ ret = jpeg_v4l2_querybuf(fd, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output QUERYBUF failed", __func__, ret);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_qbuf(fd, in_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_qbuf(fd, out_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_streamon(fd, in_buf->buf_type);
+ ret = jpeg_v4l2_streamon(fd, out_buf->buf_type);
+
+ ret = jpeg_v4l2_dqbuf(fd, in_buf->buf_type, in_buf->memory);
+ ret = jpeg_v4l2_dqbuf(fd, out_buf->buf_type, out_buf->memory);
+
+ return ret;
+}
+
+int jpeghal_dec_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_exe(fd, in_buf, out_buf);
+ if (ret < 0)
+ LOGE("[%s]: JPEG decoding is failed", __func__);
+
+ return ret;
+}
+
+int jpeghal_enc_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_exe(fd, in_buf, out_buf);
+ if (ret < 0)
+ LOGE("[%s]: JPEG Encoding is failed", __func__);
+
+ return ret;
+}
+
+int jpeghal_deinit(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ jpeg_v4l2_streamoff(fd, in_buf->buf_type);
+ jpeg_v4l2_streamoff(fd, out_buf->buf_type);
+
+ if (in_buf->memory == V4L2_MEMORY_MMAP)
+ munmap((char *)(in_buf->start[0]), in_buf->length[0]);
+
+ if (out_buf->memory == V4L2_MEMORY_MMAP)
+ munmap((char *)(out_buf->start[0]), out_buf->length[0]);
+
+ jpeg_v4l2_reqbufs(fd, 0, in_buf);
+
+ jpeg_v4l2_reqbufs(fd, 0, out_buf);
+
+ ret = close(fd);
+
+ return ret;
+}
+
+int jpeghal_s_ctrl(int fd, int cid, int value)
+{
+ struct v4l2_control vc;
+ int ret = 0;
+
+ vc.id = cid;
+ vc.value = value;
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
+ if (ret != 0) {
+ LOGE("[%s] ioctl : cid(%d), value(%d)\n", __func__, cid, value);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_g_ctrl(int fd, int id)
+{
+ struct v4l2_control ctrl;
+ int ret = 0;
+
+ ctrl.id = id;
+
+ ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("[%s] ioctl : cid(%d)\n", __func__, ctrl.id);
+ return -1;
+ }
+
+ return ctrl.value;
+}
diff --git a/exynos4/hal/liblights/lights.c b/exynos4/hal/liblights/lights.c
deleted file mode 100644
index 7cbe9d4..0000000
--- a/exynos4/hal/liblights/lights.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- * Copyright (C) 2011 The CyanogenMod 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.
- */
-
-
-#define LOG_TAG "lights"
-#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include <hardware/lights.h>
-
-/******************************************************************************/
-
-static pthread_once_t g_init = PTHREAD_ONCE_INIT;
-static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
-static int g_enable_touchlight = -1;
-
-#ifdef EXYNOS4210_TABLET
-char const*const PANEL_FILE
- = "/sys/class/backlight/backlight/brightness";
-#else
-char const*const PANEL_FILE
- = "/sys/class/backlight/panel/brightness";
-
-char const*const BUTTON_POWER
- = "/sys/class/sec/sec_touchkey/enable_disable";
-
-char const*const BUTTON_FILE
- = "/sys/class/sec/sec_touchkey/brightness";
-#endif
-
-void init_globals(void)
-{
- // init the mutex
- pthread_mutex_init(&g_lock, NULL);
-}
-
-void
-load_settings()
-{
- FILE* fp = fopen("/data/.disable_touchlight", "r");
- if (!fp) {
- g_enable_touchlight = 1;
- } else {
- g_enable_touchlight = (int)(fgetc(fp));
- if (g_enable_touchlight == '1')
- g_enable_touchlight = 1;
- else
- g_enable_touchlight = 0;
-
- fclose(fp);
- }
-}
-
-static int
-write_int(char const* path, int value)
-{
- int fd;
- static int already_warned = 0;
-
- fd = open(path, O_RDWR);
- if (fd >= 0) {
- char buffer[20];
- int bytes = sprintf(buffer, "%d\n", value);
- int amt = write(fd, buffer, bytes);
- close(fd);
- return amt == -1 ? -errno : 0;
- } else {
- if (already_warned == 0) {
- LOGE("write_int failed to open %s\n", path);
- already_warned = 1;
- }
- return -errno;
- }
-}
-
-static int
-is_lit(struct light_state_t const* state)
-{
- return state->color & 0x00ffffff;
-}
-
-static int
-rgb_to_brightness(struct light_state_t const* state)
-{
- int color = state->color & 0x00ffffff;
- return ((77*((color>>16)&0x00ff))
- + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
-}
-
-static int
-set_light_backlight(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- load_settings();
-
- int err = 0;
- int brightness = rgb_to_brightness(state);
-
- pthread_mutex_lock(&g_lock);
- err = write_int(PANEL_FILE, brightness);
-
-#ifndef EXYNOS4210_TABLET
- if (g_enable_touchlight == -1 || g_enable_touchlight > 0)
- err = write_int(BUTTON_FILE, brightness > 0 ? 1 : 0);
-#endif
-
- pthread_mutex_unlock(&g_lock);
-
- return err;
-}
-
-static int
-set_light_keyboard(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- return 0;
-}
-
-static int
-set_light_buttons(struct light_device_t* dev,
- struct light_state_t const* state)
-{
-#ifdef EXYNOS4210_TABLET
- return 0;
-#else
-
- load_settings();
-
- int err = 0;
-
- pthread_mutex_lock(&g_lock);
- LOGD("set_light_button on=%d\n", g_enable_touchlight ? 1 : 0);
- err = write_int(BUTTON_FILE, g_enable_touchlight ? 1 : 0);
- pthread_mutex_unlock(&g_lock);
-
- return err;
-#endif
-}
-
-static int
-set_light_battery(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- return 0;
-}
-
-static int
-set_light_notification(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- return 0;
-}
-
-static int
-set_light_attention(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- return 0;
-}
-
-static int
-close_lights(struct light_device_t *dev)
-{
- if (dev) {
- free(dev);
- }
- return 0;
-}
-
-
-/******************************************************************************/
-static int open_lights(const struct hw_module_t* module, char const* name,
- struct hw_device_t** device)
-{
- int (*set_light)(struct light_device_t* dev,
- struct light_state_t const* state);
-
- if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
- set_light = set_light_backlight;
- }
- else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
- set_light = set_light_keyboard;
- }
- else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
- set_light = set_light_buttons;
- }
- else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
- set_light = set_light_battery;
- }
- else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
- set_light = set_light_notification;
- }
- else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
- set_light = set_light_attention;
- }
- else {
- return -EINVAL;
- }
-
- pthread_once(&g_init, init_globals);
-
- struct light_device_t *dev = malloc(sizeof(struct light_device_t));
- memset(dev, 0, sizeof(*dev));
-
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module = (struct hw_module_t*)module;
- dev->common.close = (int (*)(struct hw_device_t*))close_lights;
- dev->set_light = set_light;
-
- *device = (struct hw_device_t*)dev;
- return 0;
-}
-
-
-static struct hw_module_methods_t lights_module_methods = {
- .open = open_lights,
-};
-
-const struct hw_module_t HAL_MODULE_INFO_SYM = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = LIGHTS_HARDWARE_MODULE_ID,
- .name = "Samsung Exynos4210 Lights Module",
- .author = "The CyanogenMod Project",
- .methods = &lights_module_methods,
-};
diff --git a/exynos4/hal/libs5pjpeg/Android.mk b/exynos4/hal/libs5pjpeg/Android.mk
index e1ac187..c6d8cf6 100644
--- a/exynos4/hal/libs5pjpeg/Android.mk
+++ b/exynos4/hal/libs5pjpeg/Android.mk
@@ -15,9 +15,8 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH) \
- $(BOARD_HAL_PATH)/include \
+LOCAL_C_INCLUDES := $(LOCAL_PATH)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_SRC_FILES:= \
jpeg_api.c \
diff --git a/exynos4/hal/libsensors/AkmSensor.cpp b/exynos4/hal/libsensors/AkmSensor.cpp
deleted file mode 100644
index 98a17cb..0000000
--- a/exynos4/hal/libsensors/AkmSensor.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <poll.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/select.h>
-#include <dlfcn.h>
-
-#include "ak8973b.h"
-
-#include <cutils/log.h>
-#include "AkmSensor.h"
-
-//#define LOG_NDEBUG 0
-
-/*****************************************************************************/
-
-int (*akm_is_sensor_enabled)(uint32_t sensor_type);
-int (*akm_enable_sensor)(uint32_t sensor_type);
-int (*akm_disable_sensor)(uint32_t sensor_type);
-int (*akm_set_delay)(uint32_t sensor_type, uint64_t delay);
-
-int stub_is_sensor_enabled(uint32_t sensor_type) {
- return 0;
-}
-
-int stub_enable_disable_sensor(uint32_t sensor_type) {
- return -ENODEV;
-}
-
-int stub_set_delay(uint32_t sensor_type, uint64_t delay) {
- return -ENODEV;
-}
-
-AkmSensor::AkmSensor()
-: SensorBase(NULL, NULL),
- mEnabled(0),
- mPendingMask(0),
- mInputReader(32)
-{
- /* Open the library before opening the input device. The library
- * creates a uinput device.
- */
- if (loadAKMLibrary() == 0) {
- data_name = "compass_sensor";
- data_fd = openInput("compass_sensor");
- }
-
- memset(mPendingEvents, 0, sizeof(mPendingEvents));
-
- mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
- mPendingEvents[Accelerometer].sensor = ID_A;
- mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
- mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
-
- mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
- mPendingEvents[MagneticField].sensor = ID_M;
- mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
- mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
-
- mPendingEvents[Orientation ].version = sizeof(sensors_event_t);
- mPendingEvents[Orientation ].sensor = ID_O;
- mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION;
- mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
-
- // read the actual value of all sensors if they're enabled already
- struct input_absinfo absinfo;
- short flags = 0;
-
- if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER)) {
- mEnabled |= 1<<Accelerometer;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
- mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
- mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
- mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z;
- }
- }
- if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD)) {
- mEnabled |= 1<<MagneticField;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) {
- mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) {
- mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) {
- mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z;
- }
- }
- if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION)) {
- mEnabled |= 1<<Orientation;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) {
- mPendingEvents[Orientation].orientation.azimuth = absinfo.value;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) {
- mPendingEvents[Orientation].orientation.pitch = absinfo.value;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) {
- mPendingEvents[Orientation].orientation.roll = -absinfo.value;
- }
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) {
- mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK);
- }
- }
-
- // disable temperature sensor, since it is not supported
- akm_disable_sensor(SENSOR_TYPE_TEMPERATURE);
-}
-
-AkmSensor::~AkmSensor()
-{
- if (mLibAKM) {
- unsigned ref = ::dlclose(mLibAKM);
- }
-}
-
-int AkmSensor::enable(int32_t handle, int en)
-{
- int what = -1;
-
- switch (handle) {
- case ID_A: what = Accelerometer; break;
- case ID_M: what = MagneticField; break;
- case ID_O: what = Orientation; break;
- }
-
- if (uint32_t(what) >= numSensors)
- return -EINVAL;
-
- int newState = en ? 1 : 0;
- int err = 0;
-
- if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
- uint32_t sensor_type;
- switch (what) {
- case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER; break;
- case MagneticField: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
- case Orientation: sensor_type = SENSOR_TYPE_ORIENTATION; break;
- }
- short flags = newState;
- if (en)
- err = akm_enable_sensor(sensor_type);
- else
- err = akm_disable_sensor(sensor_type);
-
- LOGE_IF(err, "Could not change sensor state (%s)", strerror(-err));
- if (!err) {
- mEnabled &= ~(1<<what);
- mEnabled |= (uint32_t(flags)<<what);
- }
- }
- return err;
-}
-
-int AkmSensor::setDelay(int32_t handle, int64_t ns)
-{
- int what = -1;
- uint32_t sensor_type = 0;
-
- if (ns < 0)
- return -EINVAL;
-
- switch (handle) {
- case ID_A: sensor_type = SENSOR_TYPE_ACCELEROMETER; break;
- case ID_M: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
- case ID_O: sensor_type = SENSOR_TYPE_ORIENTATION; break;
- }
-
- if (sensor_type == 0)
- return -EINVAL;
-
- mDelays[what] = ns;
- return update_delay();
-}
-
-int AkmSensor::update_delay()
-{
- if (mEnabled) {
- uint64_t wanted = -1LLU;
- for (int i=0 ; i<numSensors ; i++) {
- if (mEnabled & (1<<i)) {
- uint64_t ns = mDelays[i];
- wanted = wanted < ns ? wanted : ns;
- }
- }
- short delay = int64_t(wanted) / 1000000;
- if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
- return -errno;
- }
- }
- return 0;
-}
-
-
-int AkmSensor::loadAKMLibrary()
-{
- mLibAKM = dlopen("libakm.so", RTLD_NOW);
-
- if (!mLibAKM) {
- akm_is_sensor_enabled = stub_is_sensor_enabled;
- akm_enable_sensor = stub_enable_disable_sensor;
- akm_disable_sensor = stub_enable_disable_sensor;
- akm_set_delay = stub_set_delay;
- LOGE("AkmSensor: unable to load AKM Library, %s", dlerror());
- return -ENOENT;
- }
-
- *(void **)&akm_is_sensor_enabled = dlsym(mLibAKM, "akm_is_sensor_enabled");
- *(void **)&akm_enable_sensor = dlsym(mLibAKM, "akm_enable_sensor");
- *(void **)&akm_disable_sensor = dlsym(mLibAKM, "akm_disable_sensor");
- *(void **)&akm_set_delay = dlsym(mLibAKM, "akm_set_delay");
-
- return 0;
-}
-
-int AkmSensor::readEvents(sensors_event_t* data, int count)
-{
- if (count < 1)
- return -EINVAL;
-
- ssize_t n = mInputReader.fill(data_fd);
- if (n < 0)
- return n;
-
- int numEventReceived = 0;
- input_event const* event;
-
- while (count && mInputReader.readEvent(&event)) {
- int type = event->type;
- if (type == EV_REL) {
- processEvent(event->code, event->value);
- mInputReader.next();
- } else if (type == EV_SYN) {
- int64_t time = timevalToNano(event->time);
- for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
- if (mPendingMask & (1<<j)) {
- mPendingMask &= ~(1<<j);
- mPendingEvents[j].timestamp = time;
- if (mEnabled & (1<<j)) {
- *data++ = mPendingEvents[j];
- count--;
- numEventReceived++;
- }
- }
- }
- if (!mPendingMask) {
- mInputReader.next();
- }
- } else {
- LOGE("AkmSensor: unknown event (type=%d, code=%d)",
- type, event->code);
- mInputReader.next();
- }
- }
- return numEventReceived;
-}
-
-void AkmSensor::processEvent(int code, int value)
-{
- switch (code) {
- case EVENT_TYPE_ACCEL_X:
- mPendingMask |= 1<<Accelerometer;
- mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
- break;
- case EVENT_TYPE_ACCEL_Y:
- mPendingMask |= 1<<Accelerometer;
- mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
- break;
- case EVENT_TYPE_ACCEL_Z:
- mPendingMask |= 1<<Accelerometer;
- mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
- break;
-
- case EVENT_TYPE_MAGV_X:
- LOGV("AkmSensor: EVENT_TYPE_MAGV_X value =%d", value);
- mPendingMask |= 1<<MagneticField;
- mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
- break;
- case EVENT_TYPE_MAGV_Y:
- LOGV("AkmSensor: EVENT_TYPE_MAGV_Y value =%d", value);
- mPendingMask |= 1<<MagneticField;
- mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
- break;
- case EVENT_TYPE_MAGV_Z:
- LOGV("AkmSensor: EVENT_TYPE_MAGV_Z value =%d", value);
- mPendingMask |= 1<<MagneticField;
- mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
- break;
-
- case EVENT_TYPE_YAW:
- mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_A;
- break;
- case EVENT_TYPE_PITCH:
- mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
- break;
- case EVENT_TYPE_ROLL:
- mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
- break;
- case EVENT_TYPE_ORIENT_STATUS:
- uint8_t status = uint8_t(value & SENSOR_STATE_MASK);
- if (status == 4)
- status = 0;
- mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.status = status;
- break;
- }
-}
diff --git a/exynos4/hal/libsensors/AkmSensor.h b/exynos4/hal/libsensors/AkmSensor.h
deleted file mode 100644
index c155ec2..0000000
--- a/exynos4/hal/libsensors/AkmSensor.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AKM_SENSOR_H
-#define ANDROID_AKM_SENSOR_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-
-#include "sensors.h"
-#include "SensorBase.h"
-#include "InputEventReader.h"
-
-/*****************************************************************************/
-
-struct input_event;
-
-class AkmSensor : public SensorBase {
-public:
- AkmSensor();
- virtual ~AkmSensor();
-
- enum {
- Accelerometer = 0,
- MagneticField = 1,
- Orientation = 2,
- numSensors
- };
-
- virtual int setDelay(int32_t handle, int64_t ns);
- virtual int enable(int32_t handle, int enabled);
- virtual int readEvents(sensors_event_t* data, int count);
- void processEvent(int code, int value);
-
-private:
- int loadAKMLibrary();
- int update_delay();
- void *mLibAKM;
- uint32_t mEnabled;
- uint32_t mPendingMask;
- InputEventCircularReader mInputReader;
- sensors_event_t mPendingEvents[numSensors];
- uint64_t mDelays[numSensors];
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_AKM_SENSOR_H
diff --git a/exynos4/hal/libsensors/GyroSensor.cpp b/exynos4/hal/libsensors/GyroSensor.cpp
deleted file mode 100644
index ef0c01c..0000000
--- a/exynos4/hal/libsensors/GyroSensor.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <poll.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/select.h>
-#include <cutils/log.h>
-
-#include "GyroSensor.h"
-
-#define FETCH_FULL_EVENT_BEFORE_RETURN 1
-#define IGNORE_EVENT_TIME 350000000
-/*****************************************************************************/
-
-GyroSensor::GyroSensor()
- : SensorBase(NULL, "gyro_sensor"),
- mEnabled(0),
- mInputReader(4),
- mHasPendingEvent(false),
- mEnabledTime(0)
-{
- mPendingEvent.version = sizeof(sensors_event_t);
- mPendingEvent.sensor = ID_GY;
- mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;
- memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
-
- if (data_fd) {
- strcpy(input_sysfs_path, "/sys/class/input/");
- strcat(input_sysfs_path, input_name);
- strcat(input_sysfs_path, "/device/");
- input_sysfs_path_len = strlen(input_sysfs_path);
- enable(0, 1);
- }
-}
-
-GyroSensor::~GyroSensor() {
- if (mEnabled) {
- enable(0, 0);
- }
-}
-
-int GyroSensor::setInitialState() {
- struct input_absinfo absinfo_x;
- struct input_absinfo absinfo_y;
- struct input_absinfo absinfo_z;
- float value;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) &&
- !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) &&
- !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) {
- value = absinfo_x.value;
- mPendingEvent.data[0] = value * CONVERT_GYRO_X;
- value = absinfo_x.value;
- mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
- value = absinfo_x.value;
- mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
- mHasPendingEvent = true;
- }
- return 0;
-}
-
-int GyroSensor::enable(int32_t, int en) {
- int flags = en ? 1 : 0;
- if (flags != mEnabled) {
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[2];
- int err;
- buf[1] = 0;
- if (flags) {
- buf[0] = '1';
- mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
- } else {
- buf[0] = '0';
- }
- err = write(fd, buf, sizeof(buf));
- close(fd);
- mEnabled = flags;
- setInitialState();
- return 0;
- }
- return -1;
- }
- return 0;
-}
-
-bool GyroSensor::hasPendingEvents() const {
- return mHasPendingEvent;
-}
-
-int GyroSensor::setDelay(int32_t handle, int64_t delay_ns)
-{
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[80];
- sprintf(buf, "%lld", delay_ns);
- write(fd, buf, strlen(buf)+1);
- close(fd);
- return 0;
- }
- return -1;
-}
-
-int GyroSensor::readEvents(sensors_event_t* data, int count)
-{
- if (count < 1)
- return -EINVAL;
-
- if (mHasPendingEvent) {
- mHasPendingEvent = false;
- mPendingEvent.timestamp = getTimestamp();
- *data = mPendingEvent;
- return mEnabled ? 1 : 0;
- }
-
- ssize_t n = mInputReader.fill(data_fd);
- if (n < 0)
- return n;
-
- int numEventReceived = 0;
- input_event const* event;
-
-#if FETCH_FULL_EVENT_BEFORE_RETURN
-again:
-#endif
- while (count && mInputReader.readEvent(&event)) {
- int type = event->type;
- if (type == EV_REL) {
- float value = event->value;
- if (event->code == EVENT_TYPE_GYRO_X) {
- mPendingEvent.data[0] = value * CONVERT_GYRO_X;
- } else if (event->code == EVENT_TYPE_GYRO_Y) {
- mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
- } else if (event->code == EVENT_TYPE_GYRO_Z) {
- mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
- }
- } else if (type == EV_SYN) {
- mPendingEvent.timestamp = timevalToNano(event->time);
- if (mEnabled) {
- if (mPendingEvent.timestamp >= mEnabledTime) {
- *data++ = mPendingEvent;
- numEventReceived++;
- }
- count--;
- }
- } else {
- LOGE("GyroSensor: unknown event (type=%d, code=%d)",
- type, event->code);
- }
- mInputReader.next();
- }
-
-#if FETCH_FULL_EVENT_BEFORE_RETURN
- /* if we didn't read a complete event, see if we can fill and
- try again instead of returning with nothing and redoing poll. */
- if (numEventReceived == 0 && mEnabled == 1) {
- n = mInputReader.fill(data_fd);
- if (n)
- goto again;
- }
-#endif
-
- return numEventReceived;
-}
-
diff --git a/exynos4/hal/libsensors/GyroSensor.h b/exynos4/hal/libsensors/GyroSensor.h
deleted file mode 100644
index e8997de..0000000
--- a/exynos4/hal/libsensors/GyroSensor.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GYRO_SENSOR_H
-#define ANDROID_GYRO_SENSOR_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include "sensors.h"
-#include "SensorBase.h"
-#include "InputEventReader.h"
-
-/*****************************************************************************/
-
-struct input_event;
-
-class GyroSensor : public SensorBase {
- int mEnabled;
- InputEventCircularReader mInputReader;
- sensors_event_t mPendingEvent;
- bool mHasPendingEvent;
- char input_sysfs_path[PATH_MAX];
- int input_sysfs_path_len;
- int64_t mEnabledTime;
-
- int setInitialState();
-
-public:
- GyroSensor();
- virtual ~GyroSensor();
- virtual int readEvents(sensors_event_t* data, int count);
- virtual bool hasPendingEvents() const;
- virtual int setDelay(int32_t handle, int64_t ns);
- virtual int enable(int32_t handle, int enabled);
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_GYRO_SENSOR_H
diff --git a/exynos4/hal/libsensors/InputEventReader.cpp b/exynos4/hal/libsensors/InputEventReader.cpp
deleted file mode 100644
index 1014f29..0000000
--- a/exynos4/hal/libsensors/InputEventReader.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <unistd.h>
-#include <poll.h>
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <linux/input.h>
-
-#include <cutils/log.h>
-
-#include "InputEventReader.h"
-
-/*****************************************************************************/
-
-struct input_event;
-
-InputEventCircularReader::InputEventCircularReader(size_t numEvents)
- : mBuffer(new input_event[numEvents * 2]),
- mBufferEnd(mBuffer + numEvents),
- mHead(mBuffer),
- mCurr(mBuffer),
- mFreeSpace(numEvents)
-{
-}
-
-InputEventCircularReader::~InputEventCircularReader()
-{
- delete [] mBuffer;
-}
-
-ssize_t InputEventCircularReader::fill(int fd)
-{
- size_t numEventsRead = 0;
- if (mFreeSpace) {
- const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
- if (nread<0 || nread % sizeof(input_event)) {
- // we got a partial event!!
- return nread<0 ? -errno : -EINVAL;
- }
-
- numEventsRead = nread / sizeof(input_event);
- if (numEventsRead) {
- mHead += numEventsRead;
- mFreeSpace -= numEventsRead;
- if (mHead > mBufferEnd) {
- size_t s = mHead - mBufferEnd;
- memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
- mHead = mBuffer + s;
- }
- }
- }
-
- return numEventsRead;
-}
-
-ssize_t InputEventCircularReader::readEvent(input_event const** events)
-{
- *events = mCurr;
- ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
- return available ? 1 : 0;
-}
-
-void InputEventCircularReader::next()
-{
- mCurr++;
- mFreeSpace++;
- if (mCurr >= mBufferEnd) {
- mCurr = mBuffer;
- }
-}
diff --git a/exynos4/hal/libsensors/InputEventReader.h b/exynos4/hal/libsensors/InputEventReader.h
deleted file mode 100644
index 180aade..0000000
--- a/exynos4/hal/libsensors/InputEventReader.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_INPUT_EVENT_READER_H
-#define ANDROID_INPUT_EVENT_READER_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-/*****************************************************************************/
-
-struct input_event;
-
-class InputEventCircularReader
-{
- struct input_event* const mBuffer;
- struct input_event* const mBufferEnd;
- struct input_event* mHead;
- struct input_event* mCurr;
- ssize_t mFreeSpace;
-
-public:
- InputEventCircularReader(size_t numEvents);
- ~InputEventCircularReader();
- ssize_t fill(int fd);
- ssize_t readEvent(input_event const** events);
- void next();
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_INPUT_EVENT_READER_H
diff --git a/exynos4/hal/libsensors/LightSensor.cpp b/exynos4/hal/libsensors/LightSensor.cpp
deleted file mode 100644
index 1d4f0e4..0000000
--- a/exynos4/hal/libsensors/LightSensor.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <poll.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/select.h>
-
-#include <linux/lightsensor.h>
-
-#include <cutils/log.h>
-
-#include "LightSensor.h"
-
-// #define LOG_NDEBUG 0
-
-/*****************************************************************************/
-
-LightSensor::LightSensor()
- : SensorBase(NULL, "light_sensor"),
- mEnabled(0),
- mInputReader(4),
- mHasPendingEvent(false)
-{
- mPendingEvent.version = sizeof(sensors_event_t);
- mPendingEvent.sensor = ID_L;
- mPendingEvent.type = SENSOR_TYPE_LIGHT;
- memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
-
- if (data_fd) {
- strcpy(input_sysfs_path, "/sys/class/input/");
- strcat(input_sysfs_path, input_name);
- strcat(input_sysfs_path, "/device/");
- input_sysfs_path_len = strlen(input_sysfs_path);
- enable(0, 1);
- }
-}
-
-LightSensor::~LightSensor() {
- if (mEnabled) {
- enable(0, 0);
- }
-}
-
-int LightSensor::setInitialState() {
- struct input_absinfo absinfo;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_LIGHT), &absinfo)) {
- // make sure to report an event immediately
- mHasPendingEvent = true;
- mPendingEvent.light = absinfo.value;
- }
- return 0;
-}
-
-int LightSensor::setDelay(int32_t handle, int64_t ns)
-{
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[80];
- sprintf(buf, "%lld", ns);
- write(fd, buf, strlen(buf)+1);
- close(fd);
- return 0;
- }
- return -1;
-}
-
-int LightSensor::enable(int32_t handle, int en)
-{
- int flags = en ? 1 : 0;
- if (flags != mEnabled) {
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[2];
- int err;
- buf[1] = 0;
- if (flags) {
- buf[0] = '1';
- } else {
- buf[0] = '0';
- }
- err = write(fd, buf, sizeof(buf));
- close(fd);
- mEnabled = flags;
- return 0;
- }
- return -1;
- }
- return 0;
-}
-
-bool LightSensor::hasPendingEvents() const {
- return mHasPendingEvent;
-}
-
-int LightSensor::readEvents(sensors_event_t* data, int count)
-{
- if (count < 1)
- return -EINVAL;
-
- if (mHasPendingEvent) {
- mHasPendingEvent = false;
- mPendingEvent.timestamp = getTimestamp();
- *data = mPendingEvent;
- return mEnabled ? 1 : 0;
- }
-
- ssize_t n = mInputReader.fill(data_fd);
- if (n < 0)
- return n;
-
- int numEventReceived = 0;
- input_event const* event;
-
- while (count && mInputReader.readEvent(&event)) {
- int type = event->type;
- if (type == EV_ABS) {
- if (event->code == EVENT_TYPE_LIGHT) {
- if (event->value != -1) {
- LOGV("LightSensor: event (value=%d)", event->value);
- // FIXME: not sure why we're getting -1 sometimes
- mPendingEvent.light = event->value;
- }
- }
- } else if (type == EV_SYN) {
- mPendingEvent.timestamp = timevalToNano(event->time);
- if (mEnabled) {
- *data++ = mPendingEvent;
- count--;
- numEventReceived++;
- }
- } else {
- LOGE("LightSensor: unknown event (type=%d, code=%d)",
- type, event->code);
- }
- mInputReader.next();
- }
-
- return numEventReceived;
-}
diff --git a/exynos4/hal/libsensors/LightSensor.h b/exynos4/hal/libsensors/LightSensor.h
deleted file mode 100644
index 85e65d9..0000000
--- a/exynos4/hal/libsensors/LightSensor.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIGHT_SENSOR_H
-#define ANDROID_LIGHT_SENSOR_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include "sensors.h"
-#include "SensorBase.h"
-#include "InputEventReader.h"
-
-/*****************************************************************************/
-
-struct input_event;
-
-class LightSensor : public SensorBase {
- int mEnabled;
- InputEventCircularReader mInputReader;
- sensors_event_t mPendingEvent;
- bool mHasPendingEvent;
- char input_sysfs_path[PATH_MAX];
- int input_sysfs_path_len;
-
- float indexToValue(size_t index) const;
- int setInitialState();
-
-public:
- LightSensor();
- virtual ~LightSensor();
- virtual int readEvents(sensors_event_t* data, int count);
- virtual bool hasPendingEvents() const;
- virtual int setDelay(int32_t handle, int64_t ns);
- virtual int enable(int32_t handle, int enabled);
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_LIGHT_SENSOR_H
diff --git a/exynos4/hal/libsensors/MODULE_LICENSE_APACHE2 b/exynos4/hal/libsensors/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/exynos4/hal/libsensors/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/exynos4/hal/libsensors/ProximitySensor.cpp b/exynos4/hal/libsensors/ProximitySensor.cpp
deleted file mode 100644
index 46424a5..0000000
--- a/exynos4/hal/libsensors/ProximitySensor.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <poll.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/select.h>
-
-#include <linux/capella_cm3602.h>
-
-#include <cutils/log.h>
-
-#include "ProximitySensor.h"
-
-/*****************************************************************************/
-
-ProximitySensor::ProximitySensor()
- : SensorBase(NULL, "proximity_sensor"),
- mEnabled(0),
- mInputReader(4),
- mHasPendingEvent(false)
-{
- mPendingEvent.version = sizeof(sensors_event_t);
- mPendingEvent.sensor = ID_P;
- mPendingEvent.type = SENSOR_TYPE_PROXIMITY;
- memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
-
- if (data_fd) {
- strcpy(input_sysfs_path, "/sys/class/input/");
- strcat(input_sysfs_path, input_name);
- strcat(input_sysfs_path, "/device/");
- input_sysfs_path_len = strlen(input_sysfs_path);
- enable(0, 1);
- }
-}
-
-ProximitySensor::~ProximitySensor() {
- if (mEnabled) {
- enable(0, 0);
- }
-}
-
-int ProximitySensor::setInitialState() {
- struct input_absinfo absinfo;
- if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) {
- // make sure to report an event immediately
- mHasPendingEvent = true;
- mPendingEvent.distance = indexToValue(absinfo.value);
- }
- return 0;
-}
-
-int ProximitySensor::enable(int32_t, int en) {
- int flags = en ? 1 : 0;
- if (flags != mEnabled) {
- int fd;
- strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
- fd = open(input_sysfs_path, O_RDWR);
- if (fd >= 0) {
- char buf[2];
- buf[1] = 0;
- if (flags) {
- buf[0] = '1';
- } else {
- buf[0] = '0';
- }
- write(fd, buf, sizeof(buf));
- close(fd);
- mEnabled = flags;
- setInitialState();
- return 0;
- }
- return -1;
- }
- return 0;
-}
-
-bool ProximitySensor::hasPendingEvents() const {
- return mHasPendingEvent;
-}
-
-int ProximitySensor::readEvents(sensors_event_t* data, int count)
-{
- if (count < 1)
- return -EINVAL;
-
- if (mHasPendingEvent) {
- mHasPendingEvent = false;
- mPendingEvent.timestamp = getTimestamp();
- *data = mPendingEvent;
- return mEnabled ? 1 : 0;
- }
-
- ssize_t n = mInputReader.fill(data_fd);
- if (n < 0)
- return n;
-
- int numEventReceived = 0;
- input_event const* event;
-
- while (count && mInputReader.readEvent(&event)) {
- int type = event->type;
- if (type == EV_ABS) {
- if (event->code == EVENT_TYPE_PROXIMITY) {
- mPendingEvent.distance = indexToValue(event->value);
- }
- } else if (type == EV_SYN) {
- mPendingEvent.timestamp = timevalToNano(event->time);
- if (mEnabled) {
- *data++ = mPendingEvent;
- count--;
- numEventReceived++;
- }
- } else {
- LOGE("ProximitySensor: unknown event (type=%d, code=%d)",
- type, event->code);
- }
- mInputReader.next();
- }
-
- return numEventReceived;
-}
-
-float ProximitySensor::indexToValue(size_t index) const
-{
- LOGV("ProximitySensor: Index = %zu", index);
- return index * PROXIMITY_THRESHOLD_CM;
-}
diff --git a/exynos4/hal/libsensors/ProximitySensor.h b/exynos4/hal/libsensors/ProximitySensor.h
deleted file mode 100644
index 08ea49c..0000000
--- a/exynos4/hal/libsensors/ProximitySensor.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_PROXIMITY_SENSOR_H
-#define ANDROID_PROXIMITY_SENSOR_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include "sensors.h"
-#include "SensorBase.h"
-#include "InputEventReader.h"
-
-/*****************************************************************************/
-
-struct input_event;
-
-class ProximitySensor : public SensorBase {
- int mEnabled;
- InputEventCircularReader mInputReader;
- sensors_event_t mPendingEvent;
- bool mHasPendingEvent;
- char input_sysfs_path[PATH_MAX];
- int input_sysfs_path_len;
-
- int setInitialState();
- float indexToValue(size_t index) const;
-
-public:
- ProximitySensor();
- virtual ~ProximitySensor();
- virtual int readEvents(sensors_event_t* data, int count);
- virtual bool hasPendingEvents() const;
- virtual int enable(int32_t handle, int enabled);
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_PROXIMITY_SENSOR_H
diff --git a/exynos4/hal/libsensors/SensorBase.cpp b/exynos4/hal/libsensors/SensorBase.cpp
deleted file mode 100644
index d448eb2..0000000
--- a/exynos4/hal/libsensors/SensorBase.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <poll.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/select.h>
-
-#include <cutils/log.h>
-
-#include <linux/input.h>
-
-#include "SensorBase.h"
-
-/*****************************************************************************/
-
-SensorBase::SensorBase(
- const char* dev_name,
- const char* data_name)
- : dev_name(dev_name), data_name(data_name),
- dev_fd(-1), data_fd(-1)
-{
- if (data_name) {
- data_fd = openInput(data_name);
- }
-}
-
-SensorBase::~SensorBase() {
- if (data_fd >= 0) {
- close(data_fd);
- }
- if (dev_fd >= 0) {
- close(dev_fd);
- }
-}
-
-int SensorBase::open_device() {
- if (dev_fd<0 && dev_name) {
- dev_fd = open(dev_name, O_RDONLY);
- LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
- }
- return 0;
-}
-
-int SensorBase::close_device() {
- if (dev_fd >= 0) {
- close(dev_fd);
- dev_fd = -1;
- }
- return 0;
-}
-
-int SensorBase::getFd() const {
- if (!data_name) {
- return dev_fd;
- }
- return data_fd;
-}
-
-int SensorBase::setDelay(int32_t handle, int64_t ns) {
- return 0;
-}
-
-bool SensorBase::hasPendingEvents() const {
- return false;
-}
-
-int64_t SensorBase::getTimestamp() {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
- clock_gettime(CLOCK_MONOTONIC, &t);
- return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
-}
-
-int SensorBase::openInput(const char* inputName) {
- int fd = -1;
- const char *dirname = "/dev/input";
- char devname[PATH_MAX];
- char *filename;
- DIR *dir;
- struct dirent *de;
- dir = opendir(dirname);
- if(dir == NULL)
- return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while((de = readdir(dir))) {
- if(de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' ||
- (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- fd = open(devname, O_RDONLY);
- if (fd>=0) {
- char name[80];
- if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
- name[0] = '\0';
- }
- if (!strcmp(name, inputName)) {
- strcpy(input_name, filename);
- break;
- } else {
- close(fd);
- fd = -1;
- }
- }
- }
- closedir(dir);
- LOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
- return fd;
-}
diff --git a/exynos4/hal/libsensors/SensorBase.h b/exynos4/hal/libsensors/SensorBase.h
deleted file mode 100644
index bb4d055..0000000
--- a/exynos4/hal/libsensors/SensorBase.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSOR_BASE_H
-#define ANDROID_SENSOR_BASE_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-
-/*****************************************************************************/
-
-struct sensors_event_t;
-
-class SensorBase {
-protected:
- const char* dev_name;
- const char* data_name;
- char input_name[PATH_MAX];
- int dev_fd;
- int data_fd;
-
- int openInput(const char* inputName);
- static int64_t getTimestamp();
-
-
- static int64_t timevalToNano(timeval const& t) {
- return t.tv_sec*1000000000LL + t.tv_usec*1000;
- }
-
- int open_device();
- int close_device();
-
-public:
- SensorBase(
- const char* dev_name,
- const char* data_name);
-
- virtual ~SensorBase();
-
- virtual int readEvents(sensors_event_t* data, int count) = 0;
- virtual bool hasPendingEvents() const;
- virtual int getFd() const;
- virtual int setDelay(int32_t handle, int64_t ns);
- virtual int enable(int32_t handle, int enabled) = 0;
-};
-
-/*****************************************************************************/
-
-#endif // ANDROID_SENSOR_BASE_H
diff --git a/exynos4/hal/libsensors/ak8973b.h b/exynos4/hal/libsensors/ak8973b.h
deleted file mode 100644
index 9b7ab60..0000000
--- a/exynos4/hal/libsensors/ak8973b.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Definitions for akm8973 compass chip.
- */
-#ifndef AKM8973_H
-#define AKM8973_H
-
-#include <linux/ioctl.h>
-
-#define AKM8973_I2C_NAME "ak8973b"
-
-#define AKMIO 0xA1
-
-/* IOCTLs for AKM library */
-#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x01, char*)
-#define ECS_IOCTL_READ _IOWR(AKMIO, 0x02, char*)
-#define ECS_IOCTL_RESET _IO(AKMIO, 0x03)
-#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x04, short)
-#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x05, char[SENSOR_DATA_SIZE])
-#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x06, short[12])
-#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x07, int)
-#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x08, int)
-#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, int64_t)
-#define ECS_IOCTL_GET_PROJECT_NAME _IOR(AKMIO, 0x0D, char[64])
-#define ECS_IOCTL_GET_MATRIX _IOR(AKMIO, 0x0E, short [4][3][3])
-
-/* IOCTLs for APPs */
-#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
-#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
-#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
-#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short)
-#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
-#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
-#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)
-#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17)
-#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, int64_t)
-#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
-
-/* Set raw magnetic vector flag */
-#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short)
-
-/* Get raw magnetic vector flag */
-#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short)
-
-struct akm8973_platform_data {
- short layouts[4][3][3];
- char project_name[64];
- int gpio_RST;
- int gpio_INT;
-};
-
-#endif
diff --git a/exynos4/hal/libsensors/sensors.cpp b/exynos4/hal/libsensors/sensors.cpp
deleted file mode 100644
index 6f0bdad..0000000
--- a/exynos4/hal/libsensors/sensors.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "Sensors"
-
-#include <hardware/sensors.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <math.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include <linux/input.h>
-
-#include <utils/Atomic.h>
-#include <utils/Log.h>
-
-#include "sensors.h"
-
-#include "LightSensor.h"
-#include "ProximitySensor.h"
-#include "AkmSensor.h"
-#include "GyroSensor.h"
-
-/*****************************************************************************/
-
-#define DELAY_OUT_TIME 0x7FFFFFFF
-
-#define LIGHT_SENSOR_POLLTIME 2000000000
-
-
-#define SENSORS_ACCELERATION (1<<ID_A)
-#define SENSORS_MAGNETIC_FIELD (1<<ID_M)
-#define SENSORS_ORIENTATION (1<<ID_O)
-#define SENSORS_LIGHT (1<<ID_L)
-#define SENSORS_PROXIMITY (1<<ID_P)
-#define SENSORS_GYROSCOPE (1<<ID_GY)
-
-#define SENSORS_ACCELERATION_HANDLE 0
-#define SENSORS_MAGNETIC_FIELD_HANDLE 1
-#define SENSORS_ORIENTATION_HANDLE 2
-#define SENSORS_LIGHT_HANDLE 3
-#define SENSORS_PROXIMITY_HANDLE 4
-#define SENSORS_GYROSCOPE_HANDLE 5
-
-#define AKM_FTRACE 0
-#define AKM_DEBUG 0
-#define AKM_DATA 0
-
-/*****************************************************************************/
-
-/* The SENSORS Module */
-static const struct sensor_t sSensorList[] = {
- { "KR3DM 3-axis Accelerometer",
- "STMicroelectronics",
- 1, SENSORS_ACCELERATION_HANDLE,
- SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.23f, 20000, { } },
- { "AK8975 3-axis Magnetic field sensor",
- "Asahi Kasei Microdevices",
- 1, SENSORS_MAGNETIC_FIELD_HANDLE,
- SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 16667, { } },
- { "AK8973 Orientation sensor",
- "Asahi Kasei Microdevices",
- 1, SENSORS_ORIENTATION_HANDLE,
- SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 16667, { } },
- { "CM3663 Light sensor",
- "Capella Microsystems",
- 1, SENSORS_LIGHT_HANDLE,
- SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.75f, 0, { } },
- { "CM3663 Proximity sensor",
- "Capella Microsystems",
- 1, SENSORS_PROXIMITY_HANDLE,
- SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } },
- { "K3G Gyroscope sensor",
- "STMicroelectronics",
- 1, SENSORS_GYROSCOPE_HANDLE,
- SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },
-};
-
-
-static int open_sensors(const struct hw_module_t* module, const char* id,
- struct hw_device_t** device);
-
-
-static int sensors__get_sensors_list(struct sensors_module_t* module,
- struct sensor_t const** list)
-{
- *list = sSensorList;
- return ARRAY_SIZE(sSensorList);
-}
-
-static struct hw_module_methods_t sensors_module_methods = {
- open: open_sensors
-};
-
-struct sensors_module_t HAL_MODULE_INFO_SYM = {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: SENSORS_HARDWARE_MODULE_ID,
- name: "Samsung Sensor module",
- author: "Samsung Electronic Company",
- methods: &sensors_module_methods,
- },
- get_sensors_list: sensors__get_sensors_list,
-};
-
-struct sensors_poll_context_t {
- struct sensors_poll_device_t device; // must be first
-
- sensors_poll_context_t();
- ~sensors_poll_context_t();
- int activate(int handle, int enabled);
- int setDelay(int handle, int64_t ns);
- int pollEvents(sensors_event_t* data, int count);
-
-private:
- enum {
- light = 0,
- proximity = 1,
- akm = 2,
- gyro = 3,
- numSensorDrivers,
- numFds,
- };
-
- static const size_t wake = numFds - 1;
- static const char WAKE_MESSAGE = 'W';
- struct pollfd mPollFds[numFds];
- int mWritePipeFd;
- SensorBase* mSensors[numSensorDrivers];
-
- int handleToDriver(int handle) const {
- switch (handle) {
- case ID_A:
- case ID_M:
- case ID_O:
- return akm;
- case ID_P:
- return proximity;
- case ID_L:
- return light;
- case ID_GY:
- return gyro;
- }
- return -EINVAL;
- }
-};
-
-/*****************************************************************************/
-
-sensors_poll_context_t::sensors_poll_context_t()
-{
- mSensors[light] = new LightSensor();
- mPollFds[light].fd = mSensors[light]->getFd();
- mPollFds[light].events = POLLIN;
- mPollFds[light].revents = 0;
-
- mSensors[proximity] = new ProximitySensor();
- mPollFds[proximity].fd = mSensors[proximity]->getFd();
- mPollFds[proximity].events = POLLIN;
- mPollFds[proximity].revents = 0;
-
- mSensors[akm] = new AkmSensor();
- mPollFds[akm].fd = mSensors[akm]->getFd();
- mPollFds[akm].events = POLLIN;
- mPollFds[akm].revents = 0;
-
- mSensors[gyro] = new GyroSensor();
- mPollFds[gyro].fd = mSensors[gyro]->getFd();
- mPollFds[gyro].events = POLLIN;
- mPollFds[gyro].revents = 0;
-
- int wakeFds[2];
- int result = pipe(wakeFds);
- LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
- fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
- fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
- mWritePipeFd = wakeFds[1];
-
- mPollFds[wake].fd = wakeFds[0];
- mPollFds[wake].events = POLLIN;
- mPollFds[wake].revents = 0;
-}
-
-sensors_poll_context_t::~sensors_poll_context_t() {
- for (int i=0 ; i<numSensorDrivers ; i++) {
- delete mSensors[i];
- }
- close(mPollFds[wake].fd);
- close(mWritePipeFd);
-}
-
-int sensors_poll_context_t::activate(int handle, int enabled) {
- int index = handleToDriver(handle);
- if (index < 0) return index;
- int err = mSensors[index]->enable(handle, enabled);
- if (enabled && !err) {
- const char wakeMessage(WAKE_MESSAGE);
- int result = write(mWritePipeFd, &wakeMessage, 1);
- LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
- }
- return err;
-}
-
-int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
-
- int index = handleToDriver(handle);
- if (index < 0) return index;
- return mSensors[index]->setDelay(handle, ns);
-}
-
-int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
-{
- int nbEvents = 0;
- int n = 0;
-
- do {
- // see if we have some leftover from the last poll()
- for (int i=0 ; count && i<numSensorDrivers ; i++) {
- SensorBase* const sensor(mSensors[i]);
- if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
- int nb = sensor->readEvents(data, count);
- if (nb < count) {
- // no more data for this sensor
- mPollFds[i].revents = 0;
- }
- count -= nb;
- nbEvents += nb;
- data += nb;
- }
- }
-
- if (count) {
- // we still have some room, so try to see if we can get
- // some events immediately or just wait if we don't have
- // anything to return
- n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
- if (n<0) {
- LOGE("poll() failed (%s)", strerror(errno));
- return -errno;
- }
- if (mPollFds[wake].revents & POLLIN) {
- char msg;
- int result = read(mPollFds[wake].fd, &msg, 1);
- LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
- LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
- mPollFds[wake].revents = 0;
- }
- }
- // if we have events and space, go read them
- } while (n && count);
-
- return nbEvents;
-}
-
-/*****************************************************************************/
-
-static int poll__close(struct hw_device_t *dev)
-{
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- if (ctx) {
- delete ctx;
- }
- return 0;
-}
-
-static int poll__activate(struct sensors_poll_device_t *dev,
- int handle, int enabled) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->activate(handle, enabled);
-}
-
-static int poll__setDelay(struct sensors_poll_device_t *dev,
- int handle, int64_t ns) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->setDelay(handle, ns);
-}
-
-static int poll__poll(struct sensors_poll_device_t *dev,
- sensors_event_t* data, int count) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->pollEvents(data, count);
-}
-
-/*****************************************************************************/
-
-/** Open a new instance of a sensor device using name */
-static int open_sensors(const struct hw_module_t* module, const char* id,
- struct hw_device_t** device)
-{
- int status = -EINVAL;
- sensors_poll_context_t *dev = new sensors_poll_context_t();
-
- memset(&dev->device, 0, sizeof(sensors_poll_device_t));
-
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = 0;
- dev->device.common.module = const_cast<hw_module_t*>(module);
- dev->device.common.close = poll__close;
- dev->device.activate = poll__activate;
- dev->device.setDelay = poll__setDelay;
- dev->device.poll = poll__poll;
-
- *device = &dev->device.common;
- status = 0;
-
- return status;
-}
-
diff --git a/exynos4/hal/libsensors/sensors.h b/exynos4/hal/libsensors/sensors.h
deleted file mode 100644
index ecc6fed..0000000
--- a/exynos4/hal/libsensors/sensors.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSORS_H
-#define ANDROID_SENSORS_H
-
-#include <stdint.h>
-#include <errno.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <linux/input.h>
-
-#include <hardware/hardware.h>
-#include <hardware/sensors.h>
-
-__BEGIN_DECLS
-
-/*****************************************************************************/
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-
-#define ID_A (0)
-#define ID_M (1)
-#define ID_O (2)
-#define ID_L (3)
-#define ID_P (4)
-#define ID_GY (5)
-
-/*****************************************************************************/
-
-/*
- * The SENSORS Module
- */
-
-/* the CM3663 is a binary proximity sensor that triggers around 6 cm on
- * this hardware */
-#define PROXIMITY_THRESHOLD_CM 6.0f
-
-/*****************************************************************************/
-
-#define AKM_DEVICE_NAME "/dev/akm8975"
-#define CM_DEVICE_NAME "/dev/i2c11" // FIXME Proximity
-#define LS_DEVICE_NAME "/dev/i2c11" // FIXME Lig
-
-/*
- E/Sensors ( 2656): AkmSensor: processing event (type=0, code=0)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=8)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=3)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=4)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=5)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=0)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=1)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=2)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=6)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=7)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=9)
- E/Sensors ( 2656): AkmSensor: processing event (type=0, code=0)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=8)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=3)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=4)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=5)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=0)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=1)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=2)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=6)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=7)
- E/Sensors ( 2656): AkmSensor: processing event (type=2, code=9)
-*/
-
-// for akm8975
-#define EVENT_TYPE_ACCEL_X ABS_Y //1
-#define EVENT_TYPE_ACCEL_Y ABS_X //0
-#define EVENT_TYPE_ACCEL_Z ABS_Z //2
-//#define EVENT_TYPE_ACCEL_STATUS ABS_WHEEL //8
-
-#define EVENT_TYPE_YAW ABS_RX //3
-#define EVENT_TYPE_PITCH ABS_RY //4
-#define EVENT_TYPE_ROLL ABS_RZ //5
-#define EVENT_TYPE_ORIENT_STATUS ABS_WHEEL //8
-
-#define EVENT_TYPE_MAGV_X ABS_RUDDER // 6
-#define EVENT_TYPE_MAGV_Y ABS_THROTTLE // 7
-#define EVENT_TYPE_MAGV_Z ABS_GAS // 9
-
-#define EVENT_TYPE_TEMPERATURE ABS_THROTTLE
-#define EVENT_TYPE_STEP_COUNT ABS_GAS
-#define EVENT_TYPE_PROXIMITY ABS_DISTANCE
-#define EVENT_TYPE_LIGHT ABS_MISC
-
-#define EVENT_TYPE_GYRO_X REL_RY
-#define EVENT_TYPE_GYRO_Y REL_RX
-#define EVENT_TYPE_GYRO_Z REL_RZ
-
-// 90 LSB = 1G for KR3DM
-#define LSB (90.0f)
-#define NUMOFACCDATA (8.0f)
-
-// conversion of acceleration data to SI units (m/s^2)
-#define RANGE_A (2*GRAVITY_EARTH)
-#define CONVERT_A (GRAVITY_EARTH / LSB / NUMOFACCDATA)
-#define CONVERT_A_X (CONVERT_A)
-#define CONVERT_A_Y (-CONVERT_A)
-#define CONVERT_A_Z (-CONVERT_A)
-
-// conversion of magnetic data to uT units
-#define CONVERT_M (1.0f/16.0f)
-#define CONVERT_M_X (CONVERT_M)
-#define CONVERT_M_Y (-CONVERT_M)
-#define CONVERT_M_Z (CONVERT_M)
-
-/* conversion of orientation data to degree units */
-#define CONVERT_O (1.0f/64.0f)
-#define CONVERT_O_A (CONVERT_O)
-#define CONVERT_O_P (CONVERT_O)
-#define CONVERT_O_R (-CONVERT_O)
-
-// conversion of gyro data to SI units (radian/sec)
-#define RANGE_GYRO (2000.0f*(float)M_PI/180.0f)
-#define CONVERT_GYRO ((70.0f / 1000.0f) * ((float)M_PI / 180.0f))
-#define CONVERT_GYRO_X (CONVERT_GYRO)
-#define CONVERT_GYRO_Y (-CONVERT_GYRO)
-#define CONVERT_GYRO_Z (CONVERT_GYRO)
-
-#define SENSOR_STATE_MASK (0x7FFF)
-
-/*****************************************************************************/
-
-__END_DECLS
-
-#endif // ANDROID_SENSORS_H
diff --git a/exynos4/hal/libswconverter/Android.mk b/exynos4/hal/libswconverter/Android.mk
index ce6daf4..e52aea7 100644
--- a/exynos4/hal/libswconverter/Android.mk
+++ b/exynos4/hal/libswconverter/Android.mk
@@ -1,20 +1,9 @@
-# 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_MODULE_TAGS := optional
+
LOCAL_SRC_FILES := \
swconvertor.c \
csc_linear_to_tiled_crop_neon.s \
@@ -24,21 +13,24 @@ LOCAL_SRC_FILES := \
csc_interleave_memcpy_neon.s
LOCAL_C_INCLUDES := \
- $(TOP)/$(BOARD_HMM_PATH)/openmax/include/khronos \
- $(TOP)/$(BOARD_HMM_PATH)/openmax/include/sec \
- $(TOP)/$(BOARD_HAL_PATH)/include \
- $(TOP)/$(BOARD_HAL_PATH)/libhwconverter
+ $(TOP)/$(TARGET_OMX_PATH)/include/khronos \
+ $(TOP)/$(TARGET_OMX_PATH)/include/sec \
+ $(TOP)/$(TARGET_HAL_PATH)/include \
+ $(TOP)/$(TARGET_HAL_PATH)/libhwconverter
ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true)
LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT
endif
-LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libswconverter
LOCAL_PRELINK_MODULE := false
+
+LOCAL_CFLAGS :=
+
LOCAL_ARM_MODE := arm
+LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES := liblog libfimc libhwconverter
include $(BUILD_STATIC_LIBRARY)
diff --git a/exynos4/hal/libump/Android.mk b/exynos4/hal/libump/Android.mk
deleted file mode 100644
index 306b6af..0000000
--- a/exynos4/hal/libump/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright (C) 2010 ARM Limited. All rights reserved.
-#
-# 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)
-
-UMP_SRCS := \
- arch_011_udd/ump_frontend.c \
- arch_011_udd/ump_ref_drv.c \
- arch_011_udd/ump_arch.c \
- os/linux/ump_uku.c \
- os/linux/ump_osu_memory.c \
- os/linux/ump_osu_locks.c
-
-# Shared and static library for target
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libUMP
-LOCAL_SRC_FILES := $(UMP_SRCS)
-
-LOCAL_C_INCLUDES:= \
- $(BOARD_HAL_PATH)/libump/ \
- $(BOARD_HAL_PATH)/libump/include \
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_STATIC_LIBRARIES)/
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libUMP
-LOCAL_MODULE_TAGS := optional
-LOCAL_WHOLE_STATIC_LIBRARIES := libUMP
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/
-include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos4/hal/libump/Makefile b/exynos4/hal/libump/Makefile
deleted file mode 100644
index b936fe9..0000000
--- a/exynos4/hal/libump/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright (C) 2010-2011 ARM Limited. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-UMP_DIR ?= .
-UMP_LIB ?= libUMP
-UDD_OS ?= android
-#CROSS_COMPILE ?= arm-none-linux-gnueabi-
-TARGET_CC ?= $(CROSS_COMPILE)gcc
-TARGET_AR ?= $(CROSS_COMPILE)ar
-CFLAGS += -I$(UMP_DIR)/include -I$(UMP_DIR)/include/ump -Wall -march=armv6 -mthumb-interwork -fno-strict-aliasing -Wno-strict-aliasing -Wno-long-long -O3
-
-include ump.mak
-
-%.o: %.c
- $(TARGET_CC) -c -o $@ $< $(CFLAGS)
-
-UMP_OBJS := $(UMP_SRCS:.c=.o)
-
-libUMP.so: $(UMP_OBJS)
- arm-none-linux-gnueabi-gcc -shared -o $@ $(UMP_OBJS) $(CFLAGS)
-libUMP.a: $(UMP_OBJS)
- $(TARGET_AR) rcs $@ $(UMP_OBJS)
-
-clean:
- -rm -f $(UMP_OBJS) libUMP.so libUMP.a
diff --git a/exynos4/hal/libump/arch_011_udd/ump_arch.c b/exynos4/hal/libump/arch_011_udd/ump_arch.c
deleted file mode 100644
index 79c3c18..0000000
--- a/exynos4/hal/libump/arch_011_udd/ump_arch.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_arch.c
- *
- * UMP arch layer for UMP-UDD
- */
-
-#include <ump/ump.h>
-#include "ump_arch.h"
-#include <ump/ump_debug.h>
-
-#include <ump/ump_uk_types.h>
-#include "../os/ump_uku.h"
-
-/** Pointer to an OS-Specific context that we should pass in _uku_ calls */
-void *ump_uk_ctx = NULL;
-
-/** Reference counting of ump_arch_open() and ump_arch_close(). */
-volatile static int ump_ref_count = 0;
-
-/** Lock for critical section in open/close */
-_ump_osu_lock_t * ump_lock = NULL;
-
-ump_result ump_arch_open(void)
-{
- ump_result retval = UMP_OK;
-
- _ump_osu_lock_auto_init( &ump_lock, 0, 0, 0 );
-
- /* Check that the lock was initialized */
- if (NULL == ump_lock)
- {
- UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to init lock\n"));
- return UMP_ERROR;
- }
-
- /* Attempt to obtain a lock */
- if( _UMP_OSU_ERR_OK != _ump_osu_lock_wait( ump_lock, _UMP_OSU_LOCKMODE_RW ) )
- {
- UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to acquire lock\n"));
- return UMP_ERROR;
- }
-
- /* ASSERT NEEDED */
- UMP_DEBUG_ASSERT(0 <= ump_ref_count, ("UMP: Reference count invalid at _ump_base_arch_open()"));
- ump_ref_count++;
-
- if (1 == ump_ref_count)
- {
- /* We are the first, open the UMP device driver */
-
- if (_UMP_OSU_ERR_OK != _ump_uku_open( &ump_uk_ctx ))
- {
- UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to open UMP device driver\n"));
- retval = UMP_ERROR;
- ump_ref_count--;
- }
- }
-
- /* Signal the lock so someone else can use it */
- _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW );
-
- return retval;
-}
-
-
-
-void ump_arch_close(void)
-{
- _ump_osu_lock_auto_init( &ump_lock, 0, 0, 0 );
-
- /* Check that the lock was initialized */
- if(NULL == ump_lock)
- {
- UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to init lock\n"));
- return;
- }
-
- /* Attempt to obtain a lock */
- if( _UMP_OSU_ERR_OK != _ump_osu_lock_wait( ump_lock, _UMP_OSU_LOCKMODE_RW ) )
- {
- UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to acquire lock\n"));
- return;
- }
-
- UMP_DEBUG_ASSERT(0 < ump_ref_count, ("UMP: ump_arch_close() called while no references exist"));
- if (ump_ref_count > 0)
- {
- ump_ref_count--;
- if (0 == ump_ref_count)
- {
- _ump_osu_errcode_t retval = _ump_uku_close(&ump_uk_ctx);
- UMP_DEBUG_ASSERT(retval == _UMP_OSU_ERR_OK, ("UMP: Failed to close UMP interface"));
- UMP_IGNORE(retval);
- ump_uk_ctx = NULL;
- _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW );
- _ump_osu_lock_term( ump_lock ); /* Not 100% thread safe, since another thread can already be waiting for this lock in ump_arch_open() */
- ump_lock = NULL;
- return;
- }
- }
-
- /* Signal the lock so someone else can use it */
- _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW );
-}
-
-
-
-ump_secure_id ump_arch_allocate(unsigned long * size, ump_alloc_constraints constraints)
-{
- _ump_uk_allocate_s call_arg;
-
- if ( NULL == size )
- {
- return UMP_INVALID_SECURE_ID;
- }
-
- call_arg.ctx = ump_uk_ctx;
- call_arg.secure_id = UMP_INVALID_SECURE_ID;
- call_arg.size = *size;
-#ifdef UMP_DEBUG_SKIP_CODE
- /** Run-time ASSERTing that _ump_uk_api_version_s and ump_alloc_constraints are
- * interchangable */
- switch (constraints)
- {
- case UMP_REF_DRV_CONSTRAINT_NONE:
- UMP_DEBUG_ASSERT( UMP_REF_DRV_UK_CONSTRAINT_NONE == constraints, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints") );
- break;
- case UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR:
- UMP_DEBUG_ASSERT( UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR == constraints, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints") );
- break;
- default:
- UMP_DEBUG_ASSERT( 1, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints: %d unrecognized", constraints) );
- break;
- }
-#endif
- call_arg.constraints = (ump_uk_alloc_constraints)constraints;
-
- if ( _UMP_OSU_ERR_OK != _ump_uku_allocate(&call_arg) )
- {
- return UMP_INVALID_SECURE_ID;
- }
-
- *size = call_arg.size;
-
- UMP_DEBUG_PRINT(4, ("UMP: Allocated ID %u, size %ul", call_arg.secure_id, call_arg.size));
-
- return call_arg.secure_id;
-}
-
-
-
-unsigned long ump_arch_size_get(ump_secure_id secure_id)
-{
- _ump_uk_size_get_s dd_size_call_arg;
-
- dd_size_call_arg.ctx = ump_uk_ctx;
- dd_size_call_arg.secure_id = secure_id;
- dd_size_call_arg.size = 0;
-
- if (_UMP_OSU_ERR_OK == _ump_uku_size_get( &dd_size_call_arg ) )
- {
- return dd_size_call_arg.size;
- }
-
- return 0;
-}
-
-
-void ump_arch_reference_release(ump_secure_id secure_id)
-{
- _ump_uk_release_s dd_release_call_arg;
- _ump_osu_errcode_t retval;
-
- dd_release_call_arg.ctx = ump_uk_ctx;
- dd_release_call_arg.secure_id = secure_id;
-
- UMP_DEBUG_PRINT(4, ("UMP: Releasing ID %u", secure_id));
-
- retval = _ump_uku_release( &dd_release_call_arg );
- UMP_DEBUG_ASSERT(retval == _UMP_OSU_ERR_OK, ("UMP: Failed to release reference to UMP memory"));
- UMP_IGNORE(retval);
-}
-
-
-void* ump_arch_map(ump_secure_id secure_id, unsigned long size, ump_cache_enabled cache, unsigned long *cookie_out)
-{
- _ump_uk_map_mem_s dd_map_call_arg;
-
- UMP_DEBUG_ASSERT_POINTER( cookie_out );
-
- dd_map_call_arg.ctx = ump_uk_ctx;
- dd_map_call_arg.secure_id = secure_id;
- dd_map_call_arg.size = size;
- dd_map_call_arg.is_cached = (u32) (UMP_CACHE_ENABLE==cache);
-
- if ( -1 == _ump_uku_map_mem( &dd_map_call_arg ) )
- {
- UMP_DEBUG_PRINT(4, ("UMP: Mapping failed for ID %u", secure_id));
- return NULL;
- }
-
- UMP_DEBUG_PRINT(4, ("Mapped %u at 0x%08lx", secure_id, (unsigned long)dd_map_call_arg.mapping));
-
- *cookie_out = dd_map_call_arg.cookie;
- return dd_map_call_arg.mapping;
-}
-
-
-
-void ump_arch_unmap(void* mapping, unsigned long size, unsigned long cookie)
-{
- _ump_uk_unmap_mem_s dd_unmap_call_arg;
-
- dd_unmap_call_arg.ctx = ump_uk_ctx;
- dd_unmap_call_arg.mapping = mapping;
- dd_unmap_call_arg.size = size;
- dd_unmap_call_arg.cookie = cookie;
-
- UMP_DEBUG_PRINT(4, ("Unmapping 0x%08lx", (unsigned long)mapping));
- _ump_uku_unmap_mem( &dd_unmap_call_arg );
-}
-
-/** Memory synchronization - cache flushing of mapped memory */
-int ump_arch_msync(ump_secure_id secure_id, void* mapping, unsigned long cookie, void * address, unsigned long size, ump_cpu_msync_op op)
-{
- _ump_uk_msync_s dd_msync_call_arg;
-
- dd_msync_call_arg.ctx = ump_uk_ctx;
- dd_msync_call_arg.mapping = mapping;
- dd_msync_call_arg.address = address;
- dd_msync_call_arg.size = size;
- dd_msync_call_arg.op = (ump_uk_msync_op)op;
- dd_msync_call_arg.cookie = cookie;
- dd_msync_call_arg.secure_id = secure_id;
- dd_msync_call_arg.is_cached = 0;
-
- UMP_DEBUG_PRINT(4, ("Msync 0x%08lx", (unsigned long)mapping));
- _ump_uku_msynch( &dd_msync_call_arg );
- if ( 0==dd_msync_call_arg.is_cached )
- {
- UMP_DEBUG_PRINT(4, ("Trying to flush uncached UMP mem ID: %d", secure_id));
- }
- return dd_msync_call_arg.is_cached;
-}
diff --git a/exynos4/hal/libump/arch_011_udd/ump_arch.h b/exynos4/hal/libump/arch_011_udd/ump_arch.h
deleted file mode 100644
index 064d7c5..0000000
--- a/exynos4/hal/libump/arch_011_udd/ump_arch.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_arch.h
- *
- * Header file for the arch dependent backend, which will do the communication with the UMP device driver.
- */
-
-#ifndef _UNIFIED_MEMORY_PROVIDER_ARCH_H_
-#define _UNIFIED_MEMORY_PROVIDER_ARCH_H_
-
-#include <ump/ump.h>
-#include <ump/ump_ref_drv.h>
-#include "ump_internal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-
-/** Open UMP interface. */
-ump_result ump_arch_open(void);
-
-/** Close UMP interface. */
-void ump_arch_close(void);
-
-/** Allocate UMP memory. */
-ump_secure_id ump_arch_allocate(unsigned long * size, ump_alloc_constraints constraints);
-
-/** Query size of specified UMP memory, in bytes. */
-unsigned long ump_arch_size_get(ump_secure_id secure_id);
-
-/** Release a reference from specified UMP memory. */
-void ump_arch_reference_release(ump_secure_id secure_id);
-
-/** Map specified UMP memory into CPU address space */
-void* ump_arch_map(ump_secure_id secure_id, unsigned long size, ump_cache_enabled cache, unsigned long *cookie_out);
-
-/** Unmap specified UMP memory from CPU adderss space */
-void ump_arch_unmap(void* mapping, unsigned long size, unsigned long cookie);
-
-/** Memory synchronization - cache flushing of mapped memory
- * @return Is_cached: 1==True 0==NonCached */
-int ump_arch_msync(ump_secure_id secure_id, void* mapping, unsigned long cookie, void * address, unsigned long size, ump_cpu_msync_op op);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UNIFIED_MEMORY_PROVIDER_ARCH_H_ */
diff --git a/exynos4/hal/libump/arch_011_udd/ump_frontend.c b/exynos4/hal/libump/arch_011_udd/ump_frontend.c
deleted file mode 100644
index 8c93332..0000000
--- a/exynos4/hal/libump/arch_011_udd/ump_frontend.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_frontend.c
- *
- * This file implements the user space API of the UMP API.
- * It relies heavily on a arch backend to do the communication with the UMP device driver.
- */
-
-#include <ump/ump.h>
-#include "ump_internal.h"
-#include "ump_arch.h"
-#include <ump/ump_debug.h>
-#include <ump/ump_osu.h>
-
-UMP_API_EXPORT ump_result ump_open(void)
-{
- return ump_arch_open();
-}
-
-UMP_API_EXPORT void ump_close(void)
-{
- ump_arch_close();
-}
-
-UMP_API_EXPORT ump_secure_id ump_secure_id_get(ump_handle memh)
-{
- ump_mem * mem = (ump_mem*)memh;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low"));
-
- return mem->secure_id;
-}
-
-UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id)
-{
- unsigned long size;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != secure_id, ("Secure ID is invalid"));
-
- size = ump_arch_size_get(secure_id);
- if (0 != size)
- {
- unsigned long cookie;
- /*
- * The UMP memory which the secure_id referes to could now be deleted and re-created
- * since we don't have any references to it yet. The mapping below will however fail if
- * we have supplied incorrect size, so we are safe.
- */
- void * mapping = ump_arch_map(secure_id, size, UMP_CACHE_DISABLE, &cookie);
- if (NULL != mapping)
- {
- ump_mem * mem = _ump_osu_calloc(1, sizeof(*mem));
- if (NULL != mem)
- {
- mem->secure_id = secure_id;
- mem->mapped_mem = mapping;
- mem->size = size;
- mem->cookie = cookie;
- mem->is_cached = 1; /* Is set to actually check in the ump_cpu_msync_now() function */
-
- _ump_osu_lock_auto_init(&mem->ref_lock, 0, 0, 0);
- UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n"));
- mem->ref_count = 1;
-
- /* This is called only to set the cache settings in this handle */
- ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0);
-
- UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem));
-
- return (ump_handle)mem;
- }
-
- ump_arch_unmap(mapping, size, cookie);
- }
- }
-
- UMP_DEBUG_PRINT(2, ("UMP handle creation failed for ID %u", secure_id));
-
- return UMP_INVALID_MEMORY_HANDLE;
-}
-
-UMP_API_EXPORT unsigned long ump_size_get(ump_handle memh)
-{
- ump_mem * mem = (ump_mem*)memh;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low"));
-
- return mem->size;
-}
-
-UMP_API_EXPORT void ump_read(void *dst, ump_handle srch, unsigned long offset, unsigned long length)
-{
- ump_mem * src = (ump_mem*)srch;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != srch, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != src->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < src->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < src->size, ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != src->mapped_mem, ("UMP Memory is not mapped"));
- UMP_DEBUG_ASSERT((src->size) >= (offset + length), ("Requested read beyond end of UMP memory"));
-
- _ump_osu_memcpy(dst,(char*)(src->mapped_mem) + offset, length);
-}
-
-UMP_API_EXPORT void ump_write(ump_handle dsth, unsigned long offset, const void *src, unsigned long length)
-{
- ump_mem * dst = (ump_mem*)dsth;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != dsth, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != dst->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < dst->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < dst->size, ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != dst->mapped_mem, ("UMP Memory is not mapped"));
- UMP_DEBUG_ASSERT((dst->size) >= (offset + length), ("Requested write beyond end of UMP memory"));
-
- _ump_osu_memcpy((char*)(dst->mapped_mem) + offset, src, length);
-}
-
-
-
-UMP_API_EXPORT void* ump_mapped_pointer_get(ump_handle memh)
-{
- ump_mem * mem = (ump_mem*)memh;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != mem->mapped_mem, ("Error in mapping pointer (not mapped)"));
-
- return mem->mapped_mem;
-}
-
-
-
-UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle memh)
-{
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != ((ump_mem*)memh)->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < ((ump_mem*)memh)->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < ((ump_mem*)memh)->size, ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != ((ump_mem*)memh)->mapped_mem, ("Error in mapping pointer (not mapped)"));
-
- /* noop, cos we map in the pointer when handle is created, and unmap it when handle is destroyed */
-}
-
-
-
-UMP_API_EXPORT void ump_reference_add(ump_handle memh)
-{
- ump_mem * mem = (ump_mem*)memh;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low"));
-
- _ump_osu_lock_wait(mem->ref_lock, _UMP_OSU_LOCKMODE_RW);
- mem->ref_count += 1;
- _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW);
-}
-
-
-
-UMP_API_EXPORT void ump_reference_release(ump_handle memh)
-{
- ump_mem * mem = (ump_mem*)memh;
-
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
- UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != ((ump_mem*)mem)->secure_id, ("Secure ID is inavlid"));
- UMP_DEBUG_ASSERT(0 < (((ump_mem*)mem)->ref_count), ("Reference count too low"));
- UMP_DEBUG_ASSERT(0 < ((ump_mem*)mem)->size, ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != ((ump_mem*)mem)->mapped_mem, ("Error in mapping pointer (not mapped)"));
-
- _ump_osu_lock_wait(mem->ref_lock, _UMP_OSU_LOCKMODE_RW);
- mem->ref_count -= 1;
- if (0 == mem->ref_count)
- {
- /* Remove memory mapping, which holds our only reference towards the UMP kernel space driver */
- ump_arch_unmap(mem->mapped_mem, mem->size, mem->cookie);
-
- _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW);
-
- /* Free the lock protecting the reference count */
- _ump_osu_lock_term(mem->ref_lock);
-
- /* Free the memory for this handle */
- _ump_osu_free(mem);
- } else {
- _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW);
- }
-}
diff --git a/exynos4/hal/libump/arch_011_udd/ump_internal.h b/exynos4/hal/libump/arch_011_udd/ump_internal.h
deleted file mode 100644
index bc1f2a9..0000000
--- a/exynos4/hal/libump/arch_011_udd/ump_internal.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_internal.c
- *
- * Internal definitions and debugging macros for the UMP implementation.
- */
-
-#ifndef _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_
-#define _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_
-
-#include <ump/ump.h>
-#include <ump/ump_osu.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum ump_cache_enabled
-{
- UMP_CACHE_DISABLE = 0,
- UMP_CACHE_ENABLE = 1
-} ump_cache_enabled;
-
-/**
- * The actual (hidden) definition of ump_handles.
- */
-typedef struct ump_mem
-{
- ump_secure_id secure_id; /**< UMP device driver cookie */
- void * mapped_mem; /**< Mapped memory; all read and write use this */
- unsigned long size; /**< Size of allocated memory */
- _ump_osu_lock_t* ref_lock; /**< Lock protection ref_count */
- int ref_count; /**< The reference count of the ump_handle in userspace. It is used for finding out
- when to free the memory used by this userspace handle. It is NOT the same as the
- real ump_mem reference count in the devicedriver which do reference counting
- for the memory that this handle reveals. */
- unsigned long cookie; /**< cookie for use in arch_unmap calls */
- ump_cache_enabled is_cached;
-} ump_mem;
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-#endif /* _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_ */
diff --git a/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c b/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c
deleted file mode 100644
index cf3b9eb..0000000
--- a/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_ref_drv.c
- *
- * Implementation of the user space API extensions provided by the reference implementation.
- */
-
-#include <ump/ump_ref_drv.h>
-#include <ump/ump.h>
-#include "ump_internal.h"
-#include "ump_arch.h"
-#include <ump/ump_debug.h>
-#include <ump/ump_osu.h>
-
-/* Allocate a buffer which can be used directly by hardware, 4kb aligned */
-static ump_handle ump_ref_drv_allocate_internal(unsigned long size, ump_alloc_constraints constraints, ump_cache_enabled cache);
-
-
-
-/* Allocate a buffer which can be used directly by hardware, 4kb aligned */
-ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints constraints)
-{
- ump_cache_enabled cache= UMP_CACHE_DISABLE;
- if ( 0!=(constraints&UMP_REF_DRV_CONSTRAINT_USE_CACHE) )
- {
- cache = UMP_CACHE_ENABLE;
- }
- return ump_ref_drv_allocate_internal(size, constraints, cache);
-}
-
-UMP_API_EXPORT int ump_cpu_msync_now(ump_handle memh, ump_cpu_msync_op op, void* address, int size)
-{
- ump_mem * mem = (ump_mem*)memh;
- UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid"));
-
- /* If the op is readout, we do the readout from DD.
- Else we skip flushing if the userspace handle says that it is uncached */
- if ((UMP_MSYNC_READOUT_CACHE_ENABLED!=op) && (0 == mem->is_cached) ) return 0;
-
- UMP_DEBUG_ASSERT(0 < (((ump_mem*)mem)->ref_count), ("Reference count too low"));
- UMP_DEBUG_ASSERT((size>=0) && (size <= ((ump_mem*)mem)->size), ("Memory size of passed handle too low"));
- UMP_DEBUG_ASSERT(NULL != ((ump_mem*)mem)->mapped_mem, ("Error in mapping pointer (not mapped)"));
-
- if (size > mem->size) size = mem->size;
-
- mem->is_cached = ump_arch_msync(mem->secure_id, mem->mapped_mem, mem->cookie, address, size, op);
- return mem->is_cached ;
-}
-
-/* Allocate a buffer which can be used directly by hardware, 4kb aligned */
-static ump_handle ump_ref_drv_allocate_internal(unsigned long size, ump_alloc_constraints constraints, ump_cache_enabled cache)
-{
- ump_secure_id secure_id;
- unsigned long allocated_size = size;
-
- UMP_DEBUG_PRINT(4, ("Allocating UMP memory of size %lu", size));
-
- secure_id = ump_arch_allocate(&allocated_size, constraints);
- if (secure_id != UMP_INVALID_SECURE_ID)
- {
- unsigned long cookie;
- void * mapping;
-
- mapping = ump_arch_map(secure_id, allocated_size, cache, &cookie);
- if (NULL != mapping)
- {
- /*
- * PS: By now we have actually increased the ref count in the device driver by 2,
- * one for the allocation iteself, and one for the mapping.
- */
- ump_mem * mem;
- mem = _ump_osu_calloc(1, sizeof(*mem));
- if (NULL != mem)
- {
- mem->secure_id = secure_id;
- mem->mapped_mem = mapping;
- mem->size = allocated_size;
- mem->cookie = cookie;
- mem->is_cached = 1; /* Default to ON, is disabled later if not */
-
- _ump_osu_lock_auto_init(&mem->ref_lock, 0, 0, 0);
- UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n"));
- mem->ref_count = 1;
-
- /*
- * ump_arch_allocate() gave us a kernel space reference, and the same did ump_arch_map()
- * We release the one from ump_arch_allocate(), and rely solely on the one from the ump_arch_map()
- * That is, ump_arch_unmap() should now do the final release towards the UMP kernel space driver.
- */
- ump_arch_reference_release(secure_id);
-
- /* This is called only to set the cache settings in this handle */
- ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0);
-
- UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem));
-
- return (ump_handle)mem;
- }
-
- ump_arch_unmap(mapping, allocated_size, cookie); /* Unmap the memory */
- ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */
- }
-
- ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */
- }
-
- UMP_DEBUG_PRINT(4, ("Allocation of UMP memory failed"));
- return UMP_INVALID_MEMORY_HANDLE;
-}
diff --git a/exynos4/hal/libump/include/ump/ump_debug.h b/exynos4/hal/libump/include/ump/ump_debug.h
deleted file mode 100644
index 5ede8a3..0000000
--- a/exynos4/hal/libump/include/ump/ump_debug.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_debug.h
- *
- * The file include several useful macros for debugging and printing.
- * - UMP_PRINTF(...) Do not use this function: Will be included in Release builds.
- * - UMP_DEBUG_TRACE() Prints current location in code.
- * - UMP_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=UMP_DEBUG_LEVEL.
- * - UMP_DEBUG_TPRINT(nr, X ) Prints the source trace and second argument if nr<=UMP_DEBUG_LEVEL.
- * - UMP_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message.
- * - UMP_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit.
- * - UMP_DEBUG_ASSERT_RANGE(x, min, max) Triggers if variable x is not between or equal to max and min.
- * - UMP_DEBUG_ASSERT_LEQ(x, max) Triggers if variable x is not less than equal to max.
- * - UMP_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer.
- * - UMP_DEBUG_CODE( X ) The code inside the macro is only copiled in Debug builds.
- *
- * The (X) means that you must add an extra parantese around the argumentlist.
- *
- * The printf function: UMP_PRINTF(...) is routed to _ump_sys_printf
- *
- * Suggested range for the DEBUG-LEVEL is [1:6] where
- * [1:2] Is messages with highest priority, indicate possible errors.
- * [3:4] Is messages with medium priority, output important variables.
- * [5:6] Is messages with low priority, used during extensive debugging.
- *
- */
-#ifndef _UMP_DEBUG_H_
-#define _UMP_DEBUG_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/* START: Configuration */
-#ifndef UMP_PRINTF
- #define UMP_PRINTF printf
-#endif /* UMP_PRINTF */
-
-#ifndef UMP_PRINT_FLUSH
- #define UMP_PRINT_FLUSH do {} while (0)
-#endif /* UMP_PRINT_FLUSH */
-
-#ifndef UMP_DEBUG_LEVEL
- #define UMP_DEBUG_LEVEL 1
-#endif /* UMP_DEBUG_LEVEL */
-
-#ifndef UMP_DEBUG_ERROR_START_MSG
- #define UMP_DEBUG_ERROR_START_MSG do {\
- UMP_PRINTF("*********************************************************************\n");\
- UMP_PRINT_FLUSH; } while (0)
-#endif /* UMP_DEBUG_ERROR_START_MSG */
-
-#ifndef UMP_DEBUG_ERROR_STOP_MSG
- #define UMP_DEBUG_ERROR_STOP_MSG do { UMP_PRINTF("\n"); UMP_PRINT_FLUSH; } while (0)
-#endif /* UMP_DEBUG_ERROR_STOP_MSG */
-
-#ifndef UMP_ASSERT_QUIT_CMD
- #define UMP_ASSERT_QUIT_CMD abort()
-#endif /* UMP_ASSERT_QUIT_CMD */
-/* STOP: Configuration */
-
-/**
- * The macro UMP_FUNCTION evaluates to the name of the function enclosing
- * this macro's usage, or "<unknown>" if not supported.
- */
-#if (defined(__SYMBIAN32__) && defined(__ARMCC__)) || defined(_MSC_VER)
-# define UMP_FUNCTION __FUNCTION__
-#elif __STDC__ && __STDC_VERSION__ >= 199901L
-# define UMP_FUNCTION __FUNCTION__
-#elif defined(__GNUC__) && __GNUC__ >= 2
-# define UMP_FUNCTION __FUNCTION__
-#elif defined(__func__)
-# define UMP_FUNCTION __func__
-#else
-# define UMP_FUNCTION "<unknown>"
-#endif
-
-/**
- * Explicitly ignore a parameter passed into a function, to suppress compiler warnings.
- * Should only be used with parameter names.
- */
-#define UMP_IGNORE(x) (void)x
-
-/**
- * @def UMP_DEBUG_TRACE()
- * @brief Prints current location in code.
- * Can be turned off by defining UMP_DEBUG_SKIP_TRACE
- */
-
-#ifndef UMP_DEBUG_SKIP_TRACE
- #ifndef UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME
- #define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ \
- " function: %s() line:%4d\n" , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0)
- #else
- #define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ " line:%4d\n" , __LINE__); UMP_PRINT_FLUSH; } while (0)
- #endif /* UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME */
-#else
- #define UMP_DEBUG_TRACE()
-#endif /* UMP_DEBUG_SKIP_TRACE */
-
-/**
- * @def UMP_DEBUG_PRINT(nr, (X) )
- * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL.
- * Can be turned off by defining UMP_DEBUG_SKIP_PRINT
- * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text.
- * @param X A parantese with the contents to be sent to UMP_PRINTF
- */
-#ifndef UMP_DEBUG_SKIP_PRINT
- #define UMP_DEBUG_PRINT(nr, X ) do { if ( nr<=UMP_DEBUG_LEVEL ) { UMP_PRINTF X ; UMP_PRINT_FLUSH; } } while (0)
-#else
- #define UMP_DEBUG_PRINT(nr, X )
-#endif /* UMP_DEBUG_SKIP_PRINT */
-
-/**
- * @def UMP_DEBUG_TPRINT(nr, (X) )
- * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL.
- * Can be turned off by defining UMP_DEBUG_SKIP_TPRINT.
- * Can be shortened by defining UMP_DEBUG_TPRINT_SKIP_FUNCTION.
- * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text.
- * @param X A parantese with the contents to be sent to UMP_PRINTF
- */
-
-/* helper to handle if the function name should be included or not */
-#ifndef UMP_DEBUG_TPRINT_SKIP_FUNCTION
- #define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__" %s()%4d " , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0)
-#else
- #define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__ "%4d " , __LINE__); UMP_PRINT_FLUSH; } while (0)
-#endif /* UMP_DEBUG_TPRINT_SKIP_FUNCTION */
-
-#ifndef UMP_DEBUG_SKIP_TPRINT
- #define UMP_DEBUG_TPRINT(nr, X ) \
- do{\
- if ( nr<=UMP_DEBUG_LEVEL )\
- {\
- UMP_DEBUG_TPRINT_INTERN;\
- UMP_PRINTF X ;\
- UMP_PRINT_FLUSH;\
- }\
- } while (0)
-#else
- #define UMP_DEBUG_TPRINT(nr, X )
-#endif /* UMP_DEBUG_SKIP_TPRINT */
-
-/**
- * @def UMP_DEBUG_ERROR( (X) )
- * @brief Prints an errortext, a source Trace, and the given error message.
- * Prints filename, function, linenr, and the given error message.
- * The error message must be inside a second parantese.
- * The error message is written on a separate line, and a NL char is added.
- * Can be turned of by defining UMP_DEBUG_SKIP_ERROR;
- * You do not need to type the words ERROR in the message, since it will
- * be added anyway.
- *
- * @note You should not end the text with a newline, since it is added by the macro.
- * @note You should not write "ERROR" in the text, since it is added by the macro.
- * @param X A parantese with the contents to be sent to UMP_PRINTF
- */
-
-#ifndef UMP_DEBUG_SKIP_ERROR
- #define UMP_DEBUG_ERROR( X ) \
- do{ \
- UMP_DEBUG_ERROR_START_MSG;\
- UMP_PRINTF("ERROR: ");\
- UMP_PRINT_FLUSH;\
- UMP_DEBUG_TRACE(); \
- UMP_PRINTF X ; \
- UMP_PRINT_FLUSH;\
- UMP_DEBUG_ERROR_STOP_MSG;\
- } while (0)
-#else
- #define UMP_DEBUG_ERROR( X ) do{ ; } while ( 0 )
-#endif /* UMP_DEBUG_SKIP_ERROR */
-
-/**
- * @def UMP_DEBUG_ASSERT(expr, (X) )
- * @brief If the asserted expr is false, the program will exit.
- * Prints filename, function, linenr, and the given error message.
- * The error message must be inside a second parantese.
- * The error message is written on a separate line, and a NL char is added.
- * Can be turned of by defining UMP_DEBUG_SKIP_ERROR;
- * You do not need to type the words ASSERT in the message, since it will
- * be added anyway.
- *
- * @param X A parantese with the contents to be sent to UMP_PRINTF
- * Prints filename, function, linenr, and the error message
- * on a separte line. A newline char is added at the end.
- * Can be turned of by defining UMP_DEBUG_SKIP_ASSERT
- * @param expr Will exit program if \a expr is false;
- * @param (X) Text that will be written if the assertion toggles.
- */
-
-#ifndef UMP_DEBUG_SKIP_ASSERT
- #define UMP_DEBUG_ASSERT(expr, X ) \
- do{\
- if ( !(expr) ) \
- { \
- UMP_DEBUG_ERROR_START_MSG;\
- UMP_PRINTF("ASSERT EXIT: ");\
- UMP_PRINT_FLUSH;\
- UMP_DEBUG_TRACE(); \
- UMP_PRINTF X ; \
- UMP_PRINT_FLUSH;\
- UMP_DEBUG_ERROR_STOP_MSG;\
- UMP_ASSERT_QUIT_CMD;\
- }\
- } while (0)
-#else
- #define UMP_DEBUG_ASSERT(expr, X)
-#endif /* UMP_DEBUG_SKIP_ASSERT */
-
-
-/**
- * @def UMP_DEBUG_ASSERT_POINTER(pointer)
- * @brief If the asserted pointer is NULL, the program terminates and TRACE info is printed
- * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
- */
-#define UMP_DEBUG_ASSERT_POINTER(pointer) UMP_DEBUG_ASSERT(pointer, ("Null pointer " #pointer) )
-
-/**
- * @def UMP_DEBUG_ASSERT_HANDLE(handle)
- * @brief If the asserted handle is not a valid handle, the program terminates and TRACE info is printed
- * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
- */
-#define UMP_DEBUG_ASSERT_HANDLE(handle) UMP_DEBUG_ASSERT(UMP_NO_HANDLE != (handle), ("Invalid handle" #handle) )
-
-/**
- * @def UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align)
- * @brief If the asserted pointer is not aligned to align, the program terminates with trace info printed.
- * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
- */
-#ifndef UMP_DEBUG_SKIP_ASSERT
- #define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) do { \
- UMP_DEBUG_ASSERT(0 == (align & (align - 1)), ("align %d is not a power-of-two", align)); \
- UMP_DEBUG_ASSERT(0 == (((u32)(ptr)) & (align - 1)), ("ptr %p not aligned to %d bytes", (void*)ptr, align)); \
- } while (0)
-#else
- #define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align)
-#endif /* UMP_DEBUG_SKIP_ASSERT */
-
-/**
- * @def UMP_DEBUG_ASSERT_RANGE(x,min,max)
- * @brief If variable x is not between or equal to max and min, the assertion triggers.
- * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
- */
-#define UMP_DEBUG_ASSERT_RANGE(x, min, max) \
- UMP_DEBUG_ASSERT( (x) >= (min) && (x) <= (max), \
- (#x " out of range (%2.2f)", (double)x ) \
- )
-
-/**
- * @def UMP_DEBUG_ASSERT_LEQ(x,max)
- * @brief If variable x is less than or equal to max, the assertion triggers.
- * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
- */
-#define UMP_DEBUG_ASSERT_LEQ(x, max) \
- UMP_DEBUG_ASSERT( (x) <= (max), \
- (#x " out of range (%2.2f)", (double)x ) \
- )
-
-/**
- * @def UMP_DEBUG_CODE( X )
- * @brief Run the code X on debug builds.
- * The code will not be used if UMP_DEBUG_SKIP_CODE is defined .
- *
- */
-#ifdef UMP_DEBUG_SKIP_CODE
- #define UMP_DEBUG_CODE( X )
-#else
- #define UMP_DEBUG_CODE( X ) X
-#endif /* UMP_DEBUG_SKIP_CODE */
-
-#endif /* _UMP_DEBUG_H_ */
-
diff --git a/exynos4/hal/libump/include/ump/ump_osu.h b/exynos4/hal/libump/include/ump/ump_osu.h
deleted file mode 100644
index 5c9a650..0000000
--- a/exynos4/hal/libump/include/ump/ump_osu.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_osu.h
- * Defines the OS abstraction layer for the base driver
- */
-
-#ifndef __UMP_OSU_H__
-#define __UMP_OSU_H__
-
-#include <stdarg.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-typedef unsigned int u32;
-#ifdef _MSC_VER
- typedef unsigned __int64 u64;
- typedef signed __int64 s64;
-#else
- typedef unsigned long long u64;
- typedef signed long long s64;
-#endif
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-typedef unsigned long ump_bool;
-
-#ifndef UMP_TRUE
-#define UMP_TRUE ((ump_bool)1)
-#endif
-
-#ifndef UMP_FALSE
-#define UMP_FALSE ((ump_bool)0)
-#endif
-
-#define UMP_STATIC static
-
-/**
- * @addtogroup ump_user_space_api Unified Device Driver (UDD) APIs used by UMP
- *
- * @{
- */
-
-/**
- * @defgroup ump_osuapi UDD OS Abstraction for User-side (OSU) APIs for UMP
- *
- * @{
- */
-
-/* The following is necessary to prevent the _ump_osk_errcode_t doxygen from
- * becoming unreadable: */
-/** @cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */
-
-/**
- * @brief OSU/OSK Error codes.
- *
- * Each OS may use its own set of error codes, and may require that the
- * User/Kernel interface take certain error code. This means that the common
- * error codes need to be sufficiently rich to pass the correct error code
- * through from the OSK/OSU to U/K layer, across all OSs.
- *
- * The result is that some error codes will appear redundant on some OSs.
- * Under all OSs, the OSK/OSU layer must translate native OS error codes to
- * _ump_osk/u_errcode_t codes. Similarly, the U/K layer must translate from
- * _ump_osk/u_errcode_t codes to native OS error codes.
- *
- */
-typedef enum
-{
- _UMP_OSK_ERR_OK = 0, /**< Success. */
- _UMP_OSK_ERR_FAULT = -1, /**< General non-success */
- _UMP_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */
- _UMP_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */
- _UMP_OSK_ERR_NOMEM = -4, /**< Insufficient memory */
- _UMP_OSK_ERR_TIMEOUT = -5, /**< Timeout occured */
- _UMP_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */
- _UMP_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */
- _UMP_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */
- _UMP_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */
-} _ump_osk_errcode_t;
-
-/** @endcond */ /* end cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */
-
-/**
- * @brief OSU Error codes.
- *
- * OSU error codes - enum values intentionally same as OSK
- */
-typedef enum
-{
- _UMP_OSU_ERR_OK = 0, /**< Success. */
- _UMP_OSU_ERR_FAULT = -1, /**< General non-success */
- _UMP_OSU_ERR_TIMEOUT = -2, /**< Timeout occured */
-} _ump_osu_errcode_t;
-
-/** @brief Translate OSU error code to base driver error code.
- *
- * The _UMP_OSU_TRANSLATE_ERROR macro translates an OSU error code to the
- * error codes in use by the base driver.
- */
-#define _UMP_OSU_TRANSLATE_ERROR(_ump_osu_errcode) ( ( _UMP_OSU_ERR_OK == (_ump_osu_errcode) ) ? UMP_ERR_NO_ERROR : UMP_ERR_FUNCTION_FAILED)
-
-/** @defgroup _ump_osu_lock OSU Mutual Exclusion Locks
- * @{ */
-
-/** @brief OSU Mutual Exclusion Lock flags type.
- *
- * This is made to look like and function identically to the OSK locks (refer
- * to \ref _ump_osk_lock). However, please note the following \b important
- * differences:
- * - the OSU default lock is a Sleeping, non-interruptible mutex.
- * - the OSU adds the ANYUNLOCK type of lock which allows a thread which doesn't
- * own the lock to release the lock.
- * - the order parameter when creating a lock is currently unused
- *
- * @note Pay careful attention to the difference in default locks for OSU and
- * OSK locks; OSU locks are always non-interruptible, but OSK locks are by
- * default, interruptible. This has implications for systems that do not
- * distinguish between user and kernel mode.
- */
-typedef enum
-{
- _UMP_OSU_LOCKFLAG_DEFAULT = 0, /**< Default lock type. */
- /** @enum _ump_osu_lock_flags_t
- *
- * Flags from 0x8000--0x1 are RESERVED for Kernel-mode
- */
- _UMP_OSU_LOCKFLAG_ANYUNLOCK = 0x10000, /**< Mutex that guarantees that any thread can unlock it when locked. Otherwise, this will not be possible. */
- /** @enum _ump_osu_lock_flags_t
- *
- * Flags from 0x80000000 are RESERVED for User-mode
- */
- _UMP_OSU_LOCKFLAG_STATIC = 0x80000000, /* Flag in OSU reserved range to identify lock as a statically initialized lock */
-
- } _ump_osu_lock_flags_t;
-
-typedef enum
-{
- _UMP_OSU_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */
- _UMP_OSU_LOCKMODE_RW = 0x0, /**< Default. Lock is used to protect data that is read from and written to */
- /** @enum _ump_osu_lock_mode_t
- *
- * Lock modes 0x1--0x3F are RESERVED for Kernel-mode */
-} _ump_osu_lock_mode_t;
-
-/** @brief Private type for Mutual Exclusion lock objects. */
-typedef struct _ump_osu_lock_t_struct _ump_osu_lock_t;
-
-/** @brief The number of static locks supported in _ump_osu_lock_static(). */
-#define UMP_OSU_STATIC_LOCK_COUNT (sizeof(_ump_osu_static_locks) / sizeof(_ump_osu_lock_t))
-
-/** @} */ /* end group _ump_osu_lock */
-
-/** @defgroup _ump_osu_memory OSU Memory Allocation
- * @{ */
-
-/** @brief Allocate zero-initialized memory.
- *
- * Returns a buffer capable of containing at least \a n elements of \a size
- * bytes each. The buffer is initialized to zero.
- *
- * The buffer is suitably aligned for storage and subsequent access of every
- * type that the compiler supports. Therefore, the pointer to the start of the
- * buffer may be cast into any pointer type, and be subsequently accessed from
- * such a pointer, without loss of information.
- *
- * When the buffer is no longer in use, it must be freed with _ump_osu_free().
- * Failure to do so will cause a memory leak.
- *
- * @note Most toolchains supply memory allocation functions that meet the
- * compiler's alignment requirements.
- *
- * @param n Number of elements to allocate
- * @param size Size of each element
- * @return On success, the zero-initialized buffer allocated. NULL on failure
- */
-void *_ump_osu_calloc( u32 n, u32 size );
-
-/** @brief Allocate memory.
- *
- * Returns a buffer capable of containing at least \a size bytes. The
- * contents of the buffer are undefined.
- *
- * The buffer is suitably aligned for storage and subsequent access of every
- * type that the compiler supports. Therefore, the pointer to the start of the
- * buffer may be cast into any pointer type, and be subsequently accessed from
- * such a pointer, without loss of information.
- *
- * When the buffer is no longer in use, it must be freed with _ump_osu_free().
- * Failure to do so will cause a memory leak.
- *
- * @note Most toolchains supply memory allocation functions that meet the
- * compiler's alignment requirements.
- *
- * Remember to free memory using _ump_osu_free().
- * @param size Number of bytes to allocate
- * @return On success, the buffer allocated. NULL on failure.
- */
-void *_ump_osu_malloc( u32 size );
-
-/** @brief Free memory.
- *
- * Reclaims the buffer pointed to by the parameter \a ptr for the system.
- * All memory returned from _ump_osu_malloc(), _ump_osu_calloc() and
- * _ump_osu_realloc() must be freed before the application exits. Otherwise,
- * a memory leak will occur.
- *
- * Memory must be freed once. It is an error to free the same non-NULL pointer
- * more than once.
- *
- * It is legal to free the NULL pointer.
- *
- * @param ptr Pointer to buffer to free
- */
-void _ump_osu_free( void *ptr );
-
-/** @brief Copies memory.
- *
- * Copies the \a len bytes from the buffer pointed by the parameter \a src
- * directly to the buffer pointed by \a dst.
- *
- * It is an error for \a src to overlap \a dst anywhere in \a len bytes.
- *
- * @param dst Pointer to the destination array where the content is to be
- * copied.
- * @param src Pointer to the source of data to be copied.
- * @param len Number of bytes to copy.
- * @return \a dst is always passed through unmodified.
- */
-void *_ump_osu_memcpy( void *dst, const void *src, u32 len );
-
-/** @brief Fills memory.
- *
- * Sets the first \a size bytes of the block of memory pointed to by \a ptr to
- * the specified value
- * @param ptr Pointer to the block of memory to fill.
- * @param chr Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB)
- * are used.
- * @param size Number of bytes to be set to the value.
- * @return \a ptr is always passed through unmodified
- */
-void *_ump_osu_memset( void *ptr, u32 chr, u32 size );
-
-/** @} */ /* end group _ump_osu_memory */
-
-
-/** @addtogroup _ump_osu_lock
- * @{ */
-
-/** @brief Initialize a Mutual Exclusion Lock.
- *
- * Locks are created in the signalled (unlocked) state.
- *
- * The parameter \a initial must be zero.
- *
- * At present, the parameter \a order must be zero. It remains for future
- * expansion for mutex order checking.
- *
- * @param flags flags combined with bitwise OR ('|'), or zero. There are
- * restrictions on which flags can be combined, see \ref _ump_osu_lock_flags_t.
- * @param initial For future expansion into semaphores. SBZ.
- * @param order The locking order of the mutex. SBZ.
- * @return On success, a pointer to a \ref _ump_osu_lock_t object. NULL on failure.
- */
-_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order );
-
-/** @brief Obtain a statically initialized Mutual Exclusion Lock.
- *
- * Retrieves a reference to a statically initialized lock. Up to
- * _UMP_OSU_STATIC_LOCK_COUNT statically initialized locks are
- * available. Only _ump_osu_lock_wait(), _ump_osu_lock_trywait(),
- * _ump_osu_lock_signal() can be used with statically initialized locks.
- * _UMP_OSU_LOCKMODE_RW mode should be used when waiting and signalling
- * statically initialized locks.
- *
- * For the same \a nr a pointer to the same statically initialized lock is
- * returned. That is, given the following code:
- * @code
- * extern u32 n;
- *
- * _ump_osu_lock_t *locka = _ump_osu_lock_static(n);
- * _ump_osu_lock_t *lockb = _ump_osu_lock_static(n);
- * @endcode
- * Then (locka == lockb), for all 0 <= n < UMP_OSU_STATIC_LOCK_COUNT.
- *
- * @param nr index of a statically initialized lock [0..UMP_OSU_STATIC_LOCK_COUNT-1]
- * @return On success, a pointer to a _ump_osu_lock_t object. NULL on failure.
- */
-_ump_osu_lock_t *_ump_osu_lock_static( u32 nr );
-
-/** @brief Initialize a Mutual Exclusion Lock safely across multiple threads.
- *
- * The _ump_osu_lock_auto_init() function guarantees that the given lock will
- * be initialized once and precisely once, even in a situation involving
- * multiple threads.
- *
- * This is necessary because the first call to certain Public API functions must
- * initialize the API. However, there can be a race involved to call the first
- * library function in multi-threaded applications. To resolve this race, a
- * mutex can be used. This mutex must be initialized, but initialized only once
- * by any thread that might compete for its initialization. This function
- * guarantees the initialization to happen correctly, even when there is an
- * initialization race between multiple threads.
- *
- * Otherwise, the operation is identical to the _ump_osu_lock_init() function.
- * For more details, refer to _ump_osu_lock_init().
- *
- * @param pplock pointer to storage for a _ump_osu_lock_t pointer. This
- * _ump_osu_lock_t pointer may point to a _ump_osu_lock_t that has been
- * initialized already
- * @param flags flags combined with bitwise OR ('|'), or zero. There are
- * restrictions on which flags can be combined. Refer to
- * \ref _ump_osu_lock_flags_t for more information.
- * The absence of any flags (the value 0) results in a sleeping-mutex,
- * which is non-interruptible.
- * @param initial For future expansion into semaphores. SBZ.
- * @param order The locking order of the mutex. SBZ.
- * @return On success, _UMP_OSU_ERR_OK is returned and a pointer to an
- * initialized \ref _ump_osu_lock_t object is written into \a *pplock.
- * _UMP_OSU_ERR_FAULT is returned on failure.
- */
-_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order );
-
-/** @brief Wait for a lock to be signalled (obtained).
- *
- * After a thread has successfully waited on the lock, the lock is obtained by
- * the thread, and is marked as unsignalled. The thread releases the lock by
- * signalling it.
- *
- * To prevent deadlock, locks must always be obtained in the same order.
- *
- * @param lock the lock to wait upon (obtain).
- * @param mode the mode in which the lock should be obtained. Currently this
- * must be _UMP_OSU_LOCKMODE_RW.
- * @return On success, _UMP_OSU_ERR_OK, _UMP_OSU_ERR_FAULT on error.
- */
-_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode);
-
-/** @brief Wait for a lock to be signalled (obtained) with timeout
- *
- * After a thread has successfully waited on the lock, the lock is obtained by
- * the thread, and is marked as unsignalled. The thread releases the lock by
- * signalling it.
- *
- * To prevent deadlock, locks must always be obtained in the same order.
- *
- * This version can return early if it cannot obtain the lock within the given timeout.
- *
- * @param lock the lock to wait upon (obtain).
- * @param mode the mode in which the lock should be obtained. Currently this
- * must be _UMP_OSU_LOCKMODE_RW.
- * @param timeout Relative time in microseconds for the timeout
- * @return _UMP_OSU_ERR_OK if the lock was obtained, _UMP_OSU_ERR_TIMEOUT if the timeout expired or _UMP_OSU_ERR_FAULT on error.
- */
-_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout);
-
-/** @brief Test for a lock to be signalled and obtains the lock when so.
- *
- * Obtains the lock only when it is in signalled state. The lock is then
- * marked as unsignalled. The lock is released again by signalling
- * it by _ump_osu_lock_signal().
- *
- * If the lock could not be obtained immediately (that is, another thread
- * currently holds the lock), then this function \b does \b not wait for the
- * lock to be in a signalled state. Instead, an error code is immediately
- * returned to indicate that the thread could not obtain the lock.
- *
- * To prevent deadlock, locks must always be obtained in the same order.
- *
- * @param lock the lock to wait upon (obtain).
- * @param mode the mode in which the lock should be obtained. Currently this
- * must be _UMP_OSU_LOCKMODE_RW.
- * @return When the lock was obtained, _UMP_OSU_ERR_OK. If the lock could not
- * be obtained, _UMP_OSU_ERR_FAULT.
- */
-_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode);
-
-/** @brief Signal (release) a lock.
- *
- * Locks may only be signalled by the thread that originally waited upon the
- * lock, unless the lock was created using the _UMP_OSU_LOCKFLAG_ANYUNLOCK flag.
- *
- * @param lock the lock to signal (release).
- * @param mode the mode in which the lock should be obtained. This must match
- * the mode in which the lock was waited upon.
- */
-void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode );
-
-/** @brief Terminate a lock.
- *
- * This terminates a lock and frees all associated resources.
- *
- * It is a programming error to terminate the lock when it is held (unsignalled)
- * by a thread.
- *
- * @param lock the lock to terminate.
- */
-void _ump_osu_lock_term( _ump_osu_lock_t *lock );
-/** @} */ /* end group _ump_osu_lock */
-
-/** @} */ /* end group osuapi */
-
-/** @} */ /* end group uddapi */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UMP_OSU_H__ */
diff --git a/exynos4/hal/libump/include/ump/ump_platform.h b/exynos4/hal/libump/include/ump/ump_platform.h
deleted file mode 100644
index 68e01be..0000000
--- a/exynos4/hal/libump/include/ump/ump_platform.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_platform.h
- *
- * This file should define UMP_API_EXPORT,
- * which dictates how the UMP user space API should be exported/imported.
- * Modify this file, if needed, to match your platform setup.
- */
-
-#ifndef __UMP_PLATFORM_H__
-#define __UMP_PLATFORM_H__
-
-/** @addtogroup ump_user_space_api
- * @{ */
-
-/**
- * A define which controls how UMP user space API functions are imported and exported.
- * This define should be set by the implementor of the UMP API.
- */
-#if defined(_WIN32)
-
-#define UMP_API_EXPORT
-
-#elif defined(__SYMBIAN32__)
-
-#define UMP_API_EXPORT IMPORT_C
-
-#else
-
-#if defined(__GNUC__)
-#if __GNUC__ >= 4
-# define MALI_VISIBLE __attribute__ ((visibility ("default"))) /**< Function should be visible from outside the dll */
-#else
-# define MALI_VISIBLE
-#endif
-
-#elif defined(__ARMCC_VERSION)
-/* ARMCC specific */
-# define MALI_VISIBLE __declspec(dllexport)
-
-#else
-# define MALI_VISIBLE
-
-#endif
-
-#define UMP_API_EXPORT MALI_VISIBLE
-
-#endif
-
-/** @} */ /* end group ump_user_space_api */
-
-
-#endif /* __UMP_PLATFORM_H__ */
diff --git a/exynos4/hal/libump/include/ump/ump_uk_types.h b/exynos4/hal/libump/include/ump/ump_uk_types.h
deleted file mode 100644
index 1a4c1c8..0000000
--- a/exynos4/hal/libump/include/ump/ump_uk_types.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_uk_types.h
- * Defines the types and constants used in the user-kernel interface
- */
-
-#ifndef __UMP_UK_TYPES_H__
-#define __UMP_UK_TYPES_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Helpers for API version handling */
-#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x))
-#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF))
-#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF)
-#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y))))
-
-/**
- * API version define.
- * Indicates the version of the kernel API
- * The version is a 16bit integer incremented on each API change.
- * The 16bit integer is stored twice in a 32bit integer
- * So for version 1 the value would be 0x00010001
- */
-#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2)
-
-typedef enum
-{
- _UMP_IOC_QUERY_API_VERSION = 1,
- _UMP_IOC_ALLOCATE,
- _UMP_IOC_RELEASE,
- _UMP_IOC_SIZE_GET,
- _UMP_IOC_MAP_MEM, /* not used in Linux */
- _UMP_IOC_UNMAP_MEM, /* not used in Linux */
- _UMP_IOC_MSYNC,
-}_ump_uk_functions;
-
-typedef enum
-{
- UMP_REF_DRV_UK_CONSTRAINT_NONE = 0,
- UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1,
- UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 4,
-} ump_uk_alloc_constraints;
-
-typedef enum
-{
- _UMP_UK_MSYNC_CLEAN = 0,
- _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1,
- _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128,
-} ump_uk_msync_op;
-
-/**
- * Get API version ([in,out] u32 api_version, [out] u32 compatible)
- */
-typedef struct _ump_uk_api_version_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */
- u32 compatible; /**< Non-null if the device is compatible with the client */
-} _ump_uk_api_version_s;
-
-/**
- * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints)
- */
-typedef struct _ump_uk_allocate_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 secure_id; /**< Return value from DD to Userdriver */
- u32 size; /**< Input and output. Requested size; input. Returned size; output */
- ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */
-} _ump_uk_allocate_s;
-
-/**
- * SIZE_GET ([in] u32 secure_id, [out]size )
- */
-typedef struct _ump_uk_size_get_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 secure_id; /**< Input to DD */
- u32 size; /**< Returned size; output */
-} _ump_uk_size_get_s;
-
-/**
- * Release ([in] u32 secure_id)
- */
-typedef struct _ump_uk_release_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 secure_id; /**< Input to DD */
-} _ump_uk_release_s;
-
-typedef struct _ump_uk_map_mem_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *mapping; /**< [out] Returns user-space virtual address for the mapping */
- void *phys_addr; /**< [in] physical address */
- unsigned long size; /**< [in] size */
- u32 secure_id; /**< [in] secure_id to assign to mapping */
- void * _ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */
- u32 cookie;
- u32 is_cached; /**< [in,out] caching of CPU mappings */
-} _ump_uk_map_mem_s;
-
-typedef struct _ump_uk_unmap_mem_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *mapping;
- u32 size;
- void * _ukk_private;
- u32 cookie;
-} _ump_uk_unmap_mem_s;
-
-typedef struct _ump_uk_msync_s
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *mapping; /**< [in] mapping addr */
- void *address; /**< [in] flush start addr */
- u32 size; /**< [in] size to flush */
- ump_uk_msync_op op; /**< [in] flush operation */
- u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */
- u32 secure_id; /**< [in] cookie stored with reference to the kernel mapping internals */
- u32 is_cached; /**< [out] caching of CPU mappings */
-} _ump_uk_msync_s;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UMP_UK_TYPES_H__ */
diff --git a/exynos4/hal/libump/os/linux/ump_ioctl.h b/exynos4/hal/libump/os/linux/ump_ioctl.h
deleted file mode 100644
index a62c31a..0000000
--- a/exynos4/hal/libump/os/linux/ump_ioctl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UMP_IOCTL_H__
-#define __UMP_IOCTL_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#include <ump/ump_uk_types.h>
-
-#ifndef __user
-#define __user
-#endif
-
-
-/**
- * @file UMP_ioctl.h
- * This file describes the interface needed to use the Linux device driver.
- * The interface is used by the userpace UMP driver.
- */
-
-#define UMP_IOCTL_NR 0x90
-
-
-#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s)
-#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s)
-#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s)
-#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s)
-#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_size_get_s)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UMP_IOCTL_H__ */
diff --git a/exynos4/hal/libump/os/linux/ump_osu_locks.c b/exynos4/hal/libump/os/linux/ump_osu_locks.c
deleted file mode 100644
index 97ba858..0000000
--- a/exynos4/hal/libump/os/linux/ump_osu_locks.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if ((!defined _XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 600))
-#undef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600
-#endif
-
-
-#define _POSIX_C_SOURCE 200112L
-
-#include <ump/ump_osu.h>
-#include <ump/ump_debug.h>
-
-#include <pthread.h>
-#include <time.h>
-#include <sys/time.h>
-#include <errno.h>
-
-/**
- * @file ump_osu_locks.c
- * File implements the user side of the OS interface
- */
-
-/** @opt Most of the time, we use the plain mutex type of osu_lock, and so
- * only require the flags and mutex members. This costs 2 extra DWORDS, but
- * most of the time we don't use those DWORDS.
- * Therefore, ANY_UNLOCK type osu_locks can be implemented as a second
- * structure containing the member _ump_osu_lock_t lock_t, plus the extra
- * state required. Then, we use &container->lock_t when passing out of the
- * OSU api, and CONTAINER_OF() when passing back in to recover the original
- * structure. */
-
-/** Private declaration of the OSU lock type */
-struct _ump_osu_lock_t_struct
-{
- /** At present, only two types of mutex, so we store this information as
- * the flags supplied at init time */
- _ump_osu_lock_flags_t flags;
-
- pthread_mutex_t mutex; /**< Used in both plain and ANY_UNLOCK osu_locks */
-
- /* Extra State for ANY_UNLOCK osu_locks. These are UNINITIALIZED when
- * flags does not contain _UMP_OSU_LOCKFLAG_ANYUNLOCK: */
- pthread_cond_t condition; /**< The condition object to use while blocking */
- ump_bool state; /**< The boolean which indicates the event's state */
-
- UMP_DEBUG_CODE(
- /** debug checking of locks */
- _ump_osu_lock_mode_t locked_as;
- ) /* UMP_DEBUG_CODE */
-
-};
-
-/* Provide two statically initialized locks */
-UMP_STATIC _ump_osu_lock_t _ump_osu_static_locks[] =
-{
- {
- _UMP_OSU_LOCKFLAG_STATIC,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
- UMP_FALSE,
- UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
- },
- {
- _UMP_OSU_LOCKFLAG_STATIC,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
- UMP_FALSE,
- UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
- },
- {
- _UMP_OSU_LOCKFLAG_STATIC,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
- UMP_FALSE,
- UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
- },
- {
- _UMP_OSU_LOCKFLAG_STATIC,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
- UMP_FALSE,
- UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
- },
-};
-
-/* Critical section for auto_init */
-UMP_STATIC pthread_mutex_t static_auto_init_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order )
-{
- int call_result;
- /* Validate parameters: */
- UMP_DEBUG_ASSERT_POINTER( pplock );
-
- /** @opt We don't lock the Critical Section or do anything if this is already non-null */
- if ( NULL != *pplock)
- {
- return _UMP_OSU_ERR_OK;
- }
-
- /* We MIGHT need to initialize it, lock the Critical Section and check again */
- call_result = pthread_mutex_lock(&static_auto_init_mutex);
- /* It would be a programming error for this to fail: */
- UMP_DEBUG_ASSERT( 0 == call_result,
- ("failed to lock critical section\n") );
-
- if ( NULL != *pplock )
- {
- /*
- We caught a race condition to initialize this osu_lock.
- The other thread won the race, so the osu_lock is now initialized.
- */
- call_result = pthread_mutex_unlock(&static_auto_init_mutex);
-
- UMP_DEBUG_ASSERT(0 == call_result,
- ("failed to unlock critical section\n"));
-
- return _UMP_OSU_ERR_OK;
- }
-
- /* We're the first thread in: initialize the osu_lock */
- *pplock = _ump_osu_lock_init( flags, initial, order );
-
- if ( NULL == *pplock )
- {
- /* osu_lock creation failed */
- call_result = pthread_mutex_unlock(&static_auto_init_mutex);
- UMP_DEBUG_ASSERT(0 == call_result,
- ("failed to unlock critical section\n"));
-
- return _UMP_OSU_ERR_FAULT;
- }
-
-
- /* osu_lock created OK */
- call_result = pthread_mutex_unlock(&static_auto_init_mutex);
-
- UMP_DEBUG_ASSERT(0 == call_result,
- ("failed to unlock critical section\n"));
-
- UMP_IGNORE( call_result );
-
- return _UMP_OSU_ERR_OK;
-}
-
-
-_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order )
-{
- _ump_osu_lock_t * lock;
- pthread_mutexattr_t mutex_attributes;
-
- /* Validate parameters: */
- /* Flags acceptable */
- UMP_DEBUG_ASSERT( 0 == ( flags & ~( _UMP_OSU_LOCKFLAG_ANYUNLOCK)),
- ("incorrect flags or trying to initialise a statically initialized lock, %.8X\n", flags) );
-
- /* Parameter initial SBZ - for future expansion */
- UMP_DEBUG_ASSERT( 0 == initial,
- ("initial must be zero\n") );
-
- if (0 != pthread_mutexattr_init(&mutex_attributes))
- {
- return NULL;
- }
-
-#if UMP_DEBUG_EXTENDED_MUTEX_LOCK_CHECKING
-#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK
-#else
-#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT
-#endif
-
- if (0 != pthread_mutexattr_settype(&mutex_attributes, UMP_PTHREADS_MUTEX_TYPE))
- {
- /** Return NULL on failure */
- pthread_mutexattr_destroy(&mutex_attributes);
- return NULL;
-
- }
-
-#undef UMP_PTHREADS_MUTEX_TYPE
-
- /** @opt use containing structures for the ANY_UNLOCK type, to
- * save 2 DWORDS when not in use */
- lock = _ump_osu_malloc( sizeof(_ump_osu_lock_t) );
-
- if( NULL == lock )
- {
- /** Return NULL on failure */
- pthread_mutexattr_destroy(&mutex_attributes);
- return NULL;
- }
-
- if (0 != pthread_mutex_init( &lock->mutex, &mutex_attributes ))
- {
- pthread_mutexattr_destroy(&mutex_attributes);
- _ump_osu_free( lock );
- return NULL;
- }
-
- /* done with the mutexattr object */
- pthread_mutexattr_destroy(&mutex_attributes);
-
- /* ANY_UNLOCK type */
- if ( flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK )
- {
- if (0 != pthread_cond_init( &lock->condition, NULL ))
- {
- /* cleanup */
- pthread_mutex_destroy( &lock->mutex );
- _ump_osu_free( lock );
- return NULL;
- }
- lock->state = UMP_FALSE; /* mark as unlocked by default */
- }
-
- lock->flags = flags;
-
- /** Debug lock checking */
- UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF );
-
- return lock;
-}
-
-_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout)
-{
- /* absolute time specifier */
- struct timespec ts;
- struct timeval tv;
-
- /* Parameter validation */
- UMP_DEBUG_ASSERT_POINTER( lock );
-
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
- ("unrecognised mode, %.8X\n", mode) );
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKFLAG_ANYUNLOCK == lock->flags, ("Timed operations only implemented for ANYUNLOCK type locks"));
-
- /* calculate the realtime timeout value */
-
- if (0 != gettimeofday(&tv, NULL))
- {
- UMP_DEBUG_PRINT(1,("Could not get the current realtime value to calculate the absolute value for a timed mutex lock with a timeout"));
- return _UMP_OSU_ERR_FAULT;
- }
-
- tv.tv_usec += timeout;
-
-#define UMP_USECS_PER_SECOND 1000000ULL
-#define UMP_NANOSECS_PER_USEC 1000ULL
-
- /* did we overflow a second in the usec part? */
- while (tv.tv_usec >= UMP_USECS_PER_SECOND)
- {
- tv.tv_usec -= UMP_USECS_PER_SECOND;
- tv.tv_sec++;
- }
-
- /* copy to the correct struct */
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = (tv.tv_usec * UMP_NANOSECS_PER_USEC);
-
-#undef UMP_USECS_PER_SECOND
-#undef UMP_NANOSECS_PER_USEC
-
- /* lock the mutex protecting access to the state field */
- pthread_mutex_lock( &lock->mutex );
- /* loop while locked (state is UMP_TRUE) */
- /* pthread_cond_timedwait unlocks the mutex, wait, and locks the mutex once unblocked (either due to the event or the timeout) */
- while ( UMP_TRUE == lock->state )
- {
- int res;
- res = pthread_cond_timedwait( &lock->condition, &lock->mutex, &ts );
- if (0 == res) continue; /* test the state variable again (loop condition) */
- else if (ETIMEDOUT == res)
- {
- /* timeout, need to clean up and return the correct error code */
- pthread_mutex_unlock(&lock->mutex);
- return _UMP_OSU_ERR_TIMEOUT;
- }
- else
- {
- UMP_DEBUG_PRINT(1, ("Unexpected return from pthread_cond_timedwait 0x%08X\n", res));
-
- pthread_mutex_unlock(&lock->mutex);
- return _UMP_OSU_ERR_FAULT;
- }
-
- }
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
- ("This lock was already locked\n") );
- UMP_DEBUG_CODE( lock->locked_as = mode );
-
- /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */
- lock->state = UMP_TRUE;
- /* final unlock of the mutex */
- pthread_mutex_unlock(&lock->mutex);
-
- return _UMP_OSU_ERR_OK;
-
-}
-
-_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode)
-{
- /* Parameter validation */
- UMP_DEBUG_ASSERT_POINTER( lock );
-
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
- ("unrecognised mode, %.8X\n", mode) );
-
- /** @note since only one flag can be set, we use a switch statement here.
- * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
- * implemented lock type */
- switch ( lock->flags )
- {
- case _UMP_OSU_LOCKFLAG_STATIC:
- case 0:
- /* Usual Mutex type */
- {
- int call_result;
- call_result = pthread_mutex_lock( &lock->mutex );
- UMP_DEBUG_ASSERT( 0 == call_result,
- ("pthread_mutex_lock call failed with error code %d\n", call_result));
- UMP_IGNORE( call_result );
- }
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
- ("This lock was already locked\n") );
- UMP_DEBUG_CODE( lock->locked_as = mode );
- break;
-
- case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
- /** @note Use of bitflags in a case statement ONLY works because this
- * is the ONLY flag that is supported */
-
- /* lock the mutex protecting access to the state field */
- pthread_mutex_lock( &lock->mutex );
- /* loop while locked (state is UMP_TRUE) */
- /* pthread_cond_wait unlocks the mutex, wait, and locks the mutex once unblocked */
- while ( UMP_TRUE == lock->state ) pthread_cond_wait( &lock->condition, &lock->mutex );
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
- ("This lock was already locked\n") );
- UMP_DEBUG_CODE( lock->locked_as = mode );
-
- /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */
- lock->state = UMP_TRUE;
- /* final unlock of the mutex */
- pthread_mutex_unlock(&lock->mutex);
- break;
-
- default:
- UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
- break;
- }
-
- return _UMP_OSU_ERR_OK;
-}
-
-_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode)
-{
- _ump_osu_errcode_t err = _UMP_OSU_ERR_FAULT;
- /* Parameter validation */
- UMP_DEBUG_ASSERT_POINTER( lock );
-
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
- ("unrecognised mode, %.8X\n", mode) );
-
- /** @note since only one flag can be set, we use a switch statement here.
- * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
- * implemented lock type */
- switch ( lock->flags )
- {
- case _UMP_OSU_LOCKFLAG_STATIC:
- case 0:
- /* Usual Mutex type */
- {
- /* This is not subject to UMP_CHECK - overriding the result would cause a programming error */
- if ( 0 == pthread_mutex_trylock( &lock->mutex ) )
- {
- err = _UMP_OSU_ERR_OK;
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as
- || mode == lock->locked_as,
- ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) );
- UMP_DEBUG_CODE( lock->locked_as = mode );
- }
- }
- break;
-
- case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
- /** @note Use of bitflags in a case statement ONLY works because this
- * is the ONLY flag that is supported */
-
- /* lock the mutex protecting access to the state field */
- pthread_mutex_lock(&lock->mutex);
-
- if ( UMP_FALSE == lock->state)
- {
- /* unlocked, take the lock */
- lock->state = UMP_TRUE;
- err = _UMP_OSU_ERR_OK;
- }
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- /* Can do this regardless of whether we obtained ANYUNLOCK: */
-
-
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as
- || mode == lock->locked_as,
- ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) );
- /* If we were already locked, this does no harm, because of the above assert: */
- UMP_DEBUG_CODE( lock->locked_as = mode );
-
- pthread_mutex_unlock(&lock->mutex);
- break;
-
- default:
- UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
- break;
- }
-
- return err;
-}
-
-
-void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode )
-{
- /* Parameter validation */
- UMP_DEBUG_ASSERT_POINTER( lock );
-
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
- ("unrecognised mode, %.8X\n", mode) );
-
- /** @note since only one flag can be set, we use a switch statement here.
- * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
- * implemented lock type */
- switch ( lock->flags )
- {
- case _UMP_OSU_LOCKFLAG_STATIC:
- case 0:
- /* Usual Mutex type */
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( mode == lock->locked_as,
- ("This lock was locked as==%.8X, but tried to unlock as mode==%.8X\n", lock->locked_as, mode));
- UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF );
-
- {
- int call_result;
- call_result = pthread_mutex_unlock( &lock->mutex );
- UMP_DEBUG_ASSERT( 0 == call_result,
- ("pthread_mutex_lock call failed with error code %d\n", call_result));
- UMP_IGNORE( call_result );
- }
- break;
-
- case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
- /** @note Use of bitflags in a case statement ONLY works because this
- * is the ONLY flag that is supported */
-
- pthread_mutex_lock(&lock->mutex);
- UMP_DEBUG_ASSERT( UMP_TRUE == lock->state, ("Unlocking a _ump_osu_lock_t %p which is not locked\n", lock));
-
- /* DEBUG tracking of previously locked state - occurs while lock is obtained */
- UMP_DEBUG_ASSERT( mode == lock->locked_as,
- ("This lock was locked as==%.8X, but tried to unlock as %.8X\n", lock->locked_as, mode ));
- UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF );
-
- /* mark as unlocked */
- lock->state = UMP_FALSE;
-
- /* signal the condition, only wake a single thread */
- pthread_cond_signal(&lock->condition);
-
- pthread_mutex_unlock(&lock->mutex);
- break;
-
- default:
- UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
- break;
- }
-}
-
-void _ump_osu_lock_term( _ump_osu_lock_t *lock )
-{
- int call_result;
- UMP_DEBUG_ASSERT_POINTER( lock );
-
- /** Debug lock checking: */
- /* Lock is signalled on terminate - not a guarantee, since we could be locked immediately beforehand */
- UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
- ("cannot terminate held lock\n") );
-
- call_result = pthread_mutex_destroy( &lock->mutex );
- UMP_DEBUG_ASSERT( 0 == call_result,
- ("Incorrect mutex use detected: pthread_mutex_destroy call failed with error code %d\n", call_result) );
-
- /* Destroy extra state for ANY_UNLOCK type osu_locks */
- if ( lock->flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK )
- {
- UMP_DEBUG_ASSERT( UMP_FALSE == lock->state, ("terminate called on locked object %p\n", lock));
- call_result = pthread_cond_destroy(&lock->condition);
- UMP_DEBUG_ASSERT( 0 == call_result,
- ("Incorrect condition-variable use detected: pthread_cond_destroy call failed with error code %d\n", call_result) );
- }
-
- UMP_IGNORE(call_result);
-
- _ump_osu_free( lock );
-}
-
-_ump_osu_lock_t *_ump_osu_lock_static( u32 nr )
-{
- UMP_DEBUG_ASSERT( nr < UMP_OSU_STATIC_LOCK_COUNT,
- ("provided static lock index (%d) out of bounds (0 < nr < %d)\n", nr, UMP_OSU_STATIC_LOCK_COUNT) );
- return &_ump_osu_static_locks[nr];
-}
diff --git a/exynos4/hal/libump/os/linux/ump_osu_memory.c b/exynos4/hal/libump/os/linux/ump_osu_memory.c
deleted file mode 100644
index 5807594..0000000
--- a/exynos4/hal/libump/os/linux/ump_osu_memory.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ump/ump_osu.h>
-
-#include <stdlib.h>
-#include <string.h> /* memcmp, memchr, memset */
-
-/**
- * @file ump_osu_memory.c
- * File implements the user side of the OS interface
- */
-
-void *_ump_osu_calloc( u32 n, u32 size )
-{
- return calloc( n, size );
-}
-
-void *_ump_osu_malloc( u32 size )
-{
- return malloc( size );
-}
-
-void *_ump_osu_realloc( void *ptr, u32 size )
-{
- return realloc( ptr, size );
-}
-
-void _ump_osu_free( void *ptr )
-{
- free( ptr );
-}
-
-void *_ump_osu_memcpy( void *dst, const void *src, u32 len )
-{
- return memcpy( dst, src, len );
-}
-
-void *_ump_osu_memset( void *ptr, u32 chr, u32 size )
-{
- return memset( ptr, chr, size );
-}
-
-int _ump_osu_memcmp( const void *ptr1, const void *ptr2, u32 size )
-{
- return memcmp( ptr1, ptr2, size );
-}
diff --git a/exynos4/hal/libump/os/linux/ump_uku.c b/exynos4/hal/libump/os/linux/ump_uku.c
deleted file mode 100644
index f46a2c7..0000000
--- a/exynos4/hal/libump/os/linux/ump_uku.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_uku.c
- * File implements the user side of the user-kernel interface
- */
-
-#include "../ump_uku.h"
-#include <stdio.h>
-#include "ump_ioctl.h"
-
-#include <sys/mman.h>
-
-/* Needed for file operations on the device file*/
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args);
-
-static int ump_ioctl_api_version_used = UMP_IOCTL_API_VERSION;
-
-/**
- * The device file to access the UMP device driver
- * This is a character special file giving access to the device driver.
- * Usually created using the mknod command line utility.
- */
-static const char ump_device_file_name[] = "/dev/ump";
-
-_ump_osu_errcode_t _ump_uku_open( void **context )
-{
- int ump_device_file;
- if(NULL == context)
- {
- return _UMP_OSU_ERR_FAULT;
- }
-
- ump_device_file = open(ump_device_file_name, O_RDWR);
-
- if (-1 == ump_device_file)
- {
- return _UMP_OSU_ERR_FAULT;
- }
-
- {
- struct _ump_uk_api_version_s args;
- args.ctx = (void*)ump_device_file;
- args.version = UMP_IOCTL_API_VERSION;
- args.compatible = 3;
- ump_driver_ioctl(args.ctx, UMP_IOC_QUERY_API_VERSION, &args);
- if ( 1 != args.compatible )
- {
- if (IS_API_MATCH(MAKE_VERSION_ID(1), args.version))
- {
- ump_ioctl_api_version_used = MAKE_VERSION_ID(1);
- UMP_PRINTF("The UMP devicedriver does not support cached UMP. Update it if this is needed.\n");
- }
- else
- {
- UMP_PRINTF("The UMP devicedriver is version: %d, UMP libraries is version: %d.\n", GET_VERSION(args.version), GET_VERSION(UMP_IOCTL_API_VERSION) );
- close(ump_device_file);
- return _UMP_OSU_ERR_FAULT;
- }
- }
- }
-
- *context = (void *) ump_device_file;
- return _UMP_OSU_ERR_OK;
-}
-
-_ump_osu_errcode_t _ump_uku_close( void **context )
-{
- if(NULL == context)
- {
- return _UMP_OSU_ERR_FAULT;
- }
-
- if(-1 == (int)*context)
- {
- return _UMP_OSU_ERR_FAULT;
- }
-
- close((int)*context);
- *context = (void *)-1;
-
- return _UMP_OSU_ERR_OK;
-}
-
-int _ump_uku_allocate(_ump_uk_allocate_s *args)
-{
- return ump_driver_ioctl(args->ctx, UMP_IOC_ALLOCATE, args);
-}
-
-_ump_osu_errcode_t _ump_uku_release(_ump_uk_release_s *args)
-{
- return ump_driver_ioctl(args->ctx, UMP_IOC_RELEASE, args);
-}
-
-_ump_osu_errcode_t _ump_uku_size_get(_ump_uk_size_get_s *args)
-{
- return ump_driver_ioctl(args->ctx, UMP_IOC_SIZE_GET, args);
-}
-
-
-void _ump_uku_msynch(_ump_uk_msync_s *args)
-{
- /* This is for backwards compatibillity */
- if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used)
- {
- args->is_cached = 0;
- if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED != args->op )
- {
- UMP_DEBUG_PRINT(3, ("Warning: Doing UMP cache flush operations on a Device Driver that does not support cached UMP mem.\n"));
- }
- return;
- }
- ump_driver_ioctl(args->ctx, UMP_IOC_MSYNC, args);
-}
-
-int _ump_uku_map_mem(_ump_uk_map_mem_s *args)
-{
- int flags;
- if( -1 == (int)args->ctx )
- {
- return -1;
- }
-
- flags = MAP_SHARED;
-
- /* This is for backwards compatibillity */
- if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used)
- {
- args->is_cached = 0;
- }
-
- /* If we want the Caching to be enabled we set the flags to be PRIVATE. The UMP DD reads this and do proper handling
- Note: this enforces the user to use proper invalidation*/
- if ( args->is_cached ) flags = MAP_PRIVATE;
-
- args->mapping = mmap(NULL, args->size, PROT_READ | PROT_WRITE ,flags , (int)args->ctx, (off_t)args->secure_id * sysconf(_SC_PAGE_SIZE));
- if (MAP_FAILED == args->mapping)
- {
- return -1;
- }
-
- args->cookie = 0; /* Cookie is not used in linux _ump_uku_unmap_mem */
-
- return 0;
-}
-
-void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args )
-{
- /*
- * If a smaller size is used Linux will just remove the requested range but don't tell
- * the ump driver before all of it is unmapped, either via another unmap request or upon process shutdown.
- * Unmapping too much will just ignore the overhead or hit undefined behavior,
- * only affecting the calling process which could mess itself up in other ways anyway.
- * So we don't need any security checks here.
- */
- munmap(args->mapping, args->size);
-}
-
-static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args)
-{
- /*UMP_CHECK_NON_NULL(args, _UMP_OSK_ERR_INVALID_ARGS);*/
-
- /* check for a valid file descriptor */
- /** @note manual type safety check-point */
- if( -1 == (int)context )
- {
- return _UMP_OSU_ERR_FAULT;
- }
-
- /* call ioctl handler of driver */
- if (0 != ioctl((int)context, command, args)) return -1;
- return _UMP_OSU_ERR_OK;
-}
diff --git a/exynos4/hal/libump/os/ump_uku.h b/exynos4/hal/libump/os/ump_uku.h
deleted file mode 100644
index 7da7185..0000000
--- a/exynos4/hal/libump/os/ump_uku.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ump_uku.h
- * Defines the user-side interface of the user-kernel interface
- */
-
-#ifndef __UMP_UKU_H__
-#define __UMP_UKU_H__
-
-#include <ump/ump_osu.h>
-#include <ump/ump_debug.h>
-#include <ump/ump_uk_types.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-_ump_osu_errcode_t _ump_uku_open( void **context );
-
-_ump_osu_errcode_t _ump_uku_close( void **context );
-
-_ump_osu_errcode_t _ump_uku_allocate( _ump_uk_allocate_s *args );
-
-_ump_osu_errcode_t _ump_uku_release( _ump_uk_release_s *args );
-
-_ump_osu_errcode_t _ump_uku_size_get( _ump_uk_size_get_s *args );
-
-_ump_osu_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args );
-
-int _ump_uku_map_mem( _ump_uk_map_mem_s *args );
-
-void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args );
-
-void _ump_uku_msynch(_ump_uk_msync_s *args);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UMP_UKU_H__ */
diff --git a/exynos4/hal/libump/readme.txt b/exynos4/hal/libump/readme.txt
deleted file mode 100644
index 297df38..0000000
--- a/exynos4/hal/libump/readme.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2010-2011 ARM Limited. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-Building the UMP user space library for Linux
----------------------------------------------
-
-A simple Makefile is provided, and the UMP user space library can be built
-simply by issuing make. This Makefile is setup to use the ARM GCC compiler
-from CodeSourcery, and it builds for ARMv6. Modification to this Makefile
-is needed in order to build for other configurations.
-
-In order to use this library from the Mali GPU driver, invoke the Mali GPU
-driver build system with the following two make variables set;
-- UMP_INCLUDE_DIR should point to the include folder inside this package
-- UMP_LIB should point to the built library (libUMP.so)
-
-This does not apply to Android builds, where the Android.mk file for the
-Mali GPU driver needs to be manually edited in order to add the correct
-include path and link against the correct library.