diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index 40c385eedc1d..d89acdc1a752 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -688,6 +688,67 @@ static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test)
 	vkms_config_destroy(config);
 }
 
+static void vkms_config_test_connector_get_possible_encoders(struct kunit *test)
+{
+	struct vkms_config *config;
+	struct vkms_config_connector *connector_cfg1, *connector_cfg2;
+	struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
+	struct vkms_config_encoder **array;
+	size_t length;
+	int err;
+
+	config = vkms_config_create("test");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
+
+	connector_cfg1 = vkms_config_add_connector(config);
+	connector_cfg2 = vkms_config_add_connector(config);
+	encoder_cfg1 = vkms_config_add_encoder(config);
+	encoder_cfg2 = vkms_config_add_encoder(config);
+
+	/* No possible encoders */
+	array = vkms_config_connector_get_possible_encoders(connector_cfg1, &length);
+	KUNIT_ASSERT_EQ(test, length, 0);
+	KUNIT_ASSERT_NULL(test, array);
+
+	array = vkms_config_connector_get_possible_encoders(connector_cfg2, &length);
+	KUNIT_ASSERT_EQ(test, length, 0);
+	KUNIT_ASSERT_NULL(test, array);
+
+	/* Connector 1 attached to encoders 1 and 2 */
+	err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg1);
+	KUNIT_EXPECT_EQ(test, err, 0);
+	err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2);
+	KUNIT_EXPECT_EQ(test, err, 0);
+
+	array = vkms_config_connector_get_possible_encoders(connector_cfg1, &length);
+	KUNIT_ASSERT_EQ(test, length, 2);
+	KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1);
+	KUNIT_ASSERT_PTR_EQ(test, array[1], encoder_cfg2);
+	kfree(array);
+
+	array = vkms_config_connector_get_possible_encoders(connector_cfg2, &length);
+	KUNIT_ASSERT_EQ(test, length, 0);
+	KUNIT_ASSERT_NULL(test, array);
+
+	/* Connector 1 attached to encoder 1 and connector 2 to encoder 2 */
+	vkms_config_connector_detach_encoder(connector_cfg1, encoder_cfg2);
+
+	array = vkms_config_connector_get_possible_encoders(connector_cfg1, &length);
+	KUNIT_ASSERT_EQ(test, length, 1);
+	KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1);
+	kfree(array);
+
+	err = vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg2);
+	KUNIT_EXPECT_EQ(test, err, 0);
+
+	array = vkms_config_connector_get_possible_encoders(connector_cfg2, &length);
+	KUNIT_ASSERT_EQ(test, length, 1);
+	KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg2);
+	kfree(array);
+
+	vkms_config_destroy(config);
+}
+
 static struct kunit_case vkms_config_test_cases[] = {
 	KUNIT_CASE(vkms_config_test_empty_config),
 	KUNIT_CASE_PARAM(vkms_config_test_default_config,
@@ -706,6 +767,7 @@ static struct kunit_case vkms_config_test_cases[] = {
 	KUNIT_CASE(vkms_config_test_plane_attach_crtc),
 	KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
 	KUNIT_CASE(vkms_config_test_encoder_get_possible_crtcs),
+	KUNIT_CASE(vkms_config_test_connector_get_possible_encoders),
 	{}
 };
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index e94e48fe3ad9..db6e3c71fd68 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -94,6 +94,9 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
 		goto err_alloc;
 	vkms_config_connector_set_enabled(connector_cfg, true);
 
+	if (vkms_config_connector_attach_encoder(connector_cfg, encoder_cfg))
+		goto err_alloc;
+
 	return config;
 
 err_alloc:
@@ -629,6 +632,11 @@ struct vkms_config_encoder *vkms_config_add_encoder(struct vkms_config *config)
 void vkms_config_destroy_encoder(struct vkms_config *config,
 				 struct vkms_config_encoder *encoder_cfg)
 {
+	struct vkms_config_connector *connector_cfg;
+
+	list_for_each_entry(connector_cfg, &config->connectors, link)
+		vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg);
+
 	xa_destroy(&encoder_cfg->possible_crtcs);
 	list_del(&encoder_cfg->link);
 	kfree(encoder_cfg);
@@ -702,6 +710,7 @@ struct vkms_config_connector *vkms_config_add_connector(struct vkms_config *conf
 		return ERR_PTR(-ENOMEM);
 
 	vkms_config_connector_set_enabled(connector_cfg, false);
+	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
 
 	list_add_tail(&connector_cfg->link, &config->connectors);
 
@@ -710,6 +719,66 @@ struct vkms_config_connector *vkms_config_add_connector(struct vkms_config *conf
 
 void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg)
 {
+	xa_destroy(&connector_cfg->possible_encoders);
 	list_del(&connector_cfg->link);
 	kfree(connector_cfg);
 }
+
+int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg,
+						      struct vkms_config_encoder *encoder_cfg)
+{
+	struct vkms_config_encoder *possible_encoder;
+	unsigned long idx = 0;
+	u32 encoder_idx = 0;
+
+	xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) {
+		if (possible_encoder == encoder_cfg)
+			return -EINVAL;
+	}
+
+	return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx,
+			encoder_cfg, xa_limit_32b, GFP_KERNEL);
+}
+
+void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg,
+					  struct vkms_config_encoder *encoder_cfg)
+{
+	struct vkms_config_encoder *possible_encoder;
+	unsigned long idx = 0;
+
+	xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) {
+		if (possible_encoder == encoder_cfg)
+			xa_erase(&connector_cfg->possible_encoders, idx);
+	}
+}
+
+struct vkms_config_encoder **
+vkms_config_connector_get_possible_encoders(struct vkms_config_connector *connector_cfg,
+					    size_t *out_length)
+{
+	struct vkms_config_encoder **array;
+	struct vkms_config_encoder *possible_encoder;
+	unsigned long idx;
+	size_t length = 0;
+	int n = 0;
+
+	xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder)
+		length++;
+
+	if (length == 0) {
+		*out_length = length;
+		return NULL;
+	}
+
+	array = kmalloc_array(length, sizeof(*array), GFP_KERNEL);
+	if (!array)
+		return ERR_PTR(-ENOMEM);
+
+	xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) {
+		array[n] = possible_encoder;
+		n++;
+	}
+
+	*out_length = length;
+	return array;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index cc32aadfda8d..24052de05e98 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -94,6 +94,7 @@ struct vkms_config_encoder {
  * @enabled: Connector are a different from planes, CRTCs and encoders because
  *           they can be added and removed once the device is created.
  *           This flag represents if they are part of the device or not.
+ * @possible_encoders: Array of encoders that can be used with this connector
  * @connector: Internal usage. This pointer should never be considered as valid.
  *             It can be used to store a temporary reference to a VKMS connector
  *             during device creation. This pointer is not managed by the
@@ -103,6 +104,7 @@ struct vkms_config_connector {
 	struct list_head link;
 
 	bool enabled;
+	struct xarray possible_encoders;
 
 	/* Internal usage */
 	struct vkms_connector *connector;
@@ -443,4 +445,35 @@ vkms_config_connector_set_enabled(struct vkms_config_connector *connector_cfg,
 	connector_cfg->enabled = enabled;
 }
 
+/**
+ * vkms_config_connector_attach_encoder - Attach a connector to an encoder
+ * @connector_cfg: Connector to attach
+ * @encoder_cfg: Encoder to attach @connector_cfg to
+ */
+int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg,
+						      struct vkms_config_encoder *encoder_cfg);
+
+/**
+ * vkms_config_connector_detach_encoder - Detach a connector from an encoder
+ * @connector_cfg: Connector to detach
+ * @encoder_cfg: Encoder to detach @connector_cfg from
+ */
+void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg,
+					  struct vkms_config_encoder *encoder_cfg);
+
+/**
+ * vkms_config_connector_get_possible_encoders() - Return the array of possible
+ * encoders
+ * @connector_cfg: Connector to get the possible encoders from
+ * @out_length: Length of the returned array
+ *
+ * Returns:
+ * A list of pointers to the configurations. On success, the caller is
+ * responsible to free the returned array, but not its contents. On error,
+ * it returns an error and @out_length is invalid.
+ */
+struct vkms_config_encoder **
+vkms_config_connector_get_possible_encoders(struct vkms_config_connector *connector_cfg,
+					    size_t *out_length);
+
 #endif /* _VKMS_CONFIG_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 9c3e00817add..20ee8fdfa6f8 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -8,13 +8,14 @@
 int vkms_output_init(struct vkms_device *vkmsdev)
 {
 	struct drm_device *dev = &vkmsdev->drm;
-	struct vkms_connector *connector;
 	struct vkms_config_plane **plane_cfgs = NULL;
 	size_t n_planes;
 	struct vkms_config_crtc **crtc_cfgs = NULL;
 	size_t n_crtcs;
 	struct vkms_config_encoder **encoder_cfgs = NULL;
 	size_t n_encoders;
+	struct vkms_config_connector **connector_cfgs = NULL;
+	size_t n_connectors;
 	int ret = 0;
 	int writeback;
 	unsigned int n, i;
@@ -35,6 +36,13 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		goto err_free;
 	}
 
+	connector_cfgs = vkms_config_get_connectors(vkmsdev->config,
+						    &n_connectors);
+	if (IS_ERR(connector_cfgs)) {
+		ret = PTR_ERR(connector_cfgs);
+		goto err_free;
+	}
+
 	for (n = 0; n < n_planes; n++) {
 		struct vkms_config_plane *plane_cfg;
 		enum drm_plane_type type;
@@ -136,18 +144,42 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		kfree(possible_crtcs);
 	}
 
-	connector = vkms_connector_init(vkmsdev);
-	if (IS_ERR(connector)) {
-		DRM_ERROR("Failed to init connector\n");
-		ret = PTR_ERR(connector);
-		goto err_free;
-	}
+	for (n = 0; n < n_connectors; n++) {
+		struct vkms_config_connector *connector_cfg;
+		struct vkms_config_encoder **possible_encoders;
+		size_t n_possible_encoders;
 
-	/* Attach the encoder and the connector */
-	ret = drm_connector_attach_encoder(&connector->base, encoder_cfgs[0]->encoder);
-	if (ret) {
-		DRM_ERROR("Failed to attach connector to encoder\n");
-		goto err_free;
+		connector_cfg = connector_cfgs[n];
+
+		connector_cfg->connector = vkms_connector_init(vkmsdev);
+		if (IS_ERR(connector_cfg->connector)) {
+			DRM_ERROR("Failed to init connector\n");
+			ret = PTR_ERR(connector_cfg->connector);
+			goto err_free;
+		}
+
+		possible_encoders =
+			vkms_config_connector_get_possible_encoders(connector_cfg,
+								    &n_possible_encoders);
+		if (IS_ERR(possible_encoders)) {
+			ret = PTR_ERR(possible_encoders);
+			goto err_free;
+		}
+
+		for (i = 0; i < n_possible_encoders; i++) {
+			struct vkms_config_encoder *possible_encoder;
+
+			possible_encoder = possible_encoders[i];
+			ret = drm_connector_attach_encoder(&connector_cfg->connector->base,
+							   possible_encoder->encoder);
+			if (ret) {
+				DRM_ERROR("Failed to attach connector to encoder\n");
+				kfree(possible_encoders);
+				goto err_free;
+			}
+		}
+
+		kfree(possible_encoders);
 	}
 
 	drm_mode_config_reset(dev);
@@ -156,6 +188,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 	kfree(plane_cfgs);
 	kfree(crtc_cfgs);
 	kfree(encoder_cfgs);
+	kfree(connector_cfgs);
 
 	return ret;
 }
