parent
1386f44a87
commit
c9288149a3
@ -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__ */ |
@ -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)) |
@ -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; |
||||
} |
@ -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
|
@ -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; |
||||
} |
@ -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_
|
@ -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 |
@ -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__ */ |
@ -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, |
||||
}; |
||||
} |
@ -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) |
@ -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_
|
@ -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; |
||||
} |
@ -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 new issue