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