blob: 3835dfa5c72047b1f46a5575eb02d674a088c354 [file] [log] [blame]
/*
* Copyright (c) 2023 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:
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <linux/string.h>
#include "libdrm_meson_connector.h"
#include "libdrm_meson_property.h"
#include "meson_drm_settings.h"
#include "meson_drm_log.h"
#include "meson_drm.h"
#define DEFAULT_CARD "/dev/dri/card0"
#define PROP_NAME_MAX_LEN 50
static int meson_drm_get_crtc_prop_value( int drmFd, MESON_CONNECTOR_TYPE connType,
char* name, uint32_t* prop_value );
static int meson_drm_get_conn_prop_value( int drmFd, MESON_CONNECTOR_TYPE connType,
char* name, uint32_t* propValue );
static int meson_drm_get_prop_value(int drmFd, MESON_CONNECTOR_TYPE connType,
uint32_t objType, char* name, uint32_t* propValue );
static struct mesonConnector* get_current_connector(int drmFd, MESON_CONNECTOR_TYPE connType);
static struct mesonConnector* get_default_connector(int drmFd);
static int meson_drm_set_property(int drmFd, drmModeAtomicReq *req, uint32_t objId,
uint32_t objType, char* name, uint64_t value);
static int meson_drm_get_prop_value(int drmFd, MESON_CONNECTOR_TYPE connType, uint32_t objType, char* name, uint32_t* propValue )
{
int ret = -1;
int objID = -1;
struct mesonConnector* conn = NULL;
if ( drmFd < 0 || name == NULL || propValue == NULL)
{
ERROR(" %s %d drmfd invalid, or property name invalid",__FUNCTION__,__LINE__);
goto out;
}
conn = get_current_connector(drmFd, connType);
if ( conn == NULL )
{
ERROR("%s %d get_current_connector fail",__FUNCTION__,__LINE__);
goto out;
}
objID = mesonConnectorGetId(conn);
if (objType == DRM_MODE_OBJECT_CRTC)
objID = mesonConnectorGetCRTCId(conn);
struct mesonProperty* meson_prop = NULL;
meson_prop = mesonPropertyCreate(drmFd, objID, objType, name);
if (!meson_prop) {
ERROR("%s %d meson_prop create fail",__FUNCTION__,__LINE__);
goto out;
}
uint64_t value = mesonPropertyGetValue(meson_prop);
*propValue = (uint32_t)value;
DEBUG("%s %d prop value:%llu objID:%d,name:%s",__FUNCTION__,__LINE__,value, objID,name);
mesonPropertyDestroy(meson_prop);
ret = 0;
out:
if (conn)
mesonConnectorDestroy(drmFd,conn);
return ret;
}
static int meson_drm_get_conn_prop_value( int drmFd, MESON_CONNECTOR_TYPE conn_type, char* name, uint32_t* prop_value )
{
return meson_drm_get_prop_value( drmFd, conn_type, DRM_MODE_OBJECT_CONNECTOR, name, prop_value );
}
static int meson_drm_get_crtc_prop_value( int drmFd, MESON_CONNECTOR_TYPE conn_type, char* name, uint32_t* prop_value )
{
return meson_drm_get_prop_value( drmFd, conn_type, DRM_MODE_OBJECT_CRTC, name, prop_value );
}
static struct mesonConnector* get_current_connector(int drmFd, MESON_CONNECTOR_TYPE connType)
{
struct mesonConnector* connector = NULL;
int drmConnType = DRM_MODE_CONNECTOR_HDMIA;
if (drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return NULL;
}
switch (connType)
{
case MESON_CONNECTOR_HDMIA:
drmConnType = DRM_MODE_CONNECTOR_HDMIA;
break;
case MESON_CONNECTOR_HDMIB:
drmConnType = DRM_MODE_CONNECTOR_HDMIB;
break;
case MESON_CONNECTOR_LVDS:
drmConnType = DRM_MODE_CONNECTOR_LVDS;
break;
case MESON_CONNECTOR_CVBS:
drmConnType = DRM_MODE_CONNECTOR_TV;
break;
case MESON_CONNECTOR_DUMMY:
drmConnType = DRM_MODE_CONNECTOR_VIRTUAL;
break;
default :
drmConnType = DRM_MODE_CONNECTOR_HDMIA;
break;
}
connector = mesonConnectorCreate(drmFd, drmConnType);
return connector;
}
int meson_open_drm()
{
int ret_fd = -1;
const char *card;
int ret = -1;
card= getenv("WESTEROS_DRM_CARD");
if ( !card ) {
card = DEFAULT_CARD;
}
ret_fd = open(card, O_RDONLY|O_CLOEXEC);
if ( ret_fd < 0 )
ERROR("%s %d drm card:%s open fail",__FUNCTION__,__LINE__,card);
else
drmDropMaster(ret_fd);
ret = drmSetClientCap(ret_fd, DRM_CLIENT_CAP_ATOMIC, 1);
if (ret < 0)
DEBUG("%s %d Unable to set DRM atomic capability",__FUNCTION__,__LINE__);
ret = drmSetClientCap(ret_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
if (ret < 0)
DEBUG("%s %d Unable to set UNIVERSAL_PLANES",__FUNCTION__,__LINE__);
return ret_fd;
}
void meson_close_drm(int drmFd)
{
if (drmFd >= 0)
close(drmFd);
}
static int meson_drm_set_property(int drmFd, drmModeAtomicReq *req, uint32_t objId,
uint32_t objType, char* name, uint64_t value)
{
uint32_t propId;
int rc = -1;
if (drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return rc;
}
struct mesonProperty *prop = NULL;
prop = mesonPropertyCreate(drmFd, objId, objType, name);
propId = mesonPropertyGetId(prop);
mesonPropertyDestroy(prop);
DEBUG("%s %d name:%s objId:%d propId:%d value:%llu", __FUNCTION__,__LINE__,name, objId, propId, value);
rc = drmModeAtomicAddProperty( req, objId, propId, value );
if (rc < 0)
ERROR("%s %d drmModeAtomicAddProperty fail",__FUNCTION__,__LINE__);
return rc;
}
int meson_drm_getPreferredMode( DisplayMode* mode, MESON_CONNECTOR_TYPE connType) {
int ret = -1;
int i = 0;
int count = 0;
drmModeModeInfo* modes = NULL;
int drmFd = -1;
struct mesonConnector* conn = NULL;
drmFd = meson_open_drm();
conn = get_current_connector(drmFd, connType);
if (conn == NULL || drmFd < 0)
{
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
}
if (0 != mesonConnectorGetModes(conn, drmFd, &modes, &count))
goto out;
for (i = 0; i < count; i++)
{
if (modes[i].type & DRM_MODE_TYPE_PREFERRED)
{
mode->w = modes[i].hdisplay;
mode->h = modes[i].vdisplay;
mode->interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
strcpy(mode->name, modes[i].name );
break;
}
}
ret = 0;
out:
if (conn)
mesonConnectorDestroy(drmFd,conn);
if (drmFd >= 0 )
close(drmFd);
DEBUG("%s %d get preferred mode%s %dx%d%s%dhz",__FUNCTION__,__LINE__, mode->name, mode->w, mode->h, (mode->interlace == 0? "p":"i"),mode->vrefresh);
return ret;
}
int meson_drm_getsupportedModesList(int drmFd, DisplayMode** modeInfo, int* modeCount,MESON_CONNECTOR_TYPE connType )
{
int ret = -1;
struct mesonConnector* conn = NULL;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn == NULL || drmFd < 0)
{
ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
}
drmModeModeInfo* modeall = NULL;
int count = 0;
int i = 0;
if (0 != mesonConnectorGetModes(conn, drmFd, &modeall, &count))
goto out;
DisplayMode* modestemp = (DisplayMode*)calloc(count, sizeof(DisplayMode));
for (i = 0; i < count; i++)
{
modestemp[i].w = modeall[i].hdisplay;
modestemp[i].h = modeall[i].vdisplay;
modestemp[i].vrefresh = modeall[i].vrefresh;
modestemp[i].interlace = (modeall[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
strcpy(modestemp[i].name, modeall[i].name );
}
*modeCount = count;
*modeInfo = modestemp;
ret = 0;
out:
if (conn)
mesonConnectorDestroy(drmFd,conn);
DEBUG("%s %d mode count: %d",__FUNCTION__,__LINE__,(*modeCount));
for (int i=0; i < (*modeCount); i++) {
DEBUG_EDID(" %s %dx%d%s%dhz\n", (*modeInfo)[i].name, (*modeInfo)[i].w, (*modeInfo)[i].h, ((*modeInfo)[i].interlace == 0? "p":"i"), (*modeInfo)[i].vrefresh);
}
return ret;
}
struct mesonConnector* get_default_connector(int drmFd)
{
struct mesonConnector* connectorHDMI = NULL;
struct mesonConnector* connectorLVDS = NULL;
struct mesonConnector* connectorCVBS = NULL;
int HDMIconnected = 0;
int LVDSConnected = 0;
int CVBSConnected = 0;
connectorHDMI = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
if (connectorHDMI)
HDMIconnected = mesonConnectorGetConnectState(connectorHDMI);
if (HDMIconnected == 1) {
return connectorHDMI;
} else {
mesonConnectorDestroy(drmFd,connectorHDMI);
connectorLVDS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_LVDS);
if (connectorLVDS)
LVDSConnected = mesonConnectorGetConnectState(connectorLVDS);
if (LVDSConnected == 1) {
return connectorLVDS;
} else {
mesonConnectorDestroy(drmFd,connectorLVDS);
connectorCVBS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_TV);
if (connectorCVBS)
CVBSConnected = mesonConnectorGetConnectState(connectorCVBS);
if (CVBSConnected == 1) {
return connectorCVBS;
} else {
mesonConnectorDestroy(drmFd, connectorCVBS);
return NULL;
}
}
}
}
int meson_drm_getModeInfo(int drmFd, MESON_CONNECTOR_TYPE connType, DisplayMode* modeInfo)
{
int ret = -1;
struct mesonConnector* conn = NULL;
drmModeModeInfo* mode = NULL;
if (modeInfo == NULL || drmFd < 0) {
ERROR("%s %d modeInfo == NULL || drmFd < 0 return",__FUNCTION__,__LINE__);
return ret;
}
if ( connType == MESON_CONNECTOR_RESERVED ) {
conn = get_default_connector(drmFd);
DEBUG("%s %d get default connector",__FUNCTION__,__LINE__);
} else {
conn = get_current_connector(drmFd, connType);
DEBUG("%s %d get current connector",__FUNCTION__,__LINE__);
}
if ( conn ) {
mode = mesonConnectorGetCurMode(drmFd, conn);
if (mode) {
modeInfo->w = mode->hdisplay;
modeInfo->h = mode->vdisplay;
modeInfo->vrefresh = mode->vrefresh;
modeInfo->interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
strcpy(modeInfo->name, mode->name);
free(mode);
mode = NULL;
ret = 0;
} else {
ERROR(" %s %d mode get fail ",__FUNCTION__,__LINE__);
}
} else {
ERROR("%s %d conn create fail ",__FUNCTION__,__LINE__);
}
if (conn)
mesonConnectorDestroy(drmFd,conn);
DEBUG("%s %d modeInfo %dx%d%s%dhz",__FUNCTION__,__LINE__, modeInfo->w, modeInfo->h, (modeInfo->interlace == 0 ?"p":"i"), modeInfo->vrefresh);
return ret;
}
int meson_drm_changeMode(int drmFd, drmModeAtomicReq *req, DisplayMode* modeInfo, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
struct mesonConnector* conn = NULL;
drmModeModeInfo drm_mode;
int i;
bool interlace = false;
bool found = false;
int rc = -1;
int rc1 = -1;
int rc2 = -1;
int rc3 = -1;
uint32_t connId;
uint32_t crtcId;
uint32_t blobId = 0;
drmModeModeInfo* modes = NULL;
int modesNumber = 0;
DEBUG("%s %d set modeInfo %dx%d%s%dhz connType %d",__FUNCTION__,__LINE__, modeInfo->w, modeInfo->h, (modeInfo->interlace == 0? "p":"i") , modeInfo->vrefresh,connType);
if (modeInfo == NULL || drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (connType == MESON_CONNECTOR_CVBS)
{
struct mesonConnector* connHDMI = NULL;
uint32_t HDMIconnId;
int rc4 = -1;
connHDMI = get_current_connector(drmFd, MESON_CONNECTOR_HDMIA);
HDMIconnId = mesonConnectorGetId(connHDMI);
rc4 = meson_drm_set_property(drmFd, req, HDMIconnId, DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", 0);
mesonConnectorDestroy(drmFd,connHDMI);
DEBUG(" %s %d change mode to cvbs, disconnect HDMI :%d ",__FUNCTION__,__LINE__,rc4);
}
conn = get_current_connector(drmFd, connType);
connId = mesonConnectorGetId(conn);
crtcId = mesonConnectorGetCRTCId(conn);
if ( conn ) {
DEBUG("%s %d conn create success",__FUNCTION__,__LINE__);
mesonConnectorGetModes(conn, drmFd, &modes, &modesNumber);
for ( i = 0; i < modesNumber; i++ ) {
interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE);
if ( (modeInfo->w == modes[i].hdisplay)
&& (modeInfo->h == modes[i].vdisplay)
&& (modeInfo->vrefresh == modes[i].vrefresh)
&& (interlace == modeInfo->interlace)
) {
drm_mode = modes[i];
found = true;
break;
}
}
} else {
ERROR(" %s %d conn create fail ",__FUNCTION__,__LINE__);
}
if (found) {
DEBUG("%s %d find the corresponding modeinfo",__FUNCTION__,__LINE__);
rc1 = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", crtcId);
rc = drmModeCreatePropertyBlob( drmFd, &drm_mode, sizeof(drm_mode), &blobId );
if (rc == 0) {
rc2 = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC, "MODE_ID", blobId);
rc3 = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC, "ACTIVE", 1);
DEBUG("%s %d rc1:%d rc:%d rc2:%d, rc3:%d",__FUNCTION__,__LINE__, rc1, rc,rc2,rc3);
if (rc1 >= 0 && rc2 >= 0 && rc3 >= 0)
ret = 0;
}
}
if (conn)
mesonConnectorDestroy(drmFd,conn);
return ret;
}
ENUM_MESON_CONN_CONNECTION meson_drm_getConnectionStatus(int drmFd, MESON_CONNECTOR_TYPE connType)
{
ENUM_MESON_CONN_CONNECTION ret = MESON_UNKNOWNCONNECTION;
struct mesonConnector* conn = NULL;
if ( drmFd < 0) {
ERROR( "%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn) {
DEBUG("%s %d conn create success",__FUNCTION__,__LINE__);
int ConnectState = -1;
ConnectState = mesonConnectorGetConnectState(conn);
if (ConnectState == 1) {
ret = MESON_CONNECTED;
} else if (ConnectState == 2) {
ret = MESON_DISCONNECTED;
} else {
ret = MESON_UNKNOWNCONNECTION;
}
} else {
ERROR(" %s %d conn create fail ",__FUNCTION__,__LINE__);
}
if (conn)
mesonConnectorDestroy(drmFd,conn);
DEBUG("%s %d get Connection Status %d",__FUNCTION__,__LINE__,ret);
return ret;
}
ENUM_MESON_COLOR_SPACE meson_drm_getColorSpace(int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_COLOR_SPACE);
uint32_t value = 0;
ENUM_MESON_COLOR_SPACE colorSpace = MESON_COLOR_SPACE_RESERVED;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return colorSpace;
}
if ( 0 == meson_drm_get_conn_prop_value(drmFd, connType, propName, &value )) {
switch (value)
{
case 0:
colorSpace = MESON_COLOR_SPACE_RGB;
break;
case 1:
colorSpace = MESON_COLOR_SPACE_YCBCR422;
break;
case 2:
colorSpace = MESON_COLOR_SPACE_YCBCR444;
break;
case 3:
colorSpace = MESON_COLOR_SPACE_YCBCR420;
break;
default:
colorSpace = MESON_COLOR_SPACE_RESERVED;
break;
}
} else {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get ColorSpace %d",__FUNCTION__,__LINE__,colorSpace);
return colorSpace;
}
int meson_drm_setColorSpace(int drmFd, drmModeAtomicReq *req,
ENUM_MESON_COLOR_SPACE colorSpace, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
uint32_t connId = 0;
int rc = -1;
struct mesonConnector* conn = NULL;
if ( drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn) {
DEBUG("%s %d conn create success",__FUNCTION__,__LINE__);
connId = mesonConnectorGetId(conn);
rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
DRM_CONNECTOR_PROP_COLOR_SPACE, (uint64_t)colorSpace);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG(" %s %d set colorSpace: %d",__FUNCTION__,__LINE__,colorSpace);
return ret;
}
uint32_t meson_drm_getColorDepth( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_COLOR_DEPTH);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get ColorDepth %d",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_setColorDepth(int drmFd, drmModeAtomicReq *req,
uint32_t colorDepth, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t connId = 0;
conn = get_current_connector(drmFd, connType);
if ( drmFd < 0 || req == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
connId = mesonConnectorGetId(conn);
rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
DRM_CONNECTOR_PROP_COLOR_DEPTH, (uint64_t)colorDepth);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG(" %s %d set colorDepth: %d",__FUNCTION__,__LINE__,colorDepth);
return ret;
}
ENUM_MESON_HDR_POLICY meson_drm_getHDRPolicy( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
uint32_t value = 0;
ENUM_MESON_HDR_POLICY hdrPolicy = MESON_HDR_POLICY_FOLLOW_SINK;
if ( drmFd < 0) {
ERROR( "%s %d drmFd < 0",__FUNCTION__,__LINE__);
return hdrPolicy;
}
if ( 0 == meson_drm_get_crtc_prop_value( drmFd, connType, propName, &value )) {
if (value == 0)
hdrPolicy = MESON_HDR_POLICY_FOLLOW_SINK;
if (value == 1)
hdrPolicy = MESON_HDR_POLICY_FOLLOW_SOURCE;
}
DEBUG("%s %d get HDR Policy: %d",__FUNCTION__,__LINE__,hdrPolicy);
return hdrPolicy;
}
int meson_drm_setHDRPolicy(int drmFd, drmModeAtomicReq *req,
ENUM_MESON_HDR_POLICY hdrPolicy, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t crtcId = 0;
conn = get_current_connector(drmFd, connType);
if ( drmFd < 0 || req == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
crtcId = mesonConnectorGetCRTCId(conn);
rc = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC,
DRM_CONNECTOR_PROP_TX_HDR_POLICY, (uint64_t)hdrPolicy);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set hdrPolicy %d",__FUNCTION__,__LINE__,hdrPolicy);
return ret;
}
ENUM_MESON_HDCP_VERSION meson_drm_getHdcpVersion( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDCP_AUTH_MODE);
uint32_t value = 0;
ENUM_MESON_HDCP_VERSION hdcpVersion = MESON_HDCP_RESERVED;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return hdcpVersion;
}
if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
if (value & 0x1)
hdcpVersion = MESON_HDCP_14;
if (value & 0x2)
hdcpVersion = MESON_HDCP_22;
}
DEBUG("%s %d get Hdcp Version %d",__FUNCTION__,__LINE__,hdcpVersion);
return hdcpVersion;
}
ENUM_MESON_HDR_MODE meson_drm_getHdrStatus(int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_MODE);
uint32_t value = 0;
ENUM_MESON_HDR_MODE hdrMode = MESON_SDR;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return hdrMode;
}
if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
DEBUG("%s %d get conn prop value success",__FUNCTION__,__LINE__);
switch (value)
{
case 0:
hdrMode = MESON_HDR10PLUS;
break;
case 1:
hdrMode = MESON_DOLBYVISION_STD;
break;
case 2:
hdrMode = MESON_DOLBYVISION_LL;
break;
case 3:
hdrMode = MESON_HDR10_ST2084;
break;
case 4:
hdrMode = MESON_HDR10_TRADITIONAL;
break;
case 5:
hdrMode = MESON_HDR_HLG;
break;
case 6:
hdrMode = MESON_SDR;
break;
default:
hdrMode = MESON_SDR;
break;
}
} else {
ERROR("%s %d get connnetor property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get HdrStatus %d",__FUNCTION__,__LINE__,hdrMode);
return hdrMode;
}
void meson_drm_getEDIDData(int drmFd, MESON_CONNECTOR_TYPE connType, int * data_Len, char **data )
{
int i = 0;
int count = 0;
char* edid_data = NULL;
struct mesonConnector* conn = NULL;
if (drmFd < 0 || data_Len == NULL || data == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return;
}
conn = get_current_connector(drmFd, connType);
if (conn == NULL) {
ERROR("%s %d connector create fail.return",__FUNCTION__,__LINE__);
return;
}
if (0 != mesonConnectorGetEdidBlob(conn, &count, &edid_data))
goto out;
char* edid = (char*)calloc(count, sizeof(char));
if (edid == NULL) {
ERROR("%s %d edid alloc mem fail.return",__FUNCTION__,__LINE__);
return;
}
for (i = 0; i < count; i++)
{
edid[i] = edid_data[i];
}
*data_Len = count;
*data = edid;
DEBUG("%s %d data_Len: %d",__FUNCTION__,__LINE__, (*data_Len));
for (int i = 0; i < (*data_Len); i++) {
if (i % 16 == 0)
DEBUG_EDID("\n\t\t\t");
if (*data)
DEBUG_EDID("%.2hhx", (*data)[i]);
}
out:
if (conn)
mesonConnectorDestroy(drmFd,conn);
}
int meson_drm_setAVMute(int drmFd, drmModeAtomicReq *req,
bool mute, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t connId = 0;
if ( drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
connId = mesonConnectorGetId(conn);
rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
MESON_DRM_HDMITX_PROP_AVMUTE, (uint64_t)mute);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG(" %s %d set mute %d",__FUNCTION__,__LINE__,mute);
return ret;
}
int meson_drm_getAVMute( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get AVMute: %d (AVMute control, 1 means set avmute, 0 means not set avmute)",value,__FUNCTION__,__LINE__);
return value;
}
ENUM_MESON_HDCPAUTH_STATUS meson_drm_getHdcpAuthStatus( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
uint32_t value = 0;
ENUM_MESON_HDCPAUTH_STATUS hdcpAuthStatus = MESON_AUTH_STATUS_FAIL;
if ( drmFd < 0 ) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return hdcpAuthStatus;
}
if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
if (value == 2)
hdcpAuthStatus = MESON_AUTH_STATUS_SUCCESS;
}
DEBUG(" %s %d get hdcp auth status %d",__FUNCTION__,__LINE__,hdcpAuthStatus);
return hdcpAuthStatus;
}
int meson_drm_setHDCPEnable(int drmFd, drmModeAtomicReq *req,
bool enable, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t connId = 0;
if ( drmFd < 0 || req == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
connId = mesonConnectorGetId(conn);
rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
DRM_CONNECTOR_PROP_CONTENT_PROTECTION, (uint64_t)enable);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set hdcp enable %d",__FUNCTION__,__LINE__,enable);
return ret;
}
int meson_drm_setHDCPContentType(int drmFd, drmModeAtomicReq *req,
ENUM_MESON_HDCP_Content_Type HDCPType, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t connId = 0;
if ( drmFd < 0 || req == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
conn = get_current_connector(drmFd, connType);
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
connId = mesonConnectorGetId(conn);
rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
DRM_CONNECTOR_PROP_CONTENT_TYPE, (uint64_t)HDCPType);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set hdcp content %d",__FUNCTION__,__LINE__,HDCPType);
return ret;
}
ENUM_MESON_HDCP_Content_Type meson_drm_getHDCPContentType( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
uint32_t value = 0;
ENUM_MESON_HDCP_Content_Type ContentType = MESON_HDCP_Type_RESERVED;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ContentType;
}
if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
switch (value)
{
case 0:
ContentType = MESON_HDCP_Type0;
break;
case 1:
ContentType = MESON_HDCP_Type1;
break;
default:
ContentType = MESON_HDCP_Type_RESERVED;
break;
}
} else {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get HDCP Content Type: %d",__FUNCTION__,__LINE__,ContentType);
return ContentType;
}
MESON_CONTENT_TYPE meson_drm_getContentType(int drmFd, MESON_CONNECTOR_TYPE connType ) {
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_Content_Type);
uint32_t value = 0;
MESON_CONTENT_TYPE ContentType = MESON_CONTENT_TYPE_RESERVED;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ContentType;
}
if ( 0 == meson_drm_get_conn_prop_value(drmFd, connType, propName, &value )) {
switch (value)
{
case 0:
ContentType = MESON_CONTENT_TYPE_Data;
break;
case 1:
ContentType = MESON_CONTENT_TYPE_Graphics;
break;
case 2:
ContentType = MESON_CONTENT_TYPE_Photo;
break;
case 3:
ContentType = MESON_CONTENT_TYPE_Cinema;
break;
case 4:
ContentType = MESON_CONTENT_TYPE_Game;
break;
default:
ContentType = MESON_CONTENT_TYPE_RESERVED;
break;
}
} else {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get Content Type: %d",__FUNCTION__,__LINE__,ContentType);
return ContentType;
}
int meson_drm_setDvEnable(int drmFd, drmModeAtomicReq *req,
uint32_t dvEnable, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t crtcId = 0;
conn = get_current_connector(drmFd, connType);
if ( drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
crtcId = mesonConnectorGetCRTCId(conn);
rc = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC,
DRM_CONNECTOR_PROP_DV_ENABLE, (uint64_t)dvEnable);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set dvEnable value %d",__FUNCTION__,__LINE__,dvEnable);
return ret;
}
int meson_drm_getDvEnable( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
uint32_t value = -1;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_crtc_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get crtc property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get DvEnable %d",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_setActive(int drmFd, drmModeAtomicReq *req,
uint32_t active, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t crtcId = 0;
conn = get_current_connector(drmFd, connType);
if ( drmFd < 0 || req == NULL) {
ERROR(" %s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
crtcId = mesonConnectorGetCRTCId(conn);
rc = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC,
DRM_CONNECTOR_PROP_ACTIVE, (uint64_t)active);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set active %d",__FUNCTION__,__LINE__,active);
return ret;
}
int meson_drm_getActive( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_ACTIVE);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_crtc_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get crtc property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get Active: %d",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_setVrrEnabled(int drmFd, drmModeAtomicReq *req,
uint32_t VrrEnable, MESON_CONNECTOR_TYPE connType)
{
int ret = -1;
int rc = -1;
struct mesonConnector* conn = NULL;
uint32_t crtcId = 0;
conn = get_current_connector(drmFd, connType);
if ( drmFd < 0 || req == NULL) {
ERROR("%s %d invalid parameter return",__FUNCTION__,__LINE__);
return ret;
}
if (conn) {
DEBUG("%s %d get current connector success",__FUNCTION__,__LINE__);
crtcId = mesonConnectorGetCRTCId(conn);
rc = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC,
DRM_CONNECTOR_VRR_ENABLED, (uint64_t)VrrEnable);
mesonConnectorDestroy(drmFd,conn);
}
if (rc >= 0)
ret = 0;
DEBUG("%s %d set VrrEnable %d",__FUNCTION__,__LINE__,VrrEnable);
return ret;
}
int meson_drm_getVrrEnabled( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_VRR_ENABLED);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_crtc_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get crtc property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get VrrEnabled: %d",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_getHdrCap( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDR_CAP);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get hdrcap: %d (presents the RX HDR capability [r])",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_getDvCap( int drmFd, MESON_CONNECTOR_TYPE connType )
{
char propName[PROP_NAME_MAX_LEN] = {'\0'};
sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_DV_CAP);
uint32_t value = 0;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return value;
}
if ( 0 != meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
ERROR("%s %d get connector property value fail",__FUNCTION__,__LINE__);
}
DEBUG("%s %d get dvcap:%d(presents the RX dolbyvision capability, [r] such as std or ll mode)",__FUNCTION__,__LINE__,value);
return value;
}
int meson_drm_setVideoZorder(int drmFd, unsigned int index, unsigned int zorder, unsigned int flag) {
int ret = -1;
struct video_zpos zpos;
if ( drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ret;
}
zpos.flag = flag;
zpos.index = index;
zpos.zpos = zorder;
ret = drmIoctl(drmFd, DRM_IOCTL_MESON_SET_VIDEO_ZPOS, &zpos);
if (ret) {
ERROR("\n failed to create object[%s].\n",strerror(errno));
}
return ret;
}
int meson_drm_setPlaneMute(int drmFd, unsigned int plane_type, unsigned int plane_mute)
{
int ret = -1;
struct drm_meson_plane_mute plane_info;
if (drmFd < 0) {
ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
return ret;
}
plane_info.plane_type = plane_type;
plane_info.plane_mute = plane_mute;
ret = drmIoctl(drmFd, DRM_IOCTL_MESON_MUTE_PLANE, &plane_info);
if (ret)
ERROR("\n failed to mute plane[%s].\n",strerror(errno));
return ret;
}