You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2435 lines
65 KiB
2435 lines
65 KiB
13 years ago
|
/*
|
||
|
* Copyright@ Samsung Electronics Co. LTD
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
//#define LOG_NDEBUG 0
|
||
|
//#define LOG_TAG "libhdmi"
|
||
|
#include <cutils/log.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <sys/mman.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <ctype.h>
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
#include "sec_utils_v4l2.h"
|
||
|
#include "s5p_tvout_v4l2.h"
|
||
|
#include "videodev2.h"
|
||
|
#else
|
||
|
#include "sec_utils.h"
|
||
|
#include "s5p_tvout.h"
|
||
|
#endif
|
||
|
#include "SecFimc.h"
|
||
|
#if defined(BOARD_USES_FIMGAPI)
|
||
|
#include "sec_g2d_4x.h"
|
||
|
#include "FimgApi.h"
|
||
|
#endif
|
||
|
|
||
|
#include "audio.h"
|
||
|
#include "video.h"
|
||
|
#include "../libhdmi/libsForhdmi/libedid/libedid.h"
|
||
|
#include "../libhdmi/libsForhdmi/libcec/libcec.h"
|
||
|
|
||
|
#include "SecHdmiCommon.h"
|
||
|
#include "SecHdmiV4L2Utils.h"
|
||
|
|
||
|
namespace android {
|
||
|
|
||
|
unsigned int output_type = V4L2_OUTPUT_TYPE_DIGITAL;
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
unsigned int g_preset_id = V4L2_DV_1080P30;
|
||
|
#endif
|
||
|
v4l2_std_id t_std_id = V4L2_STD_1080P_30;
|
||
|
int g_hpd_state = HPD_CABLE_OUT;
|
||
|
unsigned int g_hdcp_en = 0;
|
||
|
|
||
|
int fp_tvout = -1;
|
||
|
int fp_tvout_v = -1;
|
||
|
int fp_tvout_g0 = -1;
|
||
|
int fp_tvout_g1 = -1;
|
||
|
|
||
|
struct vid_overlay_param vo_param;
|
||
|
|
||
|
#if defined(BOARD_USES_FIMGAPI)
|
||
|
unsigned int g2d_reserved_memory[HDMI_G2D_OUTPUT_BUF_NUM];
|
||
|
unsigned int g2d_reserved_memory_size = 0;
|
||
|
unsigned int cur_g2d_address = 0;
|
||
|
unsigned int g2d_buf_index = 0;
|
||
|
#endif
|
||
|
|
||
|
void display_menu(void)
|
||
|
{
|
||
|
struct HDMIVideoParameter video;
|
||
|
struct HDMIAudioParameter audio;
|
||
|
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
audio.formatCode = LPCM_FORMAT;
|
||
|
audio.outPacket = HDMI_ASP;
|
||
|
audio.channelNum = CH_2;
|
||
|
audio.sampleFreq = SF_44KHZ;
|
||
|
|
||
|
LOGI("=============== HDMI Audio =============\n");
|
||
|
|
||
|
if (EDIDAudioModeSupport(&audio))
|
||
|
LOGI("= 2CH_PCM 44100Hz audio supported =\n");
|
||
|
|
||
|
LOGI("========= HDMI Mode & Color Space =======\n");
|
||
|
|
||
|
video.mode = HDMI;
|
||
|
if (EDIDHDMIModeSupport(&video)) {
|
||
|
video.colorSpace = HDMI_CS_YCBCR444;
|
||
|
if (EDIDColorSpaceSupport(&video))
|
||
|
LOGI("= 1. HDMI(YCbCr) =\n");
|
||
|
|
||
|
video.colorSpace = HDMI_CS_RGB;
|
||
|
if (EDIDColorSpaceSupport(&video))
|
||
|
LOGI("= 2. HDMI(RGB) =\n");
|
||
|
} else {
|
||
|
video.mode = DVI;
|
||
|
if (EDIDHDMIModeSupport(&video))
|
||
|
LOGI("= 3. DVI =\n");
|
||
|
}
|
||
|
|
||
|
LOGI("=========== HDMI Rseolution ========\n");
|
||
|
|
||
|
/* 480P */
|
||
|
video.resolution = v720x480p_60Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 4. 480P_60_16_9 (0x04000000) =\n");
|
||
|
|
||
|
video.resolution = v640x480p_60Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 5. 480P_60_4_3 (0x05000000) =\n");
|
||
|
|
||
|
/* 576P */
|
||
|
video.resolution = v720x576p_50Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 6. 576P_50_16_9 (0x06000000) =\n");
|
||
|
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 7. 576P_50_4_3 (0x07000000) =\n");
|
||
|
|
||
|
/* 720P 60 */
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 8. 720P_60 (0x08000000) =\n");
|
||
|
|
||
|
/* 720P_50 */
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 9. 720P_50 (0x09000000) =\n");
|
||
|
|
||
|
/* 1080P_60 */
|
||
|
video.resolution = v1920x1080p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= a. 1080P_60 (0x0a000000) =\n");
|
||
|
|
||
|
/* 1080P_50 */
|
||
|
video.resolution = v1920x1080p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= b. 1080P_50 (0x0b000000) =\n");
|
||
|
|
||
|
/* 1080I_60 */
|
||
|
video.resolution = v1920x1080i_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= c. 1080I_60 (0x0c000000) =\n");
|
||
|
|
||
|
/* 1080I_50 */
|
||
|
video.resolution = v1920x1080i_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= d. 1080I_50 (0x0d000000) =\n");
|
||
|
|
||
|
/* 1080P_30 */
|
||
|
video.resolution = v1920x1080p_30Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= e. 1080P_30 (0x12000000) =\n");
|
||
|
|
||
|
LOGI("=========== HDMI 3D Format ========\n");
|
||
|
|
||
|
/* 720P_60_SBS_HALF */
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= f. 720P_60_SBS_HALF (0x13000000) =\n");
|
||
|
|
||
|
/* 720P_59_SBS_HALF */
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 10. 720P_59_SBS_HALF (0x14000000) =\n");
|
||
|
|
||
|
/* 720P_50_TB */
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 11. 720P_50_TB (0x15000000) =\n");
|
||
|
|
||
|
/* 1080P_24_TB */
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 12. 1080P_24_TB (0x16000000) =\n");
|
||
|
|
||
|
/* 1080P_23_TB */
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
if (EDIDVideoResolutionSupport(&video))
|
||
|
LOGI("= 13. 1080P_24_TB (0x17000000) =\n");
|
||
|
LOGI("=========================================\n");
|
||
|
}
|
||
|
|
||
|
int tvout_open(const char *fp_name)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int fp;
|
||
|
|
||
|
fp = open(fp_name, O_RDWR);
|
||
|
if (fp < 0)
|
||
|
LOGE("drv (%s) open failed!!\n", fp_name);
|
||
|
|
||
|
return fp;
|
||
|
}
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
int tvout_std_v4l2_init(int fd, unsigned int preset_id)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: preset_id = 0x%x", __func__, preset_id);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
struct v4l2_output output;
|
||
|
struct v4l2_dv_preset preset;
|
||
|
|
||
|
unsigned int matched = 0, i = 0;
|
||
|
int output_index;
|
||
|
|
||
|
/*
|
||
|
if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL &&
|
||
|
output_type <= V4L2_OUTPUT_TYPE_DVI)
|
||
|
if (ioctl(fd_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0)
|
||
|
LOGE("%s::VIDIOC_HDCP_ENABLE failed %d", __func__, errno);
|
||
|
*/
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
do {
|
||
|
output.index = i;
|
||
|
ret = tvout_std_v4l2_enum_output(fd, &output);
|
||
|
LOGD("tvout_v4l2_enum_output():: output_type=%d output.index=%d output.name=%s", output.type, output.index, output.name);
|
||
|
if (output.type == output_type) {
|
||
|
matched = 1;
|
||
|
break;
|
||
|
}
|
||
|
i++;
|
||
|
} while (ret >=0);
|
||
|
|
||
|
if (!matched) {
|
||
|
LOGE("%s::no matched output type [type=%d]", __func__, output_type);
|
||
|
// return -1;
|
||
|
}
|
||
|
|
||
|
// set output
|
||
|
// tvout_std_v4l2_s_output(fp_tvout, output.index);
|
||
|
// output_index = 0;
|
||
|
// tvout_std_v4l2_g_output(fp_tvout, &output_index);
|
||
|
|
||
|
// if (output.capabilities & V4L2_OUT_CAP_PRESETS) {
|
||
|
tvout_std_v4l2_enum_dv_presets(fd);
|
||
|
preset.preset = preset_id;
|
||
|
if (tvout_std_v4l2_s_dv_preset(fd, &preset) < 0 ) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_dv_preset failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
// }
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_querycap(int fd, char *node)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_capability v4l2cap;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) {
|
||
|
LOGE("%s::VIDIOC_QUERYCAP failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) {
|
||
|
LOGE("%s::%s is not support streaming", __func__, node);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
|
||
|
LOGE("%s::%s is not support video output mplane", __func__, node);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_enum_dv_presets(int fd)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_dv_enum_preset enum_preset;
|
||
|
int ret = -1;
|
||
|
|
||
|
for (int index = 0; ; index++) {
|
||
|
enum_preset.index = index;
|
||
|
ret = ioctl(fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset);
|
||
|
|
||
|
if (ret < 0) {
|
||
|
if (errno == EINVAL)
|
||
|
break;
|
||
|
LOGE("%s::VIDIOC_ENUM_DV_PRESETS", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s::index=%d, preset=0x%08x, name=%s, w=%d, h=%d",
|
||
|
__func__, enum_preset.index, enum_preset.preset, enum_preset.name, enum_preset.width, enum_preset.height);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_S_DV_PRESET, preset) < 0) {
|
||
|
LOGE("%s::VIDIOC_S_DV_PRESET failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_ENUMOUTPUT
|
||
|
To query the attributes of a video outputs applications initialize the index field of struct v4l2_output
|
||
|
and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the
|
||
|
structure or return an EINVAL error code when the index is out of bounds
|
||
|
*/
|
||
|
int tvout_std_v4l2_enum_output(int fd, struct v4l2_output *output)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output);
|
||
|
|
||
|
if (ret >=0)
|
||
|
LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n",
|
||
|
output->index,output->type,output->name);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT
|
||
|
To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an
|
||
|
integer where the driver stores the number of the output, as in the struct v4l2_output index field.
|
||
|
This ioctl will fail only when there are no video outputs, returning the EINVAL error code
|
||
|
*/
|
||
|
int tvout_std_v4l2_s_output(int fd, int index)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: index = 0x%x", __func__, index);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fd, VIDIOC_S_OUTPUT, &index);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_g_output(int fd, int *index)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fd, VIDIOC_G_OUTPUT, index);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno);
|
||
|
return ret;
|
||
|
} else {
|
||
|
LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_format fmt;
|
||
|
|
||
|
fmt.type = type;
|
||
|
// if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
|
||
|
// LOGE("%s::VIDIOC_G_FMT failed", __func__);
|
||
|
// return -1;
|
||
|
// }
|
||
|
|
||
|
switch (fmt.type) {
|
||
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||
|
fmt.fmt.pix.width = w;
|
||
|
fmt.fmt.pix.height = h;
|
||
|
fmt.fmt.pix.pixelformat = colorformat;
|
||
|
fmt.fmt.pix.field = field;
|
||
|
break;
|
||
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
||
|
fmt.fmt.pix_mp.width = w;
|
||
|
fmt.fmt.pix_mp.height = h;
|
||
|
fmt.fmt.pix_mp.pixelformat = colorformat;
|
||
|
fmt.fmt.pix_mp.field = field;
|
||
|
fmt.fmt.pix_mp.num_planes = num_planes;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid buffer type", __func__);
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
|
||
|
LOGE("%s::VIDIOC_S_FMT failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field, int x, int y, int w, int h)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_crop crop;
|
||
|
|
||
|
crop.type = type;
|
||
|
crop.c.left = x;
|
||
|
crop.c.top = y;
|
||
|
crop.c.width = w;
|
||
|
crop.c.height = h;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
|
||
|
LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
|
||
|
__func__, x, y, w, h);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_s_ctrl(int fd, int id, int value)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_control vc;
|
||
|
|
||
|
vc.id = id;
|
||
|
vc.value = value;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
|
||
|
LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_requestbuffers reqbuf;
|
||
|
|
||
|
reqbuf.type = type;
|
||
|
reqbuf.memory = memory;
|
||
|
reqbuf.count = num_bufs;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
||
|
LOGE("%s::VIDIOC_REQBUFS failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (reqbuf.count < num_bufs) {
|
||
|
LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
|
||
|
__func__, reqbuf.count, num_bufs);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_buffer buf;
|
||
|
struct v4l2_plane planes[MAX_PLANES_MIXER];
|
||
|
|
||
|
memset(&buf, 0, sizeof(struct v4l2_buffer));
|
||
|
|
||
|
for (int i = 0; i < MAX_PLANES_MIXER; i++)
|
||
|
memset(&planes[i], 0, sizeof(struct v4l2_plane));
|
||
|
|
||
|
if (MAX_BUFFERS_MIXER <= buf_index || MAX_PLANES_MIXER <= num_planes) {
|
||
|
LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_planes);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
buf.type = type;
|
||
|
buf.memory = V4L2_MEMORY_MMAP;
|
||
|
buf.index = buf_index;
|
||
|
buf.length = num_planes;
|
||
|
buf.m.planes = planes;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
|
||
|
LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
for (unsigned int i = 0; i < num_planes; i++) {
|
||
|
if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length,
|
||
|
PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) {
|
||
|
LOGE("%s::mmap failed", __func__);
|
||
|
LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset);
|
||
|
LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length);
|
||
|
LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
|
||
|
return -1;
|
||
|
}
|
||
|
secBuf->size.extS[i] = buf.m.planes[i].length;
|
||
|
|
||
|
#ifdef DEBUG_LIB_FIMC
|
||
|
LOGD("%s::vaddr[bufidx=%d][planeidx=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
|
||
|
LOGD("%s::Legnth = %d" , __func__, buf.m.planes[i].length);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_buffer buf;
|
||
|
struct v4l2_plane planes[MAX_PLANES_MIXER];
|
||
|
|
||
|
memset(&buf, 0, sizeof(struct v4l2_buffer));
|
||
|
|
||
|
for (int i = 0; i < MAX_PLANES_MIXER; i++)
|
||
|
memset(&planes[i], 0, sizeof(struct v4l2_plane));
|
||
|
|
||
|
buf.type = type;
|
||
|
buf.memory = memory;
|
||
|
buf.length = num_planes;
|
||
|
buf.index = buf_index;
|
||
|
buf.m.planes = planes;
|
||
|
|
||
|
for (unsigned int i = 0; i < buf.length; i++) {
|
||
|
buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i];
|
||
|
buf.m.planes[i].length = secBuf->size.extS[i];
|
||
|
}
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
|
||
|
LOGE("%s::VIDIOC_QBUF failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_buffer buf;
|
||
|
struct v4l2_plane planes[MAX_PLANES_MIXER];
|
||
|
|
||
|
memset(&buf, 0, sizeof(struct v4l2_buffer));
|
||
|
|
||
|
for (int i = 0; i < MAX_PLANES_MIXER; i++)
|
||
|
memset(&planes[i], 0, sizeof(struct v4l2_plane));
|
||
|
|
||
|
buf.type = type;
|
||
|
buf.memory = memory;
|
||
|
buf.length = num_planes;
|
||
|
buf.m.planes = planes;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
|
||
|
LOGE("%s::VIDIOC_DQBUF failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
*buf_index = buf.index;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
|
||
|
LOGE("%s::VIDIOC_STREAMON failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
|
||
|
LOGE("%s::VIDIOC_STREAMOFF failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#else
|
||
|
int tvout_init(v4l2_std_id std_id)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: std_id = 0x%x", __func__, std_id);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
struct v4l2_output output;
|
||
|
struct v4l2_standard std;
|
||
|
v4l2_std_id std_g_id;
|
||
|
struct tvout_param tv_g_param;
|
||
|
|
||
|
unsigned int matched = 0, i = 0;
|
||
|
int output_index;
|
||
|
|
||
|
// It was initialized already
|
||
|
if (fp_tvout <= 0) {
|
||
|
fp_tvout = tvout_open(TVOUT_DEV);
|
||
|
if (fp_tvout < 0) {
|
||
|
LOGE("tvout video drv open failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL &&
|
||
|
output_type <= V4L2_OUTPUT_TYPE_DVI)
|
||
|
if (ioctl(fp_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0)
|
||
|
LOGE("tvout_init" "VIDIOC_HDCP_ENABLE failed %d\n", errno);
|
||
|
|
||
|
/* ============== query capability============== */
|
||
|
tvout_v4l2_querycap(fp_tvout);
|
||
|
|
||
|
tvout_v4l2_enum_std(fp_tvout, &std, std_id);
|
||
|
|
||
|
// set std
|
||
|
tvout_v4l2_s_std(fp_tvout, std_id);
|
||
|
tvout_v4l2_g_std(fp_tvout, &std_g_id);
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
do {
|
||
|
output.index = i;
|
||
|
ret = tvout_v4l2_enum_output(fp_tvout, &output);
|
||
|
if (output.type == output_type) {
|
||
|
matched = 1;
|
||
|
break;
|
||
|
}
|
||
|
i++;
|
||
|
} while (ret >=0);
|
||
|
|
||
|
if (!matched) {
|
||
|
LOGE("no matched output type [type : 0x%08x]\n", output_type);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// set output
|
||
|
tvout_v4l2_s_output(fp_tvout, output.index);
|
||
|
output_index = 0;
|
||
|
tvout_v4l2_g_output(fp_tvout, &output_index);
|
||
|
|
||
|
//set fmt param
|
||
|
vo_param.src.base_y = (void *)0x0;
|
||
|
vo_param.src.base_c = (void *)0x0;
|
||
|
vo_param.src.pix_fmt.width = 0;
|
||
|
vo_param.src.pix_fmt.height = 0;
|
||
|
vo_param.src.pix_fmt.field = V4L2_FIELD_NONE;
|
||
|
vo_param.src.pix_fmt.pixelformat = V4L2_PIX_FMT_NV12T;
|
||
|
|
||
|
vo_param.src_crop.left = 0;
|
||
|
vo_param.src_crop.top = 0;
|
||
|
vo_param.src_crop.width = 0;
|
||
|
vo_param.src_crop.height = 0;
|
||
|
|
||
|
return fp_tvout;
|
||
|
}
|
||
|
|
||
|
int tvout_deinit()
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
if (0 < fp_tvout) {
|
||
|
close(fp_tvout);
|
||
|
fp_tvout = -1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_querycap(int fp)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: fp = 0x%x", __func__, fp);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_capability cap;
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
|
||
|
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_querycap" "VIDIOC_QUERYCAP failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("tvout_v4l2_querycap" "DRIVER : %s, CARD : %s, CAP.: 0x%08x\n",
|
||
|
cap.driver, cap.card, cap.capabilities);
|
||
|
#endif
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_G_STD, VIDIOC_S_STD
|
||
|
To query and select the current video standard applications use the VIDIOC_G_STD and
|
||
|
VIDIOC_S_STD ioctls which take a pointer to a v4l2_std_id type as argument. VIDIOC_G_STD can
|
||
|
return a single flag or a set of flags as in struct v4l2_standard field id
|
||
|
*/
|
||
|
|
||
|
int tvout_v4l2_g_std(int fp, v4l2_std_id *std_id)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_G_STD, std_id);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_std" "VIDIOC_G_STD failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_s_std(int fp, v4l2_std_id std_id)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: std_id = 0x%x", __func__, std_id);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_S_STD, &std_id);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_std" "VIDIOC_S_STD failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_ENUMSTD
|
||
|
To query the attributes of a video standard, especially a custom (driver defined) one, applications
|
||
|
initialize the index field of struct v4l2_standard and call the VIDIOC_ENUMSTD ioctl with a pointer
|
||
|
to this structure. Drivers fill the rest of the structure or return an EINVAL error code when the index
|
||
|
is out of bounds.
|
||
|
*/
|
||
|
int tvout_v4l2_enum_std(int fp, struct v4l2_standard *std, v4l2_std_id std_id)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
std->index = 0;
|
||
|
while (0 == ioctl (fp, VIDIOC_ENUMSTD, std)) {
|
||
|
if (std->id & std_id)
|
||
|
LOGV("tvout_v4l2_enum_std" "Current video standard: %s\n", std->name);
|
||
|
|
||
|
std->index++;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_ENUMOUTPUT
|
||
|
To query the attributes of a video outputs applications initialize the index field of struct v4l2_output
|
||
|
and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the
|
||
|
structure or return an EINVAL error code when the index is out of bounds
|
||
|
*/
|
||
|
int tvout_v4l2_enum_output(int fp, struct v4l2_output *output)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_ENUMOUTPUT, output);
|
||
|
|
||
|
if (ret >=0)
|
||
|
LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n",
|
||
|
output->index,output->type,output->name);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT
|
||
|
To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an
|
||
|
integer where the driver stores the number of the output, as in the struct v4l2_output index field.
|
||
|
This ioctl will fail only when there are no video outputs, returning the EINVAL error code
|
||
|
*/
|
||
|
int tvout_v4l2_s_output(int fp, int index)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s:: index = 0x%x", __func__, index);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_S_OUTPUT, &index);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_g_output(int fp, int *index)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_G_OUTPUT, index);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno);
|
||
|
return ret;
|
||
|
} else {
|
||
|
LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
ioctl VIDIOC_ENUM_FMT
|
||
|
To enumerate image formats applications initialize the type and index field of struct v4l2_fmtdesc
|
||
|
and call the VIDIOC_ENUM_FMT ioctl with a pointer to this structure. Drivers fill the rest of the
|
||
|
structure or return an EINVAL error code. All formats are enumerable by beginning at index zero
|
||
|
and incrementing by one until EINVAL is returned.
|
||
|
*/
|
||
|
int tvout_v4l2_enum_fmt(int fp, struct v4l2_fmtdesc *desc)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
desc->index = 0;
|
||
|
while (0 == ioctl(fp, VIDIOC_ENUM_FMT, desc)) {
|
||
|
LOGV("tvout_v4l2_enum_fmt" "enum. fmt [id : 0x%08x] :: type = 0x%08x, name = %s, pxlfmt = 0x%08x\n",
|
||
|
desc->index,
|
||
|
desc->type,
|
||
|
desc->description,
|
||
|
desc->pixelformat);
|
||
|
desc->index++;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_g_fmt(int fp, int buf_type, void* ptr)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
struct v4l2_format format;
|
||
|
struct v4l2_pix_format_s5p_tvout *fmt_param = (struct v4l2_pix_format_s5p_tvout*)ptr;
|
||
|
|
||
|
format.type = (enum v4l2_buf_type)buf_type;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_G_FMT, &format);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_fmt" "type : %d, VIDIOC_G_FMT failed %d\n", buf_type, errno);
|
||
|
return ret;
|
||
|
} else {
|
||
|
memcpy(fmt_param, format.fmt.raw_data, sizeof(struct v4l2_pix_format_s5p_tvout));
|
||
|
LOGV("tvout_v4l2_g_fmt" "get. fmt [base_c : 0x%08x], [base_y : 0x%08x] type = 0x%08x, width = %d, height = %d\n",
|
||
|
fmt_param->base_c,
|
||
|
fmt_param->base_y,
|
||
|
fmt_param->pix_fmt.pixelformat,
|
||
|
fmt_param->pix_fmt.width,
|
||
|
fmt_param->pix_fmt.height);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_s_fmt(int fp, int buf_type, void *ptr)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_format format;
|
||
|
int ret;
|
||
|
|
||
|
format.type = (enum v4l2_buf_type)buf_type;
|
||
|
switch (buf_type) {
|
||
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||
|
format.fmt.win = *((struct v4l2_window *) ptr);
|
||
|
break;
|
||
|
|
||
|
case V4L2_BUF_TYPE_PRIVATE: {
|
||
|
struct v4l2_vid_overlay_src *fmt_param =
|
||
|
(struct v4l2_vid_overlay_src *) ptr;
|
||
|
|
||
|
memcpy(format.fmt.raw_data, fmt_param,
|
||
|
sizeof(struct v4l2_vid_overlay_src));
|
||
|
break;
|
||
|
}
|
||
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
|
||
|
struct v4l2_pix_format_s5p_tvout *fmt_param =
|
||
|
(struct v4l2_pix_format_s5p_tvout *)ptr;
|
||
|
memcpy(format.fmt.raw_data, fmt_param,
|
||
|
sizeof(struct v4l2_pix_format_s5p_tvout));
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_S_FMT, &format);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_fmt [tvout_v4l2_s_fmt] : type : %d, VIDIOC_S_FMT failed %d\n",
|
||
|
buf_type, errno);
|
||
|
return ret;
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_g_fbuf(int fp, struct v4l2_framebuffer *frame)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_G_FBUF, frame);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_fbuf" "VIDIOC_STREAMON failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
LOGV("tvout_v4l2_g_fbuf" "get. fbuf: base = 0x%08X, pixel format = %d\n",
|
||
|
frame->base,
|
||
|
frame->fmt.pixelformat);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_S_FBUF, frame);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_fbuf" "VIDIOC_STREAMON failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_s_baseaddr(int fp, void *base_addr)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
ret = ioctl(fp, S5PTVFB_WIN_SET_ADDR, base_addr);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_baseaddr" "VIDIOC_S_BASEADDR failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_g_crop(int fp, unsigned int type, struct v4l2_rect *rect)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret;
|
||
|
struct v4l2_crop crop;
|
||
|
crop.type = (enum v4l2_buf_type)type;
|
||
|
ret = ioctl(fp, VIDIOC_G_CROP, &crop);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_g_crop" "VIDIOC_G_CROP failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
rect->left = crop.c.left;
|
||
|
rect->top = crop.c.top;
|
||
|
rect->width = crop.c.width;
|
||
|
rect->height = crop.c.height;
|
||
|
|
||
|
LOGV("tvout_v4l2_g_crop" "get. crop : left = %d, top = %d, width = %d, height = %d\n",
|
||
|
rect->left,
|
||
|
rect->top,
|
||
|
rect->width,
|
||
|
rect->height);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_s_crop(int fp, unsigned int type, struct v4l2_rect *rect)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_crop crop;
|
||
|
int ret;
|
||
|
|
||
|
crop.type = (enum v4l2_buf_type)type;
|
||
|
|
||
|
crop.c.left = rect->left;
|
||
|
crop.c.top = rect->top;
|
||
|
crop.c.width = rect->width;
|
||
|
crop.c.height = rect->height;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_S_CROP, &crop);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_s_crop" "VIDIOC_S_CROP failed %d\n", errno);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_start_overlay(int fp)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret, start = 1;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_OVERLAY, &start);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_start_overlay" "VIDIOC_OVERLAY failed\n");
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int tvout_v4l2_stop_overlay(int fp)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int ret, stop =0;
|
||
|
|
||
|
ret = ioctl(fp, VIDIOC_OVERLAY, &stop);
|
||
|
if (ret < 0) {
|
||
|
LOGE("tvout_v4l2_stop_overlay" "VIDIOC_OVERLAY failed\n");
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int hdmi_init_layer(int layer)
|
||
|
{
|
||
|
int fd = -1;
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("### %s (layer = %d) called", __func__, layer);
|
||
|
#endif
|
||
|
|
||
|
switch (layer) {
|
||
|
case HDMI_LAYER_VIDEO :
|
||
|
if (fp_tvout_v <= 0) {
|
||
|
fp_tvout_v = tvout_open(TVOUT_DEV_V);
|
||
|
if (fp_tvout_v < 0) {
|
||
|
LOGE("tvout video layer open failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
fd = fp_tvout_v;
|
||
|
}
|
||
|
break;
|
||
|
case HDMI_LAYER_GRAPHIC_0 :
|
||
|
if (fp_tvout_g0 <= 0) {
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
fp_tvout_g0 = tvout_open(TVOUT_DEV_G0);
|
||
|
#else
|
||
|
fp_tvout_g0 = fb_open(TVOUT_FB_G0);
|
||
|
#endif
|
||
|
if (fp_tvout_g0 < 0) {
|
||
|
LOGE("tvout graphic layer 0 open failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
fd = fp_tvout_g0;
|
||
|
}
|
||
|
break;
|
||
|
case HDMI_LAYER_GRAPHIC_1 :
|
||
|
if (fp_tvout_g1 <= 0) {
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
fp_tvout_g1 = tvout_open(TVOUT_DEV_G1);
|
||
|
#else
|
||
|
fp_tvout_g1 = fb_open(TVOUT_FB_G1);
|
||
|
#endif
|
||
|
if (fp_tvout_g1 < 0) {
|
||
|
LOGE("tvout graphic layer 1 open failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
fd = fp_tvout_g1;
|
||
|
}
|
||
|
break;
|
||
|
default :
|
||
|
LOGE("%s::unmathced layer(%d) fail", __func__, layer);
|
||
|
fd = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int hdmi_deinit_layer(int layer)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("### %s(layer = %d) called", __func__, layer);
|
||
|
#endif
|
||
|
switch (layer) {
|
||
|
case HDMI_LAYER_VIDEO :
|
||
|
if (0 < fp_tvout_v) {
|
||
|
close(fp_tvout_v);
|
||
|
fp_tvout_v = -1;
|
||
|
}
|
||
|
break;
|
||
|
case HDMI_LAYER_GRAPHIC_0 :
|
||
|
if (0 < fp_tvout_g0) {
|
||
|
close(fp_tvout_g0);
|
||
|
fp_tvout_g0 = -1;
|
||
|
}
|
||
|
break;
|
||
|
case HDMI_LAYER_GRAPHIC_1 :
|
||
|
if (0 < fp_tvout_g1) {
|
||
|
close(fp_tvout_g1);
|
||
|
fp_tvout_g1 = -1;
|
||
|
}
|
||
|
break;
|
||
|
default :
|
||
|
LOGE("%s::unmathced layer(%d) fail", __func__, layer);
|
||
|
ret = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#define ROUND_UP(value, boundary) ((((uint32_t)(value)) + \
|
||
|
(((uint32_t) boundary)-1)) & \
|
||
|
(~(((uint32_t) boundary)-1)))
|
||
|
|
||
|
void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect)
|
||
|
{
|
||
|
if (dst_w * src_h <= dst_h * src_w) {
|
||
|
dst_rect->left = 0;
|
||
|
dst_rect->top = (dst_h - ((dst_w * src_h) / src_w)) >> 1;
|
||
|
dst_rect->width = dst_w;
|
||
|
dst_rect->height = ((dst_w * src_h) / src_w);
|
||
|
} else {
|
||
|
dst_rect->left = (dst_w - ((dst_h * src_w) / src_h)) >> 1;
|
||
|
dst_rect->top = 0;
|
||
|
dst_rect->width = ((dst_h * src_w) / src_h);
|
||
|
dst_rect->height = dst_h;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
int hdmi_get_src_plane(int srcColorFormat, unsigned int *num_of_plane)
|
||
|
{
|
||
|
int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
|
||
|
|
||
|
switch (v4l2ColorFormat) {
|
||
|
case V4L2_PIX_FMT_NV12:
|
||
|
case V4L2_PIX_FMT_NV21:
|
||
|
case V4L2_PIX_FMT_BGR32:
|
||
|
case V4L2_PIX_FMT_RGB32:
|
||
|
case V4L2_PIX_FMT_RGB565X:
|
||
|
*num_of_plane = 1;
|
||
|
break;
|
||
|
case V4L2_PIX_FMT_NV12M:
|
||
|
case V4L2_PIX_FMT_NV12MT:
|
||
|
case V4L2_PIX_FMT_NV21M:
|
||
|
*num_of_plane = 2;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid color type", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
int hdmi_set_v_param(int fd, int layer,
|
||
|
int srcColorFormat,
|
||
|
int src_w, int src_h,
|
||
|
SecBuffer * dstBuffer,
|
||
|
int dst_x, int dst_y, int dst_w, int dst_h)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
|
||
|
int round_up_src_w;
|
||
|
int round_up_src_h;
|
||
|
unsigned int num_of_plane;
|
||
|
struct v4l2_rect rect;
|
||
|
|
||
|
/* src_w, src_h round up to DWORD because of VP restriction */
|
||
|
#if defined(SAMSUNG_EXYNOS4x12)
|
||
|
round_up_src_w = ROUND_UP(src_w, 16);
|
||
|
#else defined(SAMSUNG_EXYNOS4210)
|
||
|
round_up_src_w = ROUND_UP(src_w, 8);
|
||
|
#endif
|
||
|
round_up_src_h = ROUND_UP(src_h, 8);
|
||
|
|
||
|
switch (v4l2ColorFormat) {
|
||
|
case V4L2_PIX_FMT_NV12:
|
||
|
case V4L2_PIX_FMT_NV21:
|
||
|
dstBuffer->size.s = (round_up_src_w * round_up_src_h * 3) >> 1;
|
||
|
num_of_plane = 1;
|
||
|
break;
|
||
|
case V4L2_PIX_FMT_NV12M:
|
||
|
case V4L2_PIX_FMT_NV12MT:
|
||
|
case V4L2_PIX_FMT_NV21M:
|
||
|
dstBuffer->size.extS[0] = (round_up_src_w * round_up_src_h * 3) >> 1;
|
||
|
dstBuffer->size.extS[1] = (round_up_src_w * round_up_src_h * 3) >> 2;
|
||
|
num_of_plane = 2;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid color type", __func__);
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hdmi_cal_rect(src_w, src_h, dst_w, dst_h, &rect);
|
||
|
rect.left = ALIGN(rect.left, 16);
|
||
|
|
||
|
/* set format for VP input */
|
||
|
if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, round_up_src_w, round_up_src_h, v4l2ColorFormat, num_of_plane) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_fmt()[video layer] failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* set crop for VP input */
|
||
|
if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY, V4L2_FIELD_ANY, 0, 0, src_w, src_h) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_crop()[video layer] failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* set crop for VP output */
|
||
|
if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_crop()[video layer] failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* request buffer for VP input */
|
||
|
if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[video layer] failed", __func__, HDMI_NUM_MIXER_BUF);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_set_g_param(int fd, int layer,
|
||
|
int srcColorFormat,
|
||
|
int src_w, int src_h,
|
||
|
SecBuffer * dstBuffer,
|
||
|
int dst_x, int dst_y, int dst_w, int dst_h)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
struct v4l2_rect rect;
|
||
|
int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat);
|
||
|
|
||
|
rect.left = dst_x;
|
||
|
rect.top = dst_y;
|
||
|
|
||
|
#if defined(BOARD_USES_FIMGAPI)
|
||
|
rect.width = dst_w;
|
||
|
rect.height = dst_h;
|
||
|
#else
|
||
|
rect.width = src_w;
|
||
|
rect.height = src_h;
|
||
|
#endif
|
||
|
|
||
|
switch (v4l2ColorFormat) {
|
||
|
case V4L2_PIX_FMT_BGR32:
|
||
|
case V4L2_PIX_FMT_RGB32:
|
||
|
dstBuffer->size.s = rect.width * rect.height << 2;
|
||
|
break;
|
||
|
case V4L2_PIX_FMT_RGB565X:
|
||
|
dstBuffer->size.s = rect.width * rect.height << 1;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid color type", __func__);
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* set format for mixer graphic layer input device*/
|
||
|
if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.width, rect.height, v4l2ColorFormat, 1) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_fmt() [layer=%d] failed", __func__, layer);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* set crop for mixer graphic layer input device*/
|
||
|
if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_crop() [layer=%d] failed", __func__, layer);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* request buffer for mixer graphic layer input device */
|
||
|
if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d) [layer=%d] failed", __func__, HDMI_NUM_MIXER_BUF, layer);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* enable alpha blending for mixer graphic layer */
|
||
|
if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* enable per-pixel blending for mixer graphic layer */
|
||
|
if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] failed", __func__, layer);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* set global alpha value for mixer graphic layer */
|
||
|
if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
|
||
|
LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_set_g_scaling(int layer,
|
||
|
int srcColorFormat,
|
||
|
int src_w, int src_h,
|
||
|
unsigned int src_address, SecBuffer * dstBuffer,
|
||
|
int dst_x, int dst_y, int dst_w, int dst_h,
|
||
|
int rotVal, unsigned int hwc_layer)
|
||
|
{
|
||
|
#if defined(BOARD_USES_FIMGAPI)
|
||
|
int dst_color_format;
|
||
|
int dst_bpp;
|
||
|
unsigned char *dst_addr;
|
||
|
fimg2d_blit BlitParam;
|
||
|
rotation g2d_rotation;
|
||
|
|
||
|
fimg2d_addr srcAddr;
|
||
|
fimg2d_image srcImage;
|
||
|
fimg2d_rect srcRect;
|
||
|
|
||
|
fimg2d_addr dstAddr;
|
||
|
fimg2d_image dstImage;
|
||
|
fimg2d_rect dstRect;
|
||
|
|
||
|
fimg2d_clip dstClip;
|
||
|
fimg2d_scale Scaling;
|
||
|
|
||
|
switch (g_preset_id) {
|
||
|
case V4L2_DV_1080P60:
|
||
|
case V4L2_DV_1080P30:
|
||
|
case V4L2_DV_1080I60:
|
||
|
case V4L2_DV_720P60_SB_HALF:
|
||
|
case V4L2_DV_720P59_94_SB_HALF:
|
||
|
case V4L2_DV_1080P24_TB:
|
||
|
case V4L2_DV_1080P23_98_TB:
|
||
|
dst_color_format = CF_ARGB_8888;
|
||
|
dst_bpp = 4;
|
||
|
break;
|
||
|
case V4L2_DV_480P60:
|
||
|
case V4L2_DV_576P50:
|
||
|
case V4L2_DV_720P60:
|
||
|
case V4L2_DV_720P50_TB:
|
||
|
default:
|
||
|
dst_color_format = CF_ARGB_4444;
|
||
|
dst_bpp = 2;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
static unsigned int prev_src_addr = 0;
|
||
|
|
||
|
if ((cur_g2d_address == 0) || (src_address != prev_src_addr)) {
|
||
|
dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index];
|
||
|
|
||
|
g2d_buf_index++;
|
||
|
if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM)
|
||
|
g2d_buf_index = 0;
|
||
|
|
||
|
cur_g2d_address = (unsigned int)dst_addr;
|
||
|
prev_src_addr = src_address;
|
||
|
|
||
|
srcAddr = {(addr_space)ADDR_USER, (unsigned long)src_address, src_w * src_h * 4, 1, 0};
|
||
|
srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888};
|
||
|
srcRect = {0, 0, src_w, src_h};
|
||
|
|
||
|
dstAddr = {(addr_space)ADDR_USER, (unsigned long)dst_addr, dst_w * dst_h * dst_bpp, 1, 0};
|
||
|
dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format};
|
||
|
dstRect = {0, 0, dst_w, dst_h};
|
||
|
dstClip = {0, 0, 0, dst_w, dst_h};
|
||
|
|
||
|
if (rotVal == 0 || rotVal == 180)
|
||
|
Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h};
|
||
|
else
|
||
|
Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w};
|
||
|
|
||
|
switch (rotVal) {
|
||
|
case 0:
|
||
|
g2d_rotation = ORIGIN;
|
||
|
break;
|
||
|
case 90:
|
||
|
g2d_rotation = ROT_90;
|
||
|
break;
|
||
|
case 180:
|
||
|
g2d_rotation = ROT_180;
|
||
|
break;
|
||
|
case 270:
|
||
|
g2d_rotation = ROT_270;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid rotVal(%d) fail", __func__, rotVal);
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0};
|
||
|
|
||
|
if (stretchFimgApi(&BlitParam) < 0) {
|
||
|
LOGE("%s::stretchFimgApi() fail", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG_MSG_ENABLE
|
||
|
LOGD("hdmi_set_g_scaling:: \n \\
|
||
|
layer=%d,\n \\
|
||
|
srcColorFormat=%d,\n \\
|
||
|
src_w=%d, src_h=%d,\n\\
|
||
|
src_address=0x%x, dst_addr=0x%x,\n\\
|
||
|
dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ",
|
||
|
layer,
|
||
|
srcColorFormat,
|
||
|
src_w, src_h,
|
||
|
src_address, dst_addr,
|
||
|
dst_x, dst_y, dst_w, dst_h);
|
||
|
#endif
|
||
|
dstBuffer->virt.p = (char *)dst_addr;
|
||
|
}
|
||
|
#else
|
||
|
dstBuffer->virt.p = (char *)src_address;
|
||
|
#endif
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#else
|
||
|
int hdmi_set_v_param(int layer,
|
||
|
int src_w, int src_h, int colorFormat,
|
||
|
unsigned int src_y_address, unsigned int src_c_address,
|
||
|
int dst_w, int dst_h)
|
||
|
{
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int round_up_src_w;
|
||
|
int round_up_src_h;
|
||
|
if (fp_tvout_v <= 0) {
|
||
|
LOGE("fp_tvout is < 0 fail\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* src_w, src_h round up to DWORD because of VP restriction */
|
||
|
#if defined(SAMSUNG_EXYNOS4x12)
|
||
|
round_up_src_w = ROUND_UP(src_w, 16);
|
||
|
#else defined(SAMSUNG_EXYNOS4210)
|
||
|
round_up_src_w = ROUND_UP(src_w, 8);
|
||
|
#endif
|
||
|
round_up_src_h = ROUND_UP(src_h, 8);
|
||
|
|
||
|
vo_param.src.base_y = (void *)src_y_address;
|
||
|
vo_param.src.base_c = (void *)src_c_address;
|
||
|
vo_param.src.pix_fmt.width = round_up_src_w;
|
||
|
vo_param.src.pix_fmt.height = round_up_src_h;
|
||
|
vo_param.src.pix_fmt.field = V4L2_FIELD_NONE;
|
||
|
vo_param.src.pix_fmt.pixelformat = colorFormat;
|
||
|
|
||
|
tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src);
|
||
|
|
||
|
vo_param.src_crop.width = src_w;
|
||
|
vo_param.src_crop.height = src_h;
|
||
|
|
||
|
tvout_v4l2_s_crop(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src_crop);
|
||
|
|
||
|
if (dst_w * src_h <= dst_h * src_w) {
|
||
|
vo_param.dst_win.w.left = 0;
|
||
|
vo_param.dst_win.w.top = (dst_h - ((dst_w * src_h) / src_w)) >> 1;
|
||
|
vo_param.dst_win.w.width = dst_w;
|
||
|
vo_param.dst_win.w.height = ((dst_w * src_h) / src_w);
|
||
|
} else {
|
||
|
vo_param.dst_win.w.left = (dst_w - ((dst_h * src_w) / src_h)) >> 1;
|
||
|
vo_param.dst_win.w.top = 0;
|
||
|
vo_param.dst_win.w.width = ((dst_h * src_w) / src_h);
|
||
|
vo_param.dst_win.w.height = dst_h;
|
||
|
}
|
||
|
|
||
|
vo_param.dst.fmt.priv = 10;
|
||
|
vo_param.dst_win.global_alpha = 255;
|
||
|
tvout_v4l2_s_fbuf(fp_tvout_v, &vo_param.dst);
|
||
|
tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_VIDEO_OVERLAY, &vo_param.dst_win);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_gl_set_param(int layer,
|
||
|
int srcColorFormat,
|
||
|
int src_w, int src_h,
|
||
|
unsigned int src_y_address, unsigned int src_c_address,
|
||
|
int dst_x, int dst_y, int dst_w, int dst_h,
|
||
|
int rotVal)
|
||
|
{
|
||
|
#if defined(BOARD_USES_FIMGAPI)
|
||
|
int dst_color_format;
|
||
|
int dst_bpp;
|
||
|
unsigned char *dst_addr;
|
||
|
fimg2d_blit BlitParam;
|
||
|
rotation g2d_rotation;
|
||
|
|
||
|
fimg2d_addr srcAddr;
|
||
|
fimg2d_image srcImage;
|
||
|
fimg2d_rect srcRect;
|
||
|
|
||
|
fimg2d_addr dstAddr;
|
||
|
fimg2d_image dstImage;
|
||
|
fimg2d_rect dstRect;
|
||
|
|
||
|
fimg2d_clip dstClip;
|
||
|
fimg2d_scale Scaling;
|
||
|
|
||
|
struct fb_var_screeninfo var;
|
||
|
struct s5ptvfb_user_window window;
|
||
|
|
||
|
int fp_tvout_g;
|
||
|
|
||
|
if(layer == HDMI_LAYER_GRAPHIC_0)
|
||
|
fp_tvout_g = fp_tvout_g0;
|
||
|
else
|
||
|
fp_tvout_g = fp_tvout_g1;
|
||
|
|
||
|
switch (t_std_id) {
|
||
|
case V4L2_STD_1080P_60:
|
||
|
case V4L2_STD_1080P_30:
|
||
|
case V4L2_STD_1080I_60:
|
||
|
case V4L2_STD_TVOUT_720P_60_SBS_HALF:
|
||
|
case V4L2_STD_TVOUT_720P_59_SBS_HALF:
|
||
|
case V4L2_STD_TVOUT_1080P_24_TB:
|
||
|
case V4L2_STD_TVOUT_1080P_23_TB:
|
||
|
dst_color_format = CF_ARGB_8888;
|
||
|
dst_bpp = 4;
|
||
|
var.bits_per_pixel = 32;
|
||
|
var.transp.length = 8;
|
||
|
break;
|
||
|
case V4L2_STD_480P_60_16_9:
|
||
|
case V4L2_STD_576P_50_16_9:
|
||
|
case V4L2_STD_720P_60:
|
||
|
case V4L2_STD_TVOUT_720P_50_TB:
|
||
|
default:
|
||
|
dst_color_format = CF_ARGB_4444;
|
||
|
dst_bpp = 2;
|
||
|
var.bits_per_pixel = 16;
|
||
|
var.transp.length = 4;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
static unsigned int prev_src_addr = 0;
|
||
|
|
||
|
if ((cur_g2d_address == 0) || (src_y_address != prev_src_addr)) {
|
||
|
dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index];
|
||
|
|
||
|
g2d_buf_index++;
|
||
|
if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM)
|
||
|
g2d_buf_index = 0;
|
||
|
|
||
|
cur_g2d_address = (unsigned int)dst_addr;
|
||
|
prev_src_addr = src_y_address;
|
||
|
|
||
|
srcAddr = {(addr_space)ADDR_PHYS, (unsigned long)src_y_address, src_w*src_h*4, 1, 0};
|
||
|
srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888};
|
||
|
srcRect = {0, 0, src_w, src_h};
|
||
|
|
||
|
dstAddr = {(addr_space)ADDR_PHYS, (unsigned long)dst_addr, dst_w*dst_h*dst_bpp, 1, 0};
|
||
|
dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format};
|
||
|
dstRect = {0, 0, dst_w, dst_h};
|
||
|
dstClip = {0, 0, 0, dst_w, dst_h};
|
||
|
|
||
|
if (rotVal == 0 || rotVal == 180)
|
||
|
Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h};
|
||
|
else
|
||
|
Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w};
|
||
|
|
||
|
switch (rotVal) {
|
||
|
case 0:
|
||
|
g2d_rotation = ORIGIN;
|
||
|
break;
|
||
|
case 90:
|
||
|
g2d_rotation = ROT_90;
|
||
|
break;
|
||
|
case 180:
|
||
|
g2d_rotation = ROT_180;
|
||
|
break;
|
||
|
case 270:
|
||
|
g2d_rotation = ROT_270;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::invalid rotVal(%d) fail", __func__, rotVal);
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0};
|
||
|
|
||
|
if (stretchFimgApi(&BlitParam) < 0) {
|
||
|
LOGE("%s::stretchFimgApi() fail", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
var.xres = dst_w;
|
||
|
var.yres = dst_h;
|
||
|
|
||
|
var.xres_virtual = var.xres;
|
||
|
var.yres_virtual = var.yres;
|
||
|
var.xoffset = 0;
|
||
|
var.yoffset = 0;
|
||
|
var.width = 0;
|
||
|
var.height = 0;
|
||
|
var.activate = FB_ACTIVATE_FORCE;
|
||
|
|
||
|
window.x = dst_x;
|
||
|
window.y = dst_y;
|
||
|
|
||
|
tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)dst_addr);
|
||
|
put_vscreeninfo(fp_tvout_g, &var);
|
||
|
|
||
|
if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) {
|
||
|
LOGE("%s::S5PTVFB_WIN_POSITION ioctl failed.", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
#else
|
||
|
struct fb_var_screeninfo var;
|
||
|
struct s5ptvfb_user_window window;
|
||
|
|
||
|
struct overlay_param ov_param;
|
||
|
|
||
|
// set base address for grp layer0 of mixer
|
||
|
int fp_tvout_g;
|
||
|
|
||
|
#ifdef DEBUG_MSG_ENABLE
|
||
|
LOGD("hdmi_gl_set_param:: \n \\
|
||
|
layer=%d,\n \\
|
||
|
srcColorFormat=%d,\n \\
|
||
|
src_w=%d, src_h=%d,\n\\
|
||
|
src_y_address=0x%x, src_c_address=0x%x,\n\\
|
||
|
dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ",
|
||
|
layer,
|
||
|
srcColorFormat,
|
||
|
src_w, src_h,
|
||
|
src_y_address, src_c_address,
|
||
|
dst_x, dst_y, dst_w, dst_h);
|
||
|
#endif
|
||
|
|
||
|
if (layer == HDMI_LAYER_GRAPHIC_0)
|
||
|
fp_tvout_g = fp_tvout_g0;
|
||
|
else
|
||
|
fp_tvout_g = fp_tvout_g1;
|
||
|
|
||
|
var.xres = src_w;
|
||
|
var.yres = src_h;
|
||
|
var.xres_virtual = var.xres;
|
||
|
var.yres_virtual = var.yres;
|
||
|
var.xoffset = 0;
|
||
|
var.yoffset = 0;
|
||
|
var.width = src_w;
|
||
|
var.height = src_h;
|
||
|
var.activate = FB_ACTIVATE_FORCE;
|
||
|
if (srcColorFormat == HAL_PIXEL_FORMAT_RGB_565) {
|
||
|
var.bits_per_pixel = 16;
|
||
|
var.transp.length = 0;
|
||
|
}
|
||
|
else {
|
||
|
var.bits_per_pixel = 32;
|
||
|
var.transp.length = 8;
|
||
|
}
|
||
|
|
||
|
window.x = dst_x;
|
||
|
window.y = dst_y;
|
||
|
|
||
|
tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)src_y_address);
|
||
|
put_vscreeninfo(fp_tvout_g, &var);
|
||
|
if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) {
|
||
|
LOGE("%s:: S5PTVFB_WIN_POSITION ioctl failed.", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int hdmi_cable_status()
|
||
|
{
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("%s", __func__);
|
||
|
#endif
|
||
|
|
||
|
int cable_status = 0;
|
||
|
int fd = 0;
|
||
|
struct v4l2_control ctrl;
|
||
|
|
||
|
fd = open(TVOUT_DEV_G0, O_RDWR);
|
||
|
if (fd <= 0) {
|
||
|
LOGE("%s: graphic layer 0 drv open failed", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ctrl.id = V4L2_CID_TV_HPD_STATUS;
|
||
|
|
||
|
if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
|
||
|
LOGE("Get HPD_STATUS fail");
|
||
|
cable_status = -1;
|
||
|
} else {
|
||
|
cable_status = ctrl.value;
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG_HDMI_HW_LEVEL
|
||
|
LOGD("HPD_STATUS = %d", cable_status);
|
||
|
#endif
|
||
|
|
||
|
close(fd);
|
||
|
|
||
|
return cable_status;
|
||
|
#else
|
||
|
int cable_status = 0;
|
||
|
int fp_hpd = 0;
|
||
|
|
||
|
fp_hpd = open(HPD_DEV, O_RDWR);
|
||
|
if (fp_hpd <= 0) {
|
||
|
LOGE("hpd drv open failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//Delay about 0.3s
|
||
|
usleep(500000);
|
||
|
if (ioctl(fp_hpd, HPD_GET_STATE, &cable_status) < 0) {
|
||
|
LOGE("hpd drv HPD_GET_STATE ioctl failed\n");
|
||
|
cable_status = -1;
|
||
|
}
|
||
|
|
||
|
close(fp_hpd);
|
||
|
|
||
|
return cable_status;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int hdmi_outputmode_2_v4l2_output_type(int output_mode)
|
||
|
{
|
||
|
int v4l2_output_type = -1;
|
||
|
|
||
|
switch (output_mode) {
|
||
|
case HDMI_OUTPUT_MODE_YCBCR:
|
||
|
v4l2_output_type = V4L2_OUTPUT_TYPE_DIGITAL;
|
||
|
break;
|
||
|
case HDMI_OUTPUT_MODE_RGB:
|
||
|
v4l2_output_type = V4L2_OUTPUT_TYPE_HDMI_RGB;
|
||
|
break;
|
||
|
case HDMI_OUTPUT_MODE_DVI:
|
||
|
v4l2_output_type = V4L2_OUTPUT_TYPE_DVI;
|
||
|
break;
|
||
|
case COMPOSITE_OUTPUT_MODE:
|
||
|
v4l2_output_type = V4L2_OUTPUT_TYPE_COMPOSITE;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced HDMI_mode(%d)", __func__, output_mode);
|
||
|
v4l2_output_type = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return v4l2_output_type;
|
||
|
}
|
||
|
|
||
|
int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type)
|
||
|
{
|
||
|
int outputMode = -1;
|
||
|
|
||
|
switch (v4l2_output_type) {
|
||
|
case V4L2_OUTPUT_TYPE_DIGITAL:
|
||
|
outputMode = HDMI_OUTPUT_MODE_YCBCR;
|
||
|
break;
|
||
|
case V4L2_OUTPUT_TYPE_HDMI_RGB:
|
||
|
outputMode = HDMI_OUTPUT_MODE_RGB;
|
||
|
break;
|
||
|
case V4L2_OUTPUT_TYPE_DVI:
|
||
|
outputMode = HDMI_OUTPUT_MODE_DVI;
|
||
|
break;
|
||
|
case V4L2_OUTPUT_TYPE_COMPOSITE:
|
||
|
outputMode = COMPOSITE_OUTPUT_MODE;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced v4l2_output_type(%d)", __func__, v4l2_output_type);
|
||
|
outputMode = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return outputMode;
|
||
|
}
|
||
|
|
||
|
int composite_std_2_v4l2_std_id(int std)
|
||
|
{
|
||
|
int std_id = -1;
|
||
|
|
||
|
switch (std) {
|
||
|
case COMPOSITE_STD_NTSC_M:
|
||
|
std_id = V4L2_STD_NTSC_M;
|
||
|
break;
|
||
|
case COMPOSITE_STD_NTSC_443:
|
||
|
std_id = V4L2_STD_NTSC_443;
|
||
|
break;
|
||
|
case COMPOSITE_STD_PAL_BDGHI:
|
||
|
std_id = V4L2_STD_PAL_BDGHI;
|
||
|
break;
|
||
|
case COMPOSITE_STD_PAL_M:
|
||
|
std_id = V4L2_STD_PAL_M;
|
||
|
break;
|
||
|
case COMPOSITE_STD_PAL_N:
|
||
|
std_id = V4L2_STD_PAL_N;
|
||
|
break;
|
||
|
case COMPOSITE_STD_PAL_Nc:
|
||
|
std_id = V4L2_STD_PAL_Nc;
|
||
|
break;
|
||
|
case COMPOSITE_STD_PAL_60:
|
||
|
std_id = V4L2_STD_PAL_60;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced composite_std(%d)", __func__, std);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return std_id;
|
||
|
}
|
||
|
|
||
|
int hdmi_check_output_mode(int v4l2_output_type)
|
||
|
{
|
||
|
struct HDMIVideoParameter video;
|
||
|
struct HDMIAudioParameter audio;
|
||
|
int calbirate_v4l2_mode = v4l2_output_type;
|
||
|
|
||
|
audio.formatCode = LPCM_FORMAT;
|
||
|
audio.outPacket = HDMI_ASP;
|
||
|
audio.channelNum = CH_2;
|
||
|
audio.sampleFreq = SF_44KHZ;
|
||
|
|
||
|
switch (v4l2_output_type) {
|
||
|
case V4L2_OUTPUT_TYPE_DIGITAL :
|
||
|
video.mode = HDMI;
|
||
|
if (!EDIDHDMIModeSupport(&video)) {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI;
|
||
|
LOGI("Change mode into DVI\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
video.colorSpace = HDMI_CS_YCBCR444;
|
||
|
if (!EDIDColorSpaceSupport(&video)) {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB;
|
||
|
LOGI("Change mode into HDMI_RGB\n");
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case V4L2_OUTPUT_TYPE_HDMI_RGB:
|
||
|
video.mode = HDMI;
|
||
|
if (!EDIDHDMIModeSupport(&video)) {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI;
|
||
|
LOGI("Change mode into DVI\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
video.colorSpace = HDMI_CS_RGB;
|
||
|
if (!EDIDColorSpaceSupport(&video)) {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL;
|
||
|
LOGI("Change mode into HDMI_YCBCR\n");
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case V4L2_OUTPUT_TYPE_DVI:
|
||
|
video.mode = DVI;
|
||
|
if (!EDIDHDMIModeSupport(&video)) {
|
||
|
video.colorSpace = HDMI_CS_YCBCR444;
|
||
|
if (!EDIDColorSpaceSupport(&video)) {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB;
|
||
|
LOGI("Change mode into HDMI_RGB\n");
|
||
|
} else {
|
||
|
calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL;
|
||
|
LOGI("Change mode into HDMI_YCBCR\n");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return calbirate_v4l2_mode;
|
||
|
}
|
||
|
|
||
|
#if defined(BOARD_USE_V4L2)
|
||
|
int hdmi_check_resolution(unsigned int preset_id)
|
||
|
{
|
||
|
struct HDMIVideoParameter video;
|
||
|
struct HDMIAudioParameter audio;
|
||
|
|
||
|
switch (preset_id) {
|
||
|
case V4L2_DV_480P60:
|
||
|
video.resolution = v720x480p_60Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_576P50:
|
||
|
video.resolution = v720x576p_50Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P60:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P50:
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P60:
|
||
|
video.resolution = v1920x1080p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P50:
|
||
|
video.resolution = v1920x1080p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080I60:
|
||
|
video.resolution = v1920x1080i_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080I50:
|
||
|
video.resolution = v1920x1080i_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_480P59_94:
|
||
|
video.resolution = v720x480p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P59_94:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080I59_94:
|
||
|
video.resolution = v1920x1080i_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P59_94:
|
||
|
video.resolution = v1920x1080p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P30:
|
||
|
video.resolution = v1920x1080p_30Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P60_SB_HALF:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P59_94_SB_HALF:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_720P50_TB:
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P24_TB:
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
case V4L2_DV_1080P23_98_TB:
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced preset_id(%d)", __func__, preset_id);
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!EDIDVideoResolutionSupport(&video)) {
|
||
|
#ifdef DEBUG_MSG_ENABLE
|
||
|
LOGD("%s::EDIDVideoResolutionSupport(%d) fail (not suppoted preset_id) \n", __func__, preset_id);
|
||
|
#endif
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_resolution_2_preset_id(unsigned int resolution, int * w, int * h, unsigned int *preset_id)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
switch (resolution) {
|
||
|
case 1080960:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080P60;
|
||
|
break;
|
||
|
case 1080950:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080P50;
|
||
|
break;
|
||
|
case 1080930:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080P30;
|
||
|
break;
|
||
|
case 1080924:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080P24_TB;
|
||
|
break;
|
||
|
case 1080160:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080I60;
|
||
|
break;
|
||
|
case 1080150:
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
*preset_id = V4L2_DV_1080I50;
|
||
|
break;
|
||
|
case 720960:
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
*preset_id = V4L2_DV_720P60;
|
||
|
break;
|
||
|
case 7209601:
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
*preset_id = V4L2_DV_720P60_SB_HALF;
|
||
|
break;
|
||
|
case 720950:
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
*preset_id = V4L2_DV_720P50;
|
||
|
break;
|
||
|
case 7209501:
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
*preset_id = V4L2_DV_720P50_TB;
|
||
|
break;
|
||
|
case 5769501:
|
||
|
*w = 720;
|
||
|
*h = 576;
|
||
|
*preset_id = V4L2_DV_576P50;
|
||
|
break;
|
||
|
case 5769502:
|
||
|
*w = 720;
|
||
|
*h = 576;
|
||
|
*preset_id = V4L2_DV_576P50;
|
||
|
break;
|
||
|
case 4809601:
|
||
|
*w = 720;
|
||
|
*h = 480;
|
||
|
*preset_id = V4L2_DV_480P60;
|
||
|
break;
|
||
|
case 4809602:
|
||
|
*w = 720;
|
||
|
*h = 480;
|
||
|
*preset_id = V4L2_DV_480P60;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced resolution(%d)", __func__, resolution);
|
||
|
ret = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#else
|
||
|
int hdmi_check_resolution(v4l2_std_id std_id)
|
||
|
{
|
||
|
struct HDMIVideoParameter video;
|
||
|
struct HDMIAudioParameter audio;
|
||
|
|
||
|
switch (std_id) {
|
||
|
case V4L2_STD_480P_60_16_9:
|
||
|
video.resolution = v720x480p_60Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_480P_60_4_3:
|
||
|
video.resolution = v640x480p_60Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_576P_50_16_9:
|
||
|
video.resolution = v720x576p_50Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_576P_50_4_3:
|
||
|
video.resolution = v720x576p_50Hz;
|
||
|
video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_720P_60:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_720P_50:
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080P_60:
|
||
|
video.resolution = v1920x1080p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080P_50:
|
||
|
video.resolution = v1920x1080p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080I_60:
|
||
|
video.resolution = v1920x1080i_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080I_50:
|
||
|
video.resolution = v1920x1080i_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_480P_59:
|
||
|
video.resolution = v720x480p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_720P_59:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080I_59:
|
||
|
video.resolution = v1920x1080i_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080P_59:
|
||
|
video.resolution = v1920x1080p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_1080P_30:
|
||
|
video.resolution = v1920x1080p_30Hz;
|
||
|
video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_TVOUT_720P_60_SBS_HALF:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_TVOUT_720P_59_SBS_HALF:
|
||
|
video.resolution = v1280x720p_60Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_SSH_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_TVOUT_720P_50_TB:
|
||
|
video.resolution = v1280x720p_50Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_TVOUT_1080P_24_TB:
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
case V4L2_STD_TVOUT_1080P_23_TB:
|
||
|
video.resolution = v1920x1080p_24Hz;
|
||
|
video.hdmi_3d_format = HDMI_3D_TB_FORMAT;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced std_id(%lld)", __func__, std_id);
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!EDIDVideoResolutionSupport(&video)) {
|
||
|
#ifdef DEBUG_MSG_ENABLE
|
||
|
LOGD("%s::EDIDVideoResolutionSupport(%llx) fail (not suppoted std_id) \n", __func__, std_id);
|
||
|
#endif
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_resolution_2_std_id(unsigned int resolution, int * w, int * h, v4l2_std_id * std_id)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
switch (resolution) {
|
||
|
case 1080960:
|
||
|
*std_id = V4L2_STD_1080P_60;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 1080950:
|
||
|
*std_id = V4L2_STD_1080P_50;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 1080930:
|
||
|
*std_id = V4L2_STD_1080P_30;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 1080924:
|
||
|
*std_id = V4L2_STD_TVOUT_1080P_24_TB;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 1080160:
|
||
|
*std_id = V4L2_STD_1080I_60;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 1080150:
|
||
|
*std_id = V4L2_STD_1080I_50;
|
||
|
*w = 1920;
|
||
|
*h = 1080;
|
||
|
break;
|
||
|
case 720960:
|
||
|
*std_id = V4L2_STD_720P_60;
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
break;
|
||
|
case 7209601:
|
||
|
*std_id = V4L2_STD_TVOUT_720P_60_SBS_HALF;
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
break;
|
||
|
case 720950:
|
||
|
*std_id = V4L2_STD_720P_50;
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
break;
|
||
|
case 7209501:
|
||
|
*std_id = V4L2_STD_TVOUT_720P_50_TB;
|
||
|
*w = 1280;
|
||
|
*h = 720;
|
||
|
break;
|
||
|
case 5769501:
|
||
|
*std_id = V4L2_STD_576P_50_16_9;
|
||
|
*w = 720;
|
||
|
*h = 576;
|
||
|
break;
|
||
|
case 5769502:
|
||
|
*std_id = V4L2_STD_576P_50_4_3;
|
||
|
*w = 720;
|
||
|
*h = 576;
|
||
|
break;
|
||
|
case 4809601:
|
||
|
*std_id = V4L2_STD_480P_60_16_9;
|
||
|
*w = 720;
|
||
|
*h = 480;
|
||
|
break;
|
||
|
case 4809602:
|
||
|
*std_id = V4L2_STD_480P_60_4_3;
|
||
|
*w = 720;
|
||
|
*h = 480;
|
||
|
break;
|
||
|
default:
|
||
|
LOGE("%s::unmathced resolution(%d)", __func__, resolution);
|
||
|
ret = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int hdmi_enable_hdcp(unsigned int hdcp_en)
|
||
|
{
|
||
|
if (ioctl(fp_tvout, VIDIOC_HDCP_ENABLE, hdcp_en) < 0) {
|
||
|
LOGD("%s::VIDIOC_HDCP_ENABLE(%d) fail \n", __func__, hdcp_en);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hdmi_check_audio(void)
|
||
|
{
|
||
|
struct HDMIAudioParameter audio;
|
||
|
enum state audio_state = ON;
|
||
|
int ret = 0;
|
||
|
|
||
|
audio.formatCode = LPCM_FORMAT;
|
||
|
audio.outPacket = HDMI_ASP;
|
||
|
audio.channelNum = CH_2;
|
||
|
audio.sampleFreq = SF_44KHZ;
|
||
|
|
||
|
#if defined(BOARD_USES_EDID)
|
||
|
if (!EDIDAudioModeSupport(&audio))
|
||
|
audio_state = NOT_SUPPORT;
|
||
|
else
|
||
|
audio_state = ON;
|
||
|
#endif
|
||
|
if (audio_state == ON) {
|
||
|
if (ioctl(fp_tvout, VIDIOC_INIT_AUDIO, 1) < 0) {
|
||
|
LOGE("%s::VIDIOC_INIT_AUDIO(1) fail", __func__);
|
||
|
ret = -1;
|
||
|
}
|
||
|
} else {
|
||
|
if (ioctl(fp_tvout, VIDIOC_INIT_AUDIO, 0) < 0) {
|
||
|
LOGE("%s::VIDIOC_INIT_AUDIO(0) fail", __func__);
|
||
|
ret = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
}
|