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;
+}
+