module: Device management API Development [1/2]
PD#OTT-23707
Problem:
API Development
Solution:
API Development
Verify:
ap222-yocto
Change-Id: I3c7a9a61df7a6408813431c412c3a8fa8f4dd705
Signed-off-by: limin.tian <limin.tian@amlogic.com>
diff --git a/meson/Makefile b/meson/Makefile
index dc3fb82..507edc8 100644
--- a/meson/Makefile
+++ b/meson/Makefile
@@ -1,22 +1,70 @@
-OBJ = meson_drm.c meson_drm_kms.c meson_drm_util.c meson_drm_async_commit.c
+LOCAL_PATH = $(shell pwd)
-TARGET = libdrm_meson.so
+MIN_GCC_VERSION = "10"
+GCC_VERSION := "`$(CC) -dumpversion | cut -f1 -d'.'`"
+IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
+ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
+CFLAGS += -std=gnu++20
+endif
-all: $(TARGET)
+LDFLAGS += -Wl,--no-as-needed -lstdc++ -lpthread -ldl -lrt -L$(STAGING_DIR)/usr/lib
+CFLAGS += -Wall -Wno-unknown-pragmas -Wno-format -Wno-format-security -Wno-error=unused-result \
+ -O3 -fexceptions -fnon-call-exceptions -D_GNU_SOURCE -I$(STAGING_DIR)/usr/include
+CFLAGS += -I$(STAGING_DIR)/usr/include/ -I$(STAGING_DIR)/usr/include/libdrm/
+LDFLAGS += -L$(STAGING_DIR)/usr/lib -ldrm
+meson_drm_SRCS = \
+ $(LOCAL_PATH)/libdrm_meson_connector.c \
+ $(LOCAL_PATH)/libdrm_meson_property.c \
+ $(LOCAL_PATH)/meson_drm.c \
+ $(LOCAL_PATH)/meson_drm_async_commit.c \
+ $(LOCAL_PATH)/meson_drm_kms.c \
+ $(LOCAL_PATH)/meson_drm_util.c \
+ $(NULL)
-TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/ -I$(STAGING_DIR)/usr/include/libdrm/
-TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib -ldrm
+meson_drm_HEADERS = \
+ $(LOCAL_PATH)\
+ $(NULL)
-$(TARGET): $(OBJ)
- $(CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -g -D_FILE_OFFSET_BITS=64 -Wall $(OBJ) -shared -fPIC -o $@
+meson_drm_test_SRCS = \
+ $(LOCAL_PATH)/meson_drm_test.c \
+ $(NULL)
-.PHONY: clean
+meson_drm_display_test_SRCS = \
+ $(LOCAL_PATH)/meson_sample/meson_drm_display_test.c \
+ $(LOCAL_PATH)/meson_sample/meson_drm_display.c \
+ $(NULL)
+# ---------------------------------------------------------------------
+# Build rules
+BUILD_TARGETS = libdrm_meson.so meson_drm_test meson_drm_display_test
+
+.PHONY: all install uninstall clean
+
+libdrm_meson.so: $(meson_drm_SRCS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -g -D_FILE_OFFSET_BITS=64 -Wall \
+ -shared -fPIC -o $@ $^ $(LDLIBS)
+
+meson_drm_test: $(meson_drm_test_SRCS) libdrm_meson.so
+ $(CC) $(CFLAGS) -I$(meson_drm_HEADERS) -L$(LOCAL_PATH) \
+ -ldrm_meson $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+meson_drm_display_test: $(meson_drm_display_test_SRCS) libdrm_meson.so
+ $(CC) $(CFLAGS) -I$(meson_drm_HEADERS) -L$(LOCAL_PATH) \
+ -ldrm_meson $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+all: $(BUILD_TARGETS)
clean:
- rm -f *.o $(TARGET)
+ rm -f *.o $(BUILD_TARGETS)
install:
- cp meson_drmif.h $(STAGING_DIR)/usr/include/
- cp meson_drm_util.h $(STAGING_DIR)/usr/include/
- cp $(TARGET) $(STAGING_DIR)/usr/lib/
- cp $(TARGET) $(TARGET_DIR)/usr/lib/
+ install -m 0644 libdrm_meson.so $(TARGET_DIR)/usr/lib
+ install -m 755 meson_drm_test $(TARGET_DIR)/usr/bin/
+ install -m 755 meson_drm_display_test $(TARGET_DIR)/usr/bin/
+
+
+uninstall:
+ rm -f $(TARGET_DIR)/usr/lib/libdrm_meson.so
+ rm -f $(TARGET_DIR)/usr/bin/meson_drm_test
+ rm -f $(TARGET_DIR)/usr/bin/meson_drm_display_test
+
+
diff --git a/meson/libdrm_meson_connector.c b/meson/libdrm_meson_connector.c
new file mode 100644
index 0000000..49ff67a
--- /dev/null
+++ b/meson/libdrm_meson_connector.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2020 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<string.h>
+#include "libdrm_meson_connector.h"
+struct mesonConnector {
+int type;
+int id;
+int count_modes;
+drmModeModeInfo* modes;
+int edid_data_Len;
+char* edid_data;
+int connection;
+int crtc_id;
+int encoder_id;
+};
+
+struct mesonConnector *mesonConnectorCreate(int drmFd, int type)
+{
+ drmModeRes *res= NULL;
+ drmModeConnector *conn= NULL;
+ struct mesonConnector* ret = NULL;
+ drmModePropertyRes *prop_ptr = NULL;
+ drmModePropertyBlobRes* edid_blob = NULL;
+ char *edid_data_temp = NULL;
+ drmModeModeInfo* modes_info = NULL;
+ drmModeEncoder* cur_encoder = NULL;
+ int i = 0;
+ int j = 0;
+ int blob_id = 0;
+ res= drmModeGetResources( drmFd );
+ ret = (struct mesonConnector*)calloc( 1,sizeof(struct mesonConnector) );
+ if ( !ret ) {
+ printf("\n mesonConnectorCreate:mesonConnector create fail \n");
+ goto exit;
+ }
+ if ( !res )
+ {
+ printf("\n mesonConnectorCreate: failed to get resources from drmFd (%d)", drmFd);
+ ret = NULL;
+ goto exit;
+ }
+ for ( i= 0; i < res->count_connectors; ++i ) {
+ conn= drmModeGetConnector( drmFd, res->connectors[i] );
+ if ( conn ) {
+ if ( conn->connector_type == type ) { //是否需要判断当前connector是否连接
+ break;
+ }
+ drmModeFreeConnector(conn);
+ conn= NULL;
+ }
+ }
+ if ( !conn ) {
+ printf("\n mesonConnectorCreate: unable to get connector for drmfd (%d) type(%d)\n", drmFd,type);
+ ret = NULL;
+ goto exit;
+ }
+ if ( conn ) {
+ ret->id = conn->connector_id;
+ ret->type = conn->connector_type;
+ ret->encoder_id = conn->encoder_id;
+ cur_encoder = drmModeGetEncoder(drmFd, ret->encoder_id);
+ if (cur_encoder)
+ ret->crtc_id = cur_encoder->crtc_id;
+ drmModeFreeEncoder(cur_encoder);
+ ret->count_modes = conn->count_modes;
+ if (ret->count_modes > 0) {
+ modes_info = (drmModeModeInfo*)calloc( ret->count_modes, sizeof(drmModeModeInfo) );
+ if (!modes_info) {
+ printf("\n mesonConnectorCreate:calloc fail\n");
+ goto exit;
+ }
+ memcpy(modes_info, conn->modes, ret->count_modes *sizeof(drmModeModeInfo));
+ }
+ ret->modes = modes_info;
+ ret->connection = conn->connection;
+ if (conn->props) {
+ for (j = 0; j < conn->count_props; j++ ) {
+ prop_ptr = drmModeGetProperty(drmFd,conn->props[j]);
+ if ( prop_ptr ) {
+ if ( strcmp(prop_ptr->name,"EDID" ) == 0 ) {
+ blob_id = conn->prop_values[j];
+ edid_blob = drmModeGetPropertyBlob(drmFd, blob_id);
+ if (edid_blob ) {
+ ret->edid_data_Len = edid_blob->length;
+ edid_data_temp = (char*)calloc( ret->edid_data_Len,sizeof(char) );
+ memcpy(edid_data_temp, edid_blob->data, ret->edid_data_Len);
+ ret->edid_data = edid_data_temp;
+ }
+ drmModeFreePropertyBlob(edid_blob);
+ }
+ }
+ drmModeFreeProperty(prop_ptr);
+ }
+ }
+ }
+exit:
+ drmModeFreeResources(res);
+ drmModeFreeConnector(conn);
+ return ret;
+}
+int mesonConnectorUpdate(int drmFd, struct mesonConnector *connector)
+{
+ int ret = -1;
+ drmModeConnector *conn= NULL;
+ drmModePropertyBlobRes* edid_blob = NULL;
+ drmModePropertyRes *prop_ptr = NULL;
+ char* edid_data_temp = NULL;
+ drmModeModeInfo* modes_info = NULL;
+ drmModeEncoder* cur_encoder = NULL;
+ int blob_id = 0;
+ int j = 0;
+ conn= drmModeGetConnector( drmFd, connector->id );
+ //ret = (struct mesonConnector*)calloc( 1,sizeof(struct mesonConnector) );
+ if ( !connector ) {
+ printf("\n mesonConnectorUpdate:invalid parameters\n");
+ goto exit;
+ }
+ if ( !ret ) {
+ printf("\n mesonConnectorUpdate:mesonConnector create fail\n");
+ goto exit;
+ }
+ if ( !conn ) {
+ printf("\n mesonConnectorCreate: unable to get connector for drmfd (%d) conn_id(%d)\n", drmFd,connector->id);
+ goto exit;
+ }
+ if ( conn ) {
+ connector->id = conn->connector_id;
+ connector->type = conn->connector_type;
+ connector->encoder_id = conn->encoder_id;
+ cur_encoder = drmModeGetEncoder(drmFd, connector->encoder_id);
+ if (cur_encoder)
+ connector->crtc_id = cur_encoder->crtc_id;
+ drmModeFreeEncoder(cur_encoder);
+ connector->count_modes = conn->count_modes;
+ if (connector->modes) {
+ free(connector->modes);
+ connector->modes = NULL;
+ }
+ if ( connector->count_modes > 0 ) {
+ modes_info = (drmModeModeInfo*)calloc( connector->count_modes, sizeof(drmModeModeInfo) );
+ if (modes_info)
+ memcpy(modes_info, conn->modes, connector->count_modes *sizeof(drmModeModeInfo));
+ }
+ connector->modes = modes_info;
+ connector->connection = conn->connection;
+ if (connector->edid_data) {
+ free(connector->edid_data);
+ connector->edid_data = NULL;
+ }
+ if (conn->props) {
+ for (j = 0; j < conn->count_props; j++ ) {
+ prop_ptr = drmModeGetProperty(drmFd,conn->props[j]);
+ if ( prop_ptr ) {
+ if ( strcmp(prop_ptr->name,"EDID") == 0 ) {
+ blob_id = conn->prop_values[j];
+ edid_blob = drmModeGetPropertyBlob(drmFd, blob_id);
+ if (edid_blob ) {
+ connector->edid_data_Len = edid_blob->length;
+ edid_data_temp = (char*)calloc( connector->edid_data_Len,sizeof(char) );
+ memcpy(edid_data_temp, edid_blob->data, connector->edid_data_Len);
+ connector->edid_data = edid_data_temp;
+ }
+ drmModeFreePropertyBlob(edid_blob);
+ }
+ }
+ drmModeFreeProperty(prop_ptr);
+ }
+ }
+ ret = 0;
+ }
+exit:
+ drmModeFreeConnector(conn);
+ return ret;
+}
+struct mesonConnector *mesonConnectorDestroy(int drmFd, struct mesonConnector *connector)
+{
+ if ( connector ) {
+ if (connector->edid_data)
+ free(connector->edid_data);
+ if (connector->modes)
+ free(connector->modes);
+ connector->edid_data = NULL;
+ connector->modes = NULL;
+ free(connector);
+ connector = NULL;
+ }
+ return connector;
+}
+int mesonConnectorGetId(struct mesonConnector* connector)
+{
+ if ( connector ) {
+ return connector->id;
+ } else {
+ printf("\n mesonConnectorGetId:invalid parameters\n");
+ return 0;
+ }
+}
+/*HDMI capabilities - Rx supported video formats*/
+int mesonConnectorGetModes(struct mesonConnector * connector, int drmFd, drmModeModeInfo **modes, int *count_modes)
+{
+ int ret = -1;
+ if ( !connector || !count_modes ) {
+ printf("\n mesonConnectorGetModes:invalid parameters\n");
+ } else {
+ *count_modes = connector->count_modes;
+ *modes = connector->modes;
+ ret = 0;
+ }
+ return ret;
+}
+/*Edid Information:*/
+int mesonConnectorGetEdidBlob(struct mesonConnector* connector, int * data_Len, char **data)
+{
+ int ret = -1;
+ if ( !connector || !data_Len ) {
+ printf("\n mesonConnectorGetEdidBlob:invalid parameters\n");
+ } else {
+ *data_Len = connector->edid_data_Len;
+ *data = connector->edid_data;
+ ret = 0;
+ }
+ return ret;
+}
+/*get connector connect status.*/
+int mesonConnectorGetConnectState(struct mesonConnector* connector)
+{
+ int ret = -1;
+ if ( !connector ) {
+ printf("\n mesonConnectorGetEdidBlob:invalid parameters\n");
+ } else {
+ ret = connector->connection;
+ }
+ return ret;
+}
+int mesonConnectorGetCRTCId(struct mesonConnector* connector)
+{
+ int ret = -1;
+ if ( !connector ) {
+ printf("\n mesonConnectorGetEdidBlob:invalid parameters\n");
+ } else {
+ ret = connector->crtc_id;
+ }
+ return ret;
+}
+drmModeModeInfo* mesonConnectorGetCurMode(int drmFd, struct mesonConnector* connector)
+{
+ drmModeConnector *conn_cur= NULL;
+ drmModeModeInfo* mode = NULL;
+ mode = (drmModeModeInfo*)calloc(1, sizeof(drmModeModeInfo));
+ conn_cur = drmModeGetConnectorCurrent(drmFd, connector->id);
+ if (conn_cur && mode) {
+ memcpy(mode, conn_cur->modes, sizeof(drmModeModeInfo));
+ }
+ drmModeFreeConnector(conn_cur);
+ return mode;
+}
+
+void dump_connector(struct mesonConnector* connector)
+{
+ int i = 0;
+ int j = 0;
+ drmModeModeInfo* mode = NULL;
+ if (connector) {
+ printf("\n connector:\n");
+ printf("id:%d\n",connector->id);
+ printf("type:%d\n",connector->type);
+ printf("connection:%d\n",connector->connection);
+ printf("count_modes:%d\n",connector->count_modes);
+ printf("modes:\n");
+ printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
+ "vss vse vtot)\n");
+ for (j = 0; j < connector->count_modes; j++) {
+ mode = &connector->modes[j];
+ printf(" %s %d %d %d %d %d %d %d %d %d %d",
+ mode->name,
+ mode->vrefresh,
+ mode->hdisplay,
+ mode->hsync_start,
+ mode->hsync_end,
+ mode->htotal,
+ mode->vdisplay,
+ mode->vsync_start,
+ mode->vsync_end,
+ mode->vtotal,
+ mode->clock);
+ }
+ printf("edid_data_Len:%d\n",connector->edid_data_Len);
+ printf("edid\n");
+ for (i = 0; i < connector->edid_data_Len; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t\t");
+ printf("%.2hhx", connector->edid_data[i]);
+ }
+ printf("\n");
+ }
+}
diff --git a/meson/libdrm_meson_connector.h b/meson/libdrm_meson_connector.h
new file mode 100644
index 0000000..80e84e1
--- /dev/null
+++ b/meson/libdrm_meson_connector.h
@@ -0,0 +1,42 @@
+ /*
+ * Copyright (c) 2021 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:
+ */
+
+#ifndef LIBDRM_MESON_CONNECTOR_H_
+#define LIBDRM_MESON_CONNECTOR_H_
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <xf86drmMode.h>
+#define MESON_DRM_HDMITX_PROP_AVMUTE "MESON_DRM_HDMITX_PROP_AVMUTE"
+#define MESON_DRM_HDMITX_PROP_EOTF "EOTF"
+#define DRM_CONNECTOR_PROP_CONTENT_PROTECTION "Content Protection"
+#define DRM_CONNECTOR_PROP_CONTENT_TYPE "HDCP Content Type"
+struct mesonConnector;
+struct mesonConnector *mesonConnectorCreate(int drmFd, int type);
+int mesonConnectorUpdate(int drmFd, struct mesonConnector *connector);
+struct mesonConnector *mesonConnectorDestroy(int drmFd, struct mesonConnector* connector);
+int mesonConnectorGetId(struct mesonConnector* connector);
+/*HDMI capabilities - Rx supported video formats*/
+int mesonConnectorGetModes(struct mesonConnector * connector,int drmFd, drmModeModeInfo** modes, int *count_modes);
+/*Edid Information:*/
+int mesonConnectorGetEdidBlob(struct mesonConnector* connector, int * data_Len, char** data);
+/*get connector connect status.*/
+int mesonConnectorGetConnectState(struct mesonConnector* connector);
+int mesonConnectorGetCRTCId(struct mesonConnector* connector);
+drmModeModeInfo* mesonConnectorGetCurMode(int drmFd, struct mesonConnector* connector);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/meson/libdrm_meson_property.c b/meson/libdrm_meson_property.c
new file mode 100644
index 0000000..529081f
--- /dev/null
+++ b/meson/libdrm_meson_property.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2020 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 <string.h>
+#include "libdrm_meson_property.h"
+struct mesonProperty {
+ drmModePropertyPtr prop_ptr;
+ uint64_t mValue;
+ uint32_t mType;
+ uint32_t mComponentId;
+ uint32_t drmObjectType;
+};
+struct mesonProperty *mesonPropertyCreate(int drmFd, uint32_t drmObject, uint32_t drmObjectType, char* name)
+{
+ int i = 0;
+ struct mesonProperty* ret = NULL;
+ drmModeObjectPropertiesPtr props;
+ drmModePropertyPtr prop = NULL;
+ drmModePropertyPtr prop_temp = NULL;
+ props = drmModeObjectGetProperties(drmFd, drmObject, drmObjectType);
+ struct drm_mode_property_enum *enums_temp = NULL;
+ uint64_t* values_temp = NULL;
+ uint32_t* blob_ids_temp = NULL;
+ if ( !props ) {
+ printf("\t No properties:mesonPropertyCreate \n");
+ goto exit;
+ }
+ prop = (drmModePropertyPtr)calloc( 1, sizeof(drmModePropertyRes));
+ if ( !prop ) {
+ printf("\t mesonPropertyCreate alloc fail\n");
+ goto exit;
+ }
+ ret = (struct mesonProperty*)calloc( 1,sizeof(struct mesonProperty) );
+ if ( !ret ) {
+ printf("\t mesonPropertyCreate alloc mesonProperty fail\n");
+ goto exit;
+ }
+ for (i = 0; i < props->count_props; i++) {
+ prop_temp = drmModeGetProperty(drmFd,props->props[i] );
+ if ( !prop_temp )
+ continue;
+ if ( strcmp(prop_temp->name, name) == 0 ) {
+ memcpy( prop, prop_temp, sizeof(drmModePropertyRes) );
+ ret->prop_ptr = prop;
+ if (prop->count_enums > 0) {
+ enums_temp = (struct drm_mode_property_enum*)calloc( prop->count_enums, sizeof(struct drm_mode_property_enum));
+ if (enums_temp)
+ memcpy( enums_temp, prop->enums, prop->count_enums*sizeof(struct drm_mode_property_enum) );
+ }
+ ret->prop_ptr->enums = enums_temp;
+
+ if ( prop->count_values > 0 ) {
+ values_temp = (uint64_t*)calloc( prop->count_values, sizeof(uint64_t));
+ if (values_temp)
+ memcpy( values_temp, prop->values, prop->count_values*sizeof(uint64_t) );
+ }
+ ret->prop_ptr->values = values_temp;
+
+ if ( prop->count_blobs > 0 ) {
+ blob_ids_temp = (uint32_t*)calloc( prop->count_blobs, sizeof(uint32_t));
+ if (blob_ids_temp)
+ memcpy(blob_ids_temp, prop->blob_ids, prop->count_blobs*sizeof(uint32_t));
+ }
+ ret->prop_ptr->blob_ids = blob_ids_temp;
+ ret->mComponentId = drmObject;
+ ret->mValue = props->prop_values[i];
+ ret->mType = prop->flags;
+ if ( drm_property_type_is(prop, DRM_MODE_PROP_BLOB) )
+ ret->mType = DRM_MODE_PROP_BLOB;
+ if ( drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE) )
+ ret->mType = DRM_MODE_PROP_SIGNED_RANGE;
+ if ( drm_property_type_is(prop, DRM_MODE_PROP_RANGE) )
+ ret->mType = DRM_MODE_PROP_RANGE;
+ if ( drm_property_type_is(prop, DRM_MODE_PROP_ENUM) )
+ ret->mType = DRM_MODE_PROP_ENUM;
+ if ( drm_property_type_is(prop, DRM_MODE_PROP_ENUM) )
+ ret->mType = DRM_MODE_PROP_ENUM;
+ ret->drmObjectType = drmObjectType;
+ break;
+ }
+ drmModeFreeProperty(prop_temp);
+ prop_temp = NULL;
+ }
+
+ if ( !prop_temp ) {
+ free(ret);
+ ret = NULL;
+ }
+exit:
+ if ( ret == NULL && prop != NULL ) {
+ free(prop);
+ }
+ drmModeFreeProperty(prop_temp);
+ drmModeFreeObjectProperties(props);
+ return ret;
+}
+/*update cached value*/
+int mesonPropertyUpdateValue(int drmFd, struct mesonProperty *mesonProp)
+{
+ int ret = -1;
+ int i = 0;
+ drmModeObjectPropertiesPtr props = NULL;
+ drmModePropertyPtr prop_temp = NULL;
+ struct drm_mode_property_enum *enums_temp = NULL;
+ uint64_t* values_temp = NULL;
+ uint32_t* blob_ids_temp = NULL;
+ if ( !mesonProp ) {
+ printf("\t mesonPropertyUpdateValue invalid parameter\n");
+ ret = -1;
+ goto exit;
+ }
+ props = drmModeObjectGetProperties(drmFd, mesonProp->mComponentId, mesonProp->drmObjectType);
+ if ( !props ) {
+ printf("\t No properties:mesonPropertyUpdateValue \n");
+ ret = -1;
+ goto exit;
+ }
+ if ( mesonProp ) {
+ for (i = 0; i < props->count_props; i++) {
+ prop_temp = drmModeGetProperty(drmFd,props->props[i] );
+ if ( !prop_temp )
+ continue;
+ if ( prop_temp->prop_id == mesonProp->prop_ptr->prop_id ) {
+ if ( mesonProp->prop_ptr->values ) {
+ free(mesonProp->prop_ptr->values);
+ mesonProp->prop_ptr->values = NULL;
+ }
+ if (mesonProp->prop_ptr->enums ) {
+ free(mesonProp->prop_ptr->enums);
+ mesonProp->prop_ptr->enums = NULL;
+ }
+ if (mesonProp->prop_ptr->blob_ids ) {
+ free(mesonProp->prop_ptr->blob_ids);
+ mesonProp->prop_ptr->blob_ids = NULL;
+ }
+ memcpy( mesonProp->prop_ptr,prop_temp, sizeof(drmModePropertyRes) );
+
+ if (mesonProp->prop_ptr->count_enums > 0) {
+ enums_temp = (struct drm_mode_property_enum*)calloc( mesonProp->prop_ptr->count_enums, sizeof(struct drm_mode_property_enum));
+ if (enums_temp)
+ memcpy( enums_temp, mesonProp->prop_ptr->enums, mesonProp->prop_ptr->count_enums*sizeof(struct drm_mode_property_enum) );
+ }
+ mesonProp->prop_ptr->enums = enums_temp;
+
+ if ( mesonProp->prop_ptr->count_values > 0 ) {
+ values_temp = (uint64_t*)calloc( mesonProp->prop_ptr->count_values, sizeof(uint64_t));
+ if (values_temp)
+ memcpy( values_temp, mesonProp->prop_ptr->values, mesonProp->prop_ptr->count_values*sizeof(uint64_t) );
+ }
+ mesonProp->prop_ptr->values = values_temp;
+
+ if ( mesonProp->prop_ptr->count_blobs > 0 ) {
+ blob_ids_temp = (uint32_t*)calloc( mesonProp->prop_ptr->count_blobs, sizeof(uint32_t));
+ if (blob_ids_temp)
+ memcpy(blob_ids_temp, mesonProp->prop_ptr->blob_ids, mesonProp->prop_ptr->count_blobs*sizeof(uint32_t));
+ }
+ mesonProp->prop_ptr->blob_ids = blob_ids_temp;
+ mesonProp->mComponentId = mesonProp->mComponentId;
+ mesonProp->mValue = props->prop_values[i];
+ mesonProp->mType = mesonProp->prop_ptr->flags;
+ mesonProp->drmObjectType = mesonProp->drmObjectType;
+ ret = 0;
+ break;
+ }
+ drmModeFreeProperty(prop_temp);
+ prop_temp = NULL;
+ }
+ }
+exit:
+ drmModeFreeProperty(prop_temp);
+ drmModeFreeObjectProperties(props);
+ return ret;
+}
+int mesonPropertyGetId(struct mesonProperty* mesonProp)
+{
+ int ret = -1;
+ if ( mesonProp ) {
+ ret = mesonProp->prop_ptr->prop_id;
+ } else {
+ printf("\t mesonPropertyGetValue invalid parameter\n");
+ }
+ return ret;
+}
+
+uint64_t mesonPropertyGetValue(struct mesonProperty* mesonProp)
+{
+ uint64_t ret = 0;
+ if ( mesonProp ) {
+ ret = mesonProp->mValue;
+ } else {
+ printf("\t mesonPropertyGetValue invalid parameter\n");
+ }
+ return ret;
+}
+
+uint32_t mesonPropertyGetType(struct mesonProperty* mesonProp)
+{
+ uint64_t ret = 0;
+ if ( mesonProp ) {
+ ret = mesonProp->mType;
+ } else {
+ printf("\t mesonPropertyGetType invalid parameter\n");
+ }
+ return ret;
+}
+
+/*only updated cached value, not update to driver*/
+int mesonPropertyDestroy(struct mesonProperty* mesonProperty)
+{
+ int ret = -1;
+ if ( mesonProperty ) {
+ if ( mesonProperty->prop_ptr) {
+ if (mesonProperty->prop_ptr->blob_ids)
+ free(mesonProperty->prop_ptr->blob_ids);
+ drmModeFreeProperty(mesonProperty->prop_ptr);
+ mesonProperty->prop_ptr = NULL;
+ }
+ free(mesonProperty);
+ mesonProperty = NULL;
+ ret = 0;
+ } else {
+ printf("\t mesonPropertyDestroy invalid parameter\n");
+ }
+ return ret;
+}
+int mesonPropertyGetBlobData(struct mesonProperty* mseonProp, int drmFd, int* len, char** data)
+{
+ int ret = -1;
+ int blob_id = -1;
+ drmModePropertyBlobPtr blobProp = NULL;
+ char *blob_data = NULL;
+ if (!mseonProp || !len ) {
+ printf("\t mesonPropertyGetBlobData invalid parameter\n");
+ goto exit;
+ }
+ if (!drm_property_type_is(mseonProp->prop_ptr, DRM_MODE_PROP_BLOB)) {
+ printf("\t mesonPropertyGetBlobData invalid parameter is not a blob property!!!\n");
+ goto exit;
+ }
+ if ( mseonProp && len ) {
+ blob_id = mseonProp->mValue;
+ blobProp = drmModeGetPropertyBlob(drmFd, blob_id);
+ if (!blobProp) {
+ goto exit;
+ }
+ *len = blobProp->length;
+ blob_data = (char*)calloc( blobProp->length, sizeof(char));
+ if (blob_data) {
+ memcpy(blob_data, blobProp->data, blobProp->length);
+ *data = blob_data;
+ }
+ else
+ printf("\t mesonPropertyGetBlobData fail to alloc buffer\n");
+ drmModeFreePropertyBlob(blobProp);
+ ret = 0;
+ }
+exit:
+ return ret;
+}
+int mesonPropertyGetRange(struct mesonProperty* mesonProp, uint64_t * min, uint64_t * max)
+{
+ int ret = -1;
+ if ( !mesonProp || !min || !max ) {
+ printf("\t mesonPropertyGetRange invalid parameter\n");
+ goto exit;
+ }
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_SIGNED_RANGE) || drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_RANGE)) {
+ *min = mesonProp->prop_ptr->values[0];
+ *max = mesonProp->prop_ptr->values[1];
+ ret = 0;
+ } else {
+ printf("\t mesonPropertyGetRange invalid parameter,not a range property\n");
+ }
+exit:
+ return ret;
+
+}
+int mesonPropertyGetEnumTypes(struct mesonProperty* mesonProp, int *len, struct drm_mode_property_enum** enumTypes)
+{
+ int ret = -1;
+ if ( !mesonProp || !len || !enumTypes ) {
+ printf("\t mesonPropertyGetEnumTypes invalid parameter\n");
+ goto exit;
+ }
+ if ( !mesonProp->prop_ptr ) {
+ printf("\t mesonPropertyGetEnumTypes invalid parameter\n");
+ goto exit;
+ }
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_ENUM)) {
+ *len = mesonProp->prop_ptr->count_enums;
+ *enumTypes = mesonProp->prop_ptr->enums;
+ ret = 0;
+ } else {
+ printf("\t mesonPropertyGetRange invalid parameter,not a enum property\n");
+ }
+exit:
+ return ret;
+}
+
+void dump_property(struct mesonProperty* mesonProp,int drmFd)
+{
+ printf("\n dump_property \n");
+ int i = 0;
+ if (mesonProp) {
+ printf("name:%s\n",mesonProp->prop_ptr->name);
+ printf("mComponentId:%d\n",mesonProp->mComponentId);
+ printf("drmObjectType:%d\n",mesonProp->drmObjectType);
+ printf("prop id:%d\n",mesonPropertyGetId(mesonProp));
+ printf("\t\tflags:");
+ if (mesonProp->drmObjectType & DRM_MODE_PROP_PENDING)
+ printf(" pending");
+ if (mesonProp->drmObjectType & DRM_MODE_PROP_IMMUTABLE)
+ printf(" immutable");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_SIGNED_RANGE))
+ printf(" signed range");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_RANGE))
+ printf(" range");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_ENUM))
+ printf(" enum");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_BITMASK))
+ printf(" bitmask");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_BLOB))
+ printf(" blob");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_OBJECT))
+ printf(" object");
+ printf("\n");
+ printf("mValue:%d\n",(int)mesonProp->mValue);
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_SIGNED_RANGE) ||
+ drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_RANGE) ) {
+ printf("\t\t range:");
+ uint64_t min = 0;
+ uint64_t max = 0;
+ mesonPropertyGetRange(mesonProp, &min, &max);
+ printf("min:%d max:%d\n", (int)min, (int)max);
+ printf("\n");
+ }
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_ENUM)) {
+ printf("\t\tenums:");
+ int enumTypeLen = 0;
+ struct drm_mode_property_enum** enumTypes = NULL;
+ mesonPropertyGetEnumTypes(mesonProp, &enumTypeLen, enumTypes );
+ printf("enumTypeLen:%d\n",enumTypeLen);
+ for ( i=0; i<enumTypeLen; i++ ) {
+ printf("%s=%llu",(*enumTypes)[i].name,(*enumTypes)[i].value);
+ }
+ }
+ printf("\t\blob:");
+ if (drm_property_type_is(mesonProp->prop_ptr, DRM_MODE_PROP_BLOB)) {
+ int blob_len = 0;
+ char** blob_data = NULL;
+ blob_data = (char**)calloc( 1, sizeof(char**) );
+ mesonPropertyGetBlobData(mesonProp, drmFd, &blob_len, blob_data);
+
+ for (i = 0; i < blob_len; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t\t");
+ printf("%x", (*blob_data)[i]);
+ }
+ printf("\n");
+ free(blob_data);
+ }
+ }
+}
diff --git a/meson/libdrm_meson_property.h b/meson/libdrm_meson_property.h
new file mode 100644
index 0000000..9dca178
--- /dev/null
+++ b/meson/libdrm_meson_property.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 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:
+ */
+#ifndef LIBDRM_MESON_PROPERTY_H_
+#define LIBDRM_MESON_PROPERTY_H_
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <xf86drmMode.h>
+struct mesonProperty;
+struct mesonProperty *mesonPropertyCreate(int drmFd, uint32_t drmObject, uint32_t drmObjectType, char * name);
+/*update cached value*/
+int mesonPropertyUpdateValue(int drmFd, struct mesonProperty* mesonProp);
+int mesonPropertyGetId(struct mesonProperty* mesonProp );
+uint64_t mesonPropertyGetValue(struct mesonProperty* mesonProp);
+uint32_t mesonPropertyGetType(struct mesonProperty* mesonProp);
+/*only updated cached value, not update to driver*/
+int mesonPropertyDestroy(struct mesonProperty* mesonProp);
+int mesonPropertyGetBlobData(struct mesonProperty* mseonProp, int drmFd, int* len, char** data);
+int mesonPropertyGetRange(struct mesonProperty *, uint64_t* min, uint64_t* max);
+int mesonPropertyGetEnumTypes(struct mesonProperty* mesonProp, int * len, struct drm_mode_property_enum** enumTypes);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/meson/meson_drm_test.c b/meson/meson_drm_test.c
new file mode 100644
index 0000000..ecc7778
--- /dev/null
+++ b/meson/meson_drm_test.c
@@ -0,0 +1,262 @@
+ /*
+ * Copyright (c) 2021 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 <linux/string.h>
+#include "libdrm_meson_connector.h"
+#include "libdrm_meson_property.h"
+
+#define DEFAULT_CARD "/dev/dri/card0"
+static int print_Mode(drmModeModeInfo *mode);
+static void meson_drm_connector_test(int drm_fd, struct mesonConnector* meson_conn);
+static void meson_drm_prop_test(int drmFd, struct mesonProperty* meson_prop);
+static int meson_drm_setprop(uint32_t obj_id, char* prop_name, int prop_value );
+
+static int print_Mode(drmModeModeInfo *mode)
+{
+ if (mode) {
+ printf("\n\nMode: %s\n", mode->name);
+ printf("\tclock : %i\n", mode->clock);
+ printf("\thdisplay : %i\n", mode->hdisplay);
+ printf("\thsync_start : %i\n", mode->hsync_start);
+ printf("\thsync_end : %i\n", mode->hsync_end);
+ printf("\thtotal : %i\n", mode->htotal);
+ printf("\thskew : %i\n", mode->hskew);
+ printf("\tvdisplay : %i\n", mode->vdisplay);
+ printf("\tvsync_start : %i\n", mode->vsync_start);
+ printf("\tvsync_end : %i\n", mode->vsync_end);
+ printf("\tvtotal : %i\n", mode->vtotal);
+ printf("\tvscan : %i\n", mode->vscan);
+ printf("\tvrefresh : %i\n", mode->vrefresh);
+ printf("\ttype : %i\n", mode->type);
+ if ( mode->type & DRM_MODE_TYPE_PREFERRED )
+ printf(" prefered!! ");
+ } else {
+ printf("\n print_Mode fail\n");
+ }
+ return 0;
+}
+static void meson_drm_connector_test(int drm_fd, struct mesonConnector* meson_conn )
+{
+ int conn_id = -1;
+ drmModeModeInfo* modes = NULL;
+ int mode_count = -1;
+ int i;
+ int edid_data_len = -1;
+ char* edid_data = NULL;
+ int ret = -255;
+ int conn_connect = -1;
+ int crtc_id = -1;
+ conn_id = mesonConnectorGetId(meson_conn);
+ printf("\n conn_id:%d\n",conn_id);
+ ret = mesonConnectorGetModes(meson_conn, drm_fd, &modes, &mode_count);
+ if (ret == 0) {
+ printf("\n mode_count:%d modes:%p\n",mode_count,modes);
+ for (i=0; i<mode_count; i++)
+ print_Mode(&(modes[i]));
+ } else {
+ printf("\n mesonConnectorGetModes return fail:%d\n", ret);
+ }
+ printf("\n EDID info:\n");
+ ret = -255;
+
+ ret = mesonConnectorGetEdidBlob(meson_conn, &edid_data_len, &edid_data);
+ if (ret == 0) {
+ for (i = 0; i < edid_data_len; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t\t");
+ if (edid_data)
+ printf("%.2hhx", edid_data[i]);
+ }
+ printf("\nedid_data:%p\n",edid_data);
+ }
+ conn_connect = mesonConnectorGetConnectState(meson_conn);
+ printf("\n connected:%d\n",conn_connect);
+ crtc_id = mesonConnectorGetCRTCId(meson_conn);
+ printf("\n CRTC id:%d\n",crtc_id);
+}
+static void meson_drm_prop_test(int drmFd, struct mesonProperty* meson_prop)
+{
+ int prop_id = -1;
+ uint64_t value = 0;
+ int ret = -1;
+ int i;
+
+ prop_id = mesonPropertyGetId(meson_prop);
+ printf("\n prop id:%d\n", prop_id);
+ value = mesonPropertyGetValue(meson_prop);
+ printf("\n value:%llu\n", value);
+ if ( (mesonPropertyGetType(meson_prop) & DRM_MODE_PROP_SIGNED_RANGE) || (mesonPropertyGetType(meson_prop) & DRM_MODE_PROP_RANGE) ) {
+ uint64_t min = 0;
+ uint64_t max = 0;
+ printf("\n prop type is DRM_MODE_PROP_RANGE or DRM_MODE_PROP_SIGNED_RANGE\n");
+ ret = mesonPropertyGetRange(meson_prop, &min, &max);
+ if (ret == 0) {
+ printf("\n range:min(%llu),max(%llu)\n", min, max);
+ }
+ }
+ if (mesonPropertyGetType(meson_prop) & DRM_MODE_PROP_ENUM) {
+ int len =-1;
+ printf("\n prop type is DRM_MODE_PROP_ENUM\n");
+ struct drm_mode_property_enum* enums = NULL;
+ ret = mesonPropertyGetEnumTypes(meson_prop, &len, &enums);
+ if (ret == 0) {
+ for ( i=0; i<len; i++ )
+ printf("\n enum name(%s) value(%llu)\n", enums[i].name, enums[i].value);
+ }
+ }
+ if (mesonPropertyGetType(meson_prop) & DRM_MODE_PROP_BLOB) {
+ int blob_count = -1;
+ printf("\n prop type is DRM_MODE_PROP_BLOB\n");
+ char* blob_data = NULL;
+ ret = mesonPropertyGetBlobData(meson_prop, drmFd, &blob_count, &blob_data);
+ if (ret == 0) {
+ for ( i=0; i<blob_count; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t");
+ printf("%.2hhx", blob_data[i]);
+ }
+ }
+ printf("\n");
+
+ }
+}
+#ifndef XDG_RUNTIME_DIR
+#define XDG_RUNTIME_DIR "/run"
+#endif
+
+static int meson_drm_setprop(uint32_t obj_id, char* prop_name, int prop_value )
+{
+ int ret = -1;
+ printf(" meson_drm_setprop: obj_id %d, prop_name: %s, prop_value:%d\n",obj_id, prop_name,prop_value);
+
+ if (prop_name) {
+ char cmdBuf[512] = {'\0'};
+ snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set property -s %d:%s:%d | grep \"Response\"",
+ XDG_RUNTIME_DIR, obj_id, prop_name, prop_value);
+ printf("Executing '%s'\n", cmdBuf);
+ FILE* fp = popen(cmdBuf, "r");
+ if (NULL != fp) {
+ char output[64] = {'\0'};
+ while (fgets(output, sizeof(output)-1, fp)) {
+ if (strlen(output) && strstr(output, "[0:")) {
+ ret = 0;
+ }
+ }
+ pclose(fp);
+ } else {
+ printf("meson_drm_setprop: popen failed\n");
+ }
+ }
+ return ret;
+}
+
+int main(void )
+{
+ printf("\n test moson_drm_test start\n");
+ const char *card;
+ int drm_fd = -1;
+ uint32_t object_type = 0;
+ card= getenv("WESTEROS_DRM_CARD");
+ if ( !card ) {
+ card= DEFAULT_CARD;
+ }
+ printf("\n drm card:%s\n",card);
+ drm_fd = open(card, O_RDONLY|O_CLOEXEC);
+ if ( drm_fd < 0 ) {
+ printf("\n drm card:%s open fail\n",card);
+ goto exit;
+ }
+ struct mesonConnector* meson_conn = NULL;
+ meson_conn = mesonConnectorCreate(drm_fd, DRM_MODE_CONNECTOR_HDMIA);
+ meson_drm_connector_test(drm_fd, meson_conn);
+
+ struct mesonConnector* meson_conn_CVBS = NULL;
+ meson_conn_CVBS = mesonConnectorCreate(drm_fd, DRM_MODE_CONNECTOR_TV);
+ meson_drm_connector_test(drm_fd, meson_conn_CVBS);
+ mesonConnectorDestroy(drm_fd,meson_conn_CVBS);
+ printf("\n connector change wait 10s\n");
+ sleep(10);
+ mesonConnectorUpdate(drm_fd, meson_conn);
+ meson_drm_connector_test(drm_fd, meson_conn);
+
+ uint32_t obj_id =mesonConnectorGetId(meson_conn);
+ uint32_t obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ printf("\n\n\n start to test prop\n");
+
+ printf("\n please select set/get prop, set->0, get->1\n");
+ int select_s_g = 0;
+ scanf("%d",&select_s_g);
+ if (select_s_g == 1) {
+ printf("\n please input object type:0->DRM_MODE_OBJECT_CONNECTOR, 1->DRM_MODE_OBJECT_CRTC\n");
+ scanf("%d",&object_type);
+ if (object_type == 0)
+ obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ else if (object_type == 1)
+ obj_type = DRM_MODE_OBJECT_CRTC;
+ else
+ obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ printf("\n please input object id: \n");
+ uint32_t object = 0;
+ scanf("%d",&object);
+ getchar();
+
+ printf("\n please input prop name: \n");
+ char name[30] = {0};
+ gets(name);
+ struct mesonProperty* meson_prop_test = NULL;
+ printf("\n drmfd:%d, drmObject:%u, drmObjectType:%u,name:%s\n",drm_fd, object, obj_type, name );
+ meson_prop_test = mesonPropertyCreate(drm_fd, object, obj_type, name);
+ meson_drm_prop_test(drm_fd, meson_prop_test);
+ mesonPropertyDestroy(meson_prop_test);
+ } else {
+ printf("\n please input object type:0->DRM_MODE_OBJECT_CONNECTOR, 1->DRM_MODE_OBJECT_CRTC\n");
+ scanf("%d",&object_type);
+ if (object_type == 0)
+ obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ else if (object_type == 1)
+ obj_type = DRM_MODE_OBJECT_CRTC;
+ else
+ obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ printf("\n please input object id: \n");
+ uint32_t object = 0;
+ scanf("%d",&object);
+ getchar();
+
+ printf("\n please input prop name: \n");
+ char name[30] = {0};
+ gets(name);
+
+ printf("\n please input prop value: \n");
+ int value = 0;
+ scanf("%d",&value);
+ struct mesonProperty* meson_prop_test_set = NULL;
+ printf("\n set prop drmfd:%d, drmObject:%u, drmObjectType:%u,name:%s value:%d\n",drm_fd, object, obj_type, name, value );
+ meson_prop_test_set = mesonPropertyCreate(drm_fd, object, obj_type, name);
+ printf("\n print before set !\n");
+ meson_drm_prop_test(drm_fd, meson_prop_test_set);
+ int ret_t = -255;
+ ret_t = meson_drm_setprop(obj_id, name, value);
+ ret_t = mesonPropertyUpdateValue(drm_fd, meson_prop_test_set);
+ if (ret_t == 0)
+ printf("\n mesonPropertyUpdateValue %s success! \n",name);
+
+ printf("\n print after set !\n");
+ meson_drm_prop_test(drm_fd, meson_prop_test_set);
+ mesonPropertyDestroy(meson_prop_test_set);
+ }
+
+ mesonConnectorDestroy(drm_fd, meson_conn);
+ close(drm_fd);
+ exit:
+ return 0;
+}
+
diff --git a/meson/meson_sample/meson_drm_display.c b/meson/meson_sample/meson_drm_display.c
new file mode 100644
index 0000000..17d78ee
--- /dev/null
+++ b/meson/meson_sample/meson_drm_display.c
@@ -0,0 +1,333 @@
+ /*
+ * Copyright (c) 2021 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 <linux/string.h>
+#include "libdrm_meson_connector.h"
+#include "libdrm_meson_property.h"
+#include "meson_drm_display.h"
+#define DEFAULT_CARD "/dev/dri/card0"
+#ifndef XDG_RUNTIME_DIR
+#define XDG_RUNTIME_DIR "/run"
+#endif
+static int s_drm_fd = -1;
+struct mesonConnector* s_conn_HDMI = NULL;
+
+static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value );
+static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value )
+{
+ int ret = -1;
+ printf(" meson_drm_setprop: obj_id %d, prop_name: %s, prop_value:%d\n",obj_id, prop_name,prop_value);
+
+ if (prop_name) {
+ char cmdBuf[512] = {'\0'};
+ snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set property -s %d:%s:%d | grep \"Response\"",
+ XDG_RUNTIME_DIR, obj_id, prop_name, prop_value);
+ printf("Executing '%s'\n", cmdBuf);
+ FILE* fp = popen(cmdBuf, "r");
+ if (NULL != fp) {
+ char output[64] = {'\0'};
+ while (fgets(output, sizeof(output)-1, fp)) {
+ if (strlen(output) && strstr(output, "[0:")) {
+ ret = 0;
+ }
+ }
+ pclose(fp);
+ } else {
+ printf("meson_drm_setprop: popen failed\n");
+ }
+ }
+ return ret;
+}
+
+bool meson_drm_init()
+{
+ bool ret = false;
+ const char *card;
+ int drm_fd = -1;
+ card= getenv("WESTEROS_DRM_CARD");
+ if ( !card ) {
+ card= DEFAULT_CARD;
+ }
+ s_drm_fd = open(card, O_RDONLY|O_CLOEXEC);
+ if ( s_drm_fd < 0 ) {
+ printf("\n drm card:%s open fail\n",card);
+ ret = false;
+ goto exit;
+ }
+ s_conn_HDMI = mesonConnectorCreate(s_drm_fd, DRM_MODE_CONNECTOR_HDMIA);
+ if ( !s_conn_HDMI ) {
+ printf("\n create HDMI connector fail\n");
+ ret = false;
+ goto exit;
+ }
+ ret = true;
+exit:
+ return ret;
+}
+
+void meson_drm_deinit()
+{
+ if (s_drm_fd >= 0 )
+ close(s_drm_fd);
+ if (s_conn_HDMI)
+ mesonConnectorDestroy(s_drm_fd,s_conn_HDMI);
+
+}
+
+int meson_drm_setHDMIEnable(bool enable)
+{
+ int ret = -1;
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ int avmute = 1;
+ if (enable)
+ avmute = 0;
+ else
+ avmute = 1;
+ if ( meson_drm_setprop(HDMI_conn_id, MESON_DRM_HDMITX_PROP_AVMUTE, avmute ) == 0 ) {
+ ret = 0;
+ }
+ return ret;
+}
+bool meson_drm_getHDMIEnable()
+{
+ bool ret = false;
+ if ( s_drm_fd >= 0 ) {
+ struct mesonProperty* meson_prop = NULL;
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ meson_prop = mesonPropertyCreate(s_drm_fd, HDMI_conn_id, DRM_MODE_OBJECT_CONNECTOR, MESON_DRM_HDMITX_PROP_AVMUTE);
+ uint64_t value = mesonPropertyGetValue(meson_prop);
+ if (value == 0)
+ ret = true;
+ else
+ ret = false;
+ mesonPropertyDestroy(meson_prop);
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+}
+int meson_drm_setVideoFormat(char* videoFormat)
+{
+ int ret = -1;;
+ printf(" meson_drm_setVideoFormat %s\n",videoFormat);
+ if (!videoFormat) {
+ ret = -1;
+ } else {
+ char cmdBuf[512] = {'\0'};
+ snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set mode %s | grep \"Response\"",
+ XDG_RUNTIME_DIR, videoFormat);
+ printf("Executing '%s'\n", cmdBuf);
+ /* FIXME: popen in use */
+ FILE* fp = popen(cmdBuf, "r");
+ if (NULL != fp) {
+ char output[64] = {'\0'};
+ while (fgets(output, sizeof(output)-1, fp)) {
+ if (strlen(output) && strstr(output, "[0:")) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ }
+ pclose(fp);
+ } else {
+ printf(" popen failed\n");
+ ret = -1;
+ }
+ }
+ return ret;
+}
+char* meson_drm_getVideoFormat()
+{
+ char cmdBuf[512] = {'\0'};
+ char output[64] = {'\0'};
+ char* mode = NULL;
+ char* mode_name = NULL;
+ snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console get mode | grep \"Response\"",
+ XDG_RUNTIME_DIR);
+ printf("Executing '%s'\n", cmdBuf);
+ /* FIXME: popen in use */
+ FILE* fp = popen(cmdBuf, "r");
+ if (NULL != fp) {
+ while (fgets(output, sizeof(output)-1, fp)) {
+ if (strlen(output) && strstr(output, "[0:")) {
+ mode = strstr(output, "[0:");
+ printf(" get response fail\n");
+ int len = strlen(mode);
+ mode_name = (char*)calloc(len, sizeof(char));
+ memcpy(mode_name, mode, len);
+ printf("\n len:%d mode_name:%s\n", len, mode_name);
+ }
+ }
+ pclose(fp);
+ } else {
+ printf(" popen failed\n");
+ }
+
+ return mode_name;
+}
+int meson_drm_setHDMItxEOTF(ENUM_DRM_HDMITX_PROP_EOTF value)
+{
+ int ret = -1;
+ int HDMI_crtc_id = mesonConnectorGetCRTCId(s_conn_HDMI);
+ if ( meson_drm_setprop(HDMI_crtc_id, MESON_DRM_HDMITX_PROP_EOTF, value ) == 0 ) {
+ ret = 0;
+ }
+ return ret;
+}
+ENUM_DRM_HDMITX_PROP_EOTF meson_drm_getHDMItxEOTF()
+{
+ ENUM_DRM_HDMITX_PROP_EOTF ret = HDMI_EOTF_MAX;
+ if ( s_drm_fd >= 0 ) {
+ int HDMI_crtc_id = mesonConnectorGetCRTCId(s_conn_HDMI);
+ struct mesonProperty* meson_prop = NULL;
+ meson_prop = mesonPropertyCreate(s_drm_fd, HDMI_crtc_id, DRM_MODE_OBJECT_CRTC, MESON_DRM_HDMITX_PROP_EOTF);
+ uint64_t value = 0;
+ value = mesonPropertyGetValue(meson_prop);
+ if (value == 0)
+ ret = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
+ else if (value == 2)
+ ret = HDMI_EOTF_SMPTE_ST2084;
+ else if (value == 18)
+ ret = HDMI_EOTF_MESON_DOLBYVISION;
+ else if (value == 19)
+ ret = HDMI_EOTF_MESON_DOLBYVISION_L;
+ else
+ ret = HDMI_EOTF_MAX;
+ mesonPropertyDestroy(meson_prop);
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+
+}
+int meson_drm_getRxSurportedModes(drmModeModeInfo **modes)
+{
+ //get from Rx EDID
+ return 0;
+}
+
+int meson_drm_getRxPreferreddMode(drmModeModeInfo *mode)
+{
+ //get from EDID
+ return 0;
+}
+int meson_drm_getRxSurportedEOTF(ENUM_DRM_HDMITX_PROP_EOTF* EOTFs)
+{
+ //get from EDID
+ return 0;
+}
+ENUM_MESON_DRM_CONNECTION meson_drm_getConnection()
+{
+ ENUM_MESON_DRM_CONNECTION ret = MESON_DRM_UNKNOWNCONNECTION;
+ if ( s_drm_fd >= 0 ) {
+ if (mesonConnectorUpdate(s_drm_fd, s_conn_HDMI) == 0) {
+ int ConnectState = -1;
+ ConnectState = mesonConnectorGetConnectState(s_conn_HDMI);
+ if (ConnectState == 1) {
+ ret = MESON_DRM_CONNECTED;
+ } else if (ConnectState == 2) {
+ ret = MESON_DRM_DISCONNECTED;
+ } else {
+ ret = MESON_DRM_UNKNOWNCONNECTION;
+ }
+ }
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+}
+int meson_drm_setContentProtection(bool enable)
+{
+ int ret = -1;
+ if ( s_drm_fd >= 0 ) {
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ if ( meson_drm_setprop(HDMI_conn_id, DRM_CONNECTOR_PROP_CONTENT_PROTECTION, (int)enable ) == 0 ) {
+ ret = 0;
+ }
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+}
+int meson_drm_setHDCPVersion(int version)
+{
+ int ret = -1;
+ if ( s_drm_fd >= 0 ) {
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ if ( meson_drm_setprop(HDMI_conn_id, DRM_CONNECTOR_PROP_CONTENT_TYPE, (int)version ) == 0 ) {
+ ret = 0;
+ }
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+}
+uint64_t meson_drm_getContentProtection()
+{
+ uint64_t ret = 0;;
+ if ( s_drm_fd >= 0 ) {
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ struct mesonProperty* meson_prop = NULL;
+ meson_prop = mesonPropertyCreate(s_drm_fd, HDMI_conn_id, DRM_MODE_OBJECT_CONNECTOR, DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
+ ret = mesonPropertyGetValue(meson_prop);
+ mesonPropertyDestroy(meson_prop);
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+
+}
+uint64_t meson_drm_getHDCPVersion()
+{
+ uint64_t ret = 0;
+ if ( s_drm_fd >= 0 ) {
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ struct mesonProperty* meson_prop = NULL;
+ meson_prop = mesonPropertyCreate(s_drm_fd, HDMI_conn_id, DRM_MODE_OBJECT_CONNECTOR, DRM_CONNECTOR_PROP_CONTENT_TYPE);
+ ret = mesonPropertyGetValue(meson_prop);
+ mesonPropertyDestroy(meson_prop);
+ } else {
+ printf("\n drm open fail\n");
+ }
+ return ret;
+
+}
+
+int meson_drm_getRxSupportedHDCPVersion(int* count, int** values)
+{
+ int ret = -1;
+ if (s_drm_fd >= 0 ) {
+ int HDMI_conn_id = mesonConnectorGetId(s_conn_HDMI);
+ struct mesonProperty* meson_prop = NULL;
+ meson_prop = mesonPropertyCreate(s_drm_fd, HDMI_conn_id, DRM_MODE_OBJECT_CONNECTOR, DRM_CONNECTOR_PROP_CONTENT_TYPE);
+ int len = 0;
+ struct drm_mode_property_enum* types = NULL;
+ mesonPropertyGetEnumTypes(meson_prop, &len, &types);
+ int i = 0;
+ int* values_temp = NULL;
+ *count = len;
+ values_temp = (int*)calloc(len, sizeof(int));
+ if (values_temp) {
+ for ( i=0; i<len; i++ ) {
+ values_temp[i] = (int)types[i].value;
+ }
+ *values = values_temp;
+ }
+ mesonPropertyDestroy(meson_prop);
+ ret = 0;
+ } else {
+ printf("\n drm open fail\n");
+ ret = -1;
+ }
+ return ret;
+}
+
diff --git a/meson/meson_sample/meson_drm_display.h b/meson/meson_sample/meson_drm_display.h
new file mode 100644
index 0000000..6448219
--- /dev/null
+++ b/meson/meson_sample/meson_drm_display.h
@@ -0,0 +1,60 @@
+ /*
+ * Copyright (c) 2021 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:
+ */
+
+#ifndef MESON_DRM_DISPLAY_H_
+#define MESON_DRM_DISPLAY_H_
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <xf86drmMode.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define DRM_DISPLAY_MODE_LEN 32
+typedef enum
+{
+ HDMI_EOTF_TRADITIONAL_GAMMA_SDR = 0,
+ HDMI_EOTF_SMPTE_ST2084 = 2,
+ HDMI_EOTF_MESON_DOLBYVISION = 18,
+ HDMI_EOTF_MESON_DOLBYVISION_L = 19,
+ HDMI_EOTF_MAX
+
+} ENUM_DRM_HDMITX_PROP_EOTF;
+
+typedef enum {
+ MESON_DRM_DISCONNECTED = 0,
+ MESON_DRM_CONNECTED = 1,
+ MESON_DRM_UNKNOWNCONNECTION = 2
+} ENUM_MESON_DRM_CONNECTION;
+
+bool meson_drm_init();
+void meson_drm_deinit();
+int meson_drm_setHDMIEnable(bool enable);
+bool meson_drm_getHDMIEnable();
+int meson_drm_setVideoFormat(char* videoFormat);
+char* meson_drm_getVideoFormat();
+int meson_drm_setHDMItxEOTF(ENUM_DRM_HDMITX_PROP_EOTF value);
+ENUM_DRM_HDMITX_PROP_EOTF meson_drm_getHDMItxEOTF();
+int meson_drm_getRxSurportedModes(drmModeModeInfo **modes);
+int meson_drm_getRxPreferreddMode(drmModeModeInfo *mode);
+int meson_drm_getRxSurportedEOTF(ENUM_DRM_HDMITX_PROP_EOTF* EOTFs);
+ENUM_MESON_DRM_CONNECTION meson_drm_getConnection();
+int meson_drm_setContentProtection(bool enable);
+int meson_drm_setHDCPVersion(int version);
+uint64_t meson_drm_getContentProtection();
+uint64_t meson_drm_getHDCPVersion();
+int meson_drm_getRxSupportedHDCPVersion(int* count, int** values);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/meson/meson_sample/meson_drm_display_test.c b/meson/meson_sample/meson_drm_display_test.c
new file mode 100644
index 0000000..4e4efde
--- /dev/null
+++ b/meson/meson_sample/meson_drm_display_test.c
@@ -0,0 +1,116 @@
+ /*
+ * Copyright (c) 2021 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 <linux/string.h>
+#include "libdrm_meson_connector.h"
+#include "libdrm_meson_property.h"
+#include "meson_drm_display.h"
+
+int main(void )
+{
+ printf("\n test meson_drm_display_test start\n");
+ if (!meson_drm_init()) {
+ printf("\n meson_drm_init int fail\n");
+ goto exit;
+ }
+ int select_s_g = 0;
+ printf("\n 1->get 0->set\n");
+ scanf("%d",&select_s_g);
+ if (select_s_g == 1) {
+ printf("get value:1->HDMI enable 2->video format 3->EOTF value 4->HDMI connected 5->SupportedHDCPVersion 6->HDCP version 7->Content Protection \n");
+ int get = 0;
+ scanf("%d", &get);
+ if (get == 1) {
+ printf("\n get HDMI enable:%d\n", meson_drm_getHDMIEnable());
+
+ } else if (get == 2) {
+ char* video_format = meson_drm_getVideoFormat();
+ printf("\n get HDMI :%s\n", meson_drm_getVideoFormat());
+ free(video_format);
+
+ } else if (get == 3) {
+ printf("\n EOTF:%d\n",meson_drm_getHDMItxEOTF());
+
+ } else if (get == 4) {
+ printf("\n HDMI connected:%d\n",meson_drm_getConnection());
+ } else if (get ==5 ) {
+ int len = 0;
+ int i = 0;
+ int* types = NULL;
+ if (meson_drm_getRxSupportedHDCPVersion(&len, &types) == 0) {
+ for ( i=0; i<len; i++ ) {
+ printf("\n %d\n", types[i]);
+ }
+ }
+ } else if (get == 6) {
+ uint64_t value = meson_drm_getHDCPVersion();
+ printf("\n HDMI version:%llu\n",value);
+
+ } else if (get == 7) {
+ uint64_t value = meson_drm_getContentProtection();
+ printf("\n Content Protection:%llu\n", value);
+ } else {
+ printf("\n invalid input\n");
+ }
+
+ } else {
+ printf("get value:1->HDMI enable 2->video format 3->EOTF value 4->Content Protection 5->HDCP Version \n");
+ int set = 0;
+ scanf("%d", &set);
+ if (set == 1) {
+ printf("\n 0->disable HDMI AV. 1->enable HDMI AV\n");
+ int enable = 1;
+ scanf("%d",&enable);
+ if (meson_drm_setHDMIEnable( (bool)enable ) == 0)
+ printf("\n set HDMI enable success\n");
+
+ } else if (set == 2) {
+ printf("\n set video format\n");
+ int enable = 1;
+ getchar();
+ char video_format[30] = {0};
+ gets(video_format);
+ if (meson_drm_setVideoFormat( video_format ) == 0)
+ printf("\n set Video Format success\n");
+
+ } else if (set == 3) {
+ printf("\n HDMI_EOTF_TRADITIONAL_GAMMA_SDR = 0 \n"
+ " HDMI_EOTF_SMPTE_ST20842 = 2 \n"
+ " HDMI_EOTF_NODV_HDR_SDR = 21 \n"
+ " HDMI_EOTF_NODV_SDR_HDR = 22 \n"
+ );
+ int hdr = 1;
+ scanf("%d",&hdr);
+ if (meson_drm_setHDMItxEOTF( (ENUM_DRM_HDMITX_PROP_EOTF)hdr ) == 0)
+ printf("\n set HDMI eotf success\n");
+
+ } else if (set == 4) {
+ printf("\n 0->disable content protection. 1->enable content protection\n");
+ int enable = 1;
+ scanf("%d",&enable);
+ if (meson_drm_setContentProtection( (bool)enable ) == 0)
+ printf("\n set HDMI enable success\n");
+
+ } else if (set == 5) {
+ printf("\n version:\n");
+ int version = 1;
+ scanf("%d",&version);
+ if (meson_drm_setHDCPVersion( version ) == 0)
+ printf("\n set HDCP Version success\n");
+ }
+ }
+ meson_drm_deinit();
+ getchar();
+exit:
+ return 0;
+}
+