diff mbox series

[RFC,v2,13/18] drm/vkms: Introduce config for connector

Message ID 20241122-google-remove-crtc-index-from-parameter-v2-13-81540742535a@bootlin.com (mailing list archive)
State New
Headers show
Series drm/vkms: Introduce detailed configuration | expand

Commit Message

Louis Chauvet Nov. 22, 2024, 5:20 p.m. UTC
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 62 +++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_config.h | 18 +++++++++--
 drivers/gpu/drm/vkms/vkms_drv.c    |  2 +-
 drivers/gpu/drm/vkms/vkms_output.c | 37 ++++++++++++-----------
 4 files changed, 98 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 3252f657ce515c0193a8c0e709bfe861feba0aca..998bdc50405116507e9cefd72a7b472c4c17e36d 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -17,6 +17,7 @@  struct vkms_config *vkms_config_create(void)
 	INIT_LIST_HEAD(&config->planes);
 	INIT_LIST_HEAD(&config->crtcs);
 	INIT_LIST_HEAD(&config->encoders);
+	INIT_LIST_HEAD(&config->connectors);
 
 	return config;
 }
@@ -28,6 +29,7 @@  struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 	struct vkms_config_plane *plane;
 	struct vkms_config_encoder *encoder;
 	struct vkms_config_crtc *crtc;
+	struct vkms_config_connector *connector;
 	struct vkms_config *vkms_config = vkms_config_create();
 
 	if (IS_ERR(vkms_config))
@@ -53,6 +55,12 @@  struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 	if (vkms_config_encoder_attach_crtc(encoder, crtc))
 		goto err_alloc;
 
+	connector = vkms_config_create_connector(vkms_config);
+	if (!connector)
+		goto err_alloc;
+	if (vkms_config_connector_attach_encoder(connector, encoder))
+		goto err_alloc;
+
 	plane = vkms_config_create_plane(vkms_config);
 	if (!plane)
 		goto err_alloc;
@@ -130,6 +138,23 @@  struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_conf
 }
 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_plane);
 
+struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *vkms_config)
+{
+	if (!vkms_config)
+		return NULL;
+
+	struct vkms_config_connector *vkms_config_connector =
+		kzalloc(sizeof(*vkms_config_connector), GFP_KERNEL);
+
+	if (!vkms_config_connector)
+		return NULL;
+
+	list_add(&vkms_config_connector->link, &vkms_config->connectors);
+	xa_init_flags(&vkms_config_connector->possible_encoders, XA_FLAGS_ALLOC);
+
+	return vkms_config_connector;
+}
+
 struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *vkms_config)
 {
 	if (!vkms_config)
@@ -227,6 +252,15 @@  void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc,
 	kfree(vkms_config_crtc);
 }
 
+void vkms_config_delete_connector(struct vkms_config_connector *vkms_config_conector)
+{
+	if (!vkms_config_conector)
+		return;
+	list_del(&vkms_config_conector->link);
+
+	kfree(vkms_config_conector);
+}
+
 void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_encoder,
 				struct vkms_config *vkms_config)
 {
@@ -247,6 +281,17 @@  void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_encoder,
 		}
 	}
 
+	struct vkms_config_connector *connector_config;
+
+	list_for_each_entry(connector_config, &vkms_config->connectors, link) {
+		unsigned long idx = 0;
+
+		xa_for_each(&connector_config->possible_encoders, idx, encoder) {
+			if (encoder == vkms_config_encoder)
+				xa_erase(&connector_config->possible_encoders, idx);
+		}
+	}
+
 	kfree(vkms_config_encoder->name);
 	kfree(vkms_config_encoder);
 }
@@ -256,7 +301,7 @@  void vkms_config_destroy(struct vkms_config *config)
 	struct vkms_config_plane *vkms_config_plane, *tmp_plane;
 	struct vkms_config_encoder *vkms_config_encoder, *tmp_encoder;
 	struct vkms_config_crtc *vkms_config_crtc, *tmp_crtc;
-
+	struct vkms_config_connector *vkms_config_connector, *tmp_connector;
 	list_for_each_entry_safe(vkms_config_plane, tmp_plane, &config->planes, link) {
 		vkms_config_delete_plane(vkms_config_plane, config);
 	}
@@ -266,6 +311,9 @@  void vkms_config_destroy(struct vkms_config *config)
 	list_for_each_entry_safe(vkms_config_crtc, tmp_crtc, &config->crtcs, link) {
 		vkms_config_delete_crtc(vkms_config_crtc, config);
 	}
+	list_for_each_entry_safe(vkms_config_connector, tmp_connector, &config->connectors, link) {
+		vkms_config_delete_connector(vkms_config_connector);
+	}
 
 	kfree(config);
 }
@@ -315,6 +363,18 @@  int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *vkm
 }
 EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc);
 
+int __must_check
+vkms_config_connector_attach_encoder(struct vkms_config_connector *vkms_config_connector,
+				     struct vkms_config_encoder *vkms_config_encoder)
+{
+	u32 encoder_idx;
+	int ret;
+
+	ret = xa_alloc(&vkms_config_connector->possible_encoders, &encoder_idx, vkms_config_encoder,
+		       xa_limit_32b, GFP_KERNEL);
+	return ret;
+}
+
 bool vkms_config_is_valid(struct vkms_config *config)
 {
 	struct vkms_config_plane *config_plane;
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 4a4c16dea7855cf36060986ef247be698974fafc..d64024e6682d217f7d9265f436ff2e6135860260 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -23,6 +23,7 @@  struct vkms_config {
 	struct list_head planes;
 	struct list_head crtcs;
 	struct list_head encoders;
+	struct list_head connectors;
 };
 
 /**
@@ -103,6 +104,15 @@  struct vkms_config_plane {
 	struct vkms_plane *plane;
 };
 
+struct vkms_config_connector {
+	struct list_head link;
+
+	struct xarray possible_encoders;
+
+	/* Internal usage */
+	struct drm_connector *connector;
+};
+
 /**
  * vkms_config_register_debugfs() - Register the debugfs file to display current configuration
  */
@@ -133,6 +143,8 @@  bool vkms_config_is_valid(struct vkms_config *vkms_config);
  */
 struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_config);
 
+struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *vkms_config);
+
 /**
  * vkms_config_create_crtc() - Create a crtc configuration
  *
@@ -153,7 +165,9 @@  int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *vkms_co
 					       struct vkms_config_crtc *vkms_config_crtc);
 int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *vkms_config_encoder,
 						 struct vkms_config_crtc *vkms_config_crtc);
-
+int __must_check
+vkms_config_connector_attach_encoder(struct vkms_config_connector *vkms_config_connector,
+				     struct vkms_config_encoder *vkms_config_encoder);
 /**
  * vkms_config_delete_plane() - Remove a plane configuration and frees its memory
  *
@@ -190,7 +204,7 @@  void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc,
  */
 void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_encoder,
 				struct vkms_config *vkms_config);
-
+void vkms_config_delete_connector(struct vkms_config_connector *vkms_config_conector);
 /**
  * vkms_config_alloc_default() - Allocate the configuration for the default device
  * @enable_writeback: Enable the writeback connector for this configuration
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 61ae2986568093ab0df7174a0a4678a75f9aad0c..eb6fd570b4549639f6818ff63fb334f2a461b23d 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -185,7 +185,7 @@  static int vkms_create(struct vkms_config *config)
 		goto out_devres;
 	}
 
-	ret = drm_vblank_init(&vkms_device->drm, 1);
+	ret = drm_vblank_init(&vkms_device->drm, list_count_nodes(&config->crtcs));
 	if (ret) {
 		DRM_ERROR("Failed to vblank\n");
 		goto out_devres;
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 6277ad72fdd476d1eff52ad037389bdb1a254f5e..90c0fa8eba53bef4ca80c374b40d69b0de155144 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -35,7 +35,7 @@  int vkms_output_init(struct vkms_device *vkmsdev)
 	struct drm_device *dev = &vkmsdev->drm;
 	struct vkms_config_plane *config_plane;
 	struct vkms_config_crtc *config_crtc;
-	struct drm_connector *connector;
+	struct vkms_config_connector *config_connector;
 	unsigned long idx;
 	int ret;
 
@@ -71,21 +71,6 @@  int vkms_output_init(struct vkms_device *vkmsdev)
 		}
 	}
 
-	connector = drmm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
-	if (!connector) {
-		DRM_ERROR("Failed to allocate connector\n");
-		return -ENOMEM;
-	}
-
-	ret = drmm_connector_init(dev, connector, &vkms_connector_funcs,
-				  DRM_MODE_CONNECTOR_VIRTUAL, NULL);
-	if (ret) {
-		DRM_ERROR("Failed to init connector\n");
-		return ret;
-	}
-
-	drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
-
 	list_for_each_entry(config_encoder, &vkmsdev->config->encoders, link) {
 		config_encoder->encoder = drmm_kzalloc(dev, sizeof(*config_encoder->encoder),
 						       GFP_KERNEL);
@@ -97,14 +82,32 @@  int vkms_output_init(struct vkms_device *vkmsdev)
 			DRM_ERROR("Failed to init encoder\n");
 			return ret;
 		}
+
 		xa_for_each(&config_encoder->possible_crtcs, idx, config_crtc) {
 			config_encoder->encoder->possible_crtcs |= drm_crtc_mask(&config_crtc->crtc->base);
 		}
 		if (IS_ERR(config_encoder->encoder))
 			return PTR_ERR(config_encoder->encoder);
-		ret = drm_connector_attach_encoder(connector, config_encoder->encoder);
+	}
+
+	list_for_each_entry(config_connector, &vkmsdev->config->connectors, link) {
+		config_connector->connector = drmm_kzalloc(&vkmsdev->drm,
+							   sizeof(*config_connector->connector),
+							   GFP_KERNEL);
+		if (!config_connector->connector)
+			return -ENOMEM;
+		ret = drmm_connector_init(&vkmsdev->drm, config_connector->connector,
+					  &vkms_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL, NULL);
 		if (ret)
 			return ret;
+		drm_connector_helper_add(config_connector->connector, &vkms_conn_helper_funcs);
+
+		xa_for_each(&config_connector->possible_encoders, idx, config_encoder) {
+			ret = drm_connector_attach_encoder(config_connector->connector,
+							   config_encoder->encoder);
+			if (ret)
+				return ret;
+		}
 	}
 
 	drm_mode_config_reset(dev);