Files
2026-08-24 10:03:24 +08:00

424 lines
11 KiB
C++

/*
* Copyright (c) 2014 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description: c++ file
*/
#define LOG_MODULE_TAG "TV"
#define LOG_CLASS_TAG "CHDMIRxManager"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "CHDMIRxManager.h"
#include "tvutils.h"
#include "CTvin.h"
#include "CTvLog.h"
CHDMIRxManager::CHDMIRxManager()
{
mHdmiRxDeviceId = HDMIRxOpenMoudle();
HdmiEnableSPDFifo(true);
}
CHDMIRxManager::~CHDMIRxManager()
{
HDMIRxCloseMoudle();
}
int CHDMIRxManager::HDMIRxOpenMoudle()
{
int fd = open ( CS_HDMIRX_DEV_PATH, O_RDWR );
if ( fd < 0 ) {
LOGE("Open %s error(%s)!\n", CS_HDMIRX_DEV_PATH, strerror ( errno ));
return -1;
}
return fd;
}
int CHDMIRxManager::HDMIRxCloseMoudle()
{
if ( mHdmiRxDeviceId != -1 ) {
close ( mHdmiRxDeviceId );
mHdmiRxDeviceId = -1;
}
return 0;
}
int CHDMIRxManager::HDMIRxDeviceIOCtl(int request, ...)
{
int ret = -1;
va_list ap;
void *arg;
va_start ( ap, request );
arg = va_arg ( ap, void *);
va_end ( ap );
ret = ioctl(mHdmiRxDeviceId, request, arg);
return ret;
}
int CHDMIRxManager::HdmiRxEdidDataSwitch(int edidBinCount, char *data)
{
int ret = 0;
if (data == NULL) {
LOGE("%s: edid data is null!\n", __FUNCTION__);
ret = -1;
} else {
int edidDataCount = edidBinCount * REAL_EDID_DATA_SIZE;
unsigned char loadData[edidDataCount];
memset(loadData, 0, edidDataCount);
int LoadConut = 0;
if (edidBinCount == 1) {
loadData[0] = 'E';
loadData[1] = 'D';
loadData[2] = 'I';
loadData[3] = 'D';
memcpy(loadData + 4, data, edidDataCount);
LoadConut = (edidDataCount + 4);
} else {
memcpy(loadData, data, edidDataCount);
LoadConut = edidDataCount;
}
int dev_fd = open(HDMI_EDID_DEV_PATH, O_RDWR);
if (dev_fd < 0) {
LOGE("open edid file ERROR(%s)!!\n", strerror(errno));
ret = -1;
} else {
if (write(dev_fd, data, LoadConut) < 0) {
LOGE("write edid file ERROR(%s)!!\n", strerror(errno));
ret = -1;
}
close(dev_fd);
dev_fd = -1;
if (edidBinCount == 1) {
HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE);
ret = 0;
}
}
}
return ret;
}
int CHDMIRxManager::GetHdmiRxLoadEdidType(int file14Size, int file21Size, int file20Size) {
int ret = TV_EDID_TYPE_256_PLUS_512;
if (file14Size == 256) {
if (file21Size ==256) {
if (file20Size == 256) {
ret = TV_EDID_TYPE_256_PLUS_256_PLUS_256;
} else {
ret = TV_EDID_TYPE_256_PLUS_256;
}
} else if (file21Size == 512) {
if (file20Size == 512) {
ret = TV_EDID_TYPE_256_PLUS_512_PLUS_512;
} else if (file20Size == 256) {
ret = TV_EDID_TYPE_256_PLUS_512_PLUS_256;
} else {
ret = TV_EDID_TYPE_256_PLUS_512;
}
}
} else if (file14Size == 512) {
if (file21Size == 512) {
ret = TV_EDID_TYPE_512_PLUS_512;
}
}
return ret;
}
int CHDMIRxManager::HdmiRxLoadEdidDataWithPort(int port, int type, int dataSize, unsigned char dataBuf[]) {
int ret = -1;
LOGD("%s: port:%d, type:%d, dataSize:%d!\n", __FUNCTION__, port, type, dataSize);
int size = dataSize + 1;
unsigned char LoadBuf[size];
memset(LoadBuf, 0, sizeof(char) * size);
LoadBuf[0] = (unsigned char)(type << 4|port);
LOGD("%s: LoadBuf[0]:%#x!\n", __FUNCTION__, LoadBuf[0]);
memcpy(LoadBuf+1, dataBuf, dataSize);
int devFd = open(HDMI_EDID_DATA_DEV_PATH, O_RDWR);
if (devFd < 0) {
LOGE("%s: open ERROR(%s)!\n", __FUNCTION__, strerror(errno));
ret = -1;
} else {
if (write(devFd, LoadBuf, size) < 0) {
LOGE("%s: write ERROR(%s)!\n", __FUNCTION__, strerror(errno));
ret = -1;
} else {
ret = 0;
}
close(devFd);
devFd = -1;
}
return ret;
}
int CHDMIRxManager::HdmiRxEdidUpdateWithPort(int port)
{
LOGD("%s, port is %d!\n", __FUNCTION__, port);
unsigned char parm = port;
int tmp_ret = HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE_WITH_PORT, &parm);
if (tmp_ret < 0) {
LOGE("%s, port:%d, error: (%s)!\n", __FUNCTION__, port, strerror ( errno ));
}
return 0;
}
int CHDMIRxManager::HdmiRxEdidVerSwitch(int verValue)
{
LOGD("%s: new all edid version: 0x%x\n", __FUNCTION__, verValue);
int ret = -1;
int devFd = open(HDMI_EDID_VERSION_DEV_PATH, O_RDWR);
if (devFd < 0) {
LOGE("%s: open %s ERROR(%s)!!\n", __FUNCTION__, HDMI_EDID_VERSION_DEV_PATH, strerror(errno));
ret = -1;
} else {
char tmp[32] = {0};
sprintf(tmp, "%x", verValue);
if (write(devFd, tmp, strlen(tmp)) < 0) {
LOGE("%s, write %s ERROR(%s)!!\n", __FUNCTION__, HDMI_EDID_VERSION_DEV_PATH, strerror(errno));
ret = -1;
} else {
ret = 0;
}
close(devFd);
devFd = -1;
}
//HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE);
return ret;
}
int CHDMIRxManager::HdmiRxHdcpVerSwitch(tv_hdmi_hdcp_version_t version)
{
int ret = -1;
if (HDMI_HDCP_VER_14 == version) {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_HDCP22_FORCE14);
} else if (HDMI_HDCP_VER_22 == version) {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_HDCP22_AUTO);
} else {
LOGE("invalid hdcp version!\n");
return -1;
}
return ret;
}
int CHDMIRxManager::HdmiRxHdcpOnOff(tv_hdmi_hdcpkey_enable_t flag)
{
int ret = -1;
if (hdcpkey_enable == flag) {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_HDCP_ON);
}else if (hdcpkey_disable == flag) {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_HDCP_OFF);
}else {
LOGE("invalid hdcp enable status!\n");
return -1;
}
return ret;
}
int CHDMIRxManager::GetHdmiHdcpKeyKsvInfo(struct _hdcp_ksv *msg)
{
return HDMIRxDeviceIOCtl(HDMI_IOC_HDCP_GET_KSV, msg);
}
int CHDMIRxManager::CalHdmiPortCecPhysicAddr()
{
tv_source_input_t tmpHdmiPortCecPhysicAddr[4] = {SOURCE_MAX};
tvin_port_t tvInport[4] = {TVIN_PORT_HDMI0,TVIN_PORT_HDMI1,TVIN_PORT_HDMI2,TVIN_PORT_HDMI3};
int HdmiPortCecPhysicAddr = 0x0;
for (int i = 0; i < 4; i++) {
tmpHdmiPortCecPhysicAddr[i] = CTvin::getInstance()->Tvin_PortToSourceInput(tvInport[i]);
}
HdmiPortCecPhysicAddr |= ((tmpHdmiPortCecPhysicAddr[0] == SOURCE_MAX? 0xf:(tmpHdmiPortCecPhysicAddr[0]-4))
|((tmpHdmiPortCecPhysicAddr[1] == SOURCE_MAX? 0xf:(tmpHdmiPortCecPhysicAddr[1]-4)) << 4)
|((tmpHdmiPortCecPhysicAddr[2] == SOURCE_MAX? 0xf:(tmpHdmiPortCecPhysicAddr[2]-4)) << 8)
|((tmpHdmiPortCecPhysicAddr[3] == SOURCE_MAX? 0xf:(tmpHdmiPortCecPhysicAddr[3]-4)) << 12));
LOGD("hdmi port map: 0x%x\n", HdmiPortCecPhysicAddr);
return HdmiPortCecPhysicAddr;
}
int CHDMIRxManager::SetHdmiPortCecPhysicAddr()
{
char buf[10] = {0};
int val = CalHdmiPortCecPhysicAddr();
sprintf(buf, "%x", val);
tvWriteSysfs(HDMI_CEC_PORT_SEQUENCE, buf);
memset(buf, 0, sizeof(buf));
sprintf(buf, "%d", val);
tvWriteSysfs(HDMI_CEC_PORT_MAP,buf);
return 0;
}
int CHDMIRxManager::UpdataEdidDataWithPort(int port, unsigned char *dataBuf)
{
int ret = -1;
int size = REAL_EDID_DATA_SIZE + 1;
unsigned char LoadBuf[size];
memset(LoadBuf, 0, sizeof(char) * size);
LoadBuf[0] = (unsigned char)port;
memcpy(LoadBuf+1, dataBuf, REAL_EDID_DATA_SIZE);
/*LOGD("%s: edid data print start.\n", __FUNCTION__);
for (int i=0;i<257;i++) {
printf("0x%x ",LoadBuf[i]);
}
LOGD("%s: edid data print end.\n", __FUNCTION__);*/
int devFd = open(HDMI_EDID_DATA_DEV_PATH, O_RDWR);
if (devFd < 0) {
LOGE("%s: open ERROR(%s)!\n", __FUNCTION__, strerror(errno));
ret = -1;
} else {
if (write(devFd, LoadBuf, size) < 0) {
LOGE("%s: write ERROR(%s)!\n", __FUNCTION__, strerror(errno));
ret = -1;
} else {
ret = 0;
}
close(devFd);
devFd = -1;
}
if (ret >= 0) {
LOGD("%s: would update edid.\n", __FUNCTION__);
HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE);
}
return ret;
}
int CHDMIRxManager::HdmiEnableSPDFifo(bool enable)
{
unsigned int pkttype = 0x83;
int ret = -1;
//has been abort
/*
if (enable) {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_PD_FIFO_PKTTYPE_EN, &pkttype);
} else {
ret = HDMIRxDeviceIOCtl(HDMI_IOC_PD_FIFO_PKTTYPE_DIS, &pkttype);
}
*/
return ret;
}
int CHDMIRxManager::HdmiRxGetSPDInfoframe(struct spd_infoframe_st* spd)
{
int ret = -1;
struct spd_infoframe_st pd;
ret = HDMIRxDeviceIOCtl(HDMI_IOC_GET_SPD_SRC_INFO, &pd);
if (ret < 0) {
LOGE("Get SPD infoframe via ioctl failed: %s.\n", strerror(errno));
} else {
memcpy(spd, &pd, sizeof(struct spd_infoframe_st));
}
return ret;
}
void CHDMIRxManager::SetHDMIFeatureInit(int allmEnable, int VrrEnable, int QmsEnable)
{
char buf[8] = {0};
sprintf(buf, "%d", allmEnable);
tvWriteSysfs(HDMI_SET_ALLM_PARAM, buf);
sprintf(buf, "%d", VrrEnable);
tvWriteSysfs(HDMI_VRR_ENABLED, buf);
sprintf(buf, "%d", QmsEnable);
tvWriteSysfs(QMS_FUNC_CTRL_PATH, buf);
}
int CHDMIRxManager::SetAllmEnabled(bool enable)
{
int ret = 0;
char buf[8] = {0};
sprintf(buf, "%d", enable);
tvWriteSysfs(HDMI_SET_ALLM_PARAM, buf);
//ret = HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE);
for (int i=TVIN_PORT_ID_1;i<TVIN_PORT_ID_MAX;i++) {
HdmiRxEdidUpdateWithPort(i);
}
return ret;
}
bool CHDMIRxManager::GetAllmEnabled()
{
char buf[32] = {0};
tvReadSysfs(HDMI_SET_ALLM_PARAM, buf);
int num;
if (sscanf(buf, "%*[^:]:%d", &num) == 1) {
return num > 0;
}
return false;
}
int CHDMIRxManager::SetVrrEnabled(bool enable)
{
int ret = 0;
char buf[8] = {0};
sprintf(buf, "%d", enable);
tvWriteSysfs(HDMI_VRR_ENABLED, buf);
//ret = HDMIRxDeviceIOCtl(HDMI_IOC_EDID_UPDATE);
for (int i=TVIN_PORT_ID_1;i<TVIN_PORT_ID_MAX;i++) {
HdmiRxEdidUpdateWithPort(i);
}
return ret;
}
bool CHDMIRxManager::GetVrrEnabled()
{
char buf[32] = {0};
tvReadSysfs(HDMI_VRR_ENABLED, buf);
int num;
if (sscanf(buf, "%*[^:]:%d", &num) == 1) {
return num > 0;
}
return false;
}
int CHDMIRxManager::SetQmsEnabled(bool enable)
{
int ret = 0;
char buf[8] = {0};
sprintf(buf, "%d", enable);
tvWriteSysfs(QMS_FUNC_CTRL_PATH, buf);
for (int i=TVIN_PORT_ID_1;i<TVIN_PORT_ID_MAX;i++) {
HdmiRxEdidUpdateWithPort(i);
}
return ret;
}
bool CHDMIRxManager::GetQmsEnabled()
{
char buf[32] = {0};
tvReadSysfs(QMS_FUNC_CTRL_PATH, buf);
int num;
if (sscanf(buf, "%*[^:]:%d", &num) == 1) {
return num > 0;
}
return false;
}