weston: modepolicy exception during multi output connection [1/1]

PD#SWPL-178691

Problem:
hdmi mode output is 720p60hz after the version is burned and started

Solution:
each output uses a modepolicy class

Verify:
bm201

Change-Id: Ic36b69929164dd3d2889c0365d0e3c78161c45ef
Signed-off-by: leng.fang <leng.fang@amlogic.com>
diff --git a/aml-weston/aml-backend.c b/aml-weston/aml-backend.c
index fdc652d..4b1e22a 100644
--- a/aml-weston/aml-backend.c
+++ b/aml-weston/aml-backend.c
@@ -238,11 +238,12 @@
 	return rc;
 }
 
-static int drm_get_scaling()
+static int drm_get_scaling(struct weston_output *output)
 {
 	int ret = 100;
 
 #ifdef ENABLE_MODE_POLICY
+	mode_policy_set_output(output);
 	ret = mode_policy_get_scaling();
 #endif
 
@@ -257,7 +258,7 @@
 #endif
 
 #ifdef MESON_DRM_FIX_UI_SIZE
-		int scaling = drm_get_scaling();
+		int scaling = drm_get_scaling(&output->base);
 		if (scaling > 40 && scaling < 100) {
 			int x_margin = output->display_size.width * (100 - scaling) / 100;
 			int y_margin = output->display_size.height * (100 - scaling) / 100;
@@ -355,8 +356,14 @@
 static int drm_set_property(const char *name, int value)
 {
 	int ret = 0;
+	struct weston_output *output = NULL;
 
+#ifdef ENABLE_DRM_HELP
+	drm_cmd *info = drm_get_cmd();
+	output = info->head->base.output;
+#endif
 #ifdef ENABLE_MODE_POLICY
+	mode_policy_set_output(output);
 	ret = mode_policy_set_property(name, value);
 #endif
 
@@ -395,6 +402,7 @@
 			{
 				ctx = drm_get_cmd();
 				ctx->b = b;
+				ctx->head = head;
 				help_set_switch_mode_function((output_ctx)base, drm_output_switch_mode_helper);
 				help_set_force_refresh_function(drm_output_force_refresh);
 				help_set_property_function(drm_set_property);
@@ -882,6 +890,7 @@
 	struct weston_mode *wst_mode = NULL;
 	int ratio = 0;
 	int ret = 0;
+	struct weston_head *head = weston_output_get_first_head((struct weston_output *)ctx);
 
 	m.width = mode->width;
 	m.height = mode->height;
@@ -893,6 +902,7 @@
 
 #ifdef ENABLE_MODE_POLICY
 	mode_policy_update_bestmode(mode->auto_mode);
+	mode_policy_set_head(head);
 	if (!mode->auto_mode)
 		wst_mode = &m;
 	else
@@ -1029,6 +1039,7 @@
 	struct weston_compositor *compositor;
 	struct drm_output *output;
 	struct weston_mode *wst_mode;
+	struct weston_head *head;
 
 	if (!b || !b->compositor)
 		return;
@@ -1040,11 +1051,16 @@
 	b->display_enable = enable;
 
 	if (enable == 1) {
-		mode_policy_resume();
-		wst_mode = mode_policy_choose_mode(NULL);
 		wl_list_for_each(output, &compositor->output_list, base.link) {
-			weston_output_mode_set_native(&output->base,
-						wst_mode, output->base.current_scale);
+			head = weston_output_get_first_head(&output->base);
+#ifdef ENABLE_MODE_POLICY
+			mode_policy_set_head(head);
+			mode_policy_resume();
+			wst_mode = mode_policy_choose_mode(NULL);
+			if (wst_mode)
+				weston_output_mode_set_native(&output->base,
+							wst_mode, output->base.current_scale);
+#endif
 			if (output->base.start_repaint_loop)
 				output->base.start_repaint_loop(&output->base);
 		}
@@ -1079,7 +1095,7 @@
 						} else if (compare_string(tok, "bestmode")) {
 							sprintf(info->response, "%d: bestmode %d", 0, drm_get_bestmode() ? 1 : 0);
 						} else if (compare_string( tok, "scaling")) {
-							sprintf(info->response, "%d: scaling %d", 0, drm_get_scaling());
+							sprintf(info->response, "%d: scaling %d", 0, drm_get_scaling(info->head->base.output));
 						}
 					}
 				} else if (compare_string(tok, "set")) {
diff --git a/aml-weston/aml-backend.h b/aml-weston/aml-backend.h
index 63bf35c..56f0f0b 100644
--- a/aml-weston/aml-backend.h
+++ b/aml-weston/aml-backend.h
@@ -21,6 +21,7 @@
 
 typedef struct _drm_cmd {
 	struct drm_backend *b;
+	struct drm_head *head;
 	char response[256 + 3];
 } drm_cmd;
 
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
index 563a346..22e1002 100644
--- a/libweston/backend-drm/drm.c
+++ b/libweston/backend-drm/drm.c
@@ -2109,9 +2109,11 @@
 	if (head->base.connected)
 		init_mode_policy_without_mode(&head->base,
 				head->backend->drm.fd, head->connector.conn);
-	if (head->base.device_changed)
+	if (head->base.device_changed) {
+		mode_policy_set_head(&head->base);
 		mode_policy_set_hotplug(head->base.connected ?
 				AML_WESTON_HOTPLUG_PLUG : AML_WESTON_HOTPLUG_UNPLUG, false);
+	}
 #endif
 
 	if (head->base.device_changed)
@@ -2644,15 +2646,24 @@
 	struct drm_output *output;
 	struct drm_crtc *crtc;
 	struct weston_mode *wst_mode;
+	struct weston_head *head;
 
 	if (compositor->session_active) {
 		weston_log("activating session\n");
 
-		mode_policy_resume();
-		wst_mode = mode_policy_choose_mode(NULL);
-		wl_list_for_each(output, &compositor->output_list, base.link)
-			weston_output_mode_set_native(&output->base,
-						wst_mode, output->base.current_scale);
+		wl_list_for_each(output, &compositor->output_list, base.link) {
+			head = weston_output_get_first_head(&output->base);
+#ifdef ENABLE_MODE_POLICY
+			mode_policy_set_head(head);
+			mode_policy_resume();
+			wst_mode = mode_policy_choose_mode(NULL);
+			if (wst_mode)
+				weston_output_mode_set_native(&output->base,
+							wst_mode, output->base.current_scale);
+#endif
+			if (output->base.start_repaint_loop && !strstr(output->base.name, "LVDS"))
+				output->base.start_repaint_loop(&output->base);
+		}
 
 		weston_compositor_wake(compositor);
 		weston_compositor_damage_all(compositor);
@@ -2663,7 +2674,6 @@
 		weston_compositor_resume_focus(compositor);
 	} else {
 		weston_log("deactivating session\n");
-		drm_change_to_dummy_mode(b->compositor);
 		udev_input_disable(&b->input);
 
 		weston_compositor_offscreen(compositor);
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index b27b3f3..54c2832 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -1081,7 +1081,9 @@
 
 	state_invalid = b->state_invalid;
 	allow_modeset = b->allow_modeset;
+#ifdef ENABLE_MODE_POLICY
 	mode_policy_update_modeset(&b->state_invalid, &b->allow_modeset);
+#endif
 	if (b->state_invalid) {
 		struct weston_head *head_base;
 		struct drm_head *head;
diff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c
index f32f0a0..e984e4c 100644
--- a/libweston/backend-drm/modes.c
+++ b/libweston/backend-drm/modes.c
@@ -827,6 +827,7 @@
 
 	strcpy(wstmodeline, modeline);
 #ifdef ENABLE_MODE_POLICY
+	mode_policy_set_head(&head->base);
 	wstmode = mode_policy_choose_mode(NULL);
 	if (wstmode)
 		sprintf(wstmodeline, "%dx%d@%d %u:%u",
diff --git a/libweston/modepolicy/DisplayAdapter.h b/libweston/modepolicy/DisplayAdapter.h
index a7cba02..6eb4699 100644
--- a/libweston/modepolicy/DisplayAdapter.h
+++ b/libweston/modepolicy/DisplayAdapter.h
@@ -43,7 +43,7 @@
     } while(0)
 #define MESON_LOGD(fmt, ...) \
     do { \
-        if (g_activeLevel >= 2) { \
+        if (g_activeLevel >= 3) { \
             weston_log("DEBUG: %s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
         } \
     } while(0)
diff --git a/libweston/modepolicy/ModePolicy.cpp b/libweston/modepolicy/ModePolicy.cpp
index cea77ad..00ac6c9 100644
--- a/libweston/modepolicy/ModePolicy.cpp
+++ b/libweston/modepolicy/ModePolicy.cpp
@@ -991,7 +991,7 @@
     setBootEnv(UBOOTENV_ISBESTMODE, "true");
 
     //save hdmi resolution to env
-    setBootEnv(UBOOTENV_HDMIMODE, "none");
+    // setBootEnv(UBOOTENV_HDMIMODE, "none");
 
     return 0;
 }
@@ -2509,7 +2509,7 @@
     uint32_t height = 1080;
     char log_level[PROPERTY_VALUE_MAX] = { 0 };
 
-    sys_get_string_prop_default("WESTEROS_GL_MODE_POLICY_DEBUG", log_level, "2");
+    sys_get_string_prop_default("WESTON_GL_MODE_POLICY_DEBUG", log_level, "2");
     g_activeLevel = atoi(log_level);
     mAdapter->setLogLevel(g_activeLevel);
 
diff --git a/libweston/modepolicy/modepolicy_aml.cpp b/libweston/modepolicy/modepolicy_aml.cpp
index 93acd83..5334395 100644
--- a/libweston/modepolicy/modepolicy_aml.cpp
+++ b/libweston/modepolicy/modepolicy_aml.cpp
@@ -4,23 +4,34 @@
 #include "DisplayAdapter.h"
 #include "modepolicy_aml.h"
 
-weston_ctx *gCtx = NULL;
+weston_ctx_list *gCtx_list = NULL;
 static int g_activeLevel = 3;
 
+/* if prop set need change mode, add it to this */
 static char *prop_changed_and_mode[] = {
 	"color_space",
 	"color_depth"
 };
 
+static weston_ctx_list *weston_get_ctx_list()
+{
+	if (!gCtx_list) {
+		gCtx_list = (weston_ctx_list *)calloc(1, sizeof(*gCtx_list));
+		wl_list_init(&gCtx_list->ctx_list);
+	}
+	return gCtx_list;
+}
+
 weston_ctx *weston_get_ctx()
 {
-	if (!gCtx) {
-		gCtx = (weston_ctx *)calloc(1, sizeof(*gCtx));
-		gCtx->need_update_hdmi_param = false;
-		gCtx->scaling = -1;
-		wl_list_init(&gCtx->prop_list);
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
+	weston_ctx *ctx, *tmp;
+
+	wl_list_for_each(ctx, &ctx_list->ctx_list, link) {
+		if (ctx->head == ctx_list->head)
+			return ctx;
 	}
-	return gCtx;
+	return NULL;
 }
 
 static void weston_prop_list_init(weston_ctx *ctx)
@@ -113,6 +124,9 @@
 {
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return 0;
+
 	return weston_get_property_value(ctx, key, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
 }
 
@@ -120,6 +134,9 @@
 {
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return 0;
+
 	return weston_get_property_value(ctx, key, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
 }
 
@@ -149,7 +166,7 @@
 	weston_ctx *ctx = weston_get_ctx();
 	struct weston_mode *wmode = NULL;
 
-	if (!wmode && ctx->current_mode.width != 0)
+	if (!wmode && ctx && ctx->current_mode.width != 0)
 		wmode = &ctx->current_mode;
 
 	return get_mode_name_for_weston_mode(ctx, wmode, mode);
@@ -325,6 +342,9 @@
 	weston_ctx *ctx = weston_get_ctx();
 	drmModeModeInfo info = {0};
 
+	if (!ctx)
+		return false;
+
 	if (westonGetDrmModeInfoByName(ctx, mode, &info)) {
 		ctx->next_mode.width = info.hdisplay;
 		ctx->next_mode.height = info.vdisplay;
@@ -342,6 +362,9 @@
 	weston_ctx *ctx = weston_get_ctx();
 	int value = 0;
 
+	if (!ctx)
+		return 0;
+
 	if (!ctx->crtc || !ctx->conn)
 		return 0;
 
@@ -360,6 +383,9 @@
 	prop_info *info;
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return 0;
+
 	wl_list_for_each(info, &ctx->prop_list, link) {
 		if (!strcmp(name, info->name) && info->item_id == id) {
 			MESON_LOGD("name: %s, id: %d, prop: %d, value: %d\n",
@@ -401,7 +427,7 @@
 {
 	weston_ctx *ctx = weston_get_ctx();
 	const char *value = bootenv_get("scaling");
-	int scaling = 1;
+	int scaling = -1;
 
 	if (value)
 		scaling = atoi(value);
@@ -446,6 +472,9 @@
 	prop_info *info;
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return 0;
+
 	wl_list_for_each(info, &ctx->prop_list, link) {
 		if (!strcmp(name, info->name)) {
 			if (info->need_change == 1)
@@ -460,6 +489,9 @@
 	prop_info *info;
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return -1;
+
 	wl_list_for_each(info, &ctx->prop_list, link) {
 		if (!strcmp(name, info->name))
 				return info->item_id;
@@ -467,9 +499,8 @@
 	return -1;
 }
 
-static int mode_policy_parse_other(const char *name, int value)
+static int mode_policy_parse_other(weston_ctx *ctx, const char *name, int value)
 {
-	weston_ctx *ctx = weston_get_ctx();
 	char attrvalue[32] = { 0 };
 
 	if (STRCMPS(name, "scaling") == 0) {
@@ -485,7 +516,6 @@
 
 static void set_color_attribute(char *space, int depth)
 {
-	weston_ctx *ctx = weston_get_ctx();
 	char attrvalue[32] = { 0 };
 	char mode[] = { 0 };
 
@@ -501,10 +531,15 @@
 	int color_space = 0;
 	int color_depth = 0;
 	int id = get_id_by_name(name);
+	weston_ctx *ctx = weston_get_ctx();
 	MESON_LOGI("id: %d, name: %s, value: %d", id, name, value);
 
+	if (!ctx)
+		return 0;
+
+	initModePolicyFun(ctx->crtc, ctx->conn, callback);
 	if (value < 0 || id < 0)
-		return mode_policy_parse_other(name, value);
+		return mode_policy_parse_other(ctx, name, value);
 
 	if (strncmp(name, "dv_mode", sizeof("dv_mode")) == 0) {
 		setDvMode(value == 0 ? 1 : (value == 1 ? 2 : 0));
@@ -533,6 +568,9 @@
 {
 	weston_ctx *ctx = weston_get_ctx();
 
+	if (!ctx)
+		return 100;
+
 	if (ctx->scaling < 0)
 		return 100;
 
@@ -611,46 +649,69 @@
 	return crtc;
 }
 
-void init_mode_policy_without_mode(struct weston_head *head, int fd, drmModeConnector *conn)
+void mode_policy_set_head(struct weston_head *head)
 {
-	weston_ctx *ctx = weston_get_ctx();
-	drmModeCrtc *crtc = NULL;
-	bool changed = false;
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
+	ctx_list->head = head;
+}
 
-	if (conn && conn->connector_type != DRM_MODE_CONNECTOR_TV) {
-		crtc = weston_get_crtc_for_conn(fd, conn);
-		if (!crtc)
-			return;
+void mode_policy_set_output(struct weston_output *output)
+{
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
+	weston_ctx *ctx, *tmp;
 
-		initModePolicyFun(crtc, conn, callback);
-		if ((ctx->crtc && ctx->crtc->crtc_id != crtc->crtc_id) || !ctx->crtc)
-			changed = true;
-
-		if (ctx->crtc)
-			drmModeFreeCrtc(ctx->crtc);
-		ctx->drm_fd = fd;
-		ctx->crtc = crtc;
-		ctx->conn = conn;
-		ctx->head = head;
-		ctx->current_mode = drm_mode_to_weston_mode(&ctx->crtc->mode);
-		if (changed) {
-			weston_prop_list_init(ctx);
-			weston_add_property(ctx, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
-			weston_add_property(ctx, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
+	wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
+		if (ctx->head && ctx->head->output == output) {
+			mode_policy_set_head(ctx->head);
+			break;
 		}
 	}
 }
 
-void init_mode_policy(int fd, drmModeConnector *conn)
+static void mode_policy_update_ctx(weston_ctx *ctx,
+			struct weston_head *head, int fd, drmModeConnector *conn)
 {
-	weston_ctx *ctx = weston_get_ctx();
-	drmModeCrtc *crtc = weston_get_crtc_for_conn(fd, conn);
+	drmModeCrtc *crtc = NULL;
+	bool changed = false;
+
+	if (!ctx)
+		return;
+
+	crtc = weston_get_crtc_for_conn(fd, conn);
+	if (!crtc)
+		return;
+
+	if ((ctx->crtc && ctx->crtc->crtc_id != crtc->crtc_id) || !ctx->crtc)
+		changed = true;
+
 	if (ctx->crtc)
 		drmModeFreeCrtc(ctx->crtc);
 	ctx->drm_fd = fd;
 	ctx->crtc = crtc;
 	ctx->conn = conn;
-	initModePolicy(crtc, conn, callback);
+	ctx->head = head;
+	if (changed) {
+		ctx->current_mode = drm_mode_to_weston_mode(&ctx->crtc->mode);
+		weston_prop_list_init(ctx);
+		weston_add_property(ctx, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
+		weston_add_property(ctx, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
+	}
+}
+
+void init_mode_policy_without_mode(struct weston_head *head, int fd, drmModeConnector *conn)
+{
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
+	weston_ctx *ctx;
+
+	mode_policy_set_head(head);
+	ctx = weston_get_ctx();
+	if (!ctx) {
+		ctx = (weston_ctx *)calloc(1, sizeof(*ctx));
+		ctx->scaling = -1;
+		wl_list_init(&ctx->prop_list);
+		wl_list_insert(&ctx_list->ctx_list, &ctx->link);
+	}
+	mode_policy_update_ctx(ctx, head, fd, conn);
 }
 
 static bool need_mode_changed(char *name)
@@ -667,25 +728,28 @@
 
 int mode_policy_add_prop(drmModeAtomicReq *req, bool mode_changed)
 {
-	weston_ctx *ctx = weston_get_ctx();
 	prop_info *info;
 	int err = 0, ret = 0;
 	int count = 0;
+	weston_ctx_list * ctx_list = weston_get_ctx_list();
+	weston_ctx *ctx, *tmp;
 
-	wl_list_for_each(info, &ctx->prop_list, link) {
-		if (info->need_change) {
-			if (need_mode_changed(info->name) && !mode_changed)
-				continue;
+	wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
+		wl_list_for_each(info, &ctx->prop_list, link) {
+			if (info->need_change) {
+				if (need_mode_changed(info->name) && !mode_changed)
+					continue;
 
-			err = drmModeAtomicAddProperty(req, info->item_id, info->prop_id, info->value);
-			if (!err)
-				MESON_LOGE("drmModeAtomicAddProperty %s fail: %d(%d)\n",
-					info->name, err, errno);
-			info->need_change = 0;
-			ret |= (err <= 0) ? -1 : 0;
-			if (!ret)
-				count++;
-			ctx->need_update_hdmi_param = true;
+				err = drmModeAtomicAddProperty(req, info->item_id, info->prop_id, info->value);
+				if (!err)
+					MESON_LOGE("drmModeAtomicAddProperty %s fail: %d(%d)\n",
+						info->name, err, errno);
+				info->need_change = 0;
+				ret |= (err <= 0) ? -1 : 0;
+				if (!ret)
+					count++;
+				ctx->need_update_hdmi_param = true;
+			}
 		}
 	}
 	return ret >= 0 ? count : ret;
@@ -693,19 +757,23 @@
 
 void mode_policy_set_hotplug(int plug, bool force)
 {
-	weston_ctx *ctx = weston_get_ctx();
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
 
 	if (force) {
-		ctx->hotplug = plug;
+		ctx_list->hotplug = plug;
 	} else {
-		if (ctx->hotplug & plug)
-			ctx->hotplug = plug;
+		if (ctx_list->hotplug & plug)
+			ctx_list->hotplug = plug;
 	}
 }
 
 void mode_policy_update_mode(struct weston_mode *mode)
 {
 	weston_ctx *ctx = weston_get_ctx();
+
+	if (!ctx)
+		return;
+
 	if (mode)
 		ctx->current_mode = *mode;
 	else if (ctx->mode_changed)
@@ -718,18 +786,23 @@
 
 struct weston_mode *mode_policy_choose_mode(struct weston_mode *mode)
 {
+	weston_ctx_list * ctx_list = weston_get_ctx_list();
 	weston_ctx *ctx = weston_get_ctx();
 	char name[32] = { 0 };
 
+	if (!ctx)
+		return NULL;
+
+	initModePolicyFun(ctx->crtc, ctx->conn, callback);
 	if (mode) {
 		if (get_mode_name_for_weston_mode(ctx, mode, name))
 			setActiveConfig(name);
 	} else {
-		if (ctx->hotplug & (AML_WESTON_HOTPLUG_PLUG | AML_WESTON_HOTPLUG_UNPLUG))
-			onHotplug(ctx->hotplug & AML_WESTON_HOTPLUG_PLUG);
-		else if (ctx->hotplug & (AML_WESTON_HOTPLUG_BOOT | AML_WESTON_HOTPLUG_SET))
+		if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_PLUG | AML_WESTON_HOTPLUG_UNPLUG))
+			onHotplug(ctx_list->hotplug & AML_WESTON_HOTPLUG_PLUG);
+		else if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_BOOT | AML_WESTON_HOTPLUG_SET))
 			initModePolicy(NULL, NULL, callback);
-		ctx->hotplug = AML_WESTON_HOTPLUG_INIT;
+		ctx_list->hotplug = AML_WESTON_HOTPLUG_INIT;
 	}
 	if (ctx->mode_update)
 		return &ctx->next_mode;
@@ -743,10 +816,18 @@
 
 void mode_policy_update_modeset(bool *state, bool *modeset)
 {
-	weston_ctx *ctx = weston_get_ctx();
+	weston_ctx_list * ctx_list = weston_get_ctx_list();
+	weston_ctx *ctx, *tmp;
+	bool mode_changed = false;
 
-	MESON_LOGI("state: %d, modeset: %d, mode_changed: %d", *state, *modeset, ctx->mode_changed);
-	if (ctx->mode_changed) {
+
+	wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
+		if (ctx->mode_changed)
+			mode_changed = true;
+	}
+
+	MESON_LOGV("state: %d, modeset: %d, mode_changed: %d", *state, *modeset, mode_changed);
+	if (mode_changed) {
 		if (!*state)
 			*state = true;
 		if (!*modeset)
@@ -759,6 +840,9 @@
 	weston_ctx *ctx = weston_get_ctx();
 	int flag;
 
+	if (!ctx)
+		return;
+
 	flag = (ctx->conn &&
 		(ctx->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
 		ctx->conn->connector_type == DRM_MODE_CONNECTOR_TV)) ?
@@ -770,18 +854,22 @@
 static void * wstUpdatenvThread(void *arg )
 {
 	long long delay = 16667LL;
-	weston_ctx *ctx = (weston_ctx *)arg;
+	weston_ctx_list *ctx_list = (weston_ctx_list *)arg;
+	weston_ctx *ctx, *tmp;
 
-	while (!ctx->update_env_thread_stop_requested)
+	while (!ctx_list->update_env_thread_stop_requested)
 	{
-		if ((ctx->mode_changed && !ctx->prop_changed) ||
-			(ctx->prop_changed && ctx->need_update_hdmi_param))
-		{
-			weston_log("%s[%d]\n", __func__, __LINE__);
-			updateEnv();
-			ctx->need_update_hdmi_param = false;
-			ctx->mode_changed = false;
-			ctx->prop_changed = false;
+		wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
+			if ((ctx->mode_changed && !ctx->prop_changed) ||
+				(ctx->prop_changed && ctx->need_update_hdmi_param))
+			{
+				weston_log("%s[%d]\n", __func__, __LINE__);
+				initModePolicyFun(ctx->crtc, ctx->conn, callback);
+				updateEnv();
+				ctx->need_update_hdmi_param = false;
+				ctx->mode_changed = false;
+				ctx->prop_changed = false;
+			}
 		}
 		usleep( delay );
 	}
@@ -792,10 +880,10 @@
 void weston_start_update_env_thread()
 {
 	int rc;
-	weston_ctx *ctx = weston_get_ctx();
+	weston_ctx_list *ctx_list = weston_get_ctx_list();
 
-	ctx->update_env_thread_stop_requested = false;
-	rc = pthread_create(&ctx->update_env_thread_id, NULL, wstUpdatenvThread, ctx);
+	ctx_list->update_env_thread_stop_requested = false;
+	rc = pthread_create(&ctx_list->update_env_thread_id, NULL, wstUpdatenvThread, ctx_list);
 	if ( rc )
 		MESON_LOGE("unable to start updatenv thread: rc %d errno %d", rc, errno);
 }
diff --git a/libweston/modepolicy/modepolicy_aml.h b/libweston/modepolicy/modepolicy_aml.h
index c372e14..2c7b6d9 100644
--- a/libweston/modepolicy/modepolicy_aml.h
+++ b/libweston/modepolicy/modepolicy_aml.h
@@ -19,8 +19,6 @@
 
 typedef struct _weston_ctx {
 	int drm_fd;
-	pthread_t update_env_thread_id;
-	bool update_env_thread_stop_requested;
 	bool mode_changed;
 	bool prop_changed;
 	bool need_update_hdmi_param;
@@ -31,10 +29,18 @@
 	struct weston_mode next_mode;
 	int scaling;
 	bool mode_update;
-	int hotplug;  // 0: init 2: hotplug 4: unplug
 	struct wl_list prop_list;
+	struct wl_list link;
 } weston_ctx;
 
+typedef struct _weston_ctx_list {
+	struct wl_list ctx_list;
+	struct weston_head *head;
+	pthread_t update_env_thread_id;
+	bool update_env_thread_stop_requested;
+	int hotplug;
+} weston_ctx_list;
+
 enum {
 	AML_WESTON_HOTPLUG_INIT = 0x0,
 	AML_WESTON_HOTPLUG_BOOT = 0x1,
@@ -45,6 +51,8 @@
 
 #define STRCMPS(str1, str2) strncmp(str1, str2, sizeof(str2))
 
+void mode_policy_set_head(struct weston_head *head);
+void mode_policy_set_output(struct weston_output *output);
 void init_mode_policy_without_mode(struct weston_head *head, int fd, drmModeConnector *conn);
 void weston_start_update_env_thread();
 bool WestonGetUbootIsBestmode();