mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "José Expósito" <jose.exposito89@gmail.com>
To: louis.chauvet@bootlin.com
Cc: hamohammed.sa@gmail.com, simona@ffwll.ch, melissa.srw@gmail.com,
	maarten.lankhorst@linux.intel.com, mripard@kernel.org,
	tzimmermann@suse.de, airlied@gmail.com,
	dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	"José Expósito" <jose.exposito89@gmail.com>
Subject: [PATCH 13/13] drm/vkms: Allow to attach connectors and encoders
Date: Wed, 29 Jan 2025 12:00:59 +0100	[thread overview]
Message-ID: <20250129110059.12199-14-jose.exposito89@gmail.com> (raw)
In-Reply-To: <20250129110059.12199-1-jose.exposito89@gmail.com>

Add a list of possible encoders to the connector configuration and
helpers to attach and detach them.

Now that the default configuration has its connector and encoder
correctly, configure the output following the configuration.

Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c | 62 +++++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.c            | 69 +++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h            | 33 +++++++++
 drivers/gpu/drm/vkms/vkms_output.c            | 57 +++++++++++----
 4 files changed, 209 insertions(+), 12 deletions(-)

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


  parent reply	other threads:[~2025-01-29 11:01 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-29 11:00 [PATCH 00/13] drm/vkms: Allow to configure device José Expósito
2025-01-29 11:00 ` [PATCH 01/13] drm/vkms: Extract vkms_connector header José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-02-11 10:37     ` José Expósito
2025-01-29 11:00 ` [PATCH 02/13] drm/vkms: Add KUnit test scaffolding José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 03/13] drm/vkms: Extract vkms_config header José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-02-11 10:39     ` José Expósito
2025-01-29 11:00 ` [PATCH 04/13] drm/vkms: Move default_config creation to its own function José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 05/13] drm/vkms: Set device name from vkms_config José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 06/13] drm/vkms: Add a validation function for VKMS configuration José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 07/13] drm/vkms: Allow to configure multiple planes José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-02-11 10:43     ` José Expósito
2025-02-12 14:10       ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 08/13] drm/vkms: Allow to configure multiple CRTCs José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-02-11 10:44     ` José Expósito
2025-02-12 14:12       ` Louis Chauvet
2025-02-13 15:26         ` José Expósito
2025-01-29 11:00 ` [PATCH 09/13] drm/vkms: Allow to attach planes and CRTCs José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-02-11 10:47     ` José Expósito
2025-02-12 14:10       ` Louis Chauvet
2025-02-13 15:32         ` José Expósito
2025-01-29 11:00 ` [PATCH 10/13] drm/vkms: Allow to configure multiple encoders José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 11/13] drm/vkms: Allow to attach encoders and CRTCs José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` [PATCH 12/13] drm/vkms: Allow to configure multiple connectors José Expósito
2025-01-30 13:48   ` Louis Chauvet
2025-01-29 11:00 ` José Expósito [this message]
2025-01-30 13:48   ` [PATCH 13/13] drm/vkms: Allow to attach connectors and encoders Louis Chauvet
2025-01-30 13:48 ` [PATCH 00/13] drm/vkms: Allow to configure device Louis Chauvet
2025-01-31  9:31   ` José Expósito
2025-01-31 13:02     ` Louis Chauvet
2025-01-31 17:13       ` José Expósito

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250129110059.12199-14-jose.exposito89@gmail.com \
    --to=jose.exposito89@gmail.com \
    --cc=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hamohammed.sa@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=louis.chauvet@bootlin.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=melissa.srw@gmail.com \
    --cc=mripard@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®