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.
hardware_samsung/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp

1986 lines
56 KiB

/*
* 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 DEBUG_MSG_ENABLE
//#define LOG_NDEBUG 0
//#define LOG_TAG "libhdmi"
#include <cutils/log.h>
#include "ion.h"
#include "SecHdmi.h"
#include "SecHdmiV4L2Utils.h"
#define CHECK_GRAPHIC_LAYER_TIME (0)
namespace android {
extern unsigned int output_type;
extern v4l2_std_id t_std_id;
extern int g_hpd_state;
extern unsigned int g_hdcp_en;
#if defined(BOARD_USES_HDMI_FIMGAPI)
extern unsigned int g2d_reserved_memory0;
extern unsigned int g2d_reserved_memory1;
extern unsigned int g2d_reserved_memory_size;
extern unsigned int cur_g2d_address;
#endif
#if defined(BOARD_USES_CEC)
SecHdmi::CECThread::~CECThread()
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s", __func__);
#endif
mFlagRunning = false;
}
bool SecHdmi::CECThread::threadLoop()
{
unsigned char buffer[CEC_MAX_FRAME_SIZE];
int size;
unsigned char lsrc, ldst, opcode;
{
Mutex::Autolock lock(mThreadLoopLock);
mFlagRunning = true;
size = CECReceiveMessage(buffer, CEC_MAX_FRAME_SIZE, 100000);
if (!size) // no data available or ctrl-c
return true;
if (size == 1)
return true; // "Polling Message"
lsrc = buffer[0] >> 4;
/* ignore messages with src address == mLaddr*/
if (lsrc == mLaddr)
return true;
opcode = buffer[1];
if (CECIgnoreMessage(opcode, lsrc)) {
LOGE("### ignore message coming from address 15 (unregistered)\n");
return true;
}
if (!CECCheckMessageSize(opcode, size)) {
LOGE("### invalid message size: %d(opcode: 0x%x) ###\n", size, opcode);
return true;
}
/* check if message broadcasted/directly addressed */
if (!CECCheckMessageMode(opcode, (buffer[0] & 0x0F) == CEC_MSG_BROADCAST ? 1 : 0)) {
LOGE("### invalid message mode (directly addressed/broadcast) ###\n");
return true;
}
ldst = lsrc;
//TODO: macroses to extract src and dst logical addresses
//TODO: macros to extract opcode
switch (opcode) {
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
/* responce with "Report Physical Address" */
buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST;
buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
buffer[2] = (mPaddr >> 8) & 0xFF;
buffer[3] = mPaddr & 0xFF;
buffer[4] = mDevtype;
size = 5;
break;
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
LOGD("[CEC_OPCODE_REQUEST_ACTIVE_SOURCE]\n");
/* responce with "Active Source" */
buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST;
buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
buffer[2] = (mPaddr >> 8) & 0xFF;
buffer[3] = mPaddr & 0xFF;
size = 4;
LOGD("Tx : [CEC_OPCODE_ACTIVE_SOURCE]\n");
break;
case CEC_OPCODE_ABORT:
case CEC_OPCODE_FEATURE_ABORT:
default:
/* send "Feature Abort" */
buffer[0] = (mLaddr << 4) | ldst;
buffer[1] = CEC_OPCODE_FEATURE_ABORT;
buffer[2] = CEC_OPCODE_ABORT;
buffer[3] = 0x04; // "refused"
size = 4;
break;
}
if (CECSendMessage(buffer, size) != size)
LOGE("CECSendMessage() failed!!!\n");
}
return true;
}
bool SecHdmi::CECThread::start()
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mThreadControlLock);
if (exitPending()) {
if (requestExitAndWait() == WOULD_BLOCK) {
LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK");
return false;
}
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("EDIDGetCECPhysicalAddress");
#endif
/* set to not valid physical address */
mPaddr = CEC_NOT_VALID_PHYSICAL_ADDRESS;
if (!EDIDGetCECPhysicalAddress(&mPaddr)) {
LOGE("Error: EDIDGetCECPhysicalAddress() failed.\n");
return false;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("CECOpen");
#endif
if (!CECOpen()) {
LOGE("CECOpen() failed!!!\n");
return false;
}
/* a logical address should only be allocated when a device \
has a valid physical address, at all other times a device \
should take the 'Unregistered' logical address (15)
*/
/* if physical address is not valid device should take \
the 'Unregistered' logical address (15)
*/
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("CECAllocLogicalAddress");
#endif
mLaddr = CECAllocLogicalAddress(mPaddr, mDevtype);
if (!mLaddr) {
LOGE("CECAllocLogicalAddress() failed!!!\n");
if (!CECClose())
LOGE("CECClose() failed!\n");
return false;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("request to run CECThread");
#endif
status_t ret = run("SecHdmi::CECThread", PRIORITY_DISPLAY);
if (ret != NO_ERROR) {
LOGE("%s fail to run thread", __func__);
return false;
}
return true;
}
bool SecHdmi::CECThread::stop()
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s request Exit", __func__);
#endif
Mutex::Autolock lock(mThreadControlLock);
if (requestExitAndWait() == WOULD_BLOCK) {
LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK");
return false;
}
if (!CECClose())
LOGE("CECClose() failed!\n");
mFlagRunning = false;
return true;
}
#endif
SecHdmi::SecHdmi():
#if defined(BOARD_USES_CEC)
mCECThread(NULL),
#endif
mFlagCreate(false),
mFlagConnected(false),
mPreviousHdmiPresetId(V4L2_DV_1080P60),
mHdmiDstWidth(0),
mHdmiDstHeight(0),
mHdmiSrcYAddr(0),
mHdmiSrcCbCrAddr(0),
mFBaddr(0),
mFBsize(0),
mFBionfd(-1),
mFBoffset(0),
mHdmiOutputMode(DEFAULT_OUPUT_MODE),
mHdmiResolutionValue(DEFAULT_HDMI_RESOLUTION_VALUE), // V4L2_STD_480P_60_4_3
mHdmiStdId(DEFAULT_HDMI_STD_ID), // V4L2_STD_480P_60_4_3
mCompositeStd(DEFAULT_COMPOSITE_STD),
mHdcpMode(false),
mAudioMode(2),
mUIRotVal(0),
mG2DUIRotVal(0),
mCurrentHdmiOutputMode(-1),
mCurrentHdmiResolutionValue(0), // 1080960
mCurrentHdcpMode(false),
mCurrentAudioMode(-1),
mHdmiInfoChange(true),
mFlagGscalerStart(false),
mGscalerDstColorFormat(0),
mDefaultFBFd(-1),
mCurrentsrcW(0),
mCurrentsrcH(0),
mCurrentsrcColorFormat(0),
mCurrentsrcYAddr(0),
mCurrentsrcCbAddr(0),
mCurrentdstX(0),
mCurrentdstY(0),
mCurrenthdmiLayer(0),
mCurrentNumOfHWCLayer(0),
mDisplayWidth(DEFALULT_DISPLAY_WIDTH),
mDisplayHeight(DEFALULT_DISPLAY_HEIGHT)
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s", __func__);
#endif
for (int i = 0; i < HDMI_LAYER_MAX; i++) {
mFlagLayerEnable[i] = false;
mFlagHdmiStart[i] = false;
mSrcWidth [i] = 0;
mSrcHeight [i] = 0;
mSrcColorFormat[i] = 0;
mHdmiResolutionWidth [i] = 0;
mHdmiResolutionHeight [i] = 0;
mPreviousNumofHwLayer [i] = 0;
mSrcIndex[i] = 0;
}
//All layer is on
mFlagLayerEnable[HDMI_LAYER_VIDEO] = true;
mFlagLayerEnable[HDMI_LAYER_GRAPHIC_0] = true;
mFlagLayerEnable[HDMI_LAYER_GRAPHIC_1] = true;
mHdmiSizeOfResolutionValueList = 14;
mHdmiResolutionValueList[0] = 1080960;
mHdmiResolutionValueList[1] = 1080950;
mHdmiResolutionValueList[2] = 1080930;
mHdmiResolutionValueList[3] = 1080924;
mHdmiResolutionValueList[4] = 1080160;
mHdmiResolutionValueList[5] = 1080150;
mHdmiResolutionValueList[6] = 720960;
mHdmiResolutionValueList[7] = 7209601;
mHdmiResolutionValueList[8] = 720950;
mHdmiResolutionValueList[9] = 7209501;
mHdmiResolutionValueList[10] = 5769501;
mHdmiResolutionValueList[11] = 5769502;
mHdmiResolutionValueList[12] = 4809601;
mHdmiResolutionValueList[13] = 4809602;
#if defined(BOARD_USES_CEC)
mCECThread = new CECThread(this);
#endif
mGscalerForceUpdate = false;
}
SecHdmi::~SecHdmi()
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s", __func__);
#endif
if (mFlagCreate == true)
LOGE("%s::this is not Destroyed fail", __func__);
else
disconnect();
}
bool SecHdmi::create(int width, int height)
{
Mutex::Autolock lock(mLock);
unsigned int fimc_buf_size = 0;
int stride;
int vstride;
int ionfd_G2D = 0;
void * ion_base_addr = NULL;
struct s3c_fb_user_ion_client ion_handle;
unsigned int FB_size = ALIGN(width, 16) * ALIGN(height, 16) * HDMI_G2D_BUFFER_BPP_SIZE * 2;
int ionfd_FB = 0;
/*
* Video plaback (I420): output buffer size of FIMC3 is (1920 x 1088 x 1.5)
* Video plaback (NV12): FIMC3 is not used.
* Camera preview (YV12): output buffer size of FIMC3 is (640 x 480 x 1.5)
* UI mode (ARGB8888) : output buffer size of FIMC3 is (480 x 800 x 1.5)
*/
#ifndef SUPPORT_1080P_FIMC_OUT
setDisplaySize(width, height);
#endif
stride = ALIGN(HDMI_MAX_WIDTH, 16);
vstride = ALIGN(HDMI_MAX_HEIGHT, 16);
fimc_buf_size = stride * vstride * HDMI_FIMC_BUFFER_BPP_SIZE;
#if defined(BOARD_USES_HDMI_FIMGAPI)
g2d_reserved_memory_size = stride * vstride * HDMI_G2D_BUFFER_BPP_SIZE;
#endif
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
if (mFlagCreate == true) {
LOGE("%s::Already Created", __func__);
return true;
}
if (mDefaultFBFd <= 0) {
if ((mDefaultFBFd = fb_open(DEFAULT_FB)) < 0) {
LOGE("%s:Failed to open default FB", __func__);
return false;
}
}
if (mSecGscaler.create(SecGscaler::DEV_3, MAX_BUFFERS_GSCALER) == false) {
LOGE("%s::SecGscaler create() failed", __func__);
goto CREATE_FAIL;
}
mIonClient = ion_client_create();
if (mIonClient < 0) {
mIonClient = -1;
LOGE("%s::ion_client_create() failed", __func__);
goto CREATE_FAIL;
}
// get framebuffer virtual address for LCD
if (ioctl(mDefaultFBFd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) == -1) {
LOGE("%s:ioctl(S3CFB_GET_ION_USER_HANDLE) failed", __func__);
return false;
}
mFBaddr = (unsigned int)ion_map(ion_handle.fd, ALIGN(FB_size, PAGE_SIZE), 0);
mFBsize = FB_size;
mFBionfd = ion_handle.fd;
#if defined(BOARD_USES_HDMI_FIMGAPI)
ionfd_G2D = ion_alloc(mIonClient, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0, ION_HEAP_EXYNOS_MASK);
if (ionfd_G2D < 0) {
LOGE("%s::ION memory allocation failed", __func__);
} else {
ion_base_addr = ion_map(ionfd_G2D, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0);
if (ion_base_addr == MAP_FAILED)
LOGE("%s::ION mmap failed", __func__);
}
g2d_reserved_memory0 = (unsigned int)ion_base_addr;
g2d_reserved_memory1 = g2d_reserved_memory0 + g2d_reserved_memory_size;
#endif
v4l2_std_id std_id;
__u32 preset_id;
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::mHdmiOutputMode(%d) \n", __func__, mHdmiOutputMode);
#endif
if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) {
std_id = composite_std_2_v4l2_std_id(mCompositeStd);
if ((int)std_id < 0) {
LOGE("%s::composite_std_2_v4l2_std_id(%d) fail\n", __func__, mCompositeStd);
goto CREATE_FAIL;
}
if (m_setCompositeResolution(mCompositeStd) == false) {
LOGE("%s::m_setCompositeResolution(%d) fail\n", __func__, mCompositeStd);
goto CREATE_FAIL;
}
} else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (hdmi_resolution_2_std_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &std_id, &preset_id) < 0) {
LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, mHdmiResolutionValue);
goto CREATE_FAIL;
}
}
if (m_setupLink() == false) {
LOGE("%s:Enable the link failed", __func__);
return false;
}
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (m_openLayer(layer) == false)
LOGE("%s::hdmi_init_layer(%d) failed", __func__, layer);
}
for (int layer = HDMI_LAYER_BASE + 2; layer < HDMI_LAYER_MAX; layer++) {
if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer);
return false;
}
if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer);
return false;
}
if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, layer);
return false;
}
}
mFlagCreate = true;
return true;
CREATE_FAIL :
if (mSecGscaler.flagCreate() == true &&
mSecGscaler.destroy() == false)
LOGE("%s::Gscaler destory failed", __func__);
return false;
}
bool SecHdmi::destroy(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
char node[32];
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Already Destroyed fail \n", __func__);
goto DESTROY_FAIL;
}
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, layer);
goto DESTROY_FAIL;
}
}
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (m_closeLayer(layer) == false)
LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer);
}
if (mSecGscaler.flagCreate() == true && mSecGscaler.destroy() == false) {
LOGE("%s::fimc destory fail \n", __func__);
goto DESTROY_FAIL;
}
#ifdef USE_LCD_ADDR_IN_HERE
{
if (0 < mDefaultFBFd) {
close(mDefaultFBFd);
mDefaultFBFd = -1;
}
}
#endif //USE_LCD_ADDR_IN_HERE
#if defined(BOARD_USES_HDMI_FIMGAPI)
ion_unmap((void *)g2d_reserved_memory0, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE));
#endif
if (0 < mFBaddr)
ion_unmap((void *)mFBaddr, ALIGN(mFBsize, PAGE_SIZE));
if (0 < mFBionfd)
ion_free(mFBionfd);
sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
mMediadevFd = open(node, O_RDONLY);
if (mMediadevFd < 0) {
LOGE("%s::open(%s) failed", __func__, node);
goto DESTROY_FAIL;
}
mlink_desc.flags = 0;
if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) {
LOGE("%s::MEDIA_IOC_SETUP_UNLINK failed", __func__);
goto DESTROY_FAIL;
}
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (m_closeLayer(layer) == false)
LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer);
}
if (0 < mMediadevFd)
close(mMediadevFd);
if (0 < mSubdevMixerFd)
close(mSubdevMixerFd);
mMediadevFd = -1;
mSubdevMixerFd = -1;
mFlagCreate = false;
return true;
DESTROY_FAIL :
return false;
}
bool SecHdmi::connect(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
{
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (mFlagConnected == true) {
LOGD("%s::Already Connected.. \n", __func__);
return true;
}
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (m_flagHWConnected() == false) {
LOGD("%s::m_flagHWConnected() fail \n", __func__);
return false;
}
#if defined(BOARD_USES_EDID)
if (!EDIDOpen())
LOGE("EDIDInit() failed!\n");
if (!EDIDRead()) {
LOGE("EDIDRead() failed!\n");
if (!EDIDClose())
LOGE("EDIDClose() failed!\n");
}
#endif
#if defined(BOARD_USES_CEC)
if (!(mCECThread->mFlagRunning))
mCECThread->start();
#endif
}
}
if (this->setHdmiOutputMode(mHdmiOutputMode, true) == false)
LOGE("%s::setHdmiOutputMode(%d) fail \n", __func__, mHdmiOutputMode);
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (this->setHdmiResolution(mHdmiResolutionValue, true) == false)
LOGE("%s::setHdmiResolution(%d) fail \n", __func__, mHdmiResolutionValue);
if (this->setHdcpMode(mHdcpMode, false) == false)
LOGE("%s::setHdcpMode(%d) fail \n", __func__, mHdcpMode);
/* if (this->m_setAudioMode(mAudioMode) == false)
LOGE("%s::m_setAudioMode(%d) fail \n", __func__, mAudioMode);
*/
mHdmiInfoChange = true;
mFlagConnected = true;
#if defined(BOARD_USES_EDID)
display_menu();
#endif
}
return true;
}
bool SecHdmi::disconnect(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (mFlagConnected == false) {
LOGE("%s::Already Disconnected.. \n", __func__);
return true;
}
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
#if defined(BOARD_USES_CEC)
if (mCECThread->mFlagRunning)
mCECThread->stop();
#endif
#if defined(BOARD_USES_EDID)
if (!EDIDClose()) {
LOGE("EDIDClose() failed!\n");
return false;
}
#endif
}
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) {
LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, layer);
return false;
}
}
mFlagConnected = false;
mPreviousHdmiPresetId = V4L2_DV_1080P60;
mHdmiOutputMode = DEFAULT_OUPUT_MODE;
mHdmiResolutionValue = DEFAULT_HDMI_RESOLUTION_VALUE;
mHdmiStdId = DEFAULT_HDMI_STD_ID;
mCompositeStd = DEFAULT_COMPOSITE_STD;
mAudioMode = 2;
mCurrentHdmiOutputMode = -1;
mCurrentHdmiResolutionValue = 0;
mCurrentAudioMode = -1;
return true;
}
bool SecHdmi::startHdmi(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagHdmiStart[hdmiLayer] == false &&
m_startHdmi(hdmiLayer) == false) {
LOGE("%s::hdmiLayer(%d) fail \n", __func__, hdmiLayer);
return false;
}
return true;
}
bool SecHdmi::stopHdmi(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagHdmiStart[hdmiLayer] == true &&
m_stopHdmi(hdmiLayer) == false) {
LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, hdmiLayer);
return false;
}
tvout_deinit();
return true;
}
bool SecHdmi::flagConnected(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
return mFlagConnected;
}
bool SecHdmi::flush(int srcW, int srcH, int srcColorFormat,
unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr,
int dstX, int dstY,
int hdmiLayer,
int num_of_hwc_layer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer=%d", __func__, hdmiLayer);
#endif
Mutex::Autolock lock(mLock);
#ifdef DEBUG_MSG_ENABLE
LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, srcCrAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d, num_of_hwc_layer=%d",
__func__, srcW, srcH, srcColorFormat,
srcYAddr, srcCbAddr, srcCrAddr,
dstX, dstY, hdmiLayer, num_of_hwc_layer);
LOGD("saved param(%d, %d, %d)",
mSrcWidth[hdmiLayer], mSrcHeight[hdmiLayer], mSrcColorFormat[hdmiLayer]);
#endif
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created", __func__);
return false;
}
if (srcW != mSrcWidth[hdmiLayer] ||
srcH != mSrcHeight[hdmiLayer] ||
srcColorFormat != mSrcColorFormat[hdmiLayer] ||
mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] ||
mHdmiInfoChange == true) {
#ifdef DEBUG_MSG_ENABLE
LOGD("m_reset param(%d, %d, %d, %d, %d, %d, %d)",
srcW, mSrcWidth[hdmiLayer],
srcH, mSrcHeight[hdmiLayer],
srcColorFormat, mSrcColorFormat[hdmiLayer],
hdmiLayer);
#endif
if (m_reset(srcW, srcH, dstX, dstY, srcColorFormat, hdmiLayer, num_of_hwc_layer) == false) {
LOGE("%s::m_reset(%d, %d, %d, %d) failed", __func__, srcW, srcH, srcColorFormat, hdmiLayer);
return false;
}
}
if (srcYAddr == 0) {
unsigned int FB_size = ALIGN(srcW, 16) * ALIGN(srcH, 16) * HDMI_G2D_BUFFER_BPP_SIZE;
srcYAddr = (unsigned int)mFBaddr + mFBoffset;
srcCbAddr = srcYAddr;
mFBoffset += FB_size;
if (FB_size < mFBoffset)
mFBoffset = 0;
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::mFBaddr=0x%08x, srcYAddr=0x%08x, mFBoffset=0x%08x", __func__, mFBaddr, srcYAddr, mFBoffset);
#endif
}
if (hdmiLayer == HDMI_LAYER_VIDEO) {
if (mSecGscaler.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) {
LOGE("%s::setSrcAddr(0x%08x, 0x%08x, 0x%08x)", __func__, srcYAddr, srcCbAddr, srcCrAddr);
return false;
}
} else {
#if CHECK_GRAPHIC_LAYER_TIME
nsecs_t start, end;
start = systemTime();
#endif
if (num_of_hwc_layer == 0) { /* UI only mode */
struct v4l2_rect rect;
if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) {
hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
} else {
hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect);
}
rect.left = ALIGN(rect.left, 16);
if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
srcColorFormat,
srcW, srcH,
srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]],
rect.left, rect.top,
rect.width, rect.height,
mG2DUIRotVal) < 0)
return false;
} else { // Video Playback + UI Mode
if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
srcColorFormat,
srcW, srcH,
srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]],
dstX, dstY,
mHdmiDstWidth, mHdmiDstHeight,
mG2DUIRotVal) < 0)
return false;
}
#if CHECK_GRAPHIC_LAYER_TIME
end = systemTime();
LOGD("[UI] hdmi_gl_set_param[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
#endif
}
if (mFlagConnected) {
if (mFlagHdmiStart[hdmiLayer] == true) {
if (m_run(hdmiLayer) == false) {
LOGE("%s::m_run(%d) failed", __func__, hdmiLayer);
return false;
}
}
if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer) == false) {
LOGE("%s::start hdmiLayer(%d) failed", __func__, hdmiLayer);
return false;
}
}
return true;
}
bool SecHdmi::clear(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) {
LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer);
return false;
}
return true;
}
void SecHdmi::clearGraphicLayer(int hdmiLayer)
{
mSrcWidth[hdmiLayer] = 0;
mSrcHeight[hdmiLayer] = 0;
mSrcColorFormat[hdmiLayer] = 0;
}
bool SecHdmi::enableGraphicLayer(int hdmiLayer)
{
Mutex::Autolock lock(mLock);
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer);
#endif
switch (hdmiLayer) {
case HDMI_LAYER_VIDEO:
case HDMI_LAYER_GRAPHIC_0:
case HDMI_LAYER_GRAPHIC_1:
mFlagLayerEnable[hdmiLayer] = true;
if (mFlagConnected == true)
m_startHdmi(hdmiLayer);
break;
default:
return false;
}
return true;
}
bool SecHdmi::disableGraphicLayer(int hdmiLayer)
{
Mutex::Autolock lock(mLock);
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer);
#endif
switch (hdmiLayer) {
case HDMI_LAYER_VIDEO:
case HDMI_LAYER_GRAPHIC_0:
case HDMI_LAYER_GRAPHIC_1:
if (mFlagConnected == true && mFlagLayerEnable[hdmiLayer])
if (m_stopHdmi(hdmiLayer) == false )
LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer);
mFlagLayerEnable[hdmiLayer] = false;
break;
default:
return false;
}
return true;
}
bool SecHdmi::setHdmiOutputMode(int hdmiOutputMode, bool forceRun)
{
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::hdmiOutputMode = %d, forceRun = %d", __func__, hdmiOutputMode, forceRun);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (forceRun == false && mHdmiOutputMode == hdmiOutputMode) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode);
#endif
return true;
}
int newHdmiOutputMode = hdmiOutputMode;
int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode);
if (v4l2OutputType < 0) {
LOGD("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode);
return false;
}
#if defined(BOARD_USES_EDID)
int newV4l2OutputType = hdmi_check_output_mode(v4l2OutputType);
if (newV4l2OutputType != v4l2OutputType) {
newHdmiOutputMode = hdmi_v4l2_output_type_2_outputmode(newV4l2OutputType);
if (newHdmiOutputMode < 0) {
LOGD("%s::hdmi_v4l2_output_type_2_outputmode(%d) fail\n", __func__, newV4l2OutputType);
return false;
}
LOGD("%s::calibration mode(%d -> %d)... \n", __func__, hdmiOutputMode, newHdmiOutputMode);
mHdmiInfoChange = true;
}
#endif
if (mHdmiOutputMode != newHdmiOutputMode) {
mHdmiOutputMode = newHdmiOutputMode;
mHdmiInfoChange = true;
}
return true;
}
bool SecHdmi::setHdmiResolution(unsigned int hdmiResolutionValue, bool forceRun)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiResolutionValue = %d, forceRun = %d", __func__, hdmiResolutionValue, forceRun);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (forceRun == false && mHdmiResolutionValue == hdmiResolutionValue) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue);
#endif
return true;
}
unsigned int newHdmiResolutionValue = hdmiResolutionValue;
int w = 0;
int h = 0;
v4l2_std_id std_id;
__u32 preset_id;
#if defined(BOARD_USES_EDID)
// find perfect resolutions..
if (hdmi_resolution_2_std_id(newHdmiResolutionValue, &w, &h, &std_id, &preset_id) < 0 ||
hdmi_check_resolution(std_id) < 0) {
bool flagFoundIndex = false;
int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue);
for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) {
if (hdmi_resolution_2_std_id(mHdmiResolutionValueList[i], &w, &h, &std_id, &preset_id) == 0 &&
hdmi_check_resolution(std_id) == 0) {
newHdmiResolutionValue = mHdmiResolutionValueList[i];
flagFoundIndex = true;
break;
}
}
if (flagFoundIndex == false) {
LOGE("%s::hdmi cannot control this resolution(%d) fail \n", __func__, hdmiResolutionValue);
// Set resolution to 480P
newHdmiResolutionValue = mHdmiResolutionValueList[mHdmiSizeOfResolutionValueList-2];
} else {
LOGD("%s::HDMI resolutions size is calibrated(%d -> %d)..\n", __func__, hdmiResolutionValue, newHdmiResolutionValue);
}
} else {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::find resolutions(%d) at once\n", __func__, hdmiResolutionValue);
#endif
}
#endif
if (mHdmiResolutionValue != newHdmiResolutionValue) {
mHdmiResolutionValue = newHdmiResolutionValue;
mHdmiInfoChange = true;
}
return true;
}
bool SecHdmi::setHdcpMode(bool hdcpMode, bool forceRun)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (forceRun == false && mHdcpMode == hdcpMode) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode);
#endif
return true;
}
mHdcpMode = hdcpMode;
mHdmiInfoChange = true;
return true;
}
bool SecHdmi::setUIRotation(unsigned int rotVal, unsigned int hwcLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
Mutex::Autolock lock(mLock);
if (mFlagCreate == false) {
LOGE("%s::Not Yet Created \n", __func__);
return false;
}
if (rotVal % 90 != 0) {
LOGE("%s::Invalid rotation value(%d)", __func__, rotVal);
return false;
}
/* G2D rotation */
if (rotVal != mG2DUIRotVal) {
mG2DUIRotVal = rotVal;
mHdmiInfoChange = true;
}
/* FIMC rotation */
if (hwcLayer == 0) { /* Rotate in UI only mode */
if (rotVal != mUIRotVal) {
mSecGscaler.setRotVal(rotVal);
mUIRotVal = rotVal;
mHdmiInfoChange = true;
}
} else { /* Don't rotate video layer when video is played. */
rotVal = 0;
if (rotVal != mUIRotVal) {
mSecGscaler.setRotVal(rotVal);
mUIRotVal = rotVal;
mHdmiInfoChange = true;
}
}
return true;
}
bool SecHdmi::setDisplaySize(int width, int height)
{
mDisplayWidth = width;
mDisplayHeight = height;
return true;
}
void SecHdmi::setDisplayInfo(int srcW, int srcH, int srcColorFormat,
unsigned int srcYAddr, unsigned int srcCbAddr,
int dstX, int dstY,
int hdmiLayer,
int num_of_hwc_layer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d",
__func__, srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, dstX, dstY, hdmiLayer);
#endif
mCurrentsrcW = srcW;
mCurrentsrcH = srcH;
mCurrentsrcColorFormat = srcColorFormat;
mCurrentsrcYAddr = srcYAddr;
mCurrentsrcCbAddr = srcCbAddr,
mCurrentdstX = dstX;
mCurrentdstY = dstY;
mCurrenthdmiLayer = hdmiLayer;
mCurrentNumOfHWCLayer = num_of_hwc_layer;
return;
}
bool SecHdmi::m_setupLink(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
int ret;
char node[32];
char subdevname[32];
char videodevname[32];
struct v4l2_capability v4l2cap;
struct media_entity_desc entity_desc;
sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
mMediadevFd = open(node, O_RDWR);
if (mMediadevFd < 0) {
LOGE("%s::open(%s) failed", __func__, node);
goto err;
}
/* open subdev fd */
sprintf(subdevname, PFX_ENTITY_SUBDEV_MIXER, 0);
for (__u32 id = 0; ; id = entity_desc.id) {
entity_desc.id = id | MEDIA_ENT_ID_FLAG_NEXT;
if (ioctl(mMediadevFd, MEDIA_IOC_ENUM_ENTITIES, &entity_desc) < 0) {
if (errno == EINVAL) {
LOGD("%s::MEDIA_IOC_ENUM_ENTITIES ended", __func__);
break;
}
LOGE("%s::MEDIA_IOC_ENUM_ENTITIES failed", __func__);
goto err;
}
LOGD("%s::entity_desc.id=%d, .minor=%d .name=%s", __func__, entity_desc.id, entity_desc.v4l.minor, entity_desc.name);
if (strncmp(entity_desc.name, subdevname, strlen(subdevname)) == 0)
mMixerSubdevEntity = entity_desc.id;
}
mlink_desc.source.entity = mSecGscaler.getSubdevEntity();
mlink_desc.source.index = GSCALER_SUBDEV_PAD_SOURCE;
mlink_desc.source.flags = MEDIA_PAD_FL_SOURCE;
mlink_desc.sink.entity = mMixerSubdevEntity;
mlink_desc.sink.index = MIXER_V_SUBDEV_PAD_SINK;
mlink_desc.sink.flags = MEDIA_PAD_FL_SINK;
mlink_desc.flags = MEDIA_LNK_FL_ENABLED;
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::mlink_desc.source.entity=%02d, .pad=%d", __func__, mlink_desc.source.entity, mlink_desc.source.index);
LOGD("%s::mlink_desc.sink.entity =%02d, .pad=%d", __func__, mlink_desc.sink.entity, mlink_desc.sink.index);
#endif
if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) {
LOGE("%s::MEDIA_IOC_SETUP_LINK [src.entity=%d->sink.entity=%d] failed", __func__, mlink_desc.source.entity, mlink_desc.sink.entity);
goto err;
}
sprintf(node, "%s%d", PFX_NODE_SUBDEV, 4); // Mixer0 minor=132 /dev/v4l-subdev4 // need to modify //carrotsm
mSubdevMixerFd = open(node, O_RDWR, 0);
if (mSubdevMixerFd < 0) {
LOGE("%s::open(%s) failed", __func__, node);
goto err;
}
if (0 < mMediadevFd)
close(mMediadevFd);
mMediadevFd = -1;
return true;
err :
if (0 < mMediadevFd)
close(mMediadevFd);
if (0 < mSubdevMixerFd)
close(mSubdevMixerFd);
mMediadevFd = -1;
mSubdevMixerFd = -1;
return false;
}
bool SecHdmi::m_openLayer(int layer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::layer=%d", __func__, layer);
#endif
char node[32];
switch (layer) {
case HDMI_LAYER_VIDEO:
mVideodevFd[layer] = mSecGscaler.getVideodevFd();
if (0 < mVideodevFd[layer]) {
LOGD("%s::Layer[%d] device already opened", __func__, layer);
return true;
}
if (mSecGscaler.openVideodevFd() == false)
LOGE("%s::open(%s) failed", __func__, node);
else
mVideodevFd[layer] = mSecGscaler.getVideodevFd();
goto open_success;
break;
case HDMI_LAYER_GRAPHIC_0:
sprintf(node, "%s", TVOUT0_DEV_G0);
break;
case HDMI_LAYER_GRAPHIC_1:
sprintf(node, "%s", TVOUT0_DEV_G1);
break;
default:
LOGE("%s::unmatched layer[%d]", __func__, layer);
return false;
break;
}
mVideodevFd[layer] = open(node, O_RDWR);
if (mVideodevFd[layer] < 0) {
LOGE("%s::open(%s) failed", __func__, node);
goto err;
}
open_success :
#ifdef DEBUG_MSG_ENABLE
LOGD("layer=%d, mVideodevFd=%d", layer, mVideodevFd[layer]);
#endif
if (tvout_std_v4l2_querycap(mVideodevFd[layer], node) < 0 ) {
LOGE("%s::tvout_std_v4l2_querycap failed", __func__);
goto err;
}
return true;
err :
if (0 < mVideodevFd[layer])
close(mVideodevFd[layer]);
mVideodevFd[layer] = -1;
return false;
}
bool SecHdmi::m_closeLayer(int layer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::layer=%d", __func__, layer);
#endif
switch (layer) {
case HDMI_LAYER_VIDEO:
mVideodevFd[layer] = mSecGscaler.getVideodevFd();
if (mVideodevFd[layer] < 0) {
LOGD("%s::Layer[%d] device already closed", __func__, layer);
return true;
} else {
mSecGscaler.closeVideodevFd();
mVideodevFd[layer] = mSecGscaler.getVideodevFd();
}
goto close_success;
break;
case HDMI_LAYER_GRAPHIC_0:
case HDMI_LAYER_GRAPHIC_1:
/* clear buffer */
if (0 < mVideodevFd[layer]) {
if (tvout_std_v4l2_reqbuf(mVideodevFd[layer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 0) < 0) {
LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 0);
return -1;
}
}
break;
default:
LOGE("%s::unmatched layer[%d]", __func__, layer);
return false;
break;
}
if (0 < mVideodevFd[layer]) {
if (close(mVideodevFd[layer]) < 0) {
LOGE("%s::close %d layer failed", __func__, layer);
return false;
}
}
mVideodevFd[layer] = -1;
close_success :
return true;
}
bool SecHdmi::m_reset(int w, int h, int dstX, int dstY, int colorFormat, int hdmiLayer, int num_of_hwc_layer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::w=%d, h=%d, dstX=%d, dstY=%d, colorFormat=%d, hdmiLayer=%d, num_of_hwc_layer=%d",
__func__, w, h, dstX, dstY, colorFormat, hdmiLayer, num_of_hwc_layer);
#endif
v4l2_std_id std_id = 0;
int srcW = w;
int srcH = h;
int dstW = 0;
int dstH = 0;
if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) {
LOGE("%s::m_stopHdmi: layer[%d] failed", __func__, hdmiLayer);
return false;
}
if (m_closeLayer(hdmiLayer) == false) {
LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer);
return false;
}
if (m_openLayer(hdmiLayer) == false) {
LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer);
return false;
}
if (w != mSrcWidth[hdmiLayer] ||
h != mSrcHeight[hdmiLayer] ||
mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] ||
mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] ||
num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] ||
colorFormat != mSrcColorFormat[hdmiLayer] ||
mHdmiInfoChange == true) {
int preVideoSrcColorFormat = mSrcColorFormat[hdmiLayer];
int videoSrcColorFormat = colorFormat;
if (preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP &&
preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP &&
preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP &&
preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) {
LOGI("%s: Unsupported preVideoSrcColorFormat = 0x%x", __func__, preVideoSrcColorFormat);
preVideoSrcColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
}
if (hdmiLayer == HDMI_LAYER_VIDEO) {
unsigned int full_wdith = ALIGN(w, 16);
unsigned int full_height = ALIGN(h, 16);
if (mSecGscaler.setSrcParams(full_wdith, full_height, 0, 0,
(unsigned int*)&w, (unsigned int*)&h, colorFormat, true) == false) {
LOGE("%s::mSecGscaler.setSrcParams(w=%d, h=%d, color=%d) failed",
__func__, w, h, colorFormat);
return false;
}
mGscalerDstColorFormat = V4L2_MBUS_FMT_YUV8_1X24;
/* calculate destination buffer width and height */
struct v4l2_rect rect;
if (mUIRotVal == 0 || mUIRotVal == 180) {
hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
} else {
hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect);
}
rect.width = ALIGN(rect.width, 16);
if (mSecGscaler.setDstParams((unsigned int)rect.width, (unsigned int)rect.height, 0, 0,
(unsigned int*)&rect.width, (unsigned int*)&rect.height, mGscalerDstColorFormat, true) == false) {
LOGE("%s::mSecGscaler.setDstParams(w=%d, h=%d, V4L2_MBUS_FMT_YUV8_1X24) failed",
__func__, rect.width, rect.height);
return false;
}
hdmi_set_videolayer(mSubdevMixerFd, mHdmiDstWidth, mHdmiDstHeight, &rect);
} else {
if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer);
return false;
}
if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer);
return false;
}
if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) {
LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, hdmiLayer);
return false;
}
struct v4l2_rect rect;
int tempSrcW, tempSrcH;
int gr_frame_size = 0;
if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) {
tempSrcW = srcW;
tempSrcH = srcH;
} else {
tempSrcW = srcH;
tempSrcH = srcW;
}
hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect);
rect.left = ALIGN(rect.left, 16);
if (num_of_hwc_layer == 0) { /* UI only mode */
hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
colorFormat, srcW, srcH,
rect.left, rect.top, rect.width, rect.height);
dstW = rect.width;
dstH = rect.height;
} else { /* Video Playback + UI Mode */
hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer,
colorFormat, srcW, srcH,
dstX, dstY, mHdmiDstWidth, mHdmiDstHeight);
dstW = mHdmiDstWidth;
dstH = mHdmiDstHeight;
}
#if defined(BOARD_USES_HDMI_FIMGAPI)
gr_frame_size = dstW * dstH;
#else
gr_frame_size = srcW * srcH;
#endif
for (int buf_index = 0; buf_index < MAX_BUFFERS_MIXER; buf_index++) {
int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
switch (v4l2ColorFormat) {
case V4L2_PIX_FMT_BGR32:
case V4L2_PIX_FMT_RGB32:
mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 2;
break;
case V4L2_PIX_FMT_RGB565X:
mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 1;
break;
default:
LOGE("%s::invalid color type", __func__);
return false;
break;
}
}
}
if (preVideoSrcColorFormat != videoSrcColorFormat)
mHdmiInfoChange = true;
mSrcWidth[hdmiLayer] = srcW;
mSrcHeight[hdmiLayer] = srcH;
mSrcColorFormat[hdmiLayer] = colorFormat;
mHdmiResolutionWidth[hdmiLayer] = mHdmiDstWidth;
mHdmiResolutionHeight[hdmiLayer] = mHdmiDstHeight;
mPreviousNumofHwLayer[hdmiLayer] = num_of_hwc_layer;
#ifdef DEBUG_MSG_ENABLE
LOGD("m_reset saved param(%d, %d, %d, %d, %d, %d, %d)",
srcW, mSrcWidth[hdmiLayer], \
srcH, mSrcHeight[hdmiLayer], \
colorFormat,mSrcColorFormat[hdmiLayer], \
hdmiLayer);
#endif
}
if (mHdmiInfoChange == true) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("mHdmiInfoChange: %d", mHdmiInfoChange);
#endif
#if defined(BOARD_USES_CEC)
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (mCECThread->mFlagRunning)
mCECThread->stop();
}
#endif
if (m_setHdmiOutputMode(mHdmiOutputMode) == false) {
LOGE("%s::m_setHdmiOutputMode() failed", __func__);
return false;
}
if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) {
std_id = composite_std_2_v4l2_std_id(mCompositeStd);
if ((int)std_id < 0) {
LOGE("%s::composite_std_2_v4l2_std_id(%d) failed", __func__, mCompositeStd);
return false;
}
if (m_setCompositeResolution(mCompositeStd) == false) {
LOGE("%s::m_setCompositeRsolution() failed", __func__);
return false;
}
} else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (m_setHdmiResolution(mHdmiResolutionValue) == false) {
LOGE("%s::m_setHdmiResolution() failed", __func__);
return false;
}
if (m_setHdcpMode(mHdcpMode) == false) {
LOGE("%s::m_setHdcpMode() failed", __func__);
return false;
}
std_id = mHdmiStdId;
}
if (mPreviousHdmiPresetId != mHdmiPresetId) {
for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) {
if (m_stopHdmi(layer) == false) {
LOGE("%s::m_stopHdmi(%d) failed", __func__, layer);
return false;
}
}
if (tvout_init(mVideodevFd[HDMI_LAYER_GRAPHIC_0], mHdmiPresetId) < 0) {
LOGE("%s::tvout_init(mHdmiPresetId=%d) failed", __func__, mHdmiPresetId);
return false;
}
mPreviousHdmiPresetId = mHdmiPresetId;
}
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
#if defined(BOARD_USES_CEC)
if (!(mCECThread->mFlagRunning))
mCECThread->start();
#endif
/* if (m_setAudioMode(mAudioMode) == false)
LOGE("%s::m_setAudioMode() failed", __func__);
*/
}
mHdmiInfoChange = false;
}
return true;
}
bool SecHdmi::m_streamOn(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
#endif
if (mFlagCreate == false) {
LOGE("%s::Not yet created", __func__);
return false;
}
if (mFlagHdmiStart[hdmiLayer] == true) {
LOGE("%s::[layer=%d] already streamon", __func__, hdmiLayer);
return true;
}
switch(hdmiLayer) {
case HDMI_LAYER_GRAPHIC_0:
break;
case HDMI_LAYER_GRAPHIC_1:
break;
default :
LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
return false;
break;
}
if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][0]) < 0) {
LOGE("%s::gsc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, mSrcIndex[hdmiLayer], 1);
return false;
}
mSrcIndex[hdmiLayer]++;
if (mSrcIndex[hdmiLayer] == MAX_BUFFERS_MIXER) {
if (tvout_std_v4l2_streamon(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
LOGE("%s::gsc_v4l2_stream_on() failed", __func__);
return false;
}
mFlagHdmiStart[hdmiLayer] = true;
}
if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) {
mSrcIndex[hdmiLayer] = 0;
}
return true;
}
bool SecHdmi::m_run(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
#endif
int buf_index = 0;
if (mFlagHdmiStart[hdmiLayer] == false || mFlagLayerEnable[hdmiLayer] == false) {
LOGD("%s::HDMI(%d layer) started not yet", __func__, hdmiLayer);
return true;
}
switch (hdmiLayer) {
case HDMI_LAYER_VIDEO:
if (mSecGscaler.run() == false) {
LOGE("%s::mSecGscaler.draw() failed", __func__);
return false;
}
break;
case HDMI_LAYER_GRAPHIC_0 :
case HDMI_LAYER_GRAPHIC_1 :
if (tvout_std_v4l2_dqbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, &buf_index, 1) < 0) {
LOGE("%s::tvout_std_v4l2_dqbuf(mNumOfBuf : %d, dqIndex=%d) failed", __func__, 1, buf_index);
return false;
}
if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR,
mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]]) < 0) {
LOGE("%s::tvout_std_v4l2_qbuf(mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, 1, mSrcIndex[hdmiLayer]);
return false;
}
mSrcIndex[hdmiLayer]++;
if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) {
mSrcIndex[hdmiLayer] = 0;
}
break;
default :
LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
return false;
break;
}
return true;
}
bool SecHdmi::m_startHdmi(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
#endif
int buf_index = 0;
if (mFlagHdmiStart[hdmiLayer] == true) {
LOGD("%s::already HDMI(%d layer) started..", __func__, hdmiLayer);
return true;
}
#ifdef DEBUG_MSG_ENABLE
LOGD("### %s: hdmiLayer(%d) called", __func__, hdmiLayer);
#endif
switch (hdmiLayer) {
case HDMI_LAYER_VIDEO:
if (mSecGscaler.streamOn() == false) {
LOGE("%s::mSecGscaler.streamOn() failed", __func__);
return false;
}
if (mSecGscaler.getFlagSteamOn() == true)
mFlagHdmiStart[hdmiLayer] = true;
break;
case HDMI_LAYER_GRAPHIC_0 :
case HDMI_LAYER_GRAPHIC_1 :
if (m_streamOn(hdmiLayer) == false) {
LOGE("%s::m_streamOn layer(%d) failed", __func__, hdmiLayer);
return false;
}
break;
default :
LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
return false;
break;
}
return true;
}
bool SecHdmi::m_stopHdmi(int hdmiLayer)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer);
#endif
if (mFlagHdmiStart[hdmiLayer] == false) {
LOGD("%s::already HDMI(%d layer) stopped..", __func__, hdmiLayer);
return true;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s : layer[%d] called", __func__, hdmiLayer);
#endif
switch (hdmiLayer) {
case HDMI_LAYER_VIDEO:
if (mSecGscaler.streamOff() == false) {
LOGE("%s::mSecGscaler.streamOff() failed", __func__);
return false;
}
mFlagHdmiStart[hdmiLayer] = false;
break;
case HDMI_LAYER_GRAPHIC_1 :
case HDMI_LAYER_GRAPHIC_0 :
#if defined(BOARD_USES_HDMI_FIMGAPI)
cur_g2d_address = 0;
#endif
if (tvout_std_v4l2_streamoff(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
LOGE("%s::tvout_std_v4l2_streamon layer(%d) failed", __func__, hdmiLayer);
return false;
}
mSrcIndex[hdmiLayer] = 0;
mFlagHdmiStart[hdmiLayer] = false;
break;
default :
LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer);
return false;
break;
}
return true;
}
bool SecHdmi::m_setHdmiOutputMode(int hdmiOutputMode)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
if (hdmiOutputMode == mCurrentHdmiOutputMode) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode);
#endif
return true;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode);
if (v4l2OutputType < 0) {
LOGE("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode);
return false;
}
output_type = v4l2OutputType;
mCurrentHdmiOutputMode = hdmiOutputMode;
return true;
}
bool SecHdmi::m_setCompositeResolution(unsigned int compositeStdId)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
int w = 0;
int h = 0;
if (mHdmiOutputMode != COMPOSITE_OUTPUT_MODE) {
LOGE("%s::not supported output type \n", __func__);
return false;
}
switch (compositeStdId) {
case COMPOSITE_STD_NTSC_M:
case COMPOSITE_STD_NTSC_443:
w = 704;
h = 480;
break;
case COMPOSITE_STD_PAL_BDGHI:
case COMPOSITE_STD_PAL_M:
case COMPOSITE_STD_PAL_N:
case COMPOSITE_STD_PAL_Nc:
case COMPOSITE_STD_PAL_60:
w = 704;
h = 576;
break;
default:
LOGE("%s::unmathced composite_std(%d)", __func__, compositeStdId);
return false;
}
t_std_id = composite_std_2_v4l2_std_id(mCompositeStd);
mHdmiDstWidth = w;
mHdmiDstHeight = h;
mCurrentHdmiResolutionValue = -1;
return true;
}
bool SecHdmi::m_setHdmiResolution(unsigned int hdmiResolutionValue)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
if (hdmiResolutionValue == mCurrentHdmiResolutionValue) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue);
#endif
return true;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
int w = 0;
int h = 0;
v4l2_std_id std_id;
if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR &&
mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) {
if (hdmi_resolution_2_std_id(hdmiResolutionValue, &w, &h, &std_id, &mHdmiPresetId) < 0) {
LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue);
return false;
}
mHdmiStdId = std_id;
} else {
LOGE("%s::not supported output type \n", __func__);
return false;
}
t_std_id = std_id;
mHdmiDstWidth = w;
mHdmiDstHeight = h;
mCurrentHdmiResolutionValue = hdmiResolutionValue;
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiStdId = 0x%x, hdmiResolutionValue = 0x%x\n",
__func__,
mHdmiDstWidth,
mHdmiDstHeight,
mHdmiStdId,
hdmiResolutionValue);
#endif
return true;
}
bool SecHdmi::m_setHdcpMode(bool hdcpMode)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
if (hdcpMode == mCurrentHdcpMode) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode);
#endif
return true;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
if (hdcpMode == true)
g_hdcp_en = 1;
else
g_hdcp_en = 0;
mCurrentHdcpMode = hdcpMode;
return true;
}
bool SecHdmi::m_setAudioMode(int audioMode)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
if (audioMode == mCurrentAudioMode) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::same audioMode(%d) \n", __func__, audioMode);
#endif
return true;
}
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
if (hdmi_check_audio(mVideodevFd[HDMI_LAYER_GRAPHIC_0]) < 0) {
LOGE("%s::hdmi_check_audio() fail \n", __func__);
return false;
}
mCurrentAudioMode = audioMode;
return true;
}
int SecHdmi::m_resolutionValueIndex(unsigned int ResolutionValue)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
int index = -1;
for (int i = 0; i < mHdmiSizeOfResolutionValueList; i++) {
if (mHdmiResolutionValueList[i] == ResolutionValue) {
index = i;
break;
}
}
return index;
}
bool SecHdmi::m_flagHWConnected(void)
{
#ifdef DEBUG_MSG_ENABLE
LOGD("%s", __func__);
#endif
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("### %s called\n", __func__);
#endif
bool ret = true;
int hdmiStatus = hdmi_cable_status();
if (hdmiStatus <= 0) {
#ifdef DEBUG_HDMI_HW_LEVEL
LOGD("%s::hdmi_cable_status() fail \n", __func__);
#endif
ret = false;
} else {
ret = true;
}
return ret;
}
}; // namespace android