* [PATCH 00/22] VKMS: Introduce multiple configFS attributes
@ 2025-10-18  2:01 Louis Chauvet
  2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
                   ` (22 more replies)
  0 siblings, 23 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS have a wide range of options. The aim of this series is to introduce
many configfs attribute so VKMS can be used to test a wide range of
configurations.
This series depends on [1] that should be applied soon.
PATCH 1-13 are for configuring planes
- name
- rotation
- color encoding
- color range
- plane formats
- zpos
PATCH 14-19 are for configuring the connector
- type
- supported colorspace
- edid
PATCH 20-22 are to enable dynamic connectors
[1]:https://lore.kernel.org/all/20251016175618.10051-1-jose.exposito89@gmail.com
PS: Each pair of config/configfs patch are independant. I could
technically create ≈10 different series, but there will be a lot of
(trivial) conflicts between them. I will be happy to reordoer, split and
partially apply this series to help the review process.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
Louis Chauvet (22):
      drm/vkms: Introduce config for plane name
      drm/vkms: Introduce configfs for plane name
      drm/vkms: Introduce config for plane rotation
      drm/vkms: Introduce configfs for plane rotation
      drm/vkms: Introduce config for plane color encoding
      drm/vkms: Introduce configfs for plane color encoding
      drm/vkms: Introduce config for plane color range
      drm/vkms: Introduce configfs for plane color range
      drm/vkms: Introduce config for plane format
      drm/vkms: Introduce configfs for plane format
      drm/vkms: Properly render plane using their zpos
      drm/vkms: Introduce config for plane zpos property
      drm/vkms: Introduce configfs for plane zpos property
      drm/vkms: Introduce config for connector type
      drm/vkms: Introduce configfs for connector type
      drm/vkms: Introduce config for connector supported colorspace
      drm/vkms: Introduce configfs for connector supported colorspace
      drm/vkms: Introduce config for connector EDID
      drm/vkms: Introduce configfs for connector EDID
      drm/vkms: Store the enabled/disabled status for connector
      drm/vkms: Allow to hot-add connectors
      drm/vkms: Allows the creation of connector at runtime
 Documentation/gpu/vkms.rst                    |  42 +-
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  18 +
 drivers/gpu/drm/vkms/vkms_config.c            | 183 ++++++
 drivers/gpu/drm/vkms/vkms_config.h            | 524 +++++++++++++++
 drivers/gpu/drm/vkms/vkms_configfs.c          | 893 +++++++++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_connector.c         | 137 +++-
 drivers/gpu/drm/vkms/vkms_connector.h         |  36 +-
 drivers/gpu/drm/vkms/vkms_crtc.c              |  11 +-
 drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
 drivers/gpu/drm/vkms/vkms_output.c            |  19 +-
 drivers/gpu/drm/vkms/vkms_plane.c             |  73 +--
 11 files changed, 1865 insertions(+), 77 deletions(-)
---
base-commit: b291e4f1a4951204ce858cd01801291d34962a33
change-id: 20251017-vkms-all-config-bd0c2a01846f
prerequisite-message-id: 20251016175618.10051-1-jose.exposito89@gmail.com
prerequisite-patch-id: 74083a8806b1f26d9b4cd2a5107c756b971c4d11
prerequisite-patch-id: f982390487699921b625b413e8460d67ca7a74c9
prerequisite-patch-id: 0afca639e43c8fbfea2af1bc395e489efc8e1f10
prerequisite-patch-id: 6285108b2fd90d30d15d4cb4fdddfef953fad51b
prerequisite-patch-id: 2eacf5ad4f25f54a60958aa7a2df633d5642ce2f
prerequisite-patch-id: 81e98ac3aeb3b6128098ab7bab56d3446a3a2705
prerequisite-patch-id: 973f94c4edb4a5822c84a57d4479ca40e9cf25de
prerequisite-patch-id: 0efbaf1b0e962a1c40bf5a744b5089d8be696f62
prerequisite-patch-id: afa0cff94085e6ab216ffd9b99cd3dc882a0a687
prerequisite-patch-id: 3561347f2b586392985a8e3af9ed1c5c7d3eefd5
prerequisite-patch-id: 94030044ae8d404f7cdaed9137bddd59cfb22e79
prerequisite-patch-id: a54b483797d5ffb7ce13b56a8943025181cd0d7a
prerequisite-patch-id: f148fe7f445cb42437e7e2ba8b59e7e0fd40da8b
prerequisite-patch-id: 1ef2045872843670c452816c5d6187b713c9258c
prerequisite-patch-id: 3b9963ea3ae3455ae15ee36b67042c06a2ef6006
prerequisite-patch-id: 519ee42dfabb4de734e41e59bd07d7a723d810bb
Best regards,
-- 
Louis Chauvet <louis.chauvet@bootlin.com>
^ permalink raw reply	[flat|nested] 48+ messages in thread
* [PATCH 01/22] drm/vkms: Introduce config for plane name
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 11:16   ` José Expósito
  2025-10-27 10:15   ` Jani Nikula
  2025-10-18  2:01 ` [PATCH 02/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (21 subsequent siblings)
  22 siblings, 2 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
As planes can have a name in DRM, prepare VKMS to configure it using
ConfigFS.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c |  4 ++++
 drivers/gpu/drm/vkms/vkms_config.h | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_drv.h    |  5 +++--
 drivers/gpu/drm/vkms/vkms_output.c |  6 +-----
 drivers/gpu/drm/vkms/vkms_plane.c  |  6 ++++--
 5 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index f8394a063ecf..ed172f800685 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -350,6 +350,8 @@ static int vkms_config_show(struct seq_file *m, void *data)
 		seq_puts(m, "plane:\n");
 		seq_printf(m, "\ttype=%d\n",
 			   vkms_config_plane_get_type(plane_cfg));
+		seq_printf(m, "\tname=%s\n",
+			   vkms_config_plane_get_name(plane_cfg));
 	}
 
 	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
@@ -390,6 +392,7 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
 
 	plane_cfg->config = config;
 	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
+	vkms_config_plane_set_name(plane_cfg, NULL);
 	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
 
 	list_add_tail(&plane_cfg->link, &config->planes);
@@ -402,6 +405,7 @@ void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg)
 {
 	xa_destroy(&plane_cfg->possible_crtcs);
 	list_del(&plane_cfg->link);
+	kfree_const(plane_cfg->name);
 	kfree(plane_cfg);
 }
 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane);
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 4c8d668e7ef8..b69c35097ba0 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -35,6 +35,7 @@ struct vkms_config {
  *
  * @link: Link to the others planes in vkms_config
  * @config: The vkms_config this plane belongs to
+ * @name: Name of the plane
  * @type: Type of the plane. The creator of configuration needs to ensures that
  *        at least one primary plane is present.
  * @possible_crtcs: Array of CRTCs that can be used with this plane
@@ -47,6 +48,7 @@ struct vkms_config_plane {
 	struct list_head link;
 	struct vkms_config *config;
 
+	const char *name;
 	enum drm_plane_type type;
 	struct xarray possible_crtcs;
 
@@ -288,6 +290,30 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
 	plane_cfg->type = type;
 }
 
+/**
+ * vkms_config_plane_set_name() - Set the plane name
+ * @plane_cfg: Plane to set the name to
+ * @name: New plane name. The name is copied.
+ */
+static inline void
+vkms_config_plane_set_name(struct vkms_config_plane *plane_cfg,
+			   const char *name)
+{
+	if (plane_cfg->name)
+		kfree_const(plane_cfg->name);
+	plane_cfg->name = kstrdup_const(name, GFP_KERNEL);
+}
+
+/**
+ * vkms_config_plane_get_name - Get the plane name
+ * @plane_cfg: Plane to get the name from
+ */
+static inline const char *
+vkms_config_plane_get_name(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->name;
+}
+
 /**
  * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
  * @plane_cfg: Plane to attach
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index db260df1d4f6..9ad286f043b5 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -225,6 +225,7 @@ struct vkms_output {
 };
 
 struct vkms_config;
+struct vkms_config_plane;
 
 /**
  * struct vkms_device - Description of a VKMS device
@@ -298,10 +299,10 @@ int vkms_output_init(struct vkms_device *vkmsdev);
  * vkms_plane_init() - Initialize a plane
  *
  * @vkmsdev: VKMS device containing the plane
- * @type: type of plane to initialize
+ * @config: plane configuration
  */
 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
-				   enum drm_plane_type type);
+				   struct vkms_config_plane *config);
 
 /* CRC Support */
 const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 2ee3749e2b28..22208d02afa4 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -19,11 +19,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		return -EINVAL;
 
 	vkms_config_for_each_plane(vkmsdev->config, plane_cfg) {
-		enum drm_plane_type type;
-
-		type = vkms_config_plane_get_type(plane_cfg);
-
-		plane_cfg->plane = vkms_plane_init(vkmsdev, type);
+		plane_cfg->plane = vkms_plane_init(vkmsdev, plane_cfg);
 		if (IS_ERR(plane_cfg->plane)) {
 			DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n");
 			return PTR_ERR(plane_cfg->plane);
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index e592e47a5736..263376686794 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -11,6 +11,7 @@
 
 #include "vkms_drv.h"
 #include "vkms_formats.h"
+#include "vkms_config.h"
 
 static const u32 vkms_formats[] = {
 	DRM_FORMAT_ARGB8888,
@@ -217,7 +218,7 @@ static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
 };
 
 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
-				   enum drm_plane_type type)
+				   struct vkms_config_plane *config)
 {
 	struct drm_device *dev = &vkmsdev->drm;
 	struct vkms_plane *plane;
@@ -225,7 +226,8 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
 					   &vkms_plane_funcs,
 					   vkms_formats, ARRAY_SIZE(vkms_formats),
-					   NULL, type, NULL);
+					   NULL, vkms_config_plane_get_type(config),
+					   vkms_config_plane_get_name(config));
 	if (IS_ERR(plane))
 		return plane;
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 02/22] drm/vkms: Introduce configfs for plane name
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
  2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 11:20   ` José Expósito
  2025-10-18  2:01 ` [PATCH 03/22] drm/vkms: Introduce config for plane rotation Louis Chauvet
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Use directory name as name for the plane.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_configfs.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 07ab794e1052..ea245e2e2fd2 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -376,6 +376,7 @@ static struct config_group *make_plane_group(struct config_group *group,
 			kfree(plane);
 			return ERR_CAST(plane->config);
 		}
+		vkms_config_plane_set_name(plane->config, name);
 
 		config_group_init_type_name(&plane->group, name, &plane_item_type);
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 03/22] drm/vkms: Introduce config for plane rotation
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
  2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
  2025-10-18  2:01 ` [PATCH 02/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 11:53   ` José Expósito
  2025-10-18  2:01 ` [PATCH 04/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS driver supports all the rotation on planes, but for testing it can be
useful to only advertise few of them. This new configuration interface
will allow configuring the rotation per planes.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 26 ++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h | 54 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_plane.c  |  6 +++--
 3 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index ed172f800685..b8cabe6f6cf8 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -144,6 +144,22 @@ static bool valid_plane_number(const struct vkms_config *config)
 	return true;
 }
 
+static bool valid_plane_properties(const struct vkms_config *config)
+{
+	struct drm_device *dev = config->dev ? &config->dev->drm : NULL;
+	struct vkms_config_plane *plane_cfg;
+
+	vkms_config_for_each_plane(config, plane_cfg) {
+		if ((vkms_config_plane_get_default_rotation(plane_cfg) &
+		     vkms_config_plane_get_supported_rotations(plane_cfg)) !=
+		    vkms_config_plane_get_default_rotation(plane_cfg)) {
+			drm_info(dev, "Configured default rotation is not supported by the plane\n");
+			return false;
+		}
+	}
+	return true;
+}
+
 static bool valid_planes_for_crtc(const struct vkms_config *config,
 				  struct vkms_config_crtc *crtc_cfg)
 {
@@ -302,6 +318,9 @@ bool vkms_config_is_valid(const struct vkms_config *config)
 {
 	struct vkms_config_crtc *crtc_cfg;
 
+	if (!valid_plane_properties(config))
+		return false;
+
 	if (!valid_plane_number(config))
 		return false;
 
@@ -352,6 +371,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
 			   vkms_config_plane_get_type(plane_cfg));
 		seq_printf(m, "\tname=%s\n",
 			   vkms_config_plane_get_name(plane_cfg));
+		seq_printf(m, "\tsupported rotations: 0x%x\n",
+			   vkms_config_plane_get_supported_rotations(plane_cfg));
+		seq_printf(m, "\tdefault rotation: 0x%x\n",
+			   vkms_config_plane_get_default_rotation(plane_cfg));
 	}
 
 	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
@@ -393,6 +416,9 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
 	plane_cfg->config = config;
 	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
 	vkms_config_plane_set_name(plane_cfg, NULL);
+	vkms_config_plane_set_supported_rotations(plane_cfg, DRM_MODE_ROTATE_MASK);
+	vkms_config_plane_set_default_rotation(plane_cfg, DRM_MODE_ROTATE_0);
+
 	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
 
 	list_add_tail(&plane_cfg->link, &config->planes);
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index b69c35097ba0..3c3cbefcc67f 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -39,6 +39,8 @@ struct vkms_config {
  * @type: Type of the plane. The creator of configuration needs to ensures that
  *        at least one primary plane is present.
  * @possible_crtcs: Array of CRTCs that can be used with this plane
+ * @default_rotation: Default rotation that should be used by this plane
+ * @supported_rotation: Rotation that this plane will support
  * @plane: Internal usage. This pointer should never be considered as valid.
  *         It can be used to store a temporary reference to a VKMS plane during
  *         device creation. This pointer is not managed by the configuration and
@@ -50,6 +52,8 @@ struct vkms_config_plane {
 
 	const char *name;
 	enum drm_plane_type type;
+	unsigned int default_rotation;
+	unsigned int supported_rotations;
 	struct xarray possible_crtcs;
 
 	/* Internal usage */
@@ -290,6 +294,56 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
 	plane_cfg->type = type;
 }
 
+/**
+ * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
+ * @plane_cfg: Plane to get the default rotation from
+ *
+ * Returns:
+ * The default rotation for the plane.
+ */
+static inline unsigned int
+vkms_config_plane_get_default_rotation(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->default_rotation;
+}
+
+/**
+ * vkms_config_plane_set_default_rotation() - Set the default rotation for a plane
+ * @plane_cfg: Plane to set the default rotation to
+ * @default_rotation: New default rotation for the plane
+ */
+static inline void
+vkms_config_plane_set_default_rotation(struct vkms_config_plane *plane_cfg,
+				       unsigned int default_rotation)
+{
+	plane_cfg->default_rotation = default_rotation;
+}
+
+/**
+ * vkms_config_plane_get_supported_rotations() - Get the supported rotations for a plane
+ * @plane_cfg: Plane to get the supported rotations from
+ *
+ * Returns:
+ * The supported rotations for the plane.
+ */
+static inline unsigned int
+vkms_config_plane_get_supported_rotations(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->supported_rotations;
+}
+
+/**
+ * vkms_config_plane_set_supported_rotations() - Set the supported rotations for a plane
+ * @plane_cfg: Plane to set the supported rotations to
+ * @supported_rotations: New supported rotations for the plane
+ */
+static inline void
+vkms_config_plane_set_supported_rotations(struct vkms_config_plane *plane_cfg,
+					  unsigned int supported_rotations)
+{
+	plane_cfg->supported_rotations = supported_rotations;
+}
+
 /**
  * vkms_config_plane_set_name() - Set the plane name
  * @plane_cfg: Plane to set the name to
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 263376686794..6e6bfe1b7400 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 
+#include "vkms_config.h"
 #include <linux/iosys-map.h>
 
 #include <drm/drm_atomic.h>
@@ -233,8 +234,9 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 
 	drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
 
-	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
-					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
+	drm_plane_create_rotation_property(&plane->base,
+					   vkms_config_plane_get_default_rotation(config),
+					   vkms_config_plane_get_supported_rotations(config));
 
 	drm_plane_create_color_properties(&plane->base,
 					  BIT(DRM_COLOR_YCBCR_BT601) |
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 04/22] drm/vkms: Introduce configfs for plane rotation
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (2 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 03/22] drm/vkms: Introduce config for plane rotation Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 14:50   ` José Expósito
  2025-10-18  2:01 ` [PATCH 05/22] drm/vkms: Introduce config for plane color encoding Louis Chauvet
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
To allows the userspace to test many hardware configuration, introduce a
new interface to configure the available rotation per planes. VKMS
supports any rotation and reflection, so the userspace can choose any
combination.
The supported rotations are configured by writing a rotation bitmask to
the file `supported_rotations` and the default rotation is chosen by
writing a rotation bitmask to `default_rotation`.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  7 ++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 94 ++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 3574e01b928d..a432968cc711 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -87,10 +87,15 @@ Start by creating one or more planes::
 
   sudo mkdir /config/vkms/my-vkms/planes/plane0
 
-Planes have 1 configurable attribute:
+Planes have 3 configurable attribute:
 
 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
   exposed by the "type" property of a plane)
+- possible_rotations: Available rotation for a plane, as a bitmask: 0x01 no rotation,
+  0x02 rotate 90°, 0x04 rotate 180°, 0x08 rotate 270°, 0x10 reflect x, 0x20 reflect y
+  (same values as those exposed by the "rotation" property of a plane)
+- default_rotation: Default rotation presented to the userspace, same values as
+  possible_rotations.
 
 Continue by creating one or more CRTCs::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index ea245e2e2fd2..450e45e66a45 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -322,10 +322,104 @@ static ssize_t plane_type_store(struct config_item *item, const char *page,
 	return (ssize_t)count;
 }
 
+static ssize_t plane_supported_rotations_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int plane_supported_rotations;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		plane_supported_rotations = vkms_config_plane_get_supported_rotations(plane->config);
+	}
+
+	return sprintf(page, "%u", plane_supported_rotations);
+}
+
+static ssize_t plane_supported_rotations_store(struct config_item *item,
+					       const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 0, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK))
+		return -EINVAL;
+	/* Should at least provide one rotation */
+	if (!(val & DRM_MODE_ROTATE_MASK))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_default_rotation(plane->config)) !=
+		     vkms_config_plane_get_default_rotation(plane->config))
+			return -EINVAL;
+
+		vkms_config_plane_set_supported_rotations(plane->config, val);
+	}
+
+	return count;
+}
+
+static ssize_t plane_default_rotation_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int plane_default_rotation;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		plane_default_rotation = vkms_config_plane_get_default_rotation(plane->config);
+	}
+
+	return sprintf(page, "%u", plane_default_rotation);
+}
+
+static ssize_t plane_default_rotation_store(struct config_item *item,
+					    const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK))
+		return -EINVAL;
+	/* Should at least provide one rotation */
+	if ((val & DRM_MODE_ROTATE_MASK) == 0)
+		return -EINVAL;
+	/* Should contains only one rotation */
+	if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_supported_rotations(plane->config)) != val)
+			return -EINVAL;
+
+		vkms_config_plane_set_default_rotation(plane->config, val);
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(plane_, type);
+CONFIGFS_ATTR(plane_, supported_rotations);
+CONFIGFS_ATTR(plane_, default_rotation);
 
 static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_type,
+	&plane_attr_supported_rotations,
+	&plane_attr_default_rotation,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 05/22] drm/vkms: Introduce config for plane color encoding
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (3 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 04/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 15:14   ` José Expósito
  2025-10-18  2:01 ` [PATCH 06/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS driver supports all the color encoding on planes, but for testing it
can be useful to only advertise few of them. This new configuration
interface will allow configuring the color encoding per planes.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 15 +++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h | 30 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_plane.c  |  6 ++----
 3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index b8cabe6f6cf8..5353719a476d 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -156,6 +156,13 @@ static bool valid_plane_properties(const struct vkms_config *config)
 			drm_info(dev, "Configured default rotation is not supported by the plane\n");
 			return false;
 		}
+
+		if ((BIT(vkms_config_plane_get_default_color_encoding(plane_cfg)) &
+		     vkms_config_plane_get_supported_color_encoding(plane_cfg)) !=
+		    BIT(vkms_config_plane_get_default_color_encoding(plane_cfg))) {
+			drm_info(dev, "Configured default color encoding is not supported by the plane\n");
+			return false;
+		}
 	}
 	return true;
 }
@@ -375,6 +382,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
 			   vkms_config_plane_get_supported_rotations(plane_cfg));
 		seq_printf(m, "\tdefault rotation: 0x%x\n",
 			   vkms_config_plane_get_default_rotation(plane_cfg));
+		seq_printf(m, "\tsupported color encoding: 0x%x\n",
+			   vkms_config_plane_get_supported_color_encoding(plane_cfg));
+		seq_printf(m, "\tdefault color encoding: %d\n",
+			   vkms_config_plane_get_default_color_encoding(plane_cfg));
 	}
 
 	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
@@ -418,6 +429,10 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
 	vkms_config_plane_set_name(plane_cfg, NULL);
 	vkms_config_plane_set_supported_rotations(plane_cfg, DRM_MODE_ROTATE_MASK);
 	vkms_config_plane_set_default_rotation(plane_cfg, DRM_MODE_ROTATE_0);
+	vkms_config_plane_set_supported_color_encoding(plane_cfg, BIT(DRM_COLOR_YCBCR_BT601) |
+							BIT(DRM_COLOR_YCBCR_BT709) |
+							BIT(DRM_COLOR_YCBCR_BT2020));
+	vkms_config_plane_set_default_color_encoding(plane_cfg, DRM_COLOR_YCBCR_BT601);
 
 	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 3c3cbefcc67f..11160c3c13bc 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -45,6 +45,8 @@ struct vkms_config {
  *         It can be used to store a temporary reference to a VKMS plane during
  *         device creation. This pointer is not managed by the configuration and
  *         must be managed by other means.
+ * @default_color_encoding: Default color encoding that should be used by this plane
+ * @supported_color_encoding: Color encoding that this plane will support
  */
 struct vkms_config_plane {
 	struct list_head link;
@@ -54,6 +56,8 @@ struct vkms_config_plane {
 	enum drm_plane_type type;
 	unsigned int default_rotation;
 	unsigned int supported_rotations;
+	enum drm_color_encoding default_color_encoding;
+	unsigned int supported_color_encoding;
 	struct xarray possible_crtcs;
 
 	/* Internal usage */
@@ -344,6 +348,32 @@ vkms_config_plane_set_supported_rotations(struct vkms_config_plane *plane_cfg,
 	plane_cfg->supported_rotations = supported_rotations;
 }
 
+static inline enum drm_color_encoding
+vkms_config_plane_get_default_color_encoding(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->default_color_encoding;
+}
+
+static inline void
+vkms_config_plane_set_default_color_encoding(struct vkms_config_plane *plane_cfg,
+					     enum drm_color_encoding default_color_encoding)
+{
+	plane_cfg->default_color_encoding = default_color_encoding;
+}
+
+static inline unsigned int
+vkms_config_plane_get_supported_color_encoding(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->supported_color_encoding;
+}
+
+static inline void
+vkms_config_plane_set_supported_color_encoding(struct vkms_config_plane *plane_cfg,
+					       unsigned int supported_color_encoding)
+{
+	plane_cfg->supported_color_encoding = supported_color_encoding;
+}
+
 /**
  * vkms_config_plane_set_name() - Set the plane name
  * @plane_cfg: Plane to set the name to
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 6e6bfe1b7400..5869000415e4 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -239,12 +239,10 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 					   vkms_config_plane_get_supported_rotations(config));
 
 	drm_plane_create_color_properties(&plane->base,
-					  BIT(DRM_COLOR_YCBCR_BT601) |
-					  BIT(DRM_COLOR_YCBCR_BT709) |
-					  BIT(DRM_COLOR_YCBCR_BT2020),
+					  vkms_config_plane_get_supported_color_encoding(config),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-					  DRM_COLOR_YCBCR_BT601,
+					  vkms_config_plane_get_default_color_encoding(config),
 					  DRM_COLOR_YCBCR_FULL_RANGE);
 
 	return plane;
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 06/22] drm/vkms: Introduce configfs for plane color encoding
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (4 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 05/22] drm/vkms: Introduce config for plane color encoding Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 15:16   ` José Expósito
  2025-10-18  2:01 ` [PATCH 07/22] drm/vkms: Introduce config for plane color range Louis Chauvet
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
To allows the userspace to test many hardware configuration, introduce a
new interface to configure the available color encoding per planes. VKMS
supports multiple color encoding, so the userspace can choose any
combination.
The supported color encoding are configured by writing a color encoding
bitmask to the file `supported_color_encoding` and the default color
encoding is chosen by writing a color encoding bitmask to
`default_color_encoding`.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |   7 ++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 102 +++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index a432968cc711..4ff75b53a386 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -87,7 +87,7 @@ Start by creating one or more planes::
 
   sudo mkdir /config/vkms/my-vkms/planes/plane0
 
-Planes have 3 configurable attribute:
+Planes have 5 configurable attribute:
 
 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
   exposed by the "type" property of a plane)
@@ -96,6 +96,11 @@ Planes have 3 configurable attribute:
   (same values as those exposed by the "rotation" property of a plane)
 - default_rotation: Default rotation presented to the userspace, same values as
   possible_rotations.
+- supported_color_encoding: Available encoding for a plane, as a bitmask:
+  0x01 YCBCR_BT601, 0x02: YCBCR_BT709, 0x04 YCBCR_BT2020 (same values as those exposed
+  by the COLOR_ENCODING property of a plane)
+- default_color_encoding: Default color encoding presented to the userspace, same
+  values as supported_color_encoding
 
 Continue by creating one or more CRTCs::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 450e45e66a45..a4e0e054cf2d 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -412,14 +412,116 @@ static ssize_t plane_default_rotation_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t plane_supported_color_encoding_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int supported_color_encoding;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		supported_color_encoding = vkms_config_plane_get_supported_color_encoding(plane->config);
+	}
+
+	return sprintf(page, "%u", supported_color_encoding);
+}
+
+static ssize_t plane_supported_color_encoding_store(struct config_item *item,
+						    const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(BIT(DRM_COLOR_YCBCR_BT601) |
+		    BIT(DRM_COLOR_YCBCR_BT709) |
+		    BIT(DRM_COLOR_YCBCR_BT2020)))
+		return -EINVAL;
+	/* Should at least provide one color range */
+	if ((val & (BIT(DRM_COLOR_YCBCR_BT601) |
+		    BIT(DRM_COLOR_YCBCR_BT709) |
+		    BIT(DRM_COLOR_YCBCR_BT2020))) == 0)
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_default_color_encoding(plane->config)) !=
+		     vkms_config_plane_get_default_color_encoding(plane->config))
+			return -EINVAL;
+
+		vkms_config_plane_set_supported_color_encoding(plane->config, val);
+	}
+
+	return count;
+}
+
+/* Plane default_color_encoding : vkms/<device>/planes/<plane>/default_color_encoding */
+
+static ssize_t plane_default_color_encoding_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int default_color_encoding;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		default_color_encoding = vkms_config_plane_get_default_color_encoding(plane->config);
+	}
+
+	return sprintf(page, "%u", default_color_encoding);
+}
+
+static ssize_t plane_default_color_encoding_store(struct config_item *item,
+						  const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(BIT(DRM_COLOR_YCBCR_BT601) |
+		    BIT(DRM_COLOR_YCBCR_BT709) |
+		    BIT(DRM_COLOR_YCBCR_BT2020)))
+		return -EINVAL;
+	/* Should at least provide one color range */
+	if ((val & (BIT(DRM_COLOR_YCBCR_BT601) |
+		    BIT(DRM_COLOR_YCBCR_BT709) |
+		    BIT(DRM_COLOR_YCBCR_BT2020))) == 0)
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_supported_color_encoding(plane->config)) !=
+		     val)
+			return -EINVAL;
+
+		vkms_config_plane_set_default_color_encoding(plane->config, val);
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(plane_, type);
 CONFIGFS_ATTR(plane_, supported_rotations);
 CONFIGFS_ATTR(plane_, default_rotation);
+CONFIGFS_ATTR(plane_, supported_color_encoding);
+CONFIGFS_ATTR(plane_, default_color_encoding);
 
 static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_type,
 	&plane_attr_supported_rotations,
 	&plane_attr_default_rotation,
+	&plane_attr_supported_color_encoding,
+	&plane_attr_default_color_encoding,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 07/22] drm/vkms: Introduce config for plane color range
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (5 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 06/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 15:25   ` José Expósito
  2025-10-18  2:01 ` [PATCH 08/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS driver supports all the color range on planes, but for testing it can
be useful to only advertise few of them. This new configuration interface
will allow configuring the color range per planes.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 14 ++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h | 30 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_plane.c  |  5 ++---
 3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 5353719a476d..8f00ca21ed6e 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -163,6 +163,13 @@ static bool valid_plane_properties(const struct vkms_config *config)
 			drm_info(dev, "Configured default color encoding is not supported by the plane\n");
 			return false;
 		}
+
+		if ((BIT(vkms_config_plane_get_default_color_range(plane_cfg)) &
+		     vkms_config_plane_get_supported_color_range(plane_cfg)) !=
+		    BIT(vkms_config_plane_get_default_color_range(plane_cfg))) {
+			drm_info(dev, "Configured default color range is not supported by the plane\n");
+			return false;
+		}
 	}
 	return true;
 }
@@ -386,6 +393,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
 			   vkms_config_plane_get_supported_color_encoding(plane_cfg));
 		seq_printf(m, "\tdefault color encoding: %d\n",
 			   vkms_config_plane_get_default_color_encoding(plane_cfg));
+		seq_printf(m, "\tsupported color range: 0x%x\n",
+			   vkms_config_plane_get_supported_color_range(plane_cfg));
+		seq_printf(m, "\tdefault color range: %d\n",
+			   vkms_config_plane_get_default_color_range(plane_cfg));
 	}
 
 	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
@@ -433,6 +444,9 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
 							BIT(DRM_COLOR_YCBCR_BT709) |
 							BIT(DRM_COLOR_YCBCR_BT2020));
 	vkms_config_plane_set_default_color_encoding(plane_cfg, DRM_COLOR_YCBCR_BT601);
+	vkms_config_plane_set_supported_color_range(plane_cfg, BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+							       BIT(DRM_COLOR_YCBCR_FULL_RANGE));
+	vkms_config_plane_set_default_color_range(plane_cfg, DRM_COLOR_YCBCR_FULL_RANGE);
 
 	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 11160c3c13bc..8127e12f00dc 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -47,6 +47,8 @@ struct vkms_config {
  *         must be managed by other means.
  * @default_color_encoding: Default color encoding that should be used by this plane
  * @supported_color_encoding: Color encoding that this plane will support
+ * @default_color_range: Default color range that should be used by this plane
+ * @supported_color_range: Color range that this plane will support
  */
 struct vkms_config_plane {
 	struct list_head link;
@@ -58,6 +60,8 @@ struct vkms_config_plane {
 	unsigned int supported_rotations;
 	enum drm_color_encoding default_color_encoding;
 	unsigned int supported_color_encoding;
+	enum drm_color_range default_color_range;
+	unsigned int supported_color_range;
 	struct xarray possible_crtcs;
 
 	/* Internal usage */
@@ -374,6 +378,32 @@ vkms_config_plane_set_supported_color_encoding(struct vkms_config_plane *plane_c
 	plane_cfg->supported_color_encoding = supported_color_encoding;
 }
 
+static inline enum drm_color_range
+vkms_config_plane_get_default_color_range(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->default_color_range;
+}
+
+static inline void
+vkms_config_plane_set_default_color_range(struct vkms_config_plane *plane_cfg,
+					  enum drm_color_range default_color_range)
+{
+	plane_cfg->default_color_range = default_color_range;
+}
+
+static inline unsigned int
+vkms_config_plane_get_supported_color_range(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->supported_color_range;
+}
+
+static inline void
+vkms_config_plane_set_supported_color_range(struct vkms_config_plane *plane_cfg,
+					    unsigned int supported_color_range)
+{
+	plane_cfg->supported_color_range = supported_color_range;
+}
+
 /**
  * vkms_config_plane_set_name() - Set the plane name
  * @plane_cfg: Plane to set the name to
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 5869000415e4..ab719da2ca0b 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -240,10 +240,9 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 
 	drm_plane_create_color_properties(&plane->base,
 					  vkms_config_plane_get_supported_color_encoding(config),
-					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  vkms_config_plane_get_supported_color_range(config),
 					  vkms_config_plane_get_default_color_encoding(config),
-					  DRM_COLOR_YCBCR_FULL_RANGE);
+					  vkms_config_plane_get_default_color_range(config));
 
 	return plane;
 }
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 08/22] drm/vkms: Introduce configfs for plane color range
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (6 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 07/22] drm/vkms: Introduce config for plane color range Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 15:27   ` José Expósito
  2025-10-18  2:01 ` [PATCH 09/22] drm/vkms: Introduce config for plane format Louis Chauvet
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
To allows the userspace to test many hardware configuration, introduce a
new interface to configure the available color ranges per planes. VKMS
supports multiple color ranges, so the userspace can choose any
combination.
The supported color ranges are configured by writing a color range bitmask
to the file `supported_color_ranges` and the default color range is
chosen by writing a color encoding bitmask to `default_color_range`.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  7 ++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 93 ++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 4ff75b53a386..979f8a545498 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -87,7 +87,7 @@ Start by creating one or more planes::
 
   sudo mkdir /config/vkms/my-vkms/planes/plane0
 
-Planes have 5 configurable attribute:
+Planes have 7 configurable attribute:
 
 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
   exposed by the "type" property of a plane)
@@ -101,6 +101,11 @@ Planes have 5 configurable attribute:
   by the COLOR_ENCODING property of a plane)
 - default_color_encoding: Default color encoding presented to the userspace, same
   values as supported_color_encoding
+- supported_color_range: Available color range for a plane, as a bitmask:
+  0x1 DRM_COLOR_YCBCR_LIMITED_RANGE, 0x2 DRM_COLOR_YCBCR_FULL_RANGE (same values as
+  those exposed by the COLOR_RANGE property of a plane)
+- default_color_range: Default color range presented to the userspace, same
+  values as supported_color_range
 
 Continue by creating one or more CRTCs::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index a4e0e054cf2d..0b280c73b0cc 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -412,6 +412,95 @@ static ssize_t plane_default_rotation_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t plane_supported_color_range_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int supported_color_range;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		supported_color_range = vkms_config_plane_get_supported_color_range(plane->config);
+	}
+
+	return sprintf(page, "%u", supported_color_range);
+}
+
+static ssize_t plane_supported_color_range_store(struct config_item *item,
+						 const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+		    BIT(DRM_COLOR_YCBCR_FULL_RANGE)))
+		return -EINVAL;
+	/* Should at least provide one color range */
+	if ((val & (BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+		    BIT(DRM_COLOR_YCBCR_FULL_RANGE))) == 0)
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_default_color_range(plane->config)) !=
+		     vkms_config_plane_get_default_color_range(plane->config))
+			return -EINVAL;
+		vkms_config_plane_set_supported_color_range(plane->config, val);
+	}
+
+	return count;
+}
+
+static ssize_t plane_default_color_range_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int default_color_range;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		default_color_range = vkms_config_plane_get_default_color_range(plane->config);
+
+	return sprintf(page, "%u", default_color_range);
+}
+
+static ssize_t plane_default_color_range_store(struct config_item *item,
+					       const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
+	int ret, val = 0;
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	/* Should be a supported value */
+	if (val & ~(BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+		    BIT(DRM_COLOR_YCBCR_FULL_RANGE)))
+		return -EINVAL;
+	/* Should at least provide one color range */
+	if ((val & (BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+		    BIT(DRM_COLOR_YCBCR_FULL_RANGE))) == 0)
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		/* Ensures that the default rotation is included in supported rotation */
+		if (plane->dev->enabled ||
+		    (val & vkms_config_plane_get_supported_color_range(plane->config)) !=
+		     val)
+			return -EINVAL;
+		vkms_config_plane_set_default_color_range(plane->config, val);
+	}
+
+	return count;
+}
+
 static ssize_t plane_supported_color_encoding_show(struct config_item *item, char *page)
 {
 	struct vkms_configfs_plane *plane;
@@ -513,6 +602,8 @@ static ssize_t plane_default_color_encoding_store(struct config_item *item,
 CONFIGFS_ATTR(plane_, type);
 CONFIGFS_ATTR(plane_, supported_rotations);
 CONFIGFS_ATTR(plane_, default_rotation);
+CONFIGFS_ATTR(plane_, supported_color_range);
+CONFIGFS_ATTR(plane_, default_color_range);
 CONFIGFS_ATTR(plane_, supported_color_encoding);
 CONFIGFS_ATTR(plane_, default_color_encoding);
 
@@ -520,6 +611,8 @@ static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_type,
 	&plane_attr_supported_rotations,
 	&plane_attr_default_rotation,
+	&plane_attr_supported_color_range,
+	&plane_attr_default_color_range,
 	&plane_attr_supported_color_encoding,
 	&plane_attr_default_color_encoding,
 	NULL,
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 09/22] drm/vkms: Introduce config for plane format
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (7 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 08/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-24 15:44   ` José Expósito
  2025-10-18  2:01 ` [PATCH 10/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS driver supports all the pixel formats for planes, but for testing it
can be useful to only advertise few of them. This new configuration
interface will allow configuring the pixel format per planes.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 99 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h | 49 +++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_plane.c  | 39 +--------------
 3 files changed, 150 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 8f00ca21ed6e..0b975a0d47aa 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -8,6 +8,42 @@
 
 #include "vkms_config.h"
 
+static const u32 vkms_supported_plane_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_XRGB16161616,
+	DRM_FORMAT_XBGR16161616,
+	DRM_FORMAT_ARGB16161616,
+	DRM_FORMAT_ABGR16161616,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV61,
+	DRM_FORMAT_NV42,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YUV444,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_YVU444,
+	DRM_FORMAT_P010,
+	DRM_FORMAT_P012,
+	DRM_FORMAT_P016,
+	DRM_FORMAT_R1,
+	DRM_FORMAT_R2,
+	DRM_FORMAT_R4,
+	DRM_FORMAT_R8,
+};
+
 struct vkms_config *vkms_config_create(const char *dev_name)
 {
 	struct vkms_config *config;
@@ -435,6 +471,11 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
 	if (!plane_cfg)
 		return ERR_PTR(-ENOMEM);
 
+	if (vkms_config_plane_add_all_formats(plane_cfg)) {
+		kfree(plane_cfg);
+		return ERR_PTR(-ENOMEM);
+	}
+
 	plane_cfg->config = config;
 	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
 	vkms_config_plane_set_name(plane_cfg, NULL);
@@ -563,6 +604,64 @@ static struct vkms_config_plane *vkms_config_crtc_get_plane(const struct vkms_co
 	return NULL;
 }
 
+int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane *plane_cfg)
+{
+	u32 *ret = krealloc_array(plane_cfg->supported_formats,
+				  ARRAY_SIZE(vkms_supported_plane_formats),
+				  sizeof(uint32_t), GFP_KERNEL);
+	if (!ret)
+		return -ENOMEM;
+	plane_cfg->supported_formats = ret;
+
+	memcpy(plane_cfg->supported_formats, vkms_supported_plane_formats,
+	       sizeof(vkms_supported_plane_formats));
+	plane_cfg->supported_formats_count = ARRAY_SIZE(vkms_supported_plane_formats);
+	return 0;
+}
+
+int __must_check vkms_config_plane_add_format(struct vkms_config_plane *plane_cfg, u32 drm_format)
+{
+	bool found = false;
+
+	for (int i = 0; i < ARRAY_SIZE(vkms_supported_plane_formats); i++) {
+		if (vkms_supported_plane_formats[i] == drm_format)
+			found = true;
+	}
+
+	if (!found)
+		return -EINVAL;
+	for (unsigned int i = 0; i < plane_cfg->supported_formats_count; i++) {
+		if (plane_cfg->supported_formats[i] == drm_format)
+			return 0;
+	}
+	u32 *new_ptr = krealloc_array(plane_cfg->supported_formats,
+				      plane_cfg->supported_formats_count + 1,
+				      sizeof(*plane_cfg->supported_formats), GFP_KERNEL);
+	if (!new_ptr)
+		return -ENOMEM;
+
+	plane_cfg->supported_formats = new_ptr;
+	plane_cfg->supported_formats[plane_cfg->supported_formats_count] = drm_format;
+	plane_cfg->supported_formats_count++;
+
+	return 0;
+}
+
+void vkms_config_plane_remove_all_formats(struct vkms_config_plane *plane_cfg)
+{
+	plane_cfg->supported_formats_count = 0;
+}
+
+void vkms_config_plane_remove_format(struct vkms_config_plane *plane_cfg, u32 drm_format)
+{
+	for (unsigned int i = 0; i < plane_cfg->supported_formats_count; i++) {
+		if (plane_cfg->supported_formats[i] == drm_format) {
+			plane_cfg->supported_formats[i] = plane_cfg->supported_formats[plane_cfg->supported_formats_count - 1];
+			plane_cfg->supported_formats_count--;
+		}
+	}
+}
+
 struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms_config *config,
 							 struct vkms_config_crtc *crtc_cfg)
 {
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 8127e12f00dc..0b7067508e5f 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -62,6 +62,8 @@ struct vkms_config_plane {
 	unsigned int supported_color_encoding;
 	enum drm_color_range default_color_range;
 	unsigned int supported_color_range;
+	u32 *supported_formats;
+	unsigned int supported_formats_count;
 	struct xarray possible_crtcs;
 
 	/* Internal usage */
@@ -404,6 +406,53 @@ vkms_config_plane_set_supported_color_range(struct vkms_config_plane *plane_cfg,
 	plane_cfg->supported_color_range = supported_color_range;
 }
 
+static inline u32 *
+vkms_config_plane_get_supported_formats(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->supported_formats;
+}
+
+static inline unsigned int
+vkms_config_plane_get_supported_formats_count(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->supported_formats_count;
+}
+
+/** vkms_config_plane_add_format - Add a format to the list of supported format of a plane
+ *
+ * The passed drm_format can already be present in the list. This may fail if the allocation of a
+ * bigger array fails.
+ *
+ * @plane_cfg: Plane to add the format to
+ * @drm_format: Format to add to this plane
+ *
+ * Returns: 0 on success, -ENOMEM if array allocation fails, -EINVAL if the format is not supported
+ * by VKMS
+ */
+int __must_check vkms_config_plane_add_format(struct vkms_config_plane *plane_cfg, u32 drm_format);
+
+/**
+ * vkms_config_plane_add_all_formats - Helper to quickly add all the supported formats
+ * @plane_cfg: Plane to add the formats to
+ *
+ * Returns: 0 on success, -ENOMEM if array allocation fails, -EINVAL if the format is not supported
+ * by VKMS
+ */
+int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane *plane_cfg);
+
+/**
+ * vkms_config_plane_remove_format - Remove a specific format from a plane
+ * @plane_cfg: Plane to remove the format to
+ * @drm_format: Format to remove
+ */
+void vkms_config_plane_remove_format(struct vkms_config_plane *plane_cfg, u32 drm_format);
+
+/**
+ * vkms_config_plane_remove_all_formats - Remove all formast from a plane
+ * @plane_cfg: Plane to remove the formats from
+ */
+void vkms_config_plane_remove_all_formats(struct vkms_config_plane *plane_cfg);
+
 /**
  * vkms_config_plane_set_name() - Set the plane name
  * @plane_cfg: Plane to set the name to
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index ab719da2ca0b..0414865915d8 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -14,42 +14,6 @@
 #include "vkms_formats.h"
 #include "vkms_config.h"
 
-static const u32 vkms_formats[] = {
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_BGRA8888,
-	DRM_FORMAT_RGBA8888,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_XRGB16161616,
-	DRM_FORMAT_XBGR16161616,
-	DRM_FORMAT_ARGB16161616,
-	DRM_FORMAT_ABGR16161616,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_NV16,
-	DRM_FORMAT_NV24,
-	DRM_FORMAT_NV21,
-	DRM_FORMAT_NV61,
-	DRM_FORMAT_NV42,
-	DRM_FORMAT_YUV420,
-	DRM_FORMAT_YUV422,
-	DRM_FORMAT_YUV444,
-	DRM_FORMAT_YVU420,
-	DRM_FORMAT_YVU422,
-	DRM_FORMAT_YVU444,
-	DRM_FORMAT_P010,
-	DRM_FORMAT_P012,
-	DRM_FORMAT_P016,
-	DRM_FORMAT_R1,
-	DRM_FORMAT_R2,
-	DRM_FORMAT_R4,
-	DRM_FORMAT_R8,
-};
-
 static struct drm_plane_state *
 vkms_plane_duplicate_state(struct drm_plane *plane)
 {
@@ -226,7 +190,8 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 
 	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
 					   &vkms_plane_funcs,
-					   vkms_formats, ARRAY_SIZE(vkms_formats),
+					   vkms_config_plane_get_supported_formats(config),
+					   vkms_config_plane_get_supported_formats_count(config),
 					   NULL, vkms_config_plane_get_type(config),
 					   vkms_config_plane_get_name(config));
 	if (IS_ERR(plane))
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 10/22] drm/vkms: Introduce configfs for plane format
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (8 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 09/22] drm/vkms: Introduce config for plane format Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27  8:55   ` José Expósito
  2025-10-18  2:01 ` [PATCH 11/22] drm/vkms: Properly render plane using their zpos Louis Chauvet
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
To allow the userspace to test many hardware configuration, introduce a
new interface to configure the available formats per planes. VKMS supports
multiple formats, so the userspace can choose any combination.
The supported formats are configured by writing the fourcc code in
supported_formats:
 # enable AR24 format
  echo '+AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
 # disable AR24 format
  echo '-AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
 # enable all format supported by VKMS
  echo '+*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
 # disable all formats
  echo '-*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  7 ++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 82 ++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 979f8a545498..deb14e7c48ea 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -87,7 +87,7 @@ Start by creating one or more planes::
 
   sudo mkdir /config/vkms/my-vkms/planes/plane0
 
-Planes have 7 configurable attribute:
+Planes have 8 configurable attribute:
 
 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
   exposed by the "type" property of a plane)
@@ -106,6 +106,11 @@ Planes have 7 configurable attribute:
   those exposed by the COLOR_RANGE property of a plane)
 - default_color_range: Default color range presented to the userspace, same
   values as supported_color_range
+- supported_formats: List of supported formats for this plane. To add a new item in the
+  list, write it using a plus its fourcc code: +XR24
+  To remove a format, use a minus and its fourcc: -XR24
+  To add all formats use +*
+  To remove all formats, use -*
 
 Continue by creating one or more CRTCs::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 0b280c73b0cc..528f22fa2df1 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -599,6 +599,86 @@ static ssize_t plane_default_color_encoding_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t plane_supported_formats_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	page[0] = '\0';
+
+	scoped_guard(mutex, &plane->dev->lock)
+	{
+		u32 *formats = vkms_config_plane_get_supported_formats(plane->config);
+
+		for (int i = 0;
+		     i < vkms_config_plane_get_supported_formats_count(plane->config);
+		     i++) {
+			char tmp[6] = { 0 };
+			const ssize_t ret = snprintf(tmp, ARRAY_SIZE(tmp), "%.*s\n",
+					       (int)sizeof(*formats),
+					       (char *)&formats[i]);
+			if (ret < 0)
+				return ret;
+			/*
+			 * Limitation of ConfigFS attributes, an attribute can't be bigger
+			 * than PAGE_SIZE. This will crop the result if this plane support
+			 * more than ≈1000 formats.
+			 */
+			if (ret + strlen(page) > PAGE_SIZE - 1)
+				return -ENOMEM;
+			strncat(page, tmp, ARRAY_SIZE(tmp));
+		}
+	}
+
+	return strlen(page);
+}
+
+static ssize_t plane_supported_formats_store(struct config_item *item,
+					     const char *page, size_t count)
+{
+	struct vkms_configfs_plane *plane;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+	int ret = 0;
+	int ptr = 0;
+
+	scoped_guard(mutex, &plane->dev->lock)
+	{
+		while (ptr < count) {
+			char tmp[4] = { ' ', ' ', ' ', ' ' };
+
+			memcpy(tmp, &page[ptr + 1], min(sizeof(tmp), count - (ptr + 1)));
+			if (page[ptr] == '+') {
+				if (tmp[0] == '*') {
+					ret = vkms_config_plane_add_all_formats(plane->config);
+					if (ret)
+						return ret;
+					ptr += 1;
+				} else {
+					ret = vkms_config_plane_add_format(plane->config,
+									   *(int *)tmp);
+					if (ret)
+						return ret;
+					ptr += 4;
+				}
+			} else if (page[ptr] == '-') {
+				if (tmp[0] == '*') {
+					vkms_config_plane_remove_all_formats(plane->config);
+					ptr += 1;
+				} else {
+					vkms_config_plane_remove_format(plane->config, *(int *)tmp);
+					ptr += 4;
+				}
+			}
+			/* Skip anything that is not a + or a - */
+			ptr += 1;
+		}
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(plane_, type);
 CONFIGFS_ATTR(plane_, supported_rotations);
 CONFIGFS_ATTR(plane_, default_rotation);
@@ -606,6 +686,7 @@ CONFIGFS_ATTR(plane_, supported_color_range);
 CONFIGFS_ATTR(plane_, default_color_range);
 CONFIGFS_ATTR(plane_, supported_color_encoding);
 CONFIGFS_ATTR(plane_, default_color_encoding);
+CONFIGFS_ATTR(plane_, supported_formats);
 
 static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_type,
@@ -615,6 +696,7 @@ static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_default_color_range,
 	&plane_attr_supported_color_encoding,
 	&plane_attr_default_color_encoding,
+	&plane_attr_supported_formats,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 11/22] drm/vkms: Properly render plane using their zpos
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (9 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 10/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-18  2:01 ` [PATCH 12/22] drm/vkms: Introduce config for plane zpos property Louis Chauvet
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Currently planes are rendered in creation order. This is not an issue, but
with the introduction of new zpos configuration, it is required to
properly render planes.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_crtc.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index bac0790c6577..0524c47460fb 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -4,6 +4,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
@@ -141,14 +142,20 @@ static int vkms_crtc_atomic_check(struct drm_crtc *crtc,
 		return -ENOMEM;
 	vkms_state->num_active_planes = i;
 
-	i = 0;
+	ret = drm_atomic_normalize_zpos(crtc->dev, state);
+	if (ret)
+		return ret;
+
 	drm_for_each_plane_mask(plane, crtc->dev, crtc_state->plane_mask) {
 		plane_state = drm_atomic_get_new_plane_state(crtc_state->state, plane);
 
 		if (!plane_state->visible)
 			continue;
 
-		vkms_state->active_planes[i++] =
+		// Order planes according to their normalized_zpos
+		// After drm_atomic_normalize_zpos, the possible values are 0..n_planes-1
+		// so store them using this index
+		vkms_state->active_planes[plane_state->normalized_zpos] =
 			to_vkms_plane_state(plane_state);
 	}
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 12/22] drm/vkms: Introduce config for plane zpos property
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (10 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 11/22] drm/vkms: Properly render plane using their zpos Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27  9:12   ` José Expósito
  2025-10-18  2:01 ` [PATCH 13/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
VKMS can render plane in any order. Introduce the appropriate
configuration.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |   3 +
 drivers/gpu/drm/vkms/vkms_config.c            |  21 ++++
 drivers/gpu/drm/vkms/vkms_config.h            | 142 ++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_plane.c             |  11 ++
 4 files changed, 177 insertions(+)
diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index d75a6252e4d2..f2b38b436252 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -172,6 +172,9 @@ static void vkms_config_test_default_config(struct kunit *test)
 			n_possible_crtcs++;
 		}
 		KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1);
+		KUNIT_EXPECT_EQ(test, vkms_config_plane_get_zpos_enabled(plane_cfg), false);
+		// No need to test the other zpos configurations as they are discarded if
+		// the zpos property is not created.
 	}
 
 	/* Encoders */
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 0b975a0d47aa..5da34a3e8114 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -86,6 +86,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
 	if (IS_ERR(plane_cfg))
 		goto err_alloc;
 	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
+	vkms_config_plane_set_zpos_enabled(plane_cfg, false);
 
 	crtc_cfg = vkms_config_create_crtc(config);
 	if (IS_ERR(crtc_cfg))
@@ -103,6 +104,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
 
 			vkms_config_plane_set_type(plane_cfg,
 						   DRM_PLANE_TYPE_OVERLAY);
+			vkms_config_plane_set_zpos_enabled(plane_cfg, false);
 
 			if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
 				goto err_alloc;
@@ -115,6 +117,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
 			goto err_alloc;
 
 		vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
+		vkms_config_plane_set_zpos_enabled(plane_cfg, false);
 
 		if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
 			goto err_alloc;
@@ -206,6 +209,24 @@ static bool valid_plane_properties(const struct vkms_config *config)
 			drm_info(dev, "Configured default color range is not supported by the plane\n");
 			return false;
 		}
+		if (vkms_config_plane_get_zpos_initial(plane_cfg) >
+		    vkms_config_plane_get_zpos_max(plane_cfg)) {
+			drm_info(dev, "Configured initial zpos value bigger than zpos max\n");
+			return false;
+		}
+
+		if (vkms_config_plane_get_zpos_max(plane_cfg) <
+		    vkms_config_plane_get_zpos_min(plane_cfg)) {
+			drm_info(dev, "Configured zpos max value smaller than zpos min\n");
+			return false;
+		}
+
+		if (vkms_config_plane_get_zpos_initial(plane_cfg) <
+		    vkms_config_plane_get_zpos_min(plane_cfg)) {
+			drm_info(dev, "Configured initial zpos value smaller than zpos min\n");
+			return false;
+		}
+
 	}
 	return true;
 }
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 0b7067508e5f..267e45f5a617 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -49,6 +49,11 @@ struct vkms_config {
  * @supported_color_encoding: Color encoding that this plane will support
  * @default_color_range: Default color range that should be used by this plane
  * @supported_color_range: Color range that this plane will support
+ * @zpos_enable: Enable or disable the zpos property
+ * @zpos_mutable: Make the zpos property mutable or not (ignored if @zpos_enable is false)
+ * @zpos_initial: Initial value for zpos property (ignored if @zpos_enable is false)
+ * @zpos_min: Minimal value for zpos property (ignored if @zpos_enable is false)
+ * @zpos_max: Maximal value for zpos property (ignored if @zpos_enable is false)
  */
 struct vkms_config_plane {
 	struct list_head link;
@@ -65,6 +70,11 @@ struct vkms_config_plane {
 	u32 *supported_formats;
 	unsigned int supported_formats_count;
 	struct xarray possible_crtcs;
+	bool zpos_enabled;
+	bool zpos_mutable;
+	unsigned int zpos_initial;
+	unsigned int zpos_min;
+	unsigned int zpos_max;
 
 	/* Internal usage */
 	struct vkms_plane *plane;
@@ -477,6 +487,138 @@ vkms_config_plane_get_name(struct vkms_config_plane *plane_cfg)
 	return plane_cfg->name;
 }
 
+/**
+ * vkms_config_plane_set_zpos_enabled() - Enable or disable zpos property for a plane
+ * @plane_cfg: Plane configuration to modify
+ * @zpos_enabled: Whether to enable the zpos property
+ */
+static inline
+void vkms_config_plane_set_zpos_enabled(struct vkms_config_plane *plane_cfg,
+					bool zpos_enabled)
+{
+	plane_cfg->zpos_enabled = zpos_enabled;
+}
+
+/**
+ * vkms_config_plane_set_zpos_mutable() - Set whether zpos property is mutable
+ * @plane_cfg: Plane configuration to modify
+ * @zpos_mutable: Whether the zpos property should be mutable
+ */
+static inline
+void vkms_config_plane_set_zpos_mutable(struct vkms_config_plane *plane_cfg,
+					bool zpos_mutable)
+{
+	plane_cfg->zpos_mutable = zpos_mutable;
+}
+
+/**
+ * vkms_config_plane_set_zpos_initial() - Set the initial zpos value
+ * @plane_cfg: Plane configuration to modify
+ * @zpos_initial: Initial zpos value
+ */
+static inline
+void vkms_config_plane_set_zpos_initial(struct vkms_config_plane *plane_cfg,
+					unsigned int zpos_initial)
+{
+	plane_cfg->zpos_initial = zpos_initial;
+}
+
+/**
+ * vkms_config_plane_set_zpos_min() - Set the minimum zpos value
+ * @plane_cfg: Plane configuration to modify
+ * @zpos_min: Minimum zpos value
+ */
+static inline
+void vkms_config_plane_set_zpos_min(struct vkms_config_plane *plane_cfg,
+				    unsigned int zpos_min)
+{
+	plane_cfg->zpos_min = zpos_min;
+}
+
+/**
+ * vkms_config_plane_set_zpos_max() - Set the maximum zpos value
+ * @plane_cfg: Plane configuration to modify
+ * @zpos_max: Maximum zpos value
+ *
+ * Sets the maximum allowed value for the zpos property. This setting is
+ * ignored if zpos is disabled.
+ */
+static inline
+void vkms_config_plane_set_zpos_max(struct vkms_config_plane *plane_cfg,
+				    unsigned int zpos_max)
+{
+	plane_cfg->zpos_max = zpos_max;
+}
+
+/**
+ * vkms_config_plane_get_zpos_enabled() - Check if zpos property is enabled
+ * @plane_cfg: Plane configuration to check
+ *
+ * Returns:
+ * True if the zpos property is enabled for this plane, false otherwise.
+ */
+static inline
+bool vkms_config_plane_get_zpos_enabled(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->zpos_enabled;
+}
+
+/**
+ * vkms_config_plane_get_zpos_mutable() - Check if zpos property is mutable
+ * @plane_cfg: Plane configuration to check
+ *
+ * Returns:
+ * True if the zpos property is mutable for this plane, false otherwise.
+ * Returns false if zpos is disabled.
+ */
+static inline
+bool vkms_config_plane_get_zpos_mutable(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->zpos_mutable;
+}
+
+/**
+ * vkms_config_plane_get_zpos_initial() - Get the initial zpos value
+ * @plane_cfg: Plane configuration to check
+ *
+ * Returns:
+ * The initial zpos value for this plane. The return value is undefined if
+ * zpos is disabled.
+ */
+static inline
+unsigned int vkms_config_plane_get_zpos_initial(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->zpos_initial;
+}
+
+/**
+ * vkms_config_plane_get_zpos_min() - Get the minimum zpos value
+ * @plane_cfg: Plane configuration to check
+ *
+ * Returns:
+ * The minimum allowed zpos value for this plane. The return value is undefined
+ * if zpos is disabled.
+ */
+static inline
+unsigned int vkms_config_plane_get_zpos_min(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->zpos_min;
+}
+
+/**
+ * vkms_config_plane_get_zpos_max() - Get the maximum zpos value
+ * @plane_cfg: Plane configuration to check
+ *
+ * Returns:
+ * The maximum allowed zpos value for this plane. The return value is undefined
+ * if zpos is disabled.
+ */
+static inline
+unsigned int vkms_config_plane_get_zpos_max(struct vkms_config_plane *plane_cfg)
+{
+	return plane_cfg->zpos_max;
+}
+
 /**
  * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
  * @plane_cfg: Plane to attach
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 0414865915d8..51f6372a6f72 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -209,5 +209,16 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 					  vkms_config_plane_get_default_color_encoding(config),
 					  vkms_config_plane_get_default_color_range(config));
 
+	if (vkms_config_plane_get_zpos_enabled(config)) {
+		if (vkms_config_plane_get_zpos_mutable(config))
+			drm_plane_create_zpos_property(&plane->base,
+						       vkms_config_plane_get_zpos_initial(config),
+						       vkms_config_plane_get_zpos_min(config),
+						       vkms_config_plane_get_zpos_max(config));
+		else
+			drm_plane_create_zpos_immutable_property(&plane->base,
+								 vkms_config_plane_get_zpos_initial(config));
+	}
+
 	return plane;
 }
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 13/22] drm/vkms: Introduce configfs for plane zpos property
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (11 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 12/22] drm/vkms: Introduce config for plane zpos property Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27  9:19   ` José Expósito
  2025-10-18  2:01 ` [PATCH 14/22] drm/vkms: Introduce config for connector type Louis Chauvet
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Modern compositor rely on zpos managment to offload some processing to
deticated hardware. In order to test multiple configurations, add zpos
configuration to configFS.
Introduce multiple attributes to configure zpos:
- zpos_enabled - Create or not the zpos property. If not created, the zpos
  is undefined.
- zpos_mutable - If the zpos property is created, allow or not the
  userspace to modify it
- zpos_initial - Intial value for zpos property. Must be between zpos_min
  and zpos_max
- zpos_min - Minimal zpos value for this plane. Must be smaller than or
  equals to zpos_max
- zpos_max - Maximal zpos value for this plane. Must be greater than or
  equals to zpos_min
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |   9 +-
 drivers/gpu/drm/vkms/vkms_configfs.c | 199 +++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index deb14e7c48ea..d4ad4af45414 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -87,7 +87,7 @@ Start by creating one or more planes::
 
   sudo mkdir /config/vkms/my-vkms/planes/plane0
 
-Planes have 8 configurable attribute:
+Planes have 13 configurable attribute:
 
 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
   exposed by the "type" property of a plane)
@@ -111,6 +111,13 @@ Planes have 8 configurable attribute:
   To remove a format, use a minus and its fourcc: -XR24
   To add all formats use +*
   To remove all formats, use -*
+- zpos_enabled: Enable or not the zpos property: 1 enable, 0 disable
+- zpos_mutable: Create the zpos property as a mutable or imutable property: 1 mutable,
+  0 disable. No effect if zpos_enabled is not set.
+- zpos_initial: Set the initial zpos value. Must be between zpos_min and zpos_max. No
+  effect if zpos_enabled is not set.
+- zpos_min: Set the minimal zpos value. No effect if zpos_enabled is not set.
+- zpos_max: Set the maximal zpos value. No effect if zpos_enabled is not set.
 
 Continue by creating one or more CRTCs::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 528f22fa2df1..fd1be7292058 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0+
+#include "asm-generic/errno-base.h"
 #include <linux/cleanup.h>
 #include <linux/configfs.h>
 #include <linux/mutex.h>
@@ -679,6 +680,194 @@ static ssize_t plane_supported_formats_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t plane_zpos_enabled_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	bool enabled;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		enabled = vkms_config_plane_get_zpos_enabled(plane->config);
+
+	return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t plane_zpos_enabled_store(struct config_item *item, const char *page,
+					size_t count)
+{
+	struct vkms_configfs_plane *plane;
+	bool enabled;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	if (kstrtobool(page, &enabled))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		if (plane->dev->enabled)
+			return -EBUSY;
+
+		vkms_config_plane_set_zpos_enabled(plane->config, enabled);
+	}
+
+	return (ssize_t)count;
+}
+
+static ssize_t plane_zpos_mutable_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	bool mutable;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		mutable = vkms_config_plane_get_zpos_mutable(plane->config);
+
+	return sprintf(page, "%d\n", mutable);
+}
+
+static ssize_t plane_zpos_mutable_store(struct config_item *item, const char *page,
+					size_t count)
+{
+	struct vkms_configfs_plane *plane;
+	bool mutable;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	if (kstrtobool(page, &mutable))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		if (plane->dev->enabled)
+			return -EBUSY;
+
+		vkms_config_plane_set_zpos_mutable(plane->config, mutable);
+	}
+
+	return (ssize_t)count;
+}
+
+static ssize_t plane_zpos_initial_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int initial;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		initial = vkms_config_plane_get_zpos_initial(plane->config);
+
+	return sprintf(page, "%u\n", initial);
+}
+
+static ssize_t plane_zpos_initial_store(struct config_item *item, const char *page,
+					size_t count)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int initial;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	if (kstrtouint(page, 10, &initial))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		if (plane->dev->enabled)
+			return -EBUSY;
+
+		if (initial > vkms_config_plane_get_zpos_max(plane->config))
+			return -EINVAL;
+
+		if (initial < vkms_config_plane_get_zpos_min(plane->config))
+			return -EINVAL;
+
+		vkms_config_plane_set_zpos_initial(plane->config, initial);
+	}
+
+	return (ssize_t)count;
+}
+
+static ssize_t plane_zpos_min_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int min;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		min = vkms_config_plane_get_zpos_min(plane->config);
+
+	return sprintf(page, "%u\n", min);
+}
+
+static ssize_t plane_zpos_min_store(struct config_item *item, const char *page,
+				    size_t count)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int min;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	if (kstrtouint(page, 10, &min))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		if (plane->dev->enabled)
+			return -EBUSY;
+
+		if (min > vkms_config_plane_get_zpos_max(plane->config))
+			return -EINVAL;
+
+		if (min > vkms_config_plane_get_zpos_initial(plane->config))
+			return -EINVAL;
+
+		vkms_config_plane_set_zpos_min(plane->config, min);
+	}
+
+	return (ssize_t)count;
+}
+
+static ssize_t plane_zpos_max_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int max;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	scoped_guard(mutex, &plane->dev->lock)
+		max = vkms_config_plane_get_zpos_max(plane->config);
+
+	return sprintf(page, "%u\n", max);
+}
+
+static ssize_t plane_zpos_max_store(struct config_item *item, const char *page,
+				    size_t count)
+{
+	struct vkms_configfs_plane *plane;
+	unsigned int max;
+
+	plane = plane_item_to_vkms_configfs_plane(item);
+
+	if (kstrtouint(page, 10, &max))
+		return -EINVAL;
+
+	scoped_guard(mutex, &plane->dev->lock) {
+		if (plane->dev->enabled)
+			return -EBUSY;
+
+		if (max < vkms_config_plane_get_zpos_min(plane->config))
+			return -EINVAL;
+
+		if (max < vkms_config_plane_get_zpos_initial(plane->config))
+			return -EINVAL;
+
+		vkms_config_plane_set_zpos_max(plane->config, max);
+	}
+
+	return (ssize_t)count;
+}
+
 CONFIGFS_ATTR(plane_, type);
 CONFIGFS_ATTR(plane_, supported_rotations);
 CONFIGFS_ATTR(plane_, default_rotation);
@@ -687,6 +876,11 @@ CONFIGFS_ATTR(plane_, default_color_range);
 CONFIGFS_ATTR(plane_, supported_color_encoding);
 CONFIGFS_ATTR(plane_, default_color_encoding);
 CONFIGFS_ATTR(plane_, supported_formats);
+CONFIGFS_ATTR(plane_, zpos_enabled);
+CONFIGFS_ATTR(plane_, zpos_mutable);
+CONFIGFS_ATTR(plane_, zpos_initial);
+CONFIGFS_ATTR(plane_, zpos_min);
+CONFIGFS_ATTR(plane_, zpos_max);
 
 static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_type,
@@ -697,6 +891,11 @@ static struct configfs_attribute *plane_item_attrs[] = {
 	&plane_attr_supported_color_encoding,
 	&plane_attr_default_color_encoding,
 	&plane_attr_supported_formats,
+	&plane_attr_zpos_enabled,
+	&plane_attr_zpos_mutable,
+	&plane_attr_zpos_initial,
+	&plane_attr_zpos_min,
+	&plane_attr_zpos_max,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 14/22] drm/vkms: Introduce config for connector type
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (12 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 13/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27  9:27   ` José Expósito
  2025-10-18  2:01 ` [PATCH 15/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
In order to emulate connector-specific behavior, add connector type
configuration.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  6 ++++++
 drivers/gpu/drm/vkms/vkms_config.c            |  1 +
 drivers/gpu/drm/vkms/vkms_config.h            | 24 ++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_connector.c         |  5 +++--
 drivers/gpu/drm/vkms/vkms_connector.h         |  3 ++-
 drivers/gpu/drm/vkms/vkms_drv.h               |  1 +
 drivers/gpu/drm/vkms/vkms_output.c            |  2 +-
 7 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index f2b38b436252..8633210342a4 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 
+#include "drm/drm_mode.h"
 #include <kunit/test.h>
 
 #include "../vkms_config.h"
@@ -126,6 +127,7 @@ static void vkms_config_test_default_config(struct kunit *test)
 	struct vkms_config *config;
 	struct vkms_config_plane *plane_cfg;
 	struct vkms_config_crtc *crtc_cfg;
+	struct vkms_config_connector *connector_cfg;
 	int n_primaries = 0;
 	int n_cursors = 0;
 	int n_overlays = 0;
@@ -182,6 +184,10 @@ static void vkms_config_test_default_config(struct kunit *test)
 
 	/* Connectors */
 	KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 1);
+	vkms_config_for_each_connector(config, connector_cfg) {
+		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_type(connector_cfg),
+				DRM_MODE_CONNECTOR_VIRTUAL);
+	}
 
 	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 5da34a3e8114..20750c9f6d08 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -771,6 +771,7 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
 
 	connector_cfg->config = config;
 	connector_cfg->status = connector_status_connected;
+	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
 	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
 
 	list_add_tail(&connector_cfg->link, &config->connectors);
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 267e45f5a617..36d289a010f6 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -126,6 +126,7 @@ struct vkms_config_encoder {
  * struct vkms_config_connector
  *
  * @link: Link to the others connector in vkms_config
+ * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
  * @config: The vkms_config this connector belongs to
  * @status: Status (connected, disconnected...) of the connector
  * @possible_encoders: Array of encoders that can be used with this connector
@@ -138,6 +139,7 @@ struct vkms_config_connector {
 	struct list_head link;
 	struct vkms_config *config;
 
+	int type;
 	enum drm_connector_status status;
 	struct xarray possible_encoders;
 
@@ -315,6 +317,28 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
 }
 
 /**
+ * vkms_config_connector_get_type() - Return the connector type
+ * @connector_cfg: Connector to get the type from
+ */
+static inline int
+vkms_config_connector_get_type(struct vkms_config_connector *connector_cfg)
+{
+	return connector_cfg->type;
+}
+
+/**
+ * vkms_config_connector_set_type() - Set the connector type
+ * @connector_cfg: Connector to set the type to
+ * @type: New connector type
+ */
+static inline void
+vkms_config_connector_set_type(struct vkms_config_connector *connector_cfg,
+			       int type)
+{
+	connector_cfg->type = type;
+}
+
+/*
  * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
  * @plane_cfg: Plane to get the default rotation from
  *
diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
index b0a6b212d3f4..5a87dc2d4c63 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.c
+++ b/drivers/gpu/drm/vkms/vkms_connector.c
@@ -68,7 +68,8 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
 	.best_encoder = vkms_conn_best_encoder,
 };
 
-struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev)
+struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
+					   struct vkms_config_connector *connector_cfg)
 {
 	struct drm_device *dev = &vkmsdev->drm;
 	struct vkms_connector *connector;
@@ -79,7 +80,7 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev)
 		return ERR_PTR(-ENOMEM);
 
 	ret = drmm_connector_init(dev, &connector->base, &vkms_connector_funcs,
-				  DRM_MODE_CONNECTOR_VIRTUAL, NULL);
+				  vkms_config_connector_get_type(connector_cfg), NULL);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/vkms_connector.h
index ed312f4eff3a..a124c5403697 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.h
+++ b/drivers/gpu/drm/vkms/vkms_connector.h
@@ -24,7 +24,8 @@ struct vkms_connector {
  * Returns:
  * The connector or an error on failure.
  */
-struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev);
+struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
+					   struct vkms_config_connector *connector_cfg);
 
 /**
  * vkms_trigger_connector_hotplug() - Update the device's connectors status
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 9ad286f043b5..07bdf3f550ae 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -226,6 +226,7 @@ struct vkms_output {
 
 struct vkms_config;
 struct vkms_config_plane;
+struct vkms_config_connector;
 
 /**
  * struct vkms_device - Description of a VKMS device
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 22208d02afa4..217f054d9598 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -96,7 +96,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		struct vkms_config_encoder *possible_encoder;
 		unsigned long idx = 0;
 
-		connector_cfg->connector = vkms_connector_init(vkmsdev);
+		connector_cfg->connector = vkms_connector_init(vkmsdev, connector_cfg);
 		if (IS_ERR(connector_cfg->connector)) {
 			DRM_ERROR("Failed to init connector\n");
 			return PTR_ERR(connector_cfg->connector);
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 15/22] drm/vkms: Introduce configfs for connector type
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (13 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 14/22] drm/vkms: Introduce config for connector type Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-18  2:01 ` [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Add a new attribute to connector to change its type. This is mostly
cosmetic and don't have direct effect in VKMS behavior.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  3 +-
 drivers/gpu/drm/vkms/vkms_configfs.c | 64 ++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index d4ad4af45414..97ea11a86bd1 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -135,10 +135,11 @@ Last but not least, create one or more connectors::
 
   sudo mkdir /config/vkms/my-vkms/connectors/connector0
 
-Connectors have 1 configurable attribute:
+Connectors have 2 configurable attribute:
 
 - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
   as those exposed by the "status" property of a connector)
+- type: Type of connector. Same values as exposed by the "type" field in drm_connector.
 
 To finish the configuration, link the different pipeline items::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index fd1be7292058..0cf7cee4eb0f 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1123,10 +1123,74 @@ static ssize_t connector_status_store(struct config_item *item,
 	return (ssize_t)count;
 }
 
+static ssize_t connector_type_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+	int type;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock) {
+		type = vkms_config_connector_get_type(connector->config);
+	}
+
+	return sprintf(page, "%u", type);
+}
+
+static ssize_t connector_type_store(struct config_item *item,
+				    const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+	int val, ret;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	ret = kstrtouint(page, 10, &val);
+
+	if (ret)
+		return ret;
+
+	switch (val) {
+	case DRM_MODE_CONNECTOR_Unknown:
+	case DRM_MODE_CONNECTOR_VGA:
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_DVIA:
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_LVDS:
+	case DRM_MODE_CONNECTOR_Component:
+	case DRM_MODE_CONNECTOR_9PinDIN:
+	case DRM_MODE_CONNECTOR_DisplayPort:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_HDMIB:
+	case DRM_MODE_CONNECTOR_TV:
+	case DRM_MODE_CONNECTOR_eDP:
+	case DRM_MODE_CONNECTOR_VIRTUAL:
+	case DRM_MODE_CONNECTOR_DSI:
+	case DRM_MODE_CONNECTOR_DPI:
+	case DRM_MODE_CONNECTOR_SPI:
+	case DRM_MODE_CONNECTOR_USB:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	scoped_guard(mutex, &connector->dev->lock) {
+		if (connector->dev->enabled)
+			return -EINVAL;
+		vkms_config_connector_set_type(connector->config, val);
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(connector_, status);
+CONFIGFS_ATTR(connector_, type);
 
 static struct configfs_attribute *connector_item_attrs[] = {
 	&connector_attr_status,
+	&connector_attr_type,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (14 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 15/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27  9:35   ` José Expósito
  2025-10-27  9:38   ` José Expósito
  2025-10-18  2:01 ` [PATCH 17/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (6 subsequent siblings)
  22 siblings, 2 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
To emulate some HDR features of displays, it is required to expose some
properties on HDMI, eDP and DP connectors.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  3 +++
 drivers/gpu/drm/vkms/vkms_config.c            |  1 +
 drivers/gpu/drm/vkms/vkms_config.h            | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_connector.c         | 15 +++++++++++++++
 4 files changed, 45 insertions(+)
diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index 8633210342a4..a89ccd75060d 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -187,6 +187,9 @@ static void vkms_config_test_default_config(struct kunit *test)
 	vkms_config_for_each_connector(config, connector_cfg) {
 		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_type(connector_cfg),
 				DRM_MODE_CONNECTOR_VIRTUAL);
+		KUNIT_EXPECT_EQ(test,
+				vkms_config_connector_get_supported_colorspaces(connector_cfg),
+				0);
 	}
 
 	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 20750c9f6d08..56e2082b91c9 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -772,6 +772,7 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
 	connector_cfg->config = config;
 	connector_cfg->status = connector_status_connected;
 	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
+	vkms_config_connector_set_supported_colorspaces(connector_cfg, 0);
 	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
 
 	list_add_tail(&connector_cfg->link, &config->connectors);
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 36d289a010f6..ec614c2d4a30 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -141,6 +141,7 @@ struct vkms_config_connector {
 
 	int type;
 	enum drm_connector_status status;
+	u32 supported_colorspaces;
 	struct xarray possible_encoders;
 
 	/* Internal usage */
@@ -239,6 +240,31 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
  */
 void vkms_config_destroy(struct vkms_config *config);
 
+/**
+ * vkms_config_connector_set_supported_colorspaces() - Set the supported colorspaces for a connector
+ * @connector_cfg: Connector configuration to modify
+ * @supported_colorspaces: Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
+ */
+static inline void
+vkms_config_connector_set_supported_colorspaces(struct vkms_config_connector *connector_cfg,
+						u32 supported_colorspaces)
+{
+	connector_cfg->supported_colorspaces = supported_colorspaces;
+}
+
+/**
+ * vkms_config_connector_get_supported_colorspaces() - Get the supported colorspaces for a connector
+ * @connector_cfg: Connector configuration to query
+ *
+ * Returns:
+ * Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
+ */
+static inline u32
+vkms_config_connector_get_supported_colorspaces(struct vkms_config_connector *connector_cfg)
+{
+	return connector_cfg->supported_colorspaces;
+}
+
 /**
  * vkms_config_get_device_name() - Return the name of the device
  * @config: Configuration to get the device name from
diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
index 5a87dc2d4c63..cc59d13c2d22 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.c
+++ b/drivers/gpu/drm/vkms/vkms_connector.c
@@ -84,6 +84,21 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
 	if (ret)
 		return ERR_PTR(ret);
 
+	if (vkms_config_connector_get_supported_colorspaces(connector_cfg)) {
+		if (connector_cfg->type == DRM_MODE_CONNECTOR_HDMIA) {
+			drm_mode_create_hdmi_colorspace_property(&connector->base,
+								 vkms_config_connector_get_supported_colorspaces(connector_cfg));
+			drm_connector_attach_hdr_output_metadata_property(&connector->base);
+			drm_connector_attach_colorspace_property(&connector->base);
+		} else if (connector_cfg->type == DRM_MODE_CONNECTOR_DisplayPort ||
+			   connector_cfg->type == DRM_MODE_CONNECTOR_eDP) {
+			drm_mode_create_dp_colorspace_property(&connector->base,
+							       vkms_config_connector_get_supported_colorspaces(connector_cfg));
+			drm_connector_attach_hdr_output_metadata_property(&connector->base);
+			drm_connector_attach_colorspace_property(&connector->base);
+		}
+	}
+
 	drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs);
 
 	return connector;
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 17/22] drm/vkms: Introduce configfs for connector supported colorspace
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (15 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-18  2:01 ` [PATCH 18/22] drm/vkms: Introduce config for connector EDID Louis Chauvet
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Add the attribute supported_colorspaces to configure the supported
colorspace of a connector. It will allows emulating some HDR features of
displays. This feature is only supported for HDMI, DP and eDP connectors.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  7 ++++++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 39 ++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 97ea11a86bd1..650d6f6e79fd 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -135,11 +135,16 @@ Last but not least, create one or more connectors::
 
   sudo mkdir /config/vkms/my-vkms/connectors/connector0
 
-Connectors have 2 configurable attribute:
+Connectors have 3 configurable attribute:
 
 - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
   as those exposed by the "status" property of a connector)
 - type: Type of connector. Same values as exposed by the "type" field in drm_connector.
+- supported_colorspaces: Supported colorspaces values for HDMI, DP and eDP connectors.
+  If supported_colorspaces is not 0, the HDR_OUTPUT_METADATA will also be created.
+  Value is a bitfield, 0x1 = NO_DATA, 0x2 = SMPTE_170M_YCC... see enum drm_colorspace
+  for full list.
+
 
 To finish the configuration, link the different pipeline items::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 0cf7cee4eb0f..909f4557caec 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1185,12 +1185,51 @@ static ssize_t connector_type_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t connector_supported_colorspaces_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+	int type;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock)
+		type = vkms_config_connector_get_supported_colorspaces(connector->config);
+
+	return sprintf(page, "%u", type);
+}
+
+static ssize_t connector_supported_colorspaces_store(struct config_item *item,
+						     const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+	int val, ret;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	ret = kstrtouint(page, 10, &val);
+	if (ret)
+		return ret;
+
+	if ((val & -BIT(DRM_MODE_COLORIMETRY_COUNT)) != 0)
+		return -EINVAL;
+
+	scoped_guard(mutex, &connector->dev->lock) {
+		if (connector->dev->enabled)
+			return -EBUSY;
+		vkms_config_connector_set_supported_colorspaces(connector->config, val);
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(connector_, status);
 CONFIGFS_ATTR(connector_, type);
+CONFIGFS_ATTR(connector_, supported_colorspaces);
 
 static struct configfs_attribute *connector_item_attrs[] = {
 	&connector_attr_status,
 	&connector_attr_type,
+	&connector_attr_supported_colorspaces,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 18/22] drm/vkms: Introduce config for connector EDID
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (16 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 17/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27 10:02   ` José Expósito
  2025-10-18  2:01 ` [PATCH 19/22] drm/vkms: Introduce configfs " Louis Chauvet
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Allows configuration of EDID for each connector.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  2 +
 drivers/gpu/drm/vkms/vkms_config.h            | 77 +++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_connector.c         | 48 +++++++++++++++--
 3 files changed, 123 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index a89ccd75060d..d1e380da31ff 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -190,6 +190,8 @@ static void vkms_config_test_default_config(struct kunit *test)
 		KUNIT_EXPECT_EQ(test,
 				vkms_config_connector_get_supported_colorspaces(connector_cfg),
 				0);
+		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_edid_enabled(connector_cfg),
+				false);
 	}
 
 	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index ec614c2d4a30..eaf76a58aab6 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -129,6 +129,8 @@ struct vkms_config_encoder {
  * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
  * @config: The vkms_config this connector belongs to
  * @status: Status (connected, disconnected...) of the connector
+ * @edid: Stores the current EDID
+ * @edid_len: Current EDID length
  * @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
@@ -142,6 +144,9 @@ struct vkms_config_connector {
 	int type;
 	enum drm_connector_status status;
 	u32 supported_colorspaces;
+	bool edid_enabled;
+	u8 *edid;
+	unsigned int edid_len;
 	struct xarray possible_encoders;
 
 	/* Internal usage */
@@ -265,6 +270,78 @@ vkms_config_connector_get_supported_colorspaces(struct vkms_config_connector *co
 	return connector_cfg->supported_colorspaces;
 }
 
+/**
+ * vkms_config_connector_get_edid_enabled() - Check if EDID is enabled for a connector
+ * @connector_cfg: Connector configuration to check
+ *
+ * Returns:
+ * True if EDID is enabled for this connector, false otherwise.
+ */
+static inline bool
+vkms_config_connector_get_edid_enabled(struct vkms_config_connector *connector_cfg)
+{
+	return connector_cfg->edid_enabled;
+}
+
+/**
+ * vkms_config_connector_set_edid_enabled() - Enable or disable EDID for a connector
+ * @connector_cfg: Connector configuration to modify
+ * @enabled: Whether to enable EDID for this connector
+ */
+static inline void
+vkms_config_connector_set_edid_enabled(struct vkms_config_connector *connector_cfg,
+				       bool enabled)
+{
+	connector_cfg->edid_enabled = enabled;
+}
+
+/**
+ * vkms_config_connector_get_edid() - Get the EDID data for a connector
+ * @connector_cfg: Connector configuration to get the EDID from
+ * @len: Pointer to store the length of the EDID data
+ *
+ * Returns:
+ * Pointer to the EDID data buffer, or NULL if no EDID is set.
+ * The length of the EDID data is stored in @len.
+ */
+static inline const u8 *
+vkms_config_connector_get_edid(const struct vkms_config_connector *connector_cfg, int *len)
+{
+	*len = connector_cfg->edid_len;
+	return connector_cfg->edid;
+}
+
+/**
+ * vkms_config_connector_set_edid() - Set the EDID data for a connector
+ * @connector_cfg: Connector configuration to modify
+ * @edid: Pointer to the EDID data buffer
+ * @len: Length of the EDID data
+ *
+ * If @len is 0, the EDID data will be cleared. If memory allocation fails,
+ * the existing EDID data will be preserved.
+ */
+static inline void
+vkms_config_connector_set_edid(struct vkms_config_connector *connector_cfg,
+			       const u8 *edid, unsigned int len)
+{
+	if (len) {
+		void *edid_tmp = krealloc(connector_cfg->edid, len, GFP_KERNEL);
+
+		if (edid_tmp) {
+			connector_cfg->edid = edid_tmp;
+			memcpy(connector_cfg->edid, edid, len);
+			connector_cfg->edid_len = len;
+		} else {
+			kfree(connector_cfg->edid);
+			connector_cfg->edid_len = 0;
+		}
+	} else {
+		kfree(connector_cfg->edid);
+		connector_cfg->edid = NULL;
+		connector_cfg->edid_len = len;
+	}
+}
+
 /**
  * vkms_config_get_device_name() - Return the name of the device
  * @config: Configuration to get the device name from
diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
index cc59d13c2d22..339d747e729e 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.c
+++ b/drivers/gpu/drm/vkms/vkms_connector.c
@@ -42,13 +42,53 @@ static const struct drm_connector_funcs vkms_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
+static int vkms_connector_read_block(void *context, u8 *buf, unsigned int block, size_t len)
+{
+	struct vkms_config_connector *config = context;
+	unsigned int edid_len;
+	const u8 *edid = vkms_config_connector_get_edid(config, &edid_len);
+
+	if (block * len + len > edid_len)
+		return 1;
+	memcpy(buf, &edid[block * len], len);
+	return 0;
+}
+
 static int vkms_conn_get_modes(struct drm_connector *connector)
 {
-	int count;
+	struct vkms_connector *vkms_connector = drm_connector_to_vkms_connector(connector);
+	const struct drm_edid *drm_edid = NULL;
+	int count = 0;
+	struct vkms_config_connector *context = NULL;
+	struct drm_device *dev = connector->dev;
+	struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
+	struct vkms_config_connector *connector_cfg;
 
-	/* Use the default modes list from DRM */
-	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
-	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
+	vkms_config_for_each_connector(vkmsdev->config, connector_cfg) {
+		if (connector_cfg->connector == vkms_connector)
+			context = connector_cfg;
+	}
+	if (context) {
+		if (vkms_config_connector_get_edid_enabled(context)) {
+			drm_edid = drm_edid_read_custom(connector,
+							vkms_connector_read_block, context);
+
+			/*
+			 * Unconditionally update the connector. If the EDID was read
+			 * successfully, fill in the connector information derived from the
+			 * EDID. Otherwise, if the EDID is NULL, clear the connector
+			 * information.
+			 */
+			drm_edid_connector_update(connector, drm_edid);
+
+			count = drm_edid_connector_add_modes(connector);
+
+			drm_edid_free(drm_edid);
+		} else {
+			count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
+			drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
+		}
+	}
 
 	return count;
 }
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 19/22] drm/vkms: Introduce configfs for connector EDID
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (17 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 18/22] drm/vkms: Introduce config for connector EDID Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27 10:16   ` José Expósito
  2025-10-18  2:01 ` [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector Louis Chauvet
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
Introduce new attributes to configure EDID of a connector:
- edid_enable - chose if the connector will have an EDD or not
- edid - raw edid content
Due to limitation of ConfigFS, the max len of EDID is PAGE_SIZE (4kB on
x86), it should be sufficient for many tests. One possible evolution is
using a ConfigFS blob to allow bigger EDID.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |  5 ++-
 drivers/gpu/drm/vkms/vkms_configfs.c | 81 +++++++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 650d6f6e79fd..bbd03f61e61c 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -135,7 +135,7 @@ Last but not least, create one or more connectors::
 
   sudo mkdir /config/vkms/my-vkms/connectors/connector0
 
-Connectors have 3 configurable attribute:
+Connectors have 5 configurable attribute:
 
 - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
   as those exposed by the "status" property of a connector)
@@ -144,6 +144,9 @@ Connectors have 3 configurable attribute:
   If supported_colorspaces is not 0, the HDR_OUTPUT_METADATA will also be created.
   Value is a bitfield, 0x1 = NO_DATA, 0x2 = SMPTE_170M_YCC... see enum drm_colorspace
   for full list.
+- edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
+  EDID but just a list of modes, this attribute allows to disable EDID property.
+- edid: Content of the EDID. Ignored if edid_enabled is not set
 
 
 To finish the configuration, link the different pipeline items::
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 909f4557caec..a977c0842cd6 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1,5 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0+
-#include "asm-generic/errno-base.h"
 #include <linux/cleanup.h>
 #include <linux/configfs.h>
 #include <linux/mutex.h>
@@ -1222,14 +1221,94 @@ static ssize_t connector_supported_colorspaces_store(struct config_item *item,
 	return count;
 }
 
+static ssize_t connector_edid_enabled_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+	bool enabled;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock)
+		enabled = vkms_config_connector_get_edid_enabled(connector->config);
+
+	return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t connector_edid_enabled_store(struct config_item *item,
+					    const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+	struct vkms_config_connector *connector_cfg;
+	bool enabled;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+	connector_cfg = connector->config;
+
+	if (kstrtobool(page, &enabled))
+		return -EINVAL;
+
+	scoped_guard(mutex, &connector->dev->lock)
+	{
+		vkms_config_connector_set_edid_enabled(connector_cfg, enabled);
+
+		if (connector->dev->enabled &&
+		    vkms_config_connector_get_status(connector_cfg) !=
+		    connector_status_disconnected)
+			vkms_trigger_connector_hotplug(connector->dev->config->dev);
+	}
+	return count;
+}
+
+static ssize_t connector_edid_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock)
+	{
+		unsigned int len = 0;
+		const u8 *edid = vkms_config_connector_get_edid(connector->config, &len);
+
+		memcpy(page, edid, min(len, PAGE_SIZE));
+		return min(len, PAGE_SIZE);
+	}
+
+	return -EINVAL;
+}
+
+static ssize_t connector_edid_store(struct config_item *item,
+				    const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock)
+	{
+		vkms_config_connector_set_edid(connector->config, page, count);
+
+		if (connector->dev->enabled &&
+		    vkms_config_connector_get_status(connector->config) !=
+		    connector_status_disconnected)
+			vkms_trigger_connector_hotplug(connector->dev->config->dev);
+	}
+
+	return count;
+}
+
 CONFIGFS_ATTR(connector_, status);
 CONFIGFS_ATTR(connector_, type);
 CONFIGFS_ATTR(connector_, supported_colorspaces);
+CONFIGFS_ATTR(connector_, edid_enabled);
+CONFIGFS_ATTR(connector_, edid);
 
 static struct configfs_attribute *connector_item_attrs[] = {
 	&connector_attr_status,
 	&connector_attr_type,
 	&connector_attr_supported_colorspaces,
+	&connector_attr_edid_enabled,
+	&connector_attr_edid,
 	NULL,
 };
 
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (18 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 19/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27 14:52   ` José Expósito
  2025-10-18  2:01 ` [PATCH 21/22] drm/vkms: Allow to hot-add connectors Louis Chauvet
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
In order to prepare for dynamic connector configuration, we need to store
if a connector is dynamic and if it is enabled.
The two new vkms_config_connector fields will helps for that.
Co-developed-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  4 ++
 drivers/gpu/drm/vkms/vkms_config.c            |  2 +
 drivers/gpu/drm/vkms/vkms_config.h            | 66 +++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)
diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index d1e380da31ff..f4b5f8f59fab 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -192,6 +192,10 @@ static void vkms_config_test_default_config(struct kunit *test)
 				0);
 		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_edid_enabled(connector_cfg),
 				false);
+		KUNIT_EXPECT_EQ(test, vkms_config_connector_is_enabled(connector_cfg),
+				true);
+		KUNIT_EXPECT_EQ(test, vkms_config_connector_is_dynamic(connector_cfg),
+				false);
 	}
 
 	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 56e2082b91c9..fd724ae2ebc9 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -773,6 +773,8 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
 	connector_cfg->status = connector_status_connected;
 	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
 	vkms_config_connector_set_supported_colorspaces(connector_cfg, 0);
+	vkms_config_connector_set_dynamic(connector_cfg, false);
+	vkms_config_connector_set_enabled(connector_cfg, true);
 	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
 
 	list_add_tail(&connector_cfg->link, &config->connectors);
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index eaf76a58aab6..6716b5a85f0d 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -128,6 +128,8 @@ struct vkms_config_encoder {
  * @link: Link to the others connector in vkms_config
  * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
  * @config: The vkms_config this connector belongs to
+ * @dynamic: Store if a connector should be created with drm_connector_dynamic_init
+ * @enabled: If @dynamic, this means that the correct is currently registered in drm
  * @status: Status (connected, disconnected...) of the connector
  * @edid: Stores the current EDID
  * @edid_len: Current EDID length
@@ -142,6 +144,8 @@ struct vkms_config_connector {
 	struct vkms_config *config;
 
 	int type;
+	bool enabled;
+	bool dynamic;
 	enum drm_connector_status status;
 	u32 supported_colorspaces;
 	bool edid_enabled;
@@ -185,6 +189,24 @@ struct vkms_config_connector {
 #define vkms_config_for_each_connector(config, connector_cfg) \
 	list_for_each_entry((connector_cfg), &(config)->connectors, link)
 
+/**
+ * vkms_config_for_each_connector_static - Iterate over the static vkms_config connectors
+ * @config: &struct vkms_config pointer
+ * @connector_cfg: &struct vkms_config_connector pointer used as cursor
+ */
+#define vkms_config_for_each_connector_static(config, connector_cfg) \
+	vkms_config_for_each_connector((config), (connector_cfg)) \
+		if (!(connector_cfg)->dynamic)
+
+/**
+ * vkms_config_for_each_connector_dynamic - Iterate over the dynamic vkms_config connectors
+ * @config: &struct vkms_config pointer
+ * @connector_cfg: &struct vkms_config_connector pointer used as cursor
+ */
+#define vkms_config_for_each_connector_dynamic(config, connector_cfg) \
+	vkms_config_for_each_connector((config), (connector_cfg)) \
+		if ((connector_cfg)->dynamic)
+
 /**
  * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config_plane
  * possible CRTCs
@@ -441,6 +463,50 @@ vkms_config_connector_set_type(struct vkms_config_connector *connector_cfg,
 	connector_cfg->type = type;
 }
 
+/**
+ * vkms_config_connector_set_enabled() - If the connector is part of the device
+ * @crtc_cfg: Target connector
+ * @enabled: Add or remove the connector
+ */
+static inline void
+vkms_config_connector_set_enabled(struct vkms_config_connector *connector_cfg,
+				  bool enabled)
+{
+	connector_cfg->enabled = enabled;
+}
+
+/**
+ * vkms_config_connector_is_enabled() - If the connector is part of the device
+ * @connector_cfg: The connector
+ */
+static inline bool
+vkms_config_connector_is_enabled(struct vkms_config_connector *connector_cfg)
+{
+	return connector_cfg->enabled;
+}
+
+/**
+ * vkms_config_connector_set_dynamic() - If the connector is dynamic
+ * @crtc_cfg: Target connector
+ * @enabled: Enable or disable the dynamic status
+ */
+static inline void
+vkms_config_connector_set_dynamic(struct vkms_config_connector *connector_cfg,
+				  bool dynamic)
+{
+	connector_cfg->dynamic = dynamic;
+}
+
+/**
+ * vkms_config_connector_is_enabled() - If the connector is dynamic
+ * @connector_cfg: The connector
+ */
+static inline bool
+vkms_config_connector_is_dynamic(struct vkms_config_connector *connector_cfg)
+{
+	return connector_cfg->dynamic;
+}
+
 /*
  * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
  * @plane_cfg: Plane to get the default rotation from
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 21/22] drm/vkms: Allow to hot-add connectors
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (19 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27 15:01   ` José Expósito
  2025-10-18  2:01 ` [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime Louis Chauvet
  2025-10-27 15:22 ` [PATCH 00/22] VKMS: Introduce multiple configFS attributes José Expósito
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
In order to allow creating dynamic connector, add the required
infrastructure in vkms_connector.
Co-developed-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
[Louis Chauvet: use drm_atomic_helper_connector_reset instead of
drm_mode_config_reset because connector is not yet registered]
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_connector.c | 69 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_connector.h | 33 +++++++++++++++++
 drivers/gpu/drm/vkms/vkms_output.c    | 11 +++++-
 3 files changed, 111 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
index 339d747e729e..77a544728721 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.c
+++ b/drivers/gpu/drm/vkms/vkms_connector.c
@@ -1,5 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0+
-
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_managed.h>
@@ -144,9 +143,77 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
 	return connector;
 }
 
+static const struct drm_connector_funcs vkms_dynamic_connector_funcs = {
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.destroy = drm_connector_cleanup,
+	.detect = vkms_connector_detect,
+};
+
 void vkms_trigger_connector_hotplug(struct vkms_device *vkmsdev)
 {
 	struct drm_device *dev = &vkmsdev->drm;
 
 	drm_kms_helper_hotplug_event(dev);
 }
+
+struct vkms_connector *vkms_connector_hot_add(struct vkms_device *vkmsdev,
+					      struct vkms_config_connector *connector_cfg)
+{
+	struct vkms_config_encoder *encoder_cfg;
+	struct vkms_connector *connector;
+	int ret;
+	unsigned long idx = 0;
+
+	connector = kzalloc(sizeof(*connector), GFP_KERNEL);
+	if (IS_ERR(connector))
+		return connector;
+	ret = drm_connector_dynamic_init(&vkmsdev->drm,
+					 &connector->base,
+					 &vkms_dynamic_connector_funcs,
+					 connector_cfg->type,
+					 NULL);
+	if (ret)
+		return ERR_PTR(ret);
+	drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs);
+
+	vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, encoder_cfg) {
+		ret = drm_connector_attach_encoder(&connector->base,
+						   encoder_cfg->encoder);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	drm_atomic_helper_connector_reset(&connector->base);
+
+	ret = drm_connector_dynamic_register(&connector->base);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return connector;
+}
+
+void vkms_connector_hot_remove(struct vkms_device *vkmsdev,
+			       struct vkms_connector *connector)
+{
+	drm_connector_unregister(&connector->base);
+	drm_mode_config_reset(&vkmsdev->drm);
+	drm_connector_put(&connector->base);
+}
+
+int vkms_connector_hot_attach_encoder(struct vkms_device *vkmsdev,
+				      struct vkms_connector *connector,
+				      struct drm_encoder *encoder)
+{
+	int ret;
+
+	ret = drm_connector_attach_encoder(&connector->base, encoder);
+	if (ret)
+		return ret;
+
+	drm_mode_config_reset(&vkmsdev->drm);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/vkms_connector.h
index a124c5403697..224950c13a93 100644
--- a/drivers/gpu/drm/vkms/vkms_connector.h
+++ b/drivers/gpu/drm/vkms/vkms_connector.h
@@ -7,6 +7,7 @@
 
 #define drm_connector_to_vkms_connector(target) \
 	container_of(target, struct vkms_connector, base)
+struct vkms_config_connector;
 
 /**
  * struct vkms_connector - VKMS custom type wrapping around the DRM connector
@@ -33,4 +34,36 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
  */
 void vkms_trigger_connector_hotplug(struct vkms_device *vkmsdev);
 
+/**
+ * vkms_connector_hot_add() - Create a connector after the device is created
+ * @vkmsdev: Device to hot-add the connector to
+ * @connector_cfg: Connector's configuration
+ *
+ * Returns:
+ * The connector or an error on failure.
+ */
+struct vkms_connector *vkms_connector_hot_add(struct vkms_device *vkmsdev,
+					      struct vkms_config_connector *connector_cfg);
+
+/**
+ * vkms_connector_hot_remove() - Remove a connector after a device is created
+ * @connector: The connector to hot-remove
+ */
+void vkms_connector_hot_remove(struct vkms_device *vkmsdev,
+			       struct vkms_connector *connector);
+
+/**
+ * vkms_connector_hot_attach_encoder() - Attach a connector to a encoder after
+ * the device is created.
+ * @vkmsdev: Device containing the connector and the encoder
+ * @connector: Connector to attach to @encoder
+ * @encoder: Target encoder
+ *
+ * Returns:
+ * 0 on success or an error on failure.
+ */
+int vkms_connector_hot_attach_encoder(struct vkms_device *vkmsdev,
+				      struct vkms_connector *connector,
+				      struct drm_encoder *encoder);
+
 #endif /* _VKMS_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 217f054d9598..aba2f9ab243d 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -92,7 +92,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		}
 	}
 
-	vkms_config_for_each_connector(vkmsdev->config, connector_cfg) {
+	vkms_config_for_each_connector_static(vkmsdev->config, connector_cfg) {
 		struct vkms_config_encoder *possible_encoder;
 		unsigned long idx = 0;
 
@@ -116,5 +116,14 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 
 	drm_mode_config_reset(dev);
 
+	vkms_config_for_each_connector_dynamic(vkmsdev->config, connector_cfg) {
+		if (connector_cfg->enabled) {
+			connector_cfg->connector = vkms_connector_hot_add(vkmsdev, connector_cfg);
+
+			if (IS_ERR(connector_cfg->connector))
+				return PTR_ERR(connector_cfg->connector);
+		}
+	}
+
 	return 0;
 }
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (20 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 21/22] drm/vkms: Allow to hot-add connectors Louis Chauvet
@ 2025-10-18  2:01 ` Louis Chauvet
  2025-10-27 15:17   ` José Expósito
  2025-10-27 15:22 ` [PATCH 00/22] VKMS: Introduce multiple configFS attributes José Expósito
  22 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-18  2:01 UTC (permalink / raw)
  To: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, jose.exposito89,
	Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
DRM allows the connector to be created after the device. To allows
emulating this, add two configfs attributes to connector to allows this.
Using the dynamic attribute you can set if a connector will be dynamic or
not.
Using the enabled attribute, you can set at runtime if a dynamic connector
is present or not.
Co-developed-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 Documentation/gpu/vkms.rst           |   6 +-
 drivers/gpu/drm/vkms/vkms_configfs.c | 146 ++++++++++++++++++++++++++++++++---
 2 files changed, 139 insertions(+), 13 deletions(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index bbd03f61e61c..8b17aaa28eeb 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -135,7 +135,7 @@ Last but not least, create one or more connectors::
 
   sudo mkdir /config/vkms/my-vkms/connectors/connector0
 
-Connectors have 5 configurable attribute:
+Connectors have 7 configurable attribute:
 
 - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
   as those exposed by the "status" property of a connector)
@@ -147,7 +147,9 @@ Connectors have 5 configurable attribute:
 - edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
   EDID but just a list of modes, this attribute allows to disable EDID property.
 - edid: Content of the EDID. Ignored if edid_enabled is not set
-
+- dynamic: Set to 1 while configuring the device to create a dynamic connector. A dynamic
+  connector can be used to emulate DP MST connectors.
+- enabled: For dynamic connector, set it to 1 to create the connector, 0 to remove it.
 
 To finish the configuration, link the different pipeline items::
 
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index a977c0842cd6..937b749142ad 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1115,8 +1115,12 @@ static ssize_t connector_status_store(struct config_item *item,
 	scoped_guard(mutex, &connector->dev->lock) {
 		vkms_config_connector_set_status(connector->config, status);
 
-		if (connector->dev->enabled)
-			vkms_trigger_connector_hotplug(connector->dev->config->dev);
+		if (connector->dev->enabled) {
+			if (connector->config->dynamic && connector->config->enabled)
+				vkms_trigger_connector_hotplug(connector->dev->config->dev);
+			if (!connector->config->dynamic)
+				vkms_trigger_connector_hotplug(connector->dev->config->dev);
+		}
 	}
 
 	return (ssize_t)count;
@@ -1176,8 +1180,12 @@ static ssize_t connector_type_store(struct config_item *item,
 	}
 
 	scoped_guard(mutex, &connector->dev->lock) {
-		if (connector->dev->enabled)
-			return -EINVAL;
+		if (connector->dev->enabled) {
+			if (connector->config->dynamic && connector->config->enabled)
+				return -EBUSY;
+			if (!connector->config->dynamic)
+				return -EBUSY;
+		}
 		vkms_config_connector_set_type(connector->config, val);
 	}
 
@@ -1293,6 +1301,102 @@ static ssize_t connector_edid_store(struct config_item *item,
 		    connector_status_disconnected)
 			vkms_trigger_connector_hotplug(connector->dev->config->dev);
 	}
+	return count;
+}
+
+static ssize_t connector_enabled_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+	bool enabled;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock)
+		enabled = vkms_config_connector_is_enabled(connector->config);
+
+	return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t connector_enabled_store(struct config_item *item,
+				       const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+	struct vkms_config_connector *connector_cfg;
+	bool enabled, was_enabled;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+	connector_cfg = connector->config;
+
+	if (kstrtobool(page, &enabled))
+		return -EINVAL;
+
+	if (!connector->dev->enabled) {
+		vkms_config_connector_set_enabled(connector_cfg, enabled);
+	} else {
+		// Only dynamic connector can be enabled/disabled at runtime
+		if (!connector_cfg->dynamic)
+			return -EBUSY;
+
+		was_enabled = vkms_config_connector_is_enabled(connector_cfg);
+		vkms_config_connector_set_enabled(connector_cfg, enabled);
+
+		// Resulting configuration is invalid (missing encoder for example)
+		// Early return to avoid drm core issue
+		if (!vkms_config_is_valid(connector->dev->config)) {
+			vkms_config_connector_set_enabled(connector_cfg, was_enabled);
+			return -EINVAL;
+		}
+
+		if (!was_enabled && enabled) {
+			// Adding the connector
+			connector_cfg->connector = vkms_connector_hot_add(connector->dev->config->dev,
+									  connector_cfg);
+			if (IS_ERR(connector_cfg->connector)) {
+				vkms_config_connector_set_enabled(connector_cfg, was_enabled);
+				return PTR_ERR(connector_cfg->connector);
+			}
+		} else if (was_enabled && !enabled) {
+			vkms_connector_hot_remove(connector->dev->config->dev,
+						  connector_cfg->connector);
+		}
+	}
+	return count;
+}
+
+static ssize_t connector_dynamic_show(struct config_item *item, char *page)
+{
+	struct vkms_configfs_connector *connector;
+	bool enabled;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+
+	scoped_guard(mutex, &connector->dev->lock) {
+		enabled = vkms_config_connector_is_dynamic(connector->config);
+	}
+
+	return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t connector_dynamic_store(struct config_item *item,
+				       const char *page, size_t count)
+{
+	struct vkms_configfs_connector *connector;
+	struct vkms_config_connector *connector_cfg;
+	bool dynamic;
+
+	connector = connector_item_to_vkms_configfs_connector(item);
+	connector_cfg = connector->config;
+
+	if (kstrtobool(page, &dynamic))
+		return -EINVAL;
+
+	scoped_guard(mutex, &connector->dev->lock) {
+		// Can't change the dynamic status when the device is activated
+		if (connector->dev->enabled)
+			return -EBUSY;
+
+		vkms_config_connector_set_dynamic(connector_cfg, dynamic);
+	}
 
 	return count;
 }
@@ -1302,6 +1406,8 @@ CONFIGFS_ATTR(connector_, type);
 CONFIGFS_ATTR(connector_, supported_colorspaces);
 CONFIGFS_ATTR(connector_, edid_enabled);
 CONFIGFS_ATTR(connector_, edid);
+CONFIGFS_ATTR(connector_, dynamic);
+CONFIGFS_ATTR(connector_, enabled);
 
 static struct configfs_attribute *connector_item_attrs[] = {
 	&connector_attr_status,
@@ -1309,19 +1415,28 @@ static struct configfs_attribute *connector_item_attrs[] = {
 	&connector_attr_supported_colorspaces,
 	&connector_attr_edid_enabled,
 	&connector_attr_edid,
+	&connector_attr_dynamic,
+	&connector_attr_enabled,
 	NULL,
 };
 
 static void connector_release(struct config_item *item)
 {
 	struct vkms_configfs_connector *connector;
+	struct vkms_config_connector *connector_cfg;
 	struct mutex *lock;
 
 	connector = connector_item_to_vkms_configfs_connector(item);
+	connector_cfg = connector->config;
 	lock = &connector->dev->lock;
 
 	scoped_guard(mutex, lock) {
+		if (connector->dev->enabled && connector_cfg->dynamic && connector_cfg->enabled)
+			vkms_connector_hot_remove(connector->dev->config->dev,
+						  connector_cfg->connector);
+
 		vkms_config_destroy_connector(connector->config);
+
 		kfree(connector);
 	}
 }
@@ -1340,6 +1455,7 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
 						  struct config_item *target)
 {
 	struct vkms_configfs_connector *connector;
+	struct vkms_config_connector *connector_cfg;
 	struct vkms_configfs_encoder *encoder;
 	int ret;
 
@@ -1347,16 +1463,25 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
 		return -EINVAL;
 
 	connector = connector_possible_encoders_item_to_vkms_configfs_connector(src);
+	connector_cfg = connector->config;
 	encoder = encoder_item_to_vkms_configfs_encoder(target);
 
 	scoped_guard(mutex, &connector->dev->lock) {
-		if (connector->dev->enabled)
-			return -EBUSY;
+		if (connector->dev->enabled && connector_cfg->enabled) {
+			if (!connector_cfg->dynamic)
+				return -EBUSY;
+			ret = vkms_connector_hot_attach_encoder(connector->dev->config->dev,
+								connector->config->connector,
+								encoder->config->encoder);
+			if (ret)
+				return ret;
+		}
 
 		ret = vkms_config_connector_attach_encoder(connector->config,
 							   encoder->config);
+		if (ret)
+			return ret;
 	}
-
 	return ret;
 }
 
@@ -1394,9 +1519,6 @@ static struct config_group *make_connector_group(struct config_group *group,
 	dev = child_group_to_vkms_configfs_device(group);
 
 	scoped_guard(mutex, &dev->lock) {
-		if (dev->enabled)
-			return ERR_PTR(-EBUSY);
-
 		connector = kzalloc(sizeof(*connector), GFP_KERNEL);
 		if (!connector)
 			return ERR_PTR(-ENOMEM);
@@ -1409,9 +1531,11 @@ static struct config_group *make_connector_group(struct config_group *group,
 			return ERR_CAST(connector->config);
 		}
 
+		vkms_config_connector_set_dynamic(connector->config, connector->dev->enabled);
+		vkms_config_connector_set_enabled(connector->config, !connector->dev->enabled);
+
 		config_group_init_type_name(&connector->group, name,
 					    &connector_item_type);
-
 		config_group_init_type_name(&connector->possible_encoders_group,
 					    "possible_encoders",
 					    &connector_possible_encoders_group_type);
-- 
2.51.0
^ permalink raw reply related	[flat|nested] 48+ messages in thread
* Re: [PATCH 01/22] drm/vkms: Introduce config for plane name
  2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
@ 2025-10-24 11:16   ` José Expósito
  2025-10-27 10:15   ` Jani Nikula
  1 sibling, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 11:16 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
Hey Louis,
Thanks a lot for this series.
I'm reviewing it on my side and adding some KUnit tests to help
me with the review/testing process. I'll send the new tests once
they are ready :)
On Sat, Oct 18, 2025 at 04:01:01AM +0200, Louis Chauvet wrote:
> As planes can have a name in DRM, prepare VKMS to configure it using
> ConfigFS.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c |  4 ++++
>  drivers/gpu/drm/vkms/vkms_config.h | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_drv.h    |  5 +++--
>  drivers/gpu/drm/vkms/vkms_output.c |  6 +-----
>  drivers/gpu/drm/vkms/vkms_plane.c  |  6 ++++--
>  5 files changed, 38 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index f8394a063ecf..ed172f800685 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -350,6 +350,8 @@ static int vkms_config_show(struct seq_file *m, void *data)
>  		seq_puts(m, "plane:\n");
>  		seq_printf(m, "\ttype=%d\n",
>  			   vkms_config_plane_get_type(plane_cfg));
> +		seq_printf(m, "\tname=%s\n",
> +			   vkms_config_plane_get_name(plane_cfg));
>  	}
>  
>  	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
> @@ -390,6 +392,7 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  
>  	plane_cfg->config = config;
>  	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
> +	vkms_config_plane_set_name(plane_cfg, NULL);
>  	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&plane_cfg->link, &config->planes);
> @@ -402,6 +405,7 @@ void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg)
>  {
>  	xa_destroy(&plane_cfg->possible_crtcs);
>  	list_del(&plane_cfg->link);
> +	kfree_const(plane_cfg->name);
>  	kfree(plane_cfg);
>  }
>  EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 4c8d668e7ef8..b69c35097ba0 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -35,6 +35,7 @@ struct vkms_config {
>   *
>   * @link: Link to the others planes in vkms_config
>   * @config: The vkms_config this plane belongs to
> + * @name: Name of the plane
>   * @type: Type of the plane. The creator of configuration needs to ensures that
>   *        at least one primary plane is present.
>   * @possible_crtcs: Array of CRTCs that can be used with this plane
> @@ -47,6 +48,7 @@ struct vkms_config_plane {
>  	struct list_head link;
>  	struct vkms_config *config;
>  
> +	const char *name;
>  	enum drm_plane_type type;
>  	struct xarray possible_crtcs;
>  
> @@ -288,6 +290,30 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
>  	plane_cfg->type = type;
>  }
>  
> +/**
> + * vkms_config_plane_set_name() - Set the plane name
> + * @plane_cfg: Plane to set the name to
> + * @name: New plane name. The name is copied.
> + */
> +static inline void
> +vkms_config_plane_set_name(struct vkms_config_plane *plane_cfg,
> +			   const char *name)
> +{
> +	if (plane_cfg->name)
> +		kfree_const(plane_cfg->name);
> +	plane_cfg->name = kstrdup_const(name, GFP_KERNEL);
> +}
I think we should limit the name to a set of well-known charaters.
The reason is that, in libinput, we had a format string vulnerability
due to the kernel exposing devices with names containing strings like
"%s" in the name (CVE-2022-1215):
https://gitlab.freedesktop.org/libinput/libinput/-/issues/752
In my opinion, we could avoid surprising user-space too much and allow
only a set of "safe" characters.
> +/**
> + * vkms_config_plane_get_name - Get the plane name
Missing "()":
vkms_config_plane_get_name() - Get the plane name
> + * @plane_cfg: Plane to get the name from
> + */
> +static inline const char *
> +vkms_config_plane_get_name(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->name;
> +}
> +
>  /**
>   * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
>   * @plane_cfg: Plane to attach
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index db260df1d4f6..9ad286f043b5 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -225,6 +225,7 @@ struct vkms_output {
>  };
>  
>  struct vkms_config;
> +struct vkms_config_plane;
>  
>  /**
>   * struct vkms_device - Description of a VKMS device
> @@ -298,10 +299,10 @@ int vkms_output_init(struct vkms_device *vkmsdev);
>   * vkms_plane_init() - Initialize a plane
>   *
>   * @vkmsdev: VKMS device containing the plane
> - * @type: type of plane to initialize
> + * @config: plane configuration
>   */
>  struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
> -				   enum drm_plane_type type);
> +				   struct vkms_config_plane *config);
>  
>  /* CRC Support */
>  const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 2ee3749e2b28..22208d02afa4 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -19,11 +19,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  		return -EINVAL;
>  
>  	vkms_config_for_each_plane(vkmsdev->config, plane_cfg) {
> -		enum drm_plane_type type;
> -
> -		type = vkms_config_plane_get_type(plane_cfg);
> -
> -		plane_cfg->plane = vkms_plane_init(vkmsdev, type);
> +		plane_cfg->plane = vkms_plane_init(vkmsdev, plane_cfg);
>  		if (IS_ERR(plane_cfg->plane)) {
>  			DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n");
>  			return PTR_ERR(plane_cfg->plane);
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index e592e47a5736..263376686794 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -11,6 +11,7 @@
>  
>  #include "vkms_drv.h"
>  #include "vkms_formats.h"
> +#include "vkms_config.h"
Nit: Includes are sorted alphabetically.
Jose
  
>  static const u32 vkms_formats[] = {
>  	DRM_FORMAT_ARGB8888,
> @@ -217,7 +218,7 @@ static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
>  };
>  
>  struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
> -				   enum drm_plane_type type)
> +				   struct vkms_config_plane *config)
>  {
>  	struct drm_device *dev = &vkmsdev->drm;
>  	struct vkms_plane *plane;
> @@ -225,7 +226,8 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
>  					   &vkms_plane_funcs,
>  					   vkms_formats, ARRAY_SIZE(vkms_formats),
> -					   NULL, type, NULL);
> +					   NULL, vkms_config_plane_get_type(config),
> +					   vkms_config_plane_get_name(config));
>  	if (IS_ERR(plane))
>  		return plane;
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 02/22] drm/vkms: Introduce configfs for plane name
  2025-10-18  2:01 ` [PATCH 02/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-24 11:20   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 11:20 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:02AM +0200, Louis Chauvet wrote:
> Use directory name as name for the plane.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_configfs.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index 07ab794e1052..ea245e2e2fd2 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -376,6 +376,7 @@ static struct config_group *make_plane_group(struct config_group *group,
>  			kfree(plane);
>  			return ERR_CAST(plane->config);
>  		}
> +		vkms_config_plane_set_name(plane->config, name);
Could this break the UAPI?
Until now, the name was NULL. In __drm_universal_plane_init(), when the name
is not set, "plane-%d" is used to compose its name.
Therefore, if we now use the directory name as the plane name, we are changing
a bit how VKMS behaves.
It is not a big deal, but I think that a "name" file could be a safer approach.
Jose
>  		config_group_init_type_name(&plane->group, name, &plane_item_type);
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 03/22] drm/vkms: Introduce config for plane rotation
  2025-10-18  2:01 ` [PATCH 03/22] drm/vkms: Introduce config for plane rotation Louis Chauvet
@ 2025-10-24 11:53   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 11:53 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:03AM +0200, Louis Chauvet wrote:
> VKMS driver supports all the rotation on planes, but for testing it can be
> useful to only advertise few of them. This new configuration interface
> will allow configuring the rotation per planes.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c | 26 ++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.h | 54 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_plane.c  |  6 +++--
>  3 files changed, 84 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index ed172f800685..b8cabe6f6cf8 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -144,6 +144,22 @@ static bool valid_plane_number(const struct vkms_config *config)
>  	return true;
>  }
>  
> +static bool valid_plane_properties(const struct vkms_config *config)
> +{
> +	struct drm_device *dev = config->dev ? &config->dev->drm : NULL;
> +	struct vkms_config_plane *plane_cfg;
> +
> +	vkms_config_for_each_plane(config, plane_cfg) {
> +		if ((vkms_config_plane_get_default_rotation(plane_cfg) &
> +		     vkms_config_plane_get_supported_rotations(plane_cfg)) !=
> +		    vkms_config_plane_get_default_rotation(plane_cfg)) {
> +			drm_info(dev, "Configured default rotation is not supported by the plane\n");
> +			return false;
> +		}
> +	}
> +	return true;
> +}
> +
>  static bool valid_planes_for_crtc(const struct vkms_config *config,
>  				  struct vkms_config_crtc *crtc_cfg)
>  {
> @@ -302,6 +318,9 @@ bool vkms_config_is_valid(const struct vkms_config *config)
>  {
>  	struct vkms_config_crtc *crtc_cfg;
>  
> +	if (!valid_plane_properties(config))
> +		return false;
> +
I think that it makes sense to check this after we are sure that the number
of display pipeline items are correct and they are linked correctly, i.e., at
the end of the function.
Also, for testing purposes, it'd be usefull to have something like:
vkms_config_for_each_plane(config, plane_cfg) {
	if (!valid_plane_name(plane_cfg)
		return false;
	if (!valid_plane_rotation(plane_cfg)
		return false;
	// ...
}
This would allow us to have smaller functions and also write unit tests
for them easily.
What do you think?
>  	if (!valid_plane_number(config))
>  		return false;
>  
> @@ -352,6 +371,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
>  			   vkms_config_plane_get_type(plane_cfg));
>  		seq_printf(m, "\tname=%s\n",
>  			   vkms_config_plane_get_name(plane_cfg));
> +		seq_printf(m, "\tsupported rotations: 0x%x\n",
> +			   vkms_config_plane_get_supported_rotations(plane_cfg));
> +		seq_printf(m, "\tdefault rotation: 0x%x\n",
> +			   vkms_config_plane_get_default_rotation(plane_cfg));
>  	}
>  
>  	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
> @@ -393,6 +416,9 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  	plane_cfg->config = config;
>  	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
>  	vkms_config_plane_set_name(plane_cfg, NULL);
> +	vkms_config_plane_set_supported_rotations(plane_cfg, DRM_MODE_ROTATE_MASK);
> +	vkms_config_plane_set_default_rotation(plane_cfg, DRM_MODE_ROTATE_0);
At the moment, drm_info returns this rotation for the default VKMS device:
"rotation": bitmask {rotate-0, rotate-90, rotate-180, rotate-270, reflect-x, reflect-y} = (rotate-0)
With this patch, this is returned:
"rotation": bitmask {rotate-0, rotate-90, rotate-180, rotate-270} = (rotate-0)
You need to add DRM_MODE_REFLECT_MASK to avoid changing the default device.
Ideally, we should add an IGT test to make sure we don't change any value
accidentally.
> +
>  	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&plane_cfg->link, &config->planes);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index b69c35097ba0..3c3cbefcc67f 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -39,6 +39,8 @@ struct vkms_config {
>   * @type: Type of the plane. The creator of configuration needs to ensures that
>   *        at least one primary plane is present.
>   * @possible_crtcs: Array of CRTCs that can be used with this plane
> + * @default_rotation: Default rotation that should be used by this plane
> + * @supported_rotation: Rotation that this plane will support
Missing final s: @supported_rotations
>   * @plane: Internal usage. This pointer should never be considered as valid.
>   *         It can be used to store a temporary reference to a VKMS plane during
>   *         device creation. This pointer is not managed by the configuration and
> @@ -50,6 +52,8 @@ struct vkms_config_plane {
>  
>  	const char *name;
>  	enum drm_plane_type type;
> +	unsigned int default_rotation;
> +	unsigned int supported_rotations;
>  	struct xarray possible_crtcs;
>  
>  	/* Internal usage */
> @@ -290,6 +294,56 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
>  	plane_cfg->type = type;
>  }
>  
> +/**
> + * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
> + * @plane_cfg: Plane to get the default rotation from
> + *
> + * Returns:
> + * The default rotation for the plane.
> + */
> +static inline unsigned int
> +vkms_config_plane_get_default_rotation(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->default_rotation;
> +}
> +
> +/**
> + * vkms_config_plane_set_default_rotation() - Set the default rotation for a plane
> + * @plane_cfg: Plane to set the default rotation to
> + * @default_rotation: New default rotation for the plane
> + */
> +static inline void
> +vkms_config_plane_set_default_rotation(struct vkms_config_plane *plane_cfg,
> +				       unsigned int default_rotation)
> +{
> +	plane_cfg->default_rotation = default_rotation;
> +}
> +
> +/**
> + * vkms_config_plane_get_supported_rotations() - Get the supported rotations for a plane
> + * @plane_cfg: Plane to get the supported rotations from
> + *
> + * Returns:
> + * The supported rotations for the plane.
> + */
> +static inline unsigned int
> +vkms_config_plane_get_supported_rotations(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->supported_rotations;
> +}
> +
> +/**
> + * vkms_config_plane_set_supported_rotations() - Set the supported rotations for a plane
> + * @plane_cfg: Plane to set the supported rotations to
> + * @supported_rotations: New supported rotations for the plane
> + */
> +static inline void
> +vkms_config_plane_set_supported_rotations(struct vkms_config_plane *plane_cfg,
> +					  unsigned int supported_rotations)
> +{
> +	plane_cfg->supported_rotations = supported_rotations;
> +}
> +
>  /**
>   * vkms_config_plane_set_name() - Set the plane name
>   * @plane_cfg: Plane to set the name to
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index 263376686794..6e6bfe1b7400 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -1,5 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  
> +#include "vkms_config.h"
This include is already present.
>  #include <linux/iosys-map.h>
>  
>  #include <drm/drm_atomic.h>
> @@ -233,8 +234,9 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  
>  	drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
>  
> -	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
> -					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
> +	drm_plane_create_rotation_property(&plane->base,
> +					   vkms_config_plane_get_default_rotation(config),
> +					   vkms_config_plane_get_supported_rotations(config));
>  
>  	drm_plane_create_color_properties(&plane->base,
>  					  BIT(DRM_COLOR_YCBCR_BT601) |
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 04/22] drm/vkms: Introduce configfs for plane rotation
  2025-10-18  2:01 ` [PATCH 04/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-24 14:50   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 14:50 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:04AM +0200, Louis Chauvet wrote:
> To allows the userspace to test many hardware configuration, introduce a
> new interface to configure the available rotation per planes. VKMS
> supports any rotation and reflection, so the userspace can choose any
> combination.
> 
> The supported rotations are configured by writing a rotation bitmask to
> the file `supported_rotations` and the default rotation is chosen by
> writing a rotation bitmask to `default_rotation`.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |  7 ++-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 94 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 100 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index 3574e01b928d..a432968cc711 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -87,10 +87,15 @@ Start by creating one or more planes::
>  
>    sudo mkdir /config/vkms/my-vkms/planes/plane0
>  
> -Planes have 1 configurable attribute:
> +Planes have 3 configurable attribute:
s/attribute/attributes/
>  
>  - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
>    exposed by the "type" property of a plane)
> +- possible_rotations: Available rotation for a plane, as a bitmask: 0x01 no rotation,
> +  0x02 rotate 90°, 0x04 rotate 180°, 0x08 rotate 270°, 0x10 reflect x, 0x20 reflect y
> +  (same values as those exposed by the "rotation" property of a plane)
> +- default_rotation: Default rotation presented to the userspace, same values as
> +  possible_rotations.
>  
>  Continue by creating one or more CRTCs::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index ea245e2e2fd2..450e45e66a45 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -322,10 +322,104 @@ static ssize_t plane_type_store(struct config_item *item, const char *page,
>  	return (ssize_t)count;
>  }
>  
> +static ssize_t plane_supported_rotations_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int plane_supported_rotations;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		plane_supported_rotations = vkms_config_plane_get_supported_rotations(plane->config);
Checkpatch is complaining about this line being 1 character longer than
it should... Feel free to ignore it:
WARNING: line length of 101 exceeds 100 columns
#58: FILE: drivers/gpu/drm/vkms/vkms_configfs.c:333:
+               plane_supported_rotations = vkms_config_plane_get_supported_rotations(plane->config);
> +	}
> +
> +	return sprintf(page, "%u", plane_supported_rotations);
> +}
> +
> +static ssize_t plane_supported_rotations_store(struct config_item *item,
> +					       const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK))
> +		return -EINVAL;
> +	/* Should at least provide one rotation */
> +	if (!(val & DRM_MODE_ROTATE_MASK))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_default_rotation(plane->config)) !=
> +		     vkms_config_plane_get_default_rotation(plane->config))
> +			return -EINVAL;
This makes a bit difficult to change the default supported rotations.
By default, default rotation is DRM_MODE_ROTATE_0. If the user wants to set the
supported rotations to DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_90,
this will fail because the default rotation is not included in the new set of
supported rotations.
Therefore, the user would need to add DRM_MODE_ROTATE_0 (DRM_MODE_REFLECT_X |
DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_0), change the default rotation
to DRM_MODE_ROTATE_90 and drop DRM_MODE_ROTATE_0 from the supported rotations.
To avoid this, I think we should check this before enabling the device instead,
in vkms_config_is_valid().
Also, having this logic as a helper called by vkms_config_is_valid() allows to
add a KUnit test to make sure all cases are covered.
What do you think?
> +		vkms_config_plane_set_supported_rotations(plane->config, val);
> +	}
> +
> +	return count;
> +}
> +
> +static ssize_t plane_default_rotation_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int plane_default_rotation;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		plane_default_rotation = vkms_config_plane_get_default_rotation(plane->config);
> +	}
> +
> +	return sprintf(page, "%u", plane_default_rotation);
> +}
> +
> +static ssize_t plane_default_rotation_store(struct config_item *item,
> +					    const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 10, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK))
> +		return -EINVAL;
> +	/* Should at least provide one rotation */
> +	if ((val & DRM_MODE_ROTATE_MASK) == 0)
> +		return -EINVAL;
> +	/* Should contains only one rotation */
> +	if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_supported_rotations(plane->config)) != val)
> +			return -EINVAL;
> +
> +		vkms_config_plane_set_default_rotation(plane->config, val);
> +	}
> +
> +	return count;
> +}
> +
>  CONFIGFS_ATTR(plane_, type);
> +CONFIGFS_ATTR(plane_, supported_rotations);
> +CONFIGFS_ATTR(plane_, default_rotation);
>  
>  static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_type,
> +	&plane_attr_supported_rotations,
> +	&plane_attr_default_rotation,
>  	NULL,
>  };
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 05/22] drm/vkms: Introduce config for plane color encoding
  2025-10-18  2:01 ` [PATCH 05/22] drm/vkms: Introduce config for plane color encoding Louis Chauvet
@ 2025-10-24 15:14   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 15:14 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:05AM +0200, Louis Chauvet wrote:
> VKMS driver supports all the color encoding on planes, but for testing it
> can be useful to only advertise few of them. This new configuration
> interface will allow configuring the color encoding per planes.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c | 15 +++++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.h | 30 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_plane.c  |  6 ++----
>  3 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index b8cabe6f6cf8..5353719a476d 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -156,6 +156,13 @@ static bool valid_plane_properties(const struct vkms_config *config)
>  			drm_info(dev, "Configured default rotation is not supported by the plane\n");
>  			return false;
>  		}
> +
> +		if ((BIT(vkms_config_plane_get_default_color_encoding(plane_cfg)) &
> +		     vkms_config_plane_get_supported_color_encoding(plane_cfg)) !=
> +		    BIT(vkms_config_plane_get_default_color_encoding(plane_cfg))) {
Could you document what kind of value should be stored when using
vkms_config_plane_set_default_color_encoding(), please?
I'm confused by the use of BIT() here but not in the next commit
("drm/vkms: Introduce configfs for plane color encoding") during
a similar validation.
> +			drm_info(dev, "Configured default color encoding is not supported by the plane\n");
> +			return false;
> +		}
>  	}
>  	return true;
>  }
> @@ -375,6 +382,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
>  			   vkms_config_plane_get_supported_rotations(plane_cfg));
>  		seq_printf(m, "\tdefault rotation: 0x%x\n",
>  			   vkms_config_plane_get_default_rotation(plane_cfg));
> +		seq_printf(m, "\tsupported color encoding: 0x%x\n",
> +			   vkms_config_plane_get_supported_color_encoding(plane_cfg));
> +		seq_printf(m, "\tdefault color encoding: %d\n",
Is this one expressed in decimal rather than hex on purpose?
> +			   vkms_config_plane_get_default_color_encoding(plane_cfg));
>  	}
>  
>  	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
> @@ -418,6 +429,10 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  	vkms_config_plane_set_name(plane_cfg, NULL);
>  	vkms_config_plane_set_supported_rotations(plane_cfg, DRM_MODE_ROTATE_MASK);
>  	vkms_config_plane_set_default_rotation(plane_cfg, DRM_MODE_ROTATE_0);
> +	vkms_config_plane_set_supported_color_encoding(plane_cfg, BIT(DRM_COLOR_YCBCR_BT601) |
> +							BIT(DRM_COLOR_YCBCR_BT709) |
> +							BIT(DRM_COLOR_YCBCR_BT2020));
> +	vkms_config_plane_set_default_color_encoding(plane_cfg, DRM_COLOR_YCBCR_BT601);
>  
>  	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 3c3cbefcc67f..11160c3c13bc 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -45,6 +45,8 @@ struct vkms_config {
>   *         It can be used to store a temporary reference to a VKMS plane during
>   *         device creation. This pointer is not managed by the configuration and
>   *         must be managed by other means.
> + * @default_color_encoding: Default color encoding that should be used by this plane
> + * @supported_color_encoding: Color encoding that this plane will support
To be consistent with "supported_rotations", should this prop
be "supported_color_encodings"?
>   */
>  struct vkms_config_plane {
>  	struct list_head link;
> @@ -54,6 +56,8 @@ struct vkms_config_plane {
>  	enum drm_plane_type type;
>  	unsigned int default_rotation;
>  	unsigned int supported_rotations;
> +	enum drm_color_encoding default_color_encoding;
> +	unsigned int supported_color_encoding;
>  	struct xarray possible_crtcs;
>  
>  	/* Internal usage */
> @@ -344,6 +348,32 @@ vkms_config_plane_set_supported_rotations(struct vkms_config_plane *plane_cfg,
>  	plane_cfg->supported_rotations = supported_rotations;
>  }
>  
> +static inline enum drm_color_encoding
> +vkms_config_plane_get_default_color_encoding(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->default_color_encoding;
> +}
> +
> +static inline void
> +vkms_config_plane_set_default_color_encoding(struct vkms_config_plane *plane_cfg,
> +					     enum drm_color_encoding default_color_encoding)
> +{
> +	plane_cfg->default_color_encoding = default_color_encoding;
> +}
> +
> +static inline unsigned int
> +vkms_config_plane_get_supported_color_encoding(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->supported_color_encoding;
> +}
> +
> +static inline void
> +vkms_config_plane_set_supported_color_encoding(struct vkms_config_plane *plane_cfg,
> +					       unsigned int supported_color_encoding)
> +{
> +	plane_cfg->supported_color_encoding = supported_color_encoding;
> +}
> +
>  /**
>   * vkms_config_plane_set_name() - Set the plane name
>   * @plane_cfg: Plane to set the name to
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index 6e6bfe1b7400..5869000415e4 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -239,12 +239,10 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  					   vkms_config_plane_get_supported_rotations(config));
>  
>  	drm_plane_create_color_properties(&plane->base,
> -					  BIT(DRM_COLOR_YCBCR_BT601) |
> -					  BIT(DRM_COLOR_YCBCR_BT709) |
> -					  BIT(DRM_COLOR_YCBCR_BT2020),
> +					  vkms_config_plane_get_supported_color_encoding(config),
>  					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
>  					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
> -					  DRM_COLOR_YCBCR_BT601,
> +					  vkms_config_plane_get_default_color_encoding(config),
>  					  DRM_COLOR_YCBCR_FULL_RANGE);
>  
>  	return plane;
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 06/22] drm/vkms: Introduce configfs for plane color encoding
  2025-10-18  2:01 ` [PATCH 06/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-24 15:16   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 15:16 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:06AM +0200, Louis Chauvet wrote:
> To allows the userspace to test many hardware configuration, introduce a
> new interface to configure the available color encoding per planes. VKMS
> supports multiple color encoding, so the userspace can choose any
> combination.
> 
> The supported color encoding are configured by writing a color encoding
> bitmask to the file `supported_color_encoding` and the default color
> encoding is chosen by writing a color encoding bitmask to
> `default_color_encoding`.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |   7 ++-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 102 +++++++++++++++++++++++++++++++++++
>  2 files changed, 108 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index a432968cc711..4ff75b53a386 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -87,7 +87,7 @@ Start by creating one or more planes::
>  
>    sudo mkdir /config/vkms/my-vkms/planes/plane0
>  
> -Planes have 3 configurable attribute:
> +Planes have 5 configurable attribute:
>  
>  - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
>    exposed by the "type" property of a plane)
> @@ -96,6 +96,11 @@ Planes have 3 configurable attribute:
>    (same values as those exposed by the "rotation" property of a plane)
>  - default_rotation: Default rotation presented to the userspace, same values as
>    possible_rotations.
> +- supported_color_encoding: Available encoding for a plane, as a bitmask:
> +  0x01 YCBCR_BT601, 0x02: YCBCR_BT709, 0x04 YCBCR_BT2020 (same values as those exposed
> +  by the COLOR_ENCODING property of a plane)
> +- default_color_encoding: Default color encoding presented to the userspace, same
> +  values as supported_color_encoding
>  
>  Continue by creating one or more CRTCs::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index 450e45e66a45..a4e0e054cf2d 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -412,14 +412,116 @@ static ssize_t plane_default_rotation_store(struct config_item *item,
>  	return count;
>  }
>  
> +static ssize_t plane_supported_color_encoding_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int supported_color_encoding;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		supported_color_encoding = vkms_config_plane_get_supported_color_encoding(plane->config);
> +	}
> +
> +	return sprintf(page, "%u", supported_color_encoding);
> +}
> +
> +static ssize_t plane_supported_color_encoding_store(struct config_item *item,
> +						    const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 10, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(BIT(DRM_COLOR_YCBCR_BT601) |
> +		    BIT(DRM_COLOR_YCBCR_BT709) |
> +		    BIT(DRM_COLOR_YCBCR_BT2020)))
> +		return -EINVAL;
> +	/* Should at least provide one color range */
> +	if ((val & (BIT(DRM_COLOR_YCBCR_BT601) |
> +		    BIT(DRM_COLOR_YCBCR_BT709) |
> +		    BIT(DRM_COLOR_YCBCR_BT2020))) == 0)
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_default_color_encoding(plane->config)) !=
> +		     vkms_config_plane_get_default_color_encoding(plane->config))
> +			return -EINVAL;
I think that the same problem that I mention having to configure
plane rotation in 2 steps applies for color encoding.
> +		vkms_config_plane_set_supported_color_encoding(plane->config, val);
> +	}
> +
> +	return count;
> +}
> +
> +/* Plane default_color_encoding : vkms/<device>/planes/<plane>/default_color_encoding */
> +
> +static ssize_t plane_default_color_encoding_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int default_color_encoding;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		default_color_encoding = vkms_config_plane_get_default_color_encoding(plane->config);
> +	}
> +
> +	return sprintf(page, "%u", default_color_encoding);
> +}
> +
> +static ssize_t plane_default_color_encoding_store(struct config_item *item,
> +						  const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 10, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(BIT(DRM_COLOR_YCBCR_BT601) |
> +		    BIT(DRM_COLOR_YCBCR_BT709) |
> +		    BIT(DRM_COLOR_YCBCR_BT2020)))
> +		return -EINVAL;
> +	/* Should at least provide one color range */
> +	if ((val & (BIT(DRM_COLOR_YCBCR_BT601) |
> +		    BIT(DRM_COLOR_YCBCR_BT709) |
> +		    BIT(DRM_COLOR_YCBCR_BT2020))) == 0)
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_supported_color_encoding(plane->config)) !=
> +		     val)
> +			return -EINVAL;
> +
> +		vkms_config_plane_set_default_color_encoding(plane->config, val);
As I mentioned in the previous patch, I think that default color encoding
is sometimes a bitmask and sometimes the actual color?
> +	}
> +
> +	return count;
> +}
> +
>  CONFIGFS_ATTR(plane_, type);
>  CONFIGFS_ATTR(plane_, supported_rotations);
>  CONFIGFS_ATTR(plane_, default_rotation);
> +CONFIGFS_ATTR(plane_, supported_color_encoding);
> +CONFIGFS_ATTR(plane_, default_color_encoding);
>  
>  static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_type,
>  	&plane_attr_supported_rotations,
>  	&plane_attr_default_rotation,
> +	&plane_attr_supported_color_encoding,
> +	&plane_attr_default_color_encoding,
>  	NULL,
>  };
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 07/22] drm/vkms: Introduce config for plane color range
  2025-10-18  2:01 ` [PATCH 07/22] drm/vkms: Introduce config for plane color range Louis Chauvet
@ 2025-10-24 15:25   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 15:25 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:07AM +0200, Louis Chauvet wrote:
> VKMS driver supports all the color range on planes, but for testing it can
> be useful to only advertise few of them. This new configuration interface
> will allow configuring the color range per planes.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c | 14 ++++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.h | 30 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_plane.c  |  5 ++---
>  3 files changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 5353719a476d..8f00ca21ed6e 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -163,6 +163,13 @@ static bool valid_plane_properties(const struct vkms_config *config)
>  			drm_info(dev, "Configured default color encoding is not supported by the plane\n");
>  			return false;
>  		}
> +
> +		if ((BIT(vkms_config_plane_get_default_color_range(plane_cfg)) &
> +		     vkms_config_plane_get_supported_color_range(plane_cfg)) !=
> +		    BIT(vkms_config_plane_get_default_color_range(plane_cfg))) {
> +			drm_info(dev, "Configured default color range is not supported by the plane\n");
> +			return false;
> +		}
>  	}
>  	return true;
>  }
> @@ -386,6 +393,10 @@ static int vkms_config_show(struct seq_file *m, void *data)
>  			   vkms_config_plane_get_supported_color_encoding(plane_cfg));
>  		seq_printf(m, "\tdefault color encoding: %d\n",
>  			   vkms_config_plane_get_default_color_encoding(plane_cfg));
> +		seq_printf(m, "\tsupported color range: 0x%x\n",
> +			   vkms_config_plane_get_supported_color_range(plane_cfg));
> +		seq_printf(m, "\tdefault color range: %d\n",
> +			   vkms_config_plane_get_default_color_range(plane_cfg));
>  	}
>  
>  	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
> @@ -433,6 +444,9 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  							BIT(DRM_COLOR_YCBCR_BT709) |
>  							BIT(DRM_COLOR_YCBCR_BT2020));
>  	vkms_config_plane_set_default_color_encoding(plane_cfg, DRM_COLOR_YCBCR_BT601);
> +	vkms_config_plane_set_supported_color_range(plane_cfg, BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> +							       BIT(DRM_COLOR_YCBCR_FULL_RANGE));
> +	vkms_config_plane_set_default_color_range(plane_cfg, DRM_COLOR_YCBCR_FULL_RANGE);
>  
>  	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 11160c3c13bc..8127e12f00dc 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -47,6 +47,8 @@ struct vkms_config {
>   *         must be managed by other means.
>   * @default_color_encoding: Default color encoding that should be used by this plane
>   * @supported_color_encoding: Color encoding that this plane will support
> + * @default_color_range: Default color range that should be used by this plane
> + * @supported_color_range: Color range that this plane will support
Similar comment about using plural or singular in supported_*
properties.
>   */
>  struct vkms_config_plane {
>  	struct list_head link;
> @@ -58,6 +60,8 @@ struct vkms_config_plane {
>  	unsigned int supported_rotations;
>  	enum drm_color_encoding default_color_encoding;
>  	unsigned int supported_color_encoding;
> +	enum drm_color_range default_color_range;
> +	unsigned int supported_color_range;
>  	struct xarray possible_crtcs;
>  
>  	/* Internal usage */
> @@ -374,6 +378,32 @@ vkms_config_plane_set_supported_color_encoding(struct vkms_config_plane *plane_c
>  	plane_cfg->supported_color_encoding = supported_color_encoding;
>  }
>  
> +static inline enum drm_color_range
> +vkms_config_plane_get_default_color_range(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->default_color_range;
> +}
> +
> +static inline void
> +vkms_config_plane_set_default_color_range(struct vkms_config_plane *plane_cfg,
> +					  enum drm_color_range default_color_range)
> +{
> +	plane_cfg->default_color_range = default_color_range;
> +}
> +
> +static inline unsigned int
> +vkms_config_plane_get_supported_color_range(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->supported_color_range;
> +}
> +
> +static inline void
> +vkms_config_plane_set_supported_color_range(struct vkms_config_plane *plane_cfg,
> +					    unsigned int supported_color_range)
> +{
> +	plane_cfg->supported_color_range = supported_color_range;
> +}
> +
>  /**
>   * vkms_config_plane_set_name() - Set the plane name
>   * @plane_cfg: Plane to set the name to
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index 5869000415e4..ab719da2ca0b 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -240,10 +240,9 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  
>  	drm_plane_create_color_properties(&plane->base,
>  					  vkms_config_plane_get_supported_color_encoding(config),
> -					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> -					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
> +					  vkms_config_plane_get_supported_color_range(config),
>  					  vkms_config_plane_get_default_color_encoding(config),
> -					  DRM_COLOR_YCBCR_FULL_RANGE);
> +					  vkms_config_plane_get_default_color_range(config));
>  
>  	return plane;
>  }
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 08/22] drm/vkms: Introduce configfs for plane color range
  2025-10-18  2:01 ` [PATCH 08/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-24 15:27   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 15:27 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:08AM +0200, Louis Chauvet wrote:
> To allows the userspace to test many hardware configuration, introduce a
> new interface to configure the available color ranges per planes. VKMS
> supports multiple color ranges, so the userspace can choose any
> combination.
> 
> The supported color ranges are configured by writing a color range bitmask
> to the file `supported_color_ranges` and the default color range is
> chosen by writing a color encoding bitmask to `default_color_range`.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |  7 ++-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 93 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 99 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index 4ff75b53a386..979f8a545498 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -87,7 +87,7 @@ Start by creating one or more planes::
>  
>    sudo mkdir /config/vkms/my-vkms/planes/plane0
>  
> -Planes have 5 configurable attribute:
> +Planes have 7 configurable attribute:
>  
>  - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
>    exposed by the "type" property of a plane)
> @@ -101,6 +101,11 @@ Planes have 5 configurable attribute:
>    by the COLOR_ENCODING property of a plane)
>  - default_color_encoding: Default color encoding presented to the userspace, same
>    values as supported_color_encoding
> +- supported_color_range: Available color range for a plane, as a bitmask:
> +  0x1 DRM_COLOR_YCBCR_LIMITED_RANGE, 0x2 DRM_COLOR_YCBCR_FULL_RANGE (same values as
> +  those exposed by the COLOR_RANGE property of a plane)
> +- default_color_range: Default color range presented to the userspace, same
> +  values as supported_color_range
>  
>  Continue by creating one or more CRTCs::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index a4e0e054cf2d..0b280c73b0cc 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -412,6 +412,95 @@ static ssize_t plane_default_rotation_store(struct config_item *item,
>  	return count;
>  }
>  
> +static ssize_t plane_supported_color_range_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int supported_color_range;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		supported_color_range = vkms_config_plane_get_supported_color_range(plane->config);
> +	}
> +
> +	return sprintf(page, "%u", supported_color_range);
> +}
> +
> +static ssize_t plane_supported_color_range_store(struct config_item *item,
> +						 const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 10, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> +		    BIT(DRM_COLOR_YCBCR_FULL_RANGE)))
> +		return -EINVAL;
> +	/* Should at least provide one color range */
> +	if ((val & (BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> +		    BIT(DRM_COLOR_YCBCR_FULL_RANGE))) == 0)
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_default_color_range(plane->config)) !=
> +		     vkms_config_plane_get_default_color_range(plane->config))
> +			return -EINVAL;
> +		vkms_config_plane_set_supported_color_range(plane->config, val);
> +	}
> +
> +	return count;
> +}
> +
> +static ssize_t plane_default_color_range_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int default_color_range;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		default_color_range = vkms_config_plane_get_default_color_range(plane->config);
> +
> +	return sprintf(page, "%u", default_color_range);
> +}
> +
> +static ssize_t plane_default_color_range_store(struct config_item *item,
> +					       const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret, val = 0;
> +
> +	ret = kstrtouint(page, 10, &val);
> +	if (ret)
> +		return ret;
> +
> +	/* Should be a supported value */
> +	if (val & ~(BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> +		    BIT(DRM_COLOR_YCBCR_FULL_RANGE)))
> +		return -EINVAL;
> +	/* Should at least provide one color range */
> +	if ((val & (BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> +		    BIT(DRM_COLOR_YCBCR_FULL_RANGE))) == 0)
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		/* Ensures that the default rotation is included in supported rotation */
> +		if (plane->dev->enabled ||
> +		    (val & vkms_config_plane_get_supported_color_range(plane->config)) !=
> +		     val)
> +			return -EINVAL;
> +		vkms_config_plane_set_default_color_range(plane->config, val);
Same comment about the validation here.
> +	}
> +
> +	return count;
> +}
> +
>  static ssize_t plane_supported_color_encoding_show(struct config_item *item, char *page)
>  {
>  	struct vkms_configfs_plane *plane;
> @@ -513,6 +602,8 @@ static ssize_t plane_default_color_encoding_store(struct config_item *item,
>  CONFIGFS_ATTR(plane_, type);
>  CONFIGFS_ATTR(plane_, supported_rotations);
>  CONFIGFS_ATTR(plane_, default_rotation);
> +CONFIGFS_ATTR(plane_, supported_color_range);
> +CONFIGFS_ATTR(plane_, default_color_range);
And the mixed use of singular and plural for supported_*.
>  CONFIGFS_ATTR(plane_, supported_color_encoding);
>  CONFIGFS_ATTR(plane_, default_color_encoding);
>  
> @@ -520,6 +611,8 @@ static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_type,
>  	&plane_attr_supported_rotations,
>  	&plane_attr_default_rotation,
> +	&plane_attr_supported_color_range,
> +	&plane_attr_default_color_range,
>  	&plane_attr_supported_color_encoding,
>  	&plane_attr_default_color_encoding,
>  	NULL,
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 09/22] drm/vkms: Introduce config for plane format
  2025-10-18  2:01 ` [PATCH 09/22] drm/vkms: Introduce config for plane format Louis Chauvet
@ 2025-10-24 15:44   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-24 15:44 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:09AM +0200, Louis Chauvet wrote:
> VKMS driver supports all the pixel formats for planes, but for testing it
> can be useful to only advertise few of them. This new configuration
> interface will allow configuring the pixel format per planes.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c | 99 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.h | 49 +++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_plane.c  | 39 +--------------
>  3 files changed, 150 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 8f00ca21ed6e..0b975a0d47aa 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -8,6 +8,42 @@
>  
>  #include "vkms_config.h"
>  
> +static const u32 vkms_supported_plane_formats[] = {
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ABGR8888,
> +	DRM_FORMAT_BGRA8888,
> +	DRM_FORMAT_RGBA8888,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_BGR888,
> +	DRM_FORMAT_XRGB16161616,
> +	DRM_FORMAT_XBGR16161616,
> +	DRM_FORMAT_ARGB16161616,
> +	DRM_FORMAT_ABGR16161616,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_BGR565,
> +	DRM_FORMAT_NV12,
> +	DRM_FORMAT_NV16,
> +	DRM_FORMAT_NV24,
> +	DRM_FORMAT_NV21,
> +	DRM_FORMAT_NV61,
> +	DRM_FORMAT_NV42,
> +	DRM_FORMAT_YUV420,
> +	DRM_FORMAT_YUV422,
> +	DRM_FORMAT_YUV444,
> +	DRM_FORMAT_YVU420,
> +	DRM_FORMAT_YVU422,
> +	DRM_FORMAT_YVU444,
> +	DRM_FORMAT_P010,
> +	DRM_FORMAT_P012,
> +	DRM_FORMAT_P016,
> +	DRM_FORMAT_R1,
> +	DRM_FORMAT_R2,
> +	DRM_FORMAT_R4,
> +	DRM_FORMAT_R8,
> +};
> +
>  struct vkms_config *vkms_config_create(const char *dev_name)
>  {
>  	struct vkms_config *config;
> @@ -435,6 +471,11 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  	if (!plane_cfg)
>  		return ERR_PTR(-ENOMEM);
>  
> +	if (vkms_config_plane_add_all_formats(plane_cfg)) {
> +		kfree(plane_cfg);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
>  	plane_cfg->config = config;
>  	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
>  	vkms_config_plane_set_name(plane_cfg, NULL);
> @@ -563,6 +604,64 @@ static struct vkms_config_plane *vkms_config_crtc_get_plane(const struct vkms_co
>  	return NULL;
>  }
>  
> +int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane *plane_cfg)
> +{
> +	u32 *ret = krealloc_array(plane_cfg->supported_formats,
> +				  ARRAY_SIZE(vkms_supported_plane_formats),
> +				  sizeof(uint32_t), GFP_KERNEL);
> +	if (!ret)
> +		return -ENOMEM;
> +	plane_cfg->supported_formats = ret;
> +
> +	memcpy(plane_cfg->supported_formats, vkms_supported_plane_formats,
> +	       sizeof(vkms_supported_plane_formats));
> +	plane_cfg->supported_formats_count = ARRAY_SIZE(vkms_supported_plane_formats);
> +	return 0;
> +}
> +
> +int __must_check vkms_config_plane_add_format(struct vkms_config_plane *plane_cfg, u32 drm_format)
> +{
> +	bool found = false;
> +
> +	for (int i = 0; i < ARRAY_SIZE(vkms_supported_plane_formats); i++) {
> +		if (vkms_supported_plane_formats[i] == drm_format)
> +			found = true;
Missing break?
> +	}
> +
> +	if (!found)
> +		return -EINVAL;
> +	for (unsigned int i = 0; i < plane_cfg->supported_formats_count; i++) {
> +		if (plane_cfg->supported_formats[i] == drm_format)
> +			return 0;
> +	}
> +	u32 *new_ptr = krealloc_array(plane_cfg->supported_formats,
> +				      plane_cfg->supported_formats_count + 1,
> +				      sizeof(*plane_cfg->supported_formats), GFP_KERNEL);
> +	if (!new_ptr)
> +		return -ENOMEM;
> +
> +	plane_cfg->supported_formats = new_ptr;
> +	plane_cfg->supported_formats[plane_cfg->supported_formats_count] = drm_format;
> +	plane_cfg->supported_formats_count++;
> +
> +	return 0;
> +}
> +
> +void vkms_config_plane_remove_all_formats(struct vkms_config_plane *plane_cfg)
> +{
> +	plane_cfg->supported_formats_count = 0;
> +}
> +
> +void vkms_config_plane_remove_format(struct vkms_config_plane *plane_cfg, u32 drm_format)
> +{
> +	for (unsigned int i = 0; i < plane_cfg->supported_formats_count; i++) {
> +		if (plane_cfg->supported_formats[i] == drm_format) {
> +			plane_cfg->supported_formats[i] = plane_cfg->supported_formats[plane_cfg->supported_formats_count - 1];
> +			plane_cfg->supported_formats_count--;
> +		}
> +	}
> +}
> +
>  struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms_config *config,
>  							 struct vkms_config_crtc *crtc_cfg)
>  {
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 8127e12f00dc..0b7067508e5f 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -62,6 +62,8 @@ struct vkms_config_plane {
>  	unsigned int supported_color_encoding;
>  	enum drm_color_range default_color_range;
>  	unsigned int supported_color_range;
> +	u32 *supported_formats;
> +	unsigned int supported_formats_count;
>  	struct xarray possible_crtcs;
>  
>  	/* Internal usage */
> @@ -404,6 +406,53 @@ vkms_config_plane_set_supported_color_range(struct vkms_config_plane *plane_cfg,
>  	plane_cfg->supported_color_range = supported_color_range;
>  }
>  
> +static inline u32 *
> +vkms_config_plane_get_supported_formats(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->supported_formats;
> +}
> +
> +static inline unsigned int
> +vkms_config_plane_get_supported_formats_count(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->supported_formats_count;
> +}
> +
> +/** vkms_config_plane_add_format - Add a format to the list of supported format of a plane
> + *
> + * The passed drm_format can already be present in the list. This may fail if the allocation of a
> + * bigger array fails.
> + *
> + * @plane_cfg: Plane to add the format to
> + * @drm_format: Format to add to this plane
> + *
> + * Returns: 0 on success, -ENOMEM if array allocation fails, -EINVAL if the format is not supported
> + * by VKMS
> + */
> +int __must_check vkms_config_plane_add_format(struct vkms_config_plane *plane_cfg, u32 drm_format);
> +
> +/**
> + * vkms_config_plane_add_all_formats - Helper to quickly add all the supported formats
> + * @plane_cfg: Plane to add the formats to
> + *
> + * Returns: 0 on success, -ENOMEM if array allocation fails, -EINVAL if the format is not supported
> + * by VKMS
> + */
> +int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane *plane_cfg);
> +
> +/**
> + * vkms_config_plane_remove_format - Remove a specific format from a plane
> + * @plane_cfg: Plane to remove the format to
> + * @drm_format: Format to remove
> + */
> +void vkms_config_plane_remove_format(struct vkms_config_plane *plane_cfg, u32 drm_format);
> +
> +/**
> + * vkms_config_plane_remove_all_formats - Remove all formast from a plane
> + * @plane_cfg: Plane to remove the formats from
> + */
> +void vkms_config_plane_remove_all_formats(struct vkms_config_plane *plane_cfg);
> +
>  /**
>   * vkms_config_plane_set_name() - Set the plane name
>   * @plane_cfg: Plane to set the name to
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index ab719da2ca0b..0414865915d8 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -14,42 +14,6 @@
>  #include "vkms_formats.h"
>  #include "vkms_config.h"
>  
> -static const u32 vkms_formats[] = {
> -	DRM_FORMAT_ARGB8888,
> -	DRM_FORMAT_ABGR8888,
> -	DRM_FORMAT_BGRA8888,
> -	DRM_FORMAT_RGBA8888,
> -	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_XBGR8888,
> -	DRM_FORMAT_RGB888,
> -	DRM_FORMAT_BGR888,
> -	DRM_FORMAT_XRGB16161616,
> -	DRM_FORMAT_XBGR16161616,
> -	DRM_FORMAT_ARGB16161616,
> -	DRM_FORMAT_ABGR16161616,
> -	DRM_FORMAT_RGB565,
> -	DRM_FORMAT_BGR565,
> -	DRM_FORMAT_NV12,
> -	DRM_FORMAT_NV16,
> -	DRM_FORMAT_NV24,
> -	DRM_FORMAT_NV21,
> -	DRM_FORMAT_NV61,
> -	DRM_FORMAT_NV42,
> -	DRM_FORMAT_YUV420,
> -	DRM_FORMAT_YUV422,
> -	DRM_FORMAT_YUV444,
> -	DRM_FORMAT_YVU420,
> -	DRM_FORMAT_YVU422,
> -	DRM_FORMAT_YVU444,
> -	DRM_FORMAT_P010,
> -	DRM_FORMAT_P012,
> -	DRM_FORMAT_P016,
> -	DRM_FORMAT_R1,
> -	DRM_FORMAT_R2,
> -	DRM_FORMAT_R4,
> -	DRM_FORMAT_R8,
> -};
> -
>  static struct drm_plane_state *
>  vkms_plane_duplicate_state(struct drm_plane *plane)
>  {
> @@ -226,7 +190,8 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  
>  	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
>  					   &vkms_plane_funcs,
> -					   vkms_formats, ARRAY_SIZE(vkms_formats),
> +					   vkms_config_plane_get_supported_formats(config),
> +					   vkms_config_plane_get_supported_formats_count(config),
>  					   NULL, vkms_config_plane_get_type(config),
>  					   vkms_config_plane_get_name(config));
>  	if (IS_ERR(plane))
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 10/22] drm/vkms: Introduce configfs for plane format
  2025-10-18  2:01 ` [PATCH 10/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-27  8:55   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  8:55 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:10AM +0200, Louis Chauvet wrote:
> To allow the userspace to test many hardware configuration, introduce a
> new interface to configure the available formats per planes. VKMS supports
> multiple formats, so the userspace can choose any combination.
> 
> The supported formats are configured by writing the fourcc code in
> supported_formats:
>  # enable AR24 format
>   echo '+AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
>  # disable AR24 format
>   echo '-AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
>  # enable all format supported by VKMS
>   echo '+*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
>  # disable all formats
>   echo '-*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |  7 ++-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 82 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 88 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index 979f8a545498..deb14e7c48ea 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -87,7 +87,7 @@ Start by creating one or more planes::
>  
>    sudo mkdir /config/vkms/my-vkms/planes/plane0
>  
> -Planes have 7 configurable attribute:
> +Planes have 8 configurable attribute:
>  
>  - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
>    exposed by the "type" property of a plane)
> @@ -106,6 +106,11 @@ Planes have 7 configurable attribute:
>    those exposed by the COLOR_RANGE property of a plane)
>  - default_color_range: Default color range presented to the userspace, same
>    values as supported_color_range
> +- supported_formats: List of supported formats for this plane. To add a new item in the
> +  list, write it using a plus its fourcc code: +XR24
> +  To remove a format, use a minus and its fourcc: -XR24
> +  To add all formats use +*
> +  To remove all formats, use -*
>  
>  Continue by creating one or more CRTCs::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index 0b280c73b0cc..528f22fa2df1 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -599,6 +599,86 @@ static ssize_t plane_default_color_encoding_store(struct config_item *item,
>  	return count;
>  }
>  
> +static ssize_t plane_supported_formats_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	page[0] = '\0';
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +	{
This "{" should go in the same line.
> +		u32 *formats = vkms_config_plane_get_supported_formats(plane->config);
> +
> +		for (int i = 0;
> +		     i < vkms_config_plane_get_supported_formats_count(plane->config);
> +		     i++) {
> +			char tmp[6] = { 0 };
> +			const ssize_t ret = snprintf(tmp, ARRAY_SIZE(tmp), "%.*s\n",
> +					       (int)sizeof(*formats),
> +					       (char *)&formats[i]);
> +			if (ret < 0)
> +				return ret;
> +			/*
> +			 * Limitation of ConfigFS attributes, an attribute can't be bigger
> +			 * than PAGE_SIZE. This will crop the result if this plane support
> +			 * more than ≈1000 formats.
> +			 */
> +			if (ret + strlen(page) > PAGE_SIZE - 1)
> +				return -ENOMEM;
> +			strncat(page, tmp, ARRAY_SIZE(tmp));
> +		}
> +	}
> +
> +	return strlen(page);
> +}
> +
> +static ssize_t plane_supported_formats_store(struct config_item *item,
> +					     const char *page, size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +	int ret = 0;
> +	int ptr = 0;
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +	{
This "{" should go in the same line.
> +		while (ptr < count) {
> +			char tmp[4] = { ' ', ' ', ' ', ' ' };
> +
> +			memcpy(tmp, &page[ptr + 1], min(sizeof(tmp), count - (ptr + 1)));
This is not handling correctly formats with less than 4 characters.
For example, "+R1" is not handled because it is adding the sctring NULL terminator
to tmp. I think you need to:
memcpy(tmp, &page[ptr + 1], min(sizeof(tmp), count - 1 - (ptr + 1)));
> +			if (page[ptr] == '+') {
> +				if (tmp[0] == '*') {
> +					ret = vkms_config_plane_add_all_formats(plane->config);
> +					if (ret)
> +						return ret;
> +					ptr += 1;
> +				} else {
> +					ret = vkms_config_plane_add_format(plane->config,
> +									   *(int *)tmp);
> +					if (ret)
> +						return ret;
> +					ptr += 4;
> +				}
> +			} else if (page[ptr] == '-') {
> +				if (tmp[0] == '*') {
> +					vkms_config_plane_remove_all_formats(plane->config);
> +					ptr += 1;
> +				} else {
> +					vkms_config_plane_remove_format(plane->config, *(int *)tmp);
> +					ptr += 4;
> +				}
> +			}
> +			/* Skip anything that is not a + or a - */
> +			ptr += 1;
> +		}
> +	}
> +
> +	return count;
> +}
> +
>  CONFIGFS_ATTR(plane_, type);
>  CONFIGFS_ATTR(plane_, supported_rotations);
>  CONFIGFS_ATTR(plane_, default_rotation);
> @@ -606,6 +686,7 @@ CONFIGFS_ATTR(plane_, supported_color_range);
>  CONFIGFS_ATTR(plane_, default_color_range);
>  CONFIGFS_ATTR(plane_, supported_color_encoding);
>  CONFIGFS_ATTR(plane_, default_color_encoding);
> +CONFIGFS_ATTR(plane_, supported_formats);
>  
>  static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_type,
> @@ -615,6 +696,7 @@ static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_default_color_range,
>  	&plane_attr_supported_color_encoding,
>  	&plane_attr_default_color_encoding,
> +	&plane_attr_supported_formats,
>  	NULL,
>  };
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 12/22] drm/vkms: Introduce config for plane zpos property
  2025-10-18  2:01 ` [PATCH 12/22] drm/vkms: Introduce config for plane zpos property Louis Chauvet
@ 2025-10-27  9:12   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  9:12 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:12AM +0200, Louis Chauvet wrote:
> VKMS can render plane in any order. Introduce the appropriate
> configuration.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |   3 +
>  drivers/gpu/drm/vkms/vkms_config.c            |  21 ++++
>  drivers/gpu/drm/vkms/vkms_config.h            | 142 ++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_plane.c             |  11 ++
>  4 files changed, 177 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index d75a6252e4d2..f2b38b436252 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -172,6 +172,9 @@ static void vkms_config_test_default_config(struct kunit *test)
>  			n_possible_crtcs++;
>  		}
>  		KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1);
> +		KUNIT_EXPECT_EQ(test, vkms_config_plane_get_zpos_enabled(plane_cfg), false);
> +		// No need to test the other zpos configurations as they are discarded if
> +		// the zpos property is not created.
>  	}
>  
>  	/* Encoders */
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 0b975a0d47aa..5da34a3e8114 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -86,6 +86,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>  	if (IS_ERR(plane_cfg))
>  		goto err_alloc;
>  	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
> +	vkms_config_plane_set_zpos_enabled(plane_cfg, false);
>  
>  	crtc_cfg = vkms_config_create_crtc(config);
>  	if (IS_ERR(crtc_cfg))
> @@ -103,6 +104,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>  
>  			vkms_config_plane_set_type(plane_cfg,
>  						   DRM_PLANE_TYPE_OVERLAY);
> +			vkms_config_plane_set_zpos_enabled(plane_cfg, false);
>  
>  			if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
>  				goto err_alloc;
> @@ -115,6 +117,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>  			goto err_alloc;
>  
>  		vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
> +		vkms_config_plane_set_zpos_enabled(plane_cfg, false);
>  
>  		if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
>  			goto err_alloc;
> @@ -206,6 +209,24 @@ static bool valid_plane_properties(const struct vkms_config *config)
>  			drm_info(dev, "Configured default color range is not supported by the plane\n");
>  			return false;
>  		}
> +		if (vkms_config_plane_get_zpos_initial(plane_cfg) >
> +		    vkms_config_plane_get_zpos_max(plane_cfg)) {
> +			drm_info(dev, "Configured initial zpos value bigger than zpos max\n");
> +			return false;
> +		}
> +
> +		if (vkms_config_plane_get_zpos_max(plane_cfg) <
> +		    vkms_config_plane_get_zpos_min(plane_cfg)) {
> +			drm_info(dev, "Configured zpos max value smaller than zpos min\n");
> +			return false;
> +		}
> +
> +		if (vkms_config_plane_get_zpos_initial(plane_cfg) <
> +		    vkms_config_plane_get_zpos_min(plane_cfg)) {
> +			drm_info(dev, "Configured initial zpos value smaller than zpos min\n");
> +			return false;
> +		}
> +
Like I suggested with other validations, it'd be nice to extract this to a
helper to simplify testing.
Also, these properties are not listed in vkms_config_show().
>  	}
>  	return true;
>  }
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 0b7067508e5f..267e45f5a617 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -49,6 +49,11 @@ struct vkms_config {
>   * @supported_color_encoding: Color encoding that this plane will support
>   * @default_color_range: Default color range that should be used by this plane
>   * @supported_color_range: Color range that this plane will support
> + * @zpos_enable: Enable or disable the zpos property
@zpos_enabled
> + * @zpos_mutable: Make the zpos property mutable or not (ignored if @zpos_enable is false)
> + * @zpos_initial: Initial value for zpos property (ignored if @zpos_enable is false)
> + * @zpos_min: Minimal value for zpos property (ignored if @zpos_enable is false)
> + * @zpos_max: Maximal value for zpos property (ignored if @zpos_enable is false)
For these 4 as well: "(ignored if @zpos_enabled...".
>   */
>  struct vkms_config_plane {
>  	struct list_head link;
> @@ -65,6 +70,11 @@ struct vkms_config_plane {
>  	u32 *supported_formats;
>  	unsigned int supported_formats_count;
>  	struct xarray possible_crtcs;
> +	bool zpos_enabled;
> +	bool zpos_mutable;
> +	unsigned int zpos_initial;
> +	unsigned int zpos_min;
> +	unsigned int zpos_max;
>  
>  	/* Internal usage */
>  	struct vkms_plane *plane;
> @@ -477,6 +487,138 @@ vkms_config_plane_get_name(struct vkms_config_plane *plane_cfg)
>  	return plane_cfg->name;
>  }
>  
> +/**
> + * vkms_config_plane_set_zpos_enabled() - Enable or disable zpos property for a plane
> + * @plane_cfg: Plane configuration to modify
> + * @zpos_enabled: Whether to enable the zpos property
> + */
> +static inline
> +void vkms_config_plane_set_zpos_enabled(struct vkms_config_plane *plane_cfg,
> +					bool zpos_enabled)
> +{
> +	plane_cfg->zpos_enabled = zpos_enabled;
> +}
> +
> +/**
> + * vkms_config_plane_set_zpos_mutable() - Set whether zpos property is mutable
> + * @plane_cfg: Plane configuration to modify
> + * @zpos_mutable: Whether the zpos property should be mutable
> + */
> +static inline
> +void vkms_config_plane_set_zpos_mutable(struct vkms_config_plane *plane_cfg,
> +					bool zpos_mutable)
> +{
> +	plane_cfg->zpos_mutable = zpos_mutable;
> +}
> +
> +/**
> + * vkms_config_plane_set_zpos_initial() - Set the initial zpos value
> + * @plane_cfg: Plane configuration to modify
> + * @zpos_initial: Initial zpos value
> + */
> +static inline
> +void vkms_config_plane_set_zpos_initial(struct vkms_config_plane *plane_cfg,
> +					unsigned int zpos_initial)
> +{
> +	plane_cfg->zpos_initial = zpos_initial;
> +}
> +
> +/**
> + * vkms_config_plane_set_zpos_min() - Set the minimum zpos value
> + * @plane_cfg: Plane configuration to modify
> + * @zpos_min: Minimum zpos value
> + */
> +static inline
> +void vkms_config_plane_set_zpos_min(struct vkms_config_plane *plane_cfg,
> +				    unsigned int zpos_min)
> +{
> +	plane_cfg->zpos_min = zpos_min;
> +}
> +
> +/**
> + * vkms_config_plane_set_zpos_max() - Set the maximum zpos value
> + * @plane_cfg: Plane configuration to modify
> + * @zpos_max: Maximum zpos value
> + *
> + * Sets the maximum allowed value for the zpos property. This setting is
> + * ignored if zpos is disabled.
> + */
> +static inline
> +void vkms_config_plane_set_zpos_max(struct vkms_config_plane *plane_cfg,
> +				    unsigned int zpos_max)
> +{
> +	plane_cfg->zpos_max = zpos_max;
> +}
> +
> +/**
> + * vkms_config_plane_get_zpos_enabled() - Check if zpos property is enabled
> + * @plane_cfg: Plane configuration to check
> + *
> + * Returns:
> + * True if the zpos property is enabled for this plane, false otherwise.
> + */
> +static inline
> +bool vkms_config_plane_get_zpos_enabled(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->zpos_enabled;
> +}
> +
> +/**
> + * vkms_config_plane_get_zpos_mutable() - Check if zpos property is mutable
> + * @plane_cfg: Plane configuration to check
> + *
> + * Returns:
> + * True if the zpos property is mutable for this plane, false otherwise.
> + * Returns false if zpos is disabled.
> + */
> +static inline
> +bool vkms_config_plane_get_zpos_mutable(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->zpos_mutable;
> +}
> +
> +/**
> + * vkms_config_plane_get_zpos_initial() - Get the initial zpos value
> + * @plane_cfg: Plane configuration to check
> + *
> + * Returns:
> + * The initial zpos value for this plane. The return value is undefined if
> + * zpos is disabled.
> + */
> +static inline
> +unsigned int vkms_config_plane_get_zpos_initial(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->zpos_initial;
> +}
> +
> +/**
> + * vkms_config_plane_get_zpos_min() - Get the minimum zpos value
> + * @plane_cfg: Plane configuration to check
> + *
> + * Returns:
> + * The minimum allowed zpos value for this plane. The return value is undefined
> + * if zpos is disabled.
> + */
> +static inline
> +unsigned int vkms_config_plane_get_zpos_min(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->zpos_min;
> +}
> +
> +/**
> + * vkms_config_plane_get_zpos_max() - Get the maximum zpos value
> + * @plane_cfg: Plane configuration to check
> + *
> + * Returns:
> + * The maximum allowed zpos value for this plane. The return value is undefined
> + * if zpos is disabled.
> + */
> +static inline
> +unsigned int vkms_config_plane_get_zpos_max(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->zpos_max;
> +}
> +
>  /**
>   * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
>   * @plane_cfg: Plane to attach
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index 0414865915d8..51f6372a6f72 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -209,5 +209,16 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  					  vkms_config_plane_get_default_color_encoding(config),
>  					  vkms_config_plane_get_default_color_range(config));
>  
> +	if (vkms_config_plane_get_zpos_enabled(config)) {
> +		if (vkms_config_plane_get_zpos_mutable(config))
> +			drm_plane_create_zpos_property(&plane->base,
> +						       vkms_config_plane_get_zpos_initial(config),
> +						       vkms_config_plane_get_zpos_min(config),
> +						       vkms_config_plane_get_zpos_max(config));
> +		else
> +			drm_plane_create_zpos_immutable_property(&plane->base,
> +								 vkms_config_plane_get_zpos_initial(config));
> +	}
> +
>  	return plane;
>  }
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 13/22] drm/vkms: Introduce configfs for plane zpos property
  2025-10-18  2:01 ` [PATCH 13/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-27  9:19   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  9:19 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:13AM +0200, Louis Chauvet wrote:
> Modern compositor rely on zpos managment to offload some processing to
> deticated hardware. In order to test multiple configurations, add zpos
> configuration to configFS.
> 
> Introduce multiple attributes to configure zpos:
> - zpos_enabled - Create or not the zpos property. If not created, the zpos
>   is undefined.
> - zpos_mutable - If the zpos property is created, allow or not the
>   userspace to modify it
> - zpos_initial - Intial value for zpos property. Must be between zpos_min
>   and zpos_max
> - zpos_min - Minimal zpos value for this plane. Must be smaller than or
>   equals to zpos_max
> - zpos_max - Maximal zpos value for this plane. Must be greater than or
>   equals to zpos_min
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |   9 +-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 199 +++++++++++++++++++++++++++++++++++
>  2 files changed, 207 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index deb14e7c48ea..d4ad4af45414 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -87,7 +87,7 @@ Start by creating one or more planes::
>  
>    sudo mkdir /config/vkms/my-vkms/planes/plane0
>  
> -Planes have 8 configurable attribute:
> +Planes have 13 configurable attribute:
>  
>  - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those
>    exposed by the "type" property of a plane)
> @@ -111,6 +111,13 @@ Planes have 8 configurable attribute:
>    To remove a format, use a minus and its fourcc: -XR24
>    To add all formats use +*
>    To remove all formats, use -*
> +- zpos_enabled: Enable or not the zpos property: 1 enable, 0 disable
> +- zpos_mutable: Create the zpos property as a mutable or imutable property: 1 mutable,
> +  0 disable. No effect if zpos_enabled is not set.
> +- zpos_initial: Set the initial zpos value. Must be between zpos_min and zpos_max. No
> +  effect if zpos_enabled is not set.
> +- zpos_min: Set the minimal zpos value. No effect if zpos_enabled is not set.
> +- zpos_max: Set the maximal zpos value. No effect if zpos_enabled is not set.
Aren't zpos_min/max also ignored when zpos_mutable is false?
>  Continue by creating one or more CRTCs::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index 528f22fa2df1..fd1be7292058 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -1,4 +1,5 @@
>  // SPDX-License-Identifier: GPL-2.0+
> +#include "asm-generic/errno-base.h"
Accidentally included by IDE?
>  #include <linux/cleanup.h>
>  #include <linux/configfs.h>
>  #include <linux/mutex.h>
> @@ -679,6 +680,194 @@ static ssize_t plane_supported_formats_store(struct config_item *item,
>  	return count;
>  }
>  
> +static ssize_t plane_zpos_enabled_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	bool enabled;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		enabled = vkms_config_plane_get_zpos_enabled(plane->config);
> +
> +	return sprintf(page, "%d\n", enabled);
> +}
> +
> +static ssize_t plane_zpos_enabled_store(struct config_item *item, const char *page,
> +					size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +	bool enabled;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	if (kstrtobool(page, &enabled))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		if (plane->dev->enabled)
> +			return -EBUSY;
> +
> +		vkms_config_plane_set_zpos_enabled(plane->config, enabled);
> +	}
> +
> +	return (ssize_t)count;
> +}
> +
> +static ssize_t plane_zpos_mutable_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	bool mutable;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		mutable = vkms_config_plane_get_zpos_mutable(plane->config);
> +
> +	return sprintf(page, "%d\n", mutable);
> +}
> +
> +static ssize_t plane_zpos_mutable_store(struct config_item *item, const char *page,
> +					size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +	bool mutable;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	if (kstrtobool(page, &mutable))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		if (plane->dev->enabled)
> +			return -EBUSY;
> +
> +		vkms_config_plane_set_zpos_mutable(plane->config, mutable);
> +	}
> +
> +	return (ssize_t)count;
> +}
> +
> +static ssize_t plane_zpos_initial_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int initial;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		initial = vkms_config_plane_get_zpos_initial(plane->config);
> +
> +	return sprintf(page, "%u\n", initial);
> +}
> +
> +static ssize_t plane_zpos_initial_store(struct config_item *item, const char *page,
> +					size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int initial;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	if (kstrtouint(page, 10, &initial))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		if (plane->dev->enabled)
> +			return -EBUSY;
> +
> +		if (initial > vkms_config_plane_get_zpos_max(plane->config))
> +			return -EINVAL;
> +
> +		if (initial < vkms_config_plane_get_zpos_min(plane->config))
> +			return -EINVAL;
> +
> +		vkms_config_plane_set_zpos_initial(plane->config, initial);
> +	}
> +
> +	return (ssize_t)count;
> +}
> +
> +static ssize_t plane_zpos_min_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int min;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		min = vkms_config_plane_get_zpos_min(plane->config);
> +
> +	return sprintf(page, "%u\n", min);
> +}
> +
> +static ssize_t plane_zpos_min_store(struct config_item *item, const char *page,
> +				    size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int min;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	if (kstrtouint(page, 10, &min))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		if (plane->dev->enabled)
> +			return -EBUSY;
> +
> +		if (min > vkms_config_plane_get_zpos_max(plane->config))
> +			return -EINVAL;
> +
> +		if (min > vkms_config_plane_get_zpos_initial(plane->config))
> +			return -EINVAL;
> +
> +		vkms_config_plane_set_zpos_min(plane->config, min);
> +	}
> +
> +	return (ssize_t)count;
> +}
> +
> +static ssize_t plane_zpos_max_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int max;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	scoped_guard(mutex, &plane->dev->lock)
> +		max = vkms_config_plane_get_zpos_max(plane->config);
> +
> +	return sprintf(page, "%u\n", max);
> +}
> +
> +static ssize_t plane_zpos_max_store(struct config_item *item, const char *page,
> +				    size_t count)
> +{
> +	struct vkms_configfs_plane *plane;
> +	unsigned int max;
> +
> +	plane = plane_item_to_vkms_configfs_plane(item);
> +
> +	if (kstrtouint(page, 10, &max))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &plane->dev->lock) {
> +		if (plane->dev->enabled)
> +			return -EBUSY;
> +
> +		if (max < vkms_config_plane_get_zpos_min(plane->config))
> +			return -EINVAL;
> +
> +		if (max < vkms_config_plane_get_zpos_initial(plane->config))
> +			return -EINVAL;
> +
> +		vkms_config_plane_set_zpos_max(plane->config, max);
> +	}
> +
> +	return (ssize_t)count;
> +}
> +
>  CONFIGFS_ATTR(plane_, type);
>  CONFIGFS_ATTR(plane_, supported_rotations);
>  CONFIGFS_ATTR(plane_, default_rotation);
> @@ -687,6 +876,11 @@ CONFIGFS_ATTR(plane_, default_color_range);
>  CONFIGFS_ATTR(plane_, supported_color_encoding);
>  CONFIGFS_ATTR(plane_, default_color_encoding);
>  CONFIGFS_ATTR(plane_, supported_formats);
> +CONFIGFS_ATTR(plane_, zpos_enabled);
> +CONFIGFS_ATTR(plane_, zpos_mutable);
> +CONFIGFS_ATTR(plane_, zpos_initial);
> +CONFIGFS_ATTR(plane_, zpos_min);
> +CONFIGFS_ATTR(plane_, zpos_max);
>  
>  static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_type,
> @@ -697,6 +891,11 @@ static struct configfs_attribute *plane_item_attrs[] = {
>  	&plane_attr_supported_color_encoding,
>  	&plane_attr_default_color_encoding,
>  	&plane_attr_supported_formats,
> +	&plane_attr_zpos_enabled,
> +	&plane_attr_zpos_mutable,
> +	&plane_attr_zpos_initial,
> +	&plane_attr_zpos_min,
> +	&plane_attr_zpos_max,
LGTM, other than my previous comment on adding validation in this layer.
It can force to change attributtes in a specific order. I think we should
only validate in vkms_config_is_valid().
>  	NULL,
>  };
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 14/22] drm/vkms: Introduce config for connector type
  2025-10-18  2:01 ` [PATCH 14/22] drm/vkms: Introduce config for connector type Louis Chauvet
@ 2025-10-27  9:27   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  9:27 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:14AM +0200, Louis Chauvet wrote:
> In order to emulate connector-specific behavior, add connector type
> configuration.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  6 ++++++
>  drivers/gpu/drm/vkms/vkms_config.c            |  1 +
>  drivers/gpu/drm/vkms/vkms_config.h            | 24 ++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_connector.c         |  5 +++--
>  drivers/gpu/drm/vkms/vkms_connector.h         |  3 ++-
>  drivers/gpu/drm/vkms/vkms_drv.h               |  1 +
>  drivers/gpu/drm/vkms/vkms_output.c            |  2 +-
>  7 files changed, 38 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index f2b38b436252..8633210342a4 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -1,5 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  
> +#include "drm/drm_mode.h"
#include <drm/drm_mode.h>?
>  #include <kunit/test.h>
>  
>  #include "../vkms_config.h"
> @@ -126,6 +127,7 @@ static void vkms_config_test_default_config(struct kunit *test)
>  	struct vkms_config *config;
>  	struct vkms_config_plane *plane_cfg;
>  	struct vkms_config_crtc *crtc_cfg;
> +	struct vkms_config_connector *connector_cfg;
>  	int n_primaries = 0;
>  	int n_cursors = 0;
>  	int n_overlays = 0;
> @@ -182,6 +184,10 @@ static void vkms_config_test_default_config(struct kunit *test)
>  
>  	/* Connectors */
>  	KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 1);
> +	vkms_config_for_each_connector(config, connector_cfg) {
> +		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_type(connector_cfg),
> +				DRM_MODE_CONNECTOR_VIRTUAL);
> +	}
>  
>  	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 5da34a3e8114..20750c9f6d08 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -771,6 +771,7 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  
>  	connector_cfg->config = config;
>  	connector_cfg->status = connector_status_connected;
> +	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
>  	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&connector_cfg->link, &config->connectors);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 267e45f5a617..36d289a010f6 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -126,6 +126,7 @@ struct vkms_config_encoder {
>   * struct vkms_config_connector
>   *
>   * @link: Link to the others connector in vkms_config
> + * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
>   * @config: The vkms_config this connector belongs to
>   * @status: Status (connected, disconnected...) of the connector
>   * @possible_encoders: Array of encoders that can be used with this connector
> @@ -138,6 +139,7 @@ struct vkms_config_connector {
>  	struct list_head link;
>  	struct vkms_config *config;
>  
> +	int type;
>  	enum drm_connector_status status;
>  	struct xarray possible_encoders;
>  
> @@ -315,6 +317,28 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
>  }
>  
>  /**
> + * vkms_config_connector_get_type() - Return the connector type
> + * @connector_cfg: Connector to get the type from
> + */
> +static inline int
> +vkms_config_connector_get_type(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->type;
> +}
> +
> +/**
> + * vkms_config_connector_set_type() - Set the connector type
> + * @connector_cfg: Connector to set the type to
> + * @type: New connector type
> + */
> +static inline void
> +vkms_config_connector_set_type(struct vkms_config_connector *connector_cfg,
> +			       int type)
> +{
> +	connector_cfg->type = type;
> +}
> +
> +/*
>   * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
>   * @plane_cfg: Plane to get the default rotation from
>   *
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> index b0a6b212d3f4..5a87dc2d4c63 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.c
> +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> @@ -68,7 +68,8 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
>  	.best_encoder = vkms_conn_best_encoder,
>  };
>  
> -struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev)
> +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
> +					   struct vkms_config_connector *connector_cfg)
>  {
>  	struct drm_device *dev = &vkmsdev->drm;
>  	struct vkms_connector *connector;
> @@ -79,7 +80,7 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev)
>  		return ERR_PTR(-ENOMEM);
>  
>  	ret = drmm_connector_init(dev, &connector->base, &vkms_connector_funcs,
> -				  DRM_MODE_CONNECTOR_VIRTUAL, NULL);
> +				  vkms_config_connector_get_type(connector_cfg), NULL);
For debugging, it'd be nice to print the connector type in vkms_config_show().
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/vkms_connector.h
> index ed312f4eff3a..a124c5403697 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.h
> +++ b/drivers/gpu/drm/vkms/vkms_connector.h
> @@ -24,7 +24,8 @@ struct vkms_connector {
>   * Returns:
>   * The connector or an error on failure.
>   */
> -struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev);
> +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
> +					   struct vkms_config_connector *connector_cfg);
>  
>  /**
>   * vkms_trigger_connector_hotplug() - Update the device's connectors status
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index 9ad286f043b5..07bdf3f550ae 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -226,6 +226,7 @@ struct vkms_output {
>  
>  struct vkms_config;
>  struct vkms_config_plane;
> +struct vkms_config_connector;
Since vkms_connector_init() is defined in vkms_connector.h, I don't think
this is required.
>  /**
>   * struct vkms_device - Description of a VKMS device
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 22208d02afa4..217f054d9598 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -96,7 +96,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  		struct vkms_config_encoder *possible_encoder;
>  		unsigned long idx = 0;
>  
> -		connector_cfg->connector = vkms_connector_init(vkmsdev);
> +		connector_cfg->connector = vkms_connector_init(vkmsdev, connector_cfg);
>  		if (IS_ERR(connector_cfg->connector)) {
>  			DRM_ERROR("Failed to init connector\n");
>  			return PTR_ERR(connector_cfg->connector);
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace
  2025-10-18  2:01 ` [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
@ 2025-10-27  9:35   ` José Expósito
  2025-10-27  9:38   ` José Expósito
  1 sibling, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  9:35 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:16AM +0200, Louis Chauvet wrote:
> To emulate some HDR features of displays, it is required to expose some
> properties on HDMI, eDP and DP connectors.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  3 +++
>  drivers/gpu/drm/vkms/vkms_config.c            |  1 +
>  drivers/gpu/drm/vkms/vkms_config.h            | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_connector.c         | 15 +++++++++++++++
>  4 files changed, 45 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index 8633210342a4..a89ccd75060d 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -187,6 +187,9 @@ static void vkms_config_test_default_config(struct kunit *test)
>  	vkms_config_for_each_connector(config, connector_cfg) {
>  		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_type(connector_cfg),
>  				DRM_MODE_CONNECTOR_VIRTUAL);
> +		KUNIT_EXPECT_EQ(test,
> +				vkms_config_connector_get_supported_colorspaces(connector_cfg),
> +				0);
>  	}
>  
>  	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 20750c9f6d08..56e2082b91c9 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -772,6 +772,7 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  	connector_cfg->config = config;
>  	connector_cfg->status = connector_status_connected;
>  	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
> +	vkms_config_connector_set_supported_colorspaces(connector_cfg, 0);
>  	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&connector_cfg->link, &config->connectors);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 36d289a010f6..ec614c2d4a30 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -141,6 +141,7 @@ struct vkms_config_connector {
>  
>  	int type;
>  	enum drm_connector_status status;
> +	u32 supported_colorspaces;
I don't know much about the specifics of colorspaces, so I'd appreciate some
additional feedback in the connector code.
Here we could add some docs and also print the value in vkms_config_show().
>  	struct xarray possible_encoders;
>  
>  	/* Internal usage */
> @@ -239,6 +240,31 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>   */
>  void vkms_config_destroy(struct vkms_config *config);
>  
> +/**
> + * vkms_config_connector_set_supported_colorspaces() - Set the supported colorspaces for a connector
> + * @connector_cfg: Connector configuration to modify
> + * @supported_colorspaces: Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
> + */
> +static inline void
> +vkms_config_connector_set_supported_colorspaces(struct vkms_config_connector *connector_cfg,
> +						u32 supported_colorspaces)
> +{
> +	connector_cfg->supported_colorspaces = supported_colorspaces;
> +}
> +
> +/**
> + * vkms_config_connector_get_supported_colorspaces() - Get the supported colorspaces for a connector
> + * @connector_cfg: Connector configuration to query
> + *
> + * Returns:
> + * Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
> + */
> +static inline u32
> +vkms_config_connector_get_supported_colorspaces(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->supported_colorspaces;
> +}
> +
>  /**
>   * vkms_config_get_device_name() - Return the name of the device
>   * @config: Configuration to get the device name from
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> index 5a87dc2d4c63..cc59d13c2d22 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.c
> +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> @@ -84,6 +84,21 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	if (vkms_config_connector_get_supported_colorspaces(connector_cfg)) {
> +		if (connector_cfg->type == DRM_MODE_CONNECTOR_HDMIA) {
> +			drm_mode_create_hdmi_colorspace_property(&connector->base,
> +								 vkms_config_connector_get_supported_colorspaces(connector_cfg));
> +			drm_connector_attach_hdr_output_metadata_property(&connector->base);
> +			drm_connector_attach_colorspace_property(&connector->base);
> +		} else if (connector_cfg->type == DRM_MODE_CONNECTOR_DisplayPort ||
> +			   connector_cfg->type == DRM_MODE_CONNECTOR_eDP) {
> +			drm_mode_create_dp_colorspace_property(&connector->base,
> +							       vkms_config_connector_get_supported_colorspaces(connector_cfg));
> +			drm_connector_attach_hdr_output_metadata_property(&connector->base);
> +			drm_connector_attach_colorspace_property(&connector->base);
> +		}
> +	}
> +
>  	drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs);
>  
>  	return connector;
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace
  2025-10-18  2:01 ` [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
  2025-10-27  9:35   ` José Expósito
@ 2025-10-27  9:38   ` José Expósito
  1 sibling, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27  9:38 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
Sorry for the additional email.
I see that the colorspace is ignored if the connector is not HDMI,
eDP or Display Port. Should we add some kind of validation?
On Sat, Oct 18, 2025 at 04:01:16AM +0200, Louis Chauvet wrote:
> To emulate some HDR features of displays, it is required to expose some
> properties on HDMI, eDP and DP connectors.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  3 +++
>  drivers/gpu/drm/vkms/vkms_config.c            |  1 +
>  drivers/gpu/drm/vkms/vkms_config.h            | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_connector.c         | 15 +++++++++++++++
>  4 files changed, 45 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index 8633210342a4..a89ccd75060d 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -187,6 +187,9 @@ static void vkms_config_test_default_config(struct kunit *test)
>  	vkms_config_for_each_connector(config, connector_cfg) {
>  		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_type(connector_cfg),
>  				DRM_MODE_CONNECTOR_VIRTUAL);
> +		KUNIT_EXPECT_EQ(test,
> +				vkms_config_connector_get_supported_colorspaces(connector_cfg),
> +				0);
>  	}
>  
>  	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 20750c9f6d08..56e2082b91c9 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -772,6 +772,7 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  	connector_cfg->config = config;
>  	connector_cfg->status = connector_status_connected;
>  	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
> +	vkms_config_connector_set_supported_colorspaces(connector_cfg, 0);
>  	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&connector_cfg->link, &config->connectors);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 36d289a010f6..ec614c2d4a30 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -141,6 +141,7 @@ struct vkms_config_connector {
>  
>  	int type;
>  	enum drm_connector_status status;
> +	u32 supported_colorspaces;
>  	struct xarray possible_encoders;
>  
>  	/* Internal usage */
> @@ -239,6 +240,31 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>   */
>  void vkms_config_destroy(struct vkms_config *config);
>  
> +/**
> + * vkms_config_connector_set_supported_colorspaces() - Set the supported colorspaces for a connector
> + * @connector_cfg: Connector configuration to modify
> + * @supported_colorspaces: Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
> + */
> +static inline void
> +vkms_config_connector_set_supported_colorspaces(struct vkms_config_connector *connector_cfg,
> +						u32 supported_colorspaces)
> +{
> +	connector_cfg->supported_colorspaces = supported_colorspaces;
> +}
> +
> +/**
> + * vkms_config_connector_get_supported_colorspaces() - Get the supported colorspaces for a connector
> + * @connector_cfg: Connector configuration to query
> + *
> + * Returns:
> + * Bitmask of supported colorspaces (DRM_COLOR_YCBCR_*)
> + */
> +static inline u32
> +vkms_config_connector_get_supported_colorspaces(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->supported_colorspaces;
> +}
> +
>  /**
>   * vkms_config_get_device_name() - Return the name of the device
>   * @config: Configuration to get the device name from
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> index 5a87dc2d4c63..cc59d13c2d22 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.c
> +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> @@ -84,6 +84,21 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
>  	if (ret)
>  		return ERR_PTR(ret);
>  
> +	if (vkms_config_connector_get_supported_colorspaces(connector_cfg)) {
> +		if (connector_cfg->type == DRM_MODE_CONNECTOR_HDMIA) {
> +			drm_mode_create_hdmi_colorspace_property(&connector->base,
> +								 vkms_config_connector_get_supported_colorspaces(connector_cfg));
> +			drm_connector_attach_hdr_output_metadata_property(&connector->base);
> +			drm_connector_attach_colorspace_property(&connector->base);
> +		} else if (connector_cfg->type == DRM_MODE_CONNECTOR_DisplayPort ||
> +			   connector_cfg->type == DRM_MODE_CONNECTOR_eDP) {
> +			drm_mode_create_dp_colorspace_property(&connector->base,
> +							       vkms_config_connector_get_supported_colorspaces(connector_cfg));
> +			drm_connector_attach_hdr_output_metadata_property(&connector->base);
> +			drm_connector_attach_colorspace_property(&connector->base);
> +		}
> +	}
> +
>  	drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs);
>  
>  	return connector;
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 18/22] drm/vkms: Introduce config for connector EDID
  2025-10-18  2:01 ` [PATCH 18/22] drm/vkms: Introduce config for connector EDID Louis Chauvet
@ 2025-10-27 10:02   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27 10:02 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:18AM +0200, Louis Chauvet wrote:
> Allows configuration of EDID for each connector.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  2 +
>  drivers/gpu/drm/vkms/vkms_config.h            | 77 +++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_connector.c         | 48 +++++++++++++++--
>  3 files changed, 123 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index a89ccd75060d..d1e380da31ff 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -190,6 +190,8 @@ static void vkms_config_test_default_config(struct kunit *test)
>  		KUNIT_EXPECT_EQ(test,
>  				vkms_config_connector_get_supported_colorspaces(connector_cfg),
>  				0);
> +		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_edid_enabled(connector_cfg),
> +				false);
>  	}
>  
>  	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index ec614c2d4a30..eaf76a58aab6 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -129,6 +129,8 @@ struct vkms_config_encoder {
>   * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
>   * @config: The vkms_config this connector belongs to
>   * @status: Status (connected, disconnected...) of the connector
@edid_enabled: If true, @edid and @edid_len are taken into account
(or similar)
> + * @edid: Stores the current EDID
> + * @edid_len: Current EDID length
>   * @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
> @@ -142,6 +144,9 @@ struct vkms_config_connector {
>  	int type;
>  	enum drm_connector_status status;
>  	u32 supported_colorspaces;
> +	bool edid_enabled;
> +	u8 *edid;
> +	unsigned int edid_len;
>  	struct xarray possible_encoders;
>  
>  	/* Internal usage */
> @@ -265,6 +270,78 @@ vkms_config_connector_get_supported_colorspaces(struct vkms_config_connector *co
>  	return connector_cfg->supported_colorspaces;
>  }
>  
> +/**
> + * vkms_config_connector_get_edid_enabled() - Check if EDID is enabled for a connector
> + * @connector_cfg: Connector configuration to check
> + *
> + * Returns:
> + * True if EDID is enabled for this connector, false otherwise.
> + */
> +static inline bool
> +vkms_config_connector_get_edid_enabled(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->edid_enabled;
> +}
> +
> +/**
> + * vkms_config_connector_set_edid_enabled() - Enable or disable EDID for a connector
> + * @connector_cfg: Connector configuration to modify
> + * @enabled: Whether to enable EDID for this connector
> + */
> +static inline void
> +vkms_config_connector_set_edid_enabled(struct vkms_config_connector *connector_cfg,
> +				       bool enabled)
> +{
> +	connector_cfg->edid_enabled = enabled;
> +}
> +
> +/**
> + * vkms_config_connector_get_edid() - Get the EDID data for a connector
> + * @connector_cfg: Connector configuration to get the EDID from
> + * @len: Pointer to store the length of the EDID data
> + *
> + * Returns:
> + * Pointer to the EDID data buffer, or NULL if no EDID is set.
> + * The length of the EDID data is stored in @len.
> + */
> +static inline const u8 *
> +vkms_config_connector_get_edid(const struct vkms_config_connector *connector_cfg, int *len)
> +{
> +	*len = connector_cfg->edid_len;
> +	return connector_cfg->edid;
> +}
> +
> +/**
> + * vkms_config_connector_set_edid() - Set the EDID data for a connector
> + * @connector_cfg: Connector configuration to modify
> + * @edid: Pointer to the EDID data buffer
> + * @len: Length of the EDID data
> + *
> + * If @len is 0, the EDID data will be cleared. If memory allocation fails,
> + * the existing EDID data will be preserved.
> + */
> +static inline void
> +vkms_config_connector_set_edid(struct vkms_config_connector *connector_cfg,
> +			       const u8 *edid, unsigned int len)
> +{
> +	if (len) {
> +		void *edid_tmp = krealloc(connector_cfg->edid, len, GFP_KERNEL);
> +
> +		if (edid_tmp) {
> +			connector_cfg->edid = edid_tmp;
> +			memcpy(connector_cfg->edid, edid, len);
> +			connector_cfg->edid_len = len;
> +		} else {
> +			kfree(connector_cfg->edid);
> +			connector_cfg->edid_len = 0;
I wonder if in case of error it makes sense to NULL connector_cfg->edid and
vkms_config_connector_set_edid_enabled(false)?
It'd be also nice to print the EDID in hex format in vkms_config_show().
> +		}
> +	} else {
> +		kfree(connector_cfg->edid);
> +		connector_cfg->edid = NULL;
> +		connector_cfg->edid_len = len;
> +	}
> +}
> +
>  /**
>   * vkms_config_get_device_name() - Return the name of the device
>   * @config: Configuration to get the device name from
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> index cc59d13c2d22..339d747e729e 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.c
> +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> @@ -42,13 +42,53 @@ static const struct drm_connector_funcs vkms_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> +static int vkms_connector_read_block(void *context, u8 *buf, unsigned int block, size_t len)
> +{
> +	struct vkms_config_connector *config = context;
> +	unsigned int edid_len;
> +	const u8 *edid = vkms_config_connector_get_edid(config, &edid_len);
> +
> +	if (block * len + len > edid_len)
> +		return 1;
> +	memcpy(buf, &edid[block * len], len);
> +	return 0;
> +}
> +
>  static int vkms_conn_get_modes(struct drm_connector *connector)
>  {
> -	int count;
> +	struct vkms_connector *vkms_connector = drm_connector_to_vkms_connector(connector);
> +	const struct drm_edid *drm_edid = NULL;
> +	int count = 0;
> +	struct vkms_config_connector *context = NULL;
> +	struct drm_device *dev = connector->dev;
> +	struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
> +	struct vkms_config_connector *connector_cfg;
>  
> -	/* Use the default modes list from DRM */
> -	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> -	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +	vkms_config_for_each_connector(vkmsdev->config, connector_cfg) {
> +		if (connector_cfg->connector == vkms_connector)
> +			context = connector_cfg;
> +	}
> +	if (context) {
> +		if (vkms_config_connector_get_edid_enabled(context)) {
> +			drm_edid = drm_edid_read_custom(connector,
> +							vkms_connector_read_block, context);
> +
> +			/*
> +			 * Unconditionally update the connector. If the EDID was read
> +			 * successfully, fill in the connector information derived from the
> +			 * EDID. Otherwise, if the EDID is NULL, clear the connector
> +			 * information.
> +			 */
> +			drm_edid_connector_update(connector, drm_edid);
> +
> +			count = drm_edid_connector_add_modes(connector);
> +
> +			drm_edid_free(drm_edid);
> +		} else {
> +			count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> +			drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +		}
> +	}
>  
>  	return count;
>  }
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 01/22] drm/vkms: Introduce config for plane name
  2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
  2025-10-24 11:16   ` José Expósito
@ 2025-10-27 10:15   ` Jani Nikula
  1 sibling, 0 replies; 48+ messages in thread
From: Jani Nikula @ 2025-10-27 10:15 UTC (permalink / raw)
  To: Louis Chauvet, Haneen Mohammed, Simona Vetter, Melissa Wen,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	jose.exposito89, Jonathan Corbet
  Cc: victoria, sebastian.wick, victoria, airlied, thomas.petazzoni,
	dri-devel, linux-kernel, linux-doc, Louis Chauvet
On Sat, 18 Oct 2025, Louis Chauvet <louis.chauvet@bootlin.com> wrote:
> As planes can have a name in DRM, prepare VKMS to configure it using
> ConfigFS.
>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_config.c |  4 ++++
>  drivers/gpu/drm/vkms/vkms_config.h | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_drv.h    |  5 +++--
>  drivers/gpu/drm/vkms/vkms_output.c |  6 +-----
>  drivers/gpu/drm/vkms/vkms_plane.c  |  6 ++++--
>  5 files changed, 38 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index f8394a063ecf..ed172f800685 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -350,6 +350,8 @@ static int vkms_config_show(struct seq_file *m, void *data)
>  		seq_puts(m, "plane:\n");
>  		seq_printf(m, "\ttype=%d\n",
>  			   vkms_config_plane_get_type(plane_cfg));
> +		seq_printf(m, "\tname=%s\n",
> +			   vkms_config_plane_get_name(plane_cfg));
>  	}
>  
>  	vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) {
> @@ -390,6 +392,7 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config)
>  
>  	plane_cfg->config = config;
>  	vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
> +	vkms_config_plane_set_name(plane_cfg, NULL);
>  	xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&plane_cfg->link, &config->planes);
> @@ -402,6 +405,7 @@ void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg)
>  {
>  	xa_destroy(&plane_cfg->possible_crtcs);
>  	list_del(&plane_cfg->link);
> +	kfree_const(plane_cfg->name);
>  	kfree(plane_cfg);
>  }
>  EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 4c8d668e7ef8..b69c35097ba0 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -35,6 +35,7 @@ struct vkms_config {
>   *
>   * @link: Link to the others planes in vkms_config
>   * @config: The vkms_config this plane belongs to
> + * @name: Name of the plane
>   * @type: Type of the plane. The creator of configuration needs to ensures that
>   *        at least one primary plane is present.
>   * @possible_crtcs: Array of CRTCs that can be used with this plane
> @@ -47,6 +48,7 @@ struct vkms_config_plane {
>  	struct list_head link;
>  	struct vkms_config *config;
>  
> +	const char *name;
>  	enum drm_plane_type type;
>  	struct xarray possible_crtcs;
>  
> @@ -288,6 +290,30 @@ vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg,
>  	plane_cfg->type = type;
>  }
>  
> +/**
> + * vkms_config_plane_set_name() - Set the plane name
> + * @plane_cfg: Plane to set the name to
> + * @name: New plane name. The name is copied.
> + */
> +static inline void
> +vkms_config_plane_set_name(struct vkms_config_plane *plane_cfg,
> +			   const char *name)
> +{
> +	if (plane_cfg->name)
> +		kfree_const(plane_cfg->name);
> +	plane_cfg->name = kstrdup_const(name, GFP_KERNEL);
> +}
> +
> +/**
> + * vkms_config_plane_get_name - Get the plane name
> + * @plane_cfg: Plane to get the name from
> + */
> +static inline const char *
> +vkms_config_plane_get_name(struct vkms_config_plane *plane_cfg)
> +{
> +	return plane_cfg->name;
> +}
What's with the abundance of static inlines being added in this header?
You'll have more files including this header, and this header will be
including more files the more static inline functionality you add, and
eventually everything just ends up including way too much. That's what
happens with static inlines, and it's a bunch of tedious refactoring
later to clean it up.
BR,
Jani.
> +
>  /**
>   * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
>   * @plane_cfg: Plane to attach
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index db260df1d4f6..9ad286f043b5 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -225,6 +225,7 @@ struct vkms_output {
>  };
>  
>  struct vkms_config;
> +struct vkms_config_plane;
>  
>  /**
>   * struct vkms_device - Description of a VKMS device
> @@ -298,10 +299,10 @@ int vkms_output_init(struct vkms_device *vkmsdev);
>   * vkms_plane_init() - Initialize a plane
>   *
>   * @vkmsdev: VKMS device containing the plane
> - * @type: type of plane to initialize
> + * @config: plane configuration
>   */
>  struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
> -				   enum drm_plane_type type);
> +				   struct vkms_config_plane *config);
>  
>  /* CRC Support */
>  const char *const *vkms_get_crc_sources(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 2ee3749e2b28..22208d02afa4 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -19,11 +19,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  		return -EINVAL;
>  
>  	vkms_config_for_each_plane(vkmsdev->config, plane_cfg) {
> -		enum drm_plane_type type;
> -
> -		type = vkms_config_plane_get_type(plane_cfg);
> -
> -		plane_cfg->plane = vkms_plane_init(vkmsdev, type);
> +		plane_cfg->plane = vkms_plane_init(vkmsdev, plane_cfg);
>  		if (IS_ERR(plane_cfg->plane)) {
>  			DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n");
>  			return PTR_ERR(plane_cfg->plane);
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index e592e47a5736..263376686794 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -11,6 +11,7 @@
>  
>  #include "vkms_drv.h"
>  #include "vkms_formats.h"
> +#include "vkms_config.h"
>  
>  static const u32 vkms_formats[] = {
>  	DRM_FORMAT_ARGB8888,
> @@ -217,7 +218,7 @@ static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
>  };
>  
>  struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
> -				   enum drm_plane_type type)
> +				   struct vkms_config_plane *config)
>  {
>  	struct drm_device *dev = &vkmsdev->drm;
>  	struct vkms_plane *plane;
> @@ -225,7 +226,8 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
>  					   &vkms_plane_funcs,
>  					   vkms_formats, ARRAY_SIZE(vkms_formats),
> -					   NULL, type, NULL);
> +					   NULL, vkms_config_plane_get_type(config),
> +					   vkms_config_plane_get_name(config));
>  	if (IS_ERR(plane))
>  		return plane;
-- 
Jani Nikula, Intel
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 19/22] drm/vkms: Introduce configfs for connector EDID
  2025-10-18  2:01 ` [PATCH 19/22] drm/vkms: Introduce configfs " Louis Chauvet
@ 2025-10-27 10:16   ` José Expósito
  2025-10-27 17:18     ` Louis Chauvet
  0 siblings, 1 reply; 48+ messages in thread
From: José Expósito @ 2025-10-27 10:16 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:19AM +0200, Louis Chauvet wrote:
> Introduce new attributes to configure EDID of a connector:
> - edid_enable - chose if the connector will have an EDD or not
> - edid - raw edid content
> 
> Due to limitation of ConfigFS, the max len of EDID is PAGE_SIZE (4kB on
> x86), it should be sufficient for many tests. One possible evolution is
> using a ConfigFS blob to allow bigger EDID.
> 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
Hey Louis,
I wasn't able to set the EDID, could you provide an example?
This is what I tried:
# I'm using QEMU's EDID:
$ cat /sys/class/drm/card0-Virtual-1/edid > qemu-edid.bin
# Create a simple device:
$ sudo mkdir /sys/kernel/config/vkms/gpu1 && \
sudo mkdir /sys/kernel/config/vkms/gpu1/planes/plane0  && \
echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/planes/plane0/type && \
sudo mkdir /sys/kernel/config/vkms/gpu1/crtcs/crtc0 && \
echo "0" | sudo tee /sys/kernel/config/vkms/gpu1/crtcs/crtc0/writeback && \
sudo mkdir /sys/kernel/config/vkms/gpu1/encoders/encoder0 && \
sudo mkdir /sys/kernel/config/vkms/gpu1/connectors/connector0 && \
sudo ln -s /sys/kernel/config/vkms/gpu1/crtcs/crtc0 /sys/kernel/config/vkms/gpu1/planes/plane0/possible_crtcs && \
sudo ln -s /sys/kernel/config/vkms/gpu1/crtcs/crtc0 /sys/kernel/config/vkms/gpu1/encoders/encoder0/possible_crtcs && \
sudo ln -s /sys/kernel/config/vkms/gpu1/encoders/encoder0 /sys/kernel/config/vkms/gpu1/connectors/connector0/possible_encoders
$ cat qemu-edid.bin | sudo tee /sys/kernel/config/vkms/gpu1/connectors/connector0/edid
# The EDID is stored and it is correct:
$ cat /sys/kernel/config/vkms/gpu1/connectors/connector0/edid | edid-decode
$ echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/connectors/connector0/edid_enabled
$ echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/enabled
# After enabling the device, the EDID is not present:
$ cat /sys/class/drm/card1-Virtual-2/edid
<empty>
And drm_info does not show the EDID property.
Am I missing something?
>  Documentation/gpu/vkms.rst           |  5 ++-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 81 +++++++++++++++++++++++++++++++++++-
>  2 files changed, 84 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index 650d6f6e79fd..bbd03f61e61c 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -135,7 +135,7 @@ Last but not least, create one or more connectors::
>  
>    sudo mkdir /config/vkms/my-vkms/connectors/connector0
>  
> -Connectors have 3 configurable attribute:
> +Connectors have 5 configurable attribute:
>  
>  - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
>    as those exposed by the "status" property of a connector)
> @@ -144,6 +144,9 @@ Connectors have 3 configurable attribute:
>    If supported_colorspaces is not 0, the HDR_OUTPUT_METADATA will also be created.
>    Value is a bitfield, 0x1 = NO_DATA, 0x2 = SMPTE_170M_YCC... see enum drm_colorspace
>    for full list.
> +- edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
> +  EDID but just a list of modes, this attribute allows to disable EDID property.
> +- edid: Content of the EDID. Ignored if edid_enabled is not set
>  
>  
>  To finish the configuration, link the different pipeline items::
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index 909f4557caec..a977c0842cd6 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -1,5 +1,4 @@
>  // SPDX-License-Identifier: GPL-2.0+
> -#include "asm-generic/errno-base.h"
>  #include <linux/cleanup.h>
>  #include <linux/configfs.h>
>  #include <linux/mutex.h>
> @@ -1222,14 +1221,94 @@ static ssize_t connector_supported_colorspaces_store(struct config_item *item,
>  	return count;
>  }
>  
> +static ssize_t connector_edid_enabled_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_connector *connector;
> +	bool enabled;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +
> +	scoped_guard(mutex, &connector->dev->lock)
> +		enabled = vkms_config_connector_get_edid_enabled(connector->config);
> +
> +	return sprintf(page, "%d\n", enabled);
> +}
> +
> +static ssize_t connector_edid_enabled_store(struct config_item *item,
> +					    const char *page, size_t count)
> +{
> +	struct vkms_configfs_connector *connector;
> +	struct vkms_config_connector *connector_cfg;
> +	bool enabled;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +	connector_cfg = connector->config;
> +
> +	if (kstrtobool(page, &enabled))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &connector->dev->lock)
> +	{
> +		vkms_config_connector_set_edid_enabled(connector_cfg, enabled);
> +
> +		if (connector->dev->enabled &&
> +		    vkms_config_connector_get_status(connector_cfg) !=
> +		    connector_status_disconnected)
> +			vkms_trigger_connector_hotplug(connector->dev->config->dev);
> +	}
> +	return count;
> +}
> +
> +static ssize_t connector_edid_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_connector *connector;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +
> +	scoped_guard(mutex, &connector->dev->lock)
> +	{
> +		unsigned int len = 0;
> +		const u8 *edid = vkms_config_connector_get_edid(connector->config, &len);
> +
> +		memcpy(page, edid, min(len, PAGE_SIZE));
> +		return min(len, PAGE_SIZE);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static ssize_t connector_edid_store(struct config_item *item,
> +				    const char *page, size_t count)
> +{
> +	struct vkms_configfs_connector *connector;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +
> +	scoped_guard(mutex, &connector->dev->lock)
> +	{
> +		vkms_config_connector_set_edid(connector->config, page, count);
> +
> +		if (connector->dev->enabled &&
> +		    vkms_config_connector_get_status(connector->config) !=
> +		    connector_status_disconnected)
> +			vkms_trigger_connector_hotplug(connector->dev->config->dev);
> +	}
> +
> +	return count;
> +}
> +
>  CONFIGFS_ATTR(connector_, status);
>  CONFIGFS_ATTR(connector_, type);
>  CONFIGFS_ATTR(connector_, supported_colorspaces);
> +CONFIGFS_ATTR(connector_, edid_enabled);
> +CONFIGFS_ATTR(connector_, edid);
>  
>  static struct configfs_attribute *connector_item_attrs[] = {
>  	&connector_attr_status,
>  	&connector_attr_type,
>  	&connector_attr_supported_colorspaces,
> +	&connector_attr_edid_enabled,
> +	&connector_attr_edid,
>  	NULL,
>  };
>  
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector
  2025-10-18  2:01 ` [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector Louis Chauvet
@ 2025-10-27 14:52   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27 14:52 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:20AM +0200, Louis Chauvet wrote:
> In order to prepare for dynamic connector configuration, we need to store
> if a connector is dynamic and if it is enabled.
> 
> The two new vkms_config_connector fields will helps for that.
> 
> Co-developed-by: José Expósito <jose.exposito89@gmail.com>
> Signed-off-by: José Expósito <jose.exposito89@gmail.com>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  4 ++
>  drivers/gpu/drm/vkms/vkms_config.c            |  2 +
>  drivers/gpu/drm/vkms/vkms_config.h            | 66 +++++++++++++++++++++++++++
>  3 files changed, 72 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index d1e380da31ff..f4b5f8f59fab 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -192,6 +192,10 @@ static void vkms_config_test_default_config(struct kunit *test)
>  				0);
>  		KUNIT_EXPECT_EQ(test, vkms_config_connector_get_edid_enabled(connector_cfg),
>  				false);
> +		KUNIT_EXPECT_EQ(test, vkms_config_connector_is_enabled(connector_cfg),
> +				true);
> +		KUNIT_EXPECT_EQ(test, vkms_config_connector_is_dynamic(connector_cfg),
> +				false);
I missed this in other reviews, but you can use KUNIT_EXPECT_TRUE/FALSE instead.
>  	}
>  
>  	KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 56e2082b91c9..fd724ae2ebc9 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -773,6 +773,8 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  	connector_cfg->status = connector_status_connected;
>  	vkms_config_connector_set_type(connector_cfg, DRM_MODE_CONNECTOR_VIRTUAL);
>  	vkms_config_connector_set_supported_colorspaces(connector_cfg, 0);
> +	vkms_config_connector_set_dynamic(connector_cfg, false);
> +	vkms_config_connector_set_enabled(connector_cfg, true);
>  	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
>  
>  	list_add_tail(&connector_cfg->link, &config->connectors);
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index eaf76a58aab6..6716b5a85f0d 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -128,6 +128,8 @@ struct vkms_config_encoder {
>   * @link: Link to the others connector in vkms_config
>   * @type: Store the type of connector using DRM_MODE_CONNECTOR_* values
>   * @config: The vkms_config this connector belongs to
> + * @dynamic: Store if a connector should be created with drm_connector_dynamic_init
> + * @enabled: If @dynamic, this means that the correct is currently registered in drm
>   * @status: Status (connected, disconnected...) of the connector
>   * @edid: Stores the current EDID
>   * @edid_len: Current EDID length
> @@ -142,6 +144,8 @@ struct vkms_config_connector {
>  	struct vkms_config *config;
>  
>  	int type;
> +	bool enabled;
> +	bool dynamic;
In this patch we could also log this in vkms_config_show().
>  	enum drm_connector_status status;
>  	u32 supported_colorspaces;
>  	bool edid_enabled;
> @@ -185,6 +189,24 @@ struct vkms_config_connector {
>  #define vkms_config_for_each_connector(config, connector_cfg) \
>  	list_for_each_entry((connector_cfg), &(config)->connectors, link)
>  
> +/**
> + * vkms_config_for_each_connector_static - Iterate over the static vkms_config connectors
> + * @config: &struct vkms_config pointer
> + * @connector_cfg: &struct vkms_config_connector pointer used as cursor
> + */
> +#define vkms_config_for_each_connector_static(config, connector_cfg) \
> +	vkms_config_for_each_connector((config), (connector_cfg)) \
> +		if (!(connector_cfg)->dynamic)
> +
> +/**
> + * vkms_config_for_each_connector_dynamic - Iterate over the dynamic vkms_config connectors
> + * @config: &struct vkms_config pointer
> + * @connector_cfg: &struct vkms_config_connector pointer used as cursor
> + */
> +#define vkms_config_for_each_connector_dynamic(config, connector_cfg) \
> +	vkms_config_for_each_connector((config), (connector_cfg)) \
> +		if ((connector_cfg)->dynamic)
> +
>  /**
>   * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config_plane
>   * possible CRTCs
> @@ -441,6 +463,50 @@ vkms_config_connector_set_type(struct vkms_config_connector *connector_cfg,
>  	connector_cfg->type = type;
>  }
>  
> +/**
> + * vkms_config_connector_set_enabled() - If the connector is part of the device
> + * @crtc_cfg: Target connector
> + * @enabled: Add or remove the connector
> + */
> +static inline void
> +vkms_config_connector_set_enabled(struct vkms_config_connector *connector_cfg,
> +				  bool enabled)
> +{
> +	connector_cfg->enabled = enabled;
> +}
> +
> +/**
> + * vkms_config_connector_is_enabled() - If the connector is part of the device
> + * @connector_cfg: The connector
> + */
> +static inline bool
> +vkms_config_connector_is_enabled(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->enabled;
> +}
> +
> +/**
> + * vkms_config_connector_set_dynamic() - If the connector is dynamic
> + * @crtc_cfg: Target connector
> + * @enabled: Enable or disable the dynamic status
> + */
> +static inline void
> +vkms_config_connector_set_dynamic(struct vkms_config_connector *connector_cfg,
> +				  bool dynamic)
> +{
> +	connector_cfg->dynamic = dynamic;
> +}
> +
> +/**
> + * vkms_config_connector_is_enabled() - If the connector is dynamic
> + * @connector_cfg: The connector
> + */
> +static inline bool
> +vkms_config_connector_is_dynamic(struct vkms_config_connector *connector_cfg)
> +{
> +	return connector_cfg->dynamic;
> +}
> +
>  /*
>   * vkms_config_plane_get_default_rotation() - Get the default rotation for a plane
>   * @plane_cfg: Plane to get the default rotation from
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 21/22] drm/vkms: Allow to hot-add connectors
  2025-10-18  2:01 ` [PATCH 21/22] drm/vkms: Allow to hot-add connectors Louis Chauvet
@ 2025-10-27 15:01   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27 15:01 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:21AM +0200, Louis Chauvet wrote:
> In order to allow creating dynamic connector, add the required
> infrastructure in vkms_connector.
> 
> Co-developed-by: José Expósito <jose.exposito89@gmail.com>
> Signed-off-by: José Expósito <jose.exposito89@gmail.com>
> [Louis Chauvet: use drm_atomic_helper_connector_reset instead of
> drm_mode_config_reset because connector is not yet registered]
Aha! That was why, thanks a lot for figuring this out :)
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  drivers/gpu/drm/vkms/vkms_connector.c | 69 ++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vkms/vkms_connector.h | 33 +++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_output.c    | 11 +++++-
>  3 files changed, 111 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> index 339d747e729e..77a544728721 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.c
> +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> @@ -1,5 +1,4 @@
>  // SPDX-License-Identifier: GPL-2.0+
> -
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_managed.h>
> @@ -144,9 +143,77 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
>  	return connector;
>  }
>  
> +static const struct drm_connector_funcs vkms_dynamic_connector_funcs = {
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +	.destroy = drm_connector_cleanup,
> +	.detect = vkms_connector_detect,
> +};
> +
>  void vkms_trigger_connector_hotplug(struct vkms_device *vkmsdev)
>  {
>  	struct drm_device *dev = &vkmsdev->drm;
>  
>  	drm_kms_helper_hotplug_event(dev);
>  }
> +
> +struct vkms_connector *vkms_connector_hot_add(struct vkms_device *vkmsdev,
> +					      struct vkms_config_connector *connector_cfg)
> +{
> +	struct vkms_config_encoder *encoder_cfg;
> +	struct vkms_connector *connector;
> +	int ret;
> +	unsigned long idx = 0;
> +
> +	connector = kzalloc(sizeof(*connector), GFP_KERNEL);
Could we use drmm_kzalloc instead?
> +	if (IS_ERR(connector))
> +		return connector;
> +	ret = drm_connector_dynamic_init(&vkmsdev->drm,
> +					 &connector->base,
> +					 &vkms_dynamic_connector_funcs,
> +					 connector_cfg->type,
> +					 NULL);
> +	if (ret)
> +		return ERR_PTR(ret);
> +	drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs);
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, encoder_cfg) {
> +		ret = drm_connector_attach_encoder(&connector->base,
> +						   encoder_cfg->encoder);
> +		if (ret)
> +			return ERR_PTR(ret);
> +	}
> +
> +	drm_atomic_helper_connector_reset(&connector->base);
> +
> +	ret = drm_connector_dynamic_register(&connector->base);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return connector;
> +}
> +
> +void vkms_connector_hot_remove(struct vkms_device *vkmsdev,
> +			       struct vkms_connector *connector)
> +{
> +	drm_connector_unregister(&connector->base);
> +	drm_mode_config_reset(&vkmsdev->drm);
> +	drm_connector_put(&connector->base);
> +}
> +
> +int vkms_connector_hot_attach_encoder(struct vkms_device *vkmsdev,
> +				      struct vkms_connector *connector,
> +				      struct drm_encoder *encoder)
> +{
> +	int ret;
> +
> +	ret = drm_connector_attach_encoder(&connector->base, encoder);
> +	if (ret)
> +		return ret;
> +
> +	drm_mode_config_reset(&vkmsdev->drm);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/vkms_connector.h
> index a124c5403697..224950c13a93 100644
> --- a/drivers/gpu/drm/vkms/vkms_connector.h
> +++ b/drivers/gpu/drm/vkms/vkms_connector.h
> @@ -7,6 +7,7 @@
>  
>  #define drm_connector_to_vkms_connector(target) \
>  	container_of(target, struct vkms_connector, base)
> +struct vkms_config_connector;
>  
>  /**
>   * struct vkms_connector - VKMS custom type wrapping around the DRM connector
> @@ -33,4 +34,36 @@ struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev,
>   */
>  void vkms_trigger_connector_hotplug(struct vkms_device *vkmsdev);
>  
> +/**
> + * vkms_connector_hot_add() - Create a connector after the device is created
> + * @vkmsdev: Device to hot-add the connector to
> + * @connector_cfg: Connector's configuration
> + *
> + * Returns:
> + * The connector or an error on failure.
> + */
> +struct vkms_connector *vkms_connector_hot_add(struct vkms_device *vkmsdev,
> +					      struct vkms_config_connector *connector_cfg);
> +
> +/**
> + * vkms_connector_hot_remove() - Remove a connector after a device is created
> + * @connector: The connector to hot-remove
> + */
> +void vkms_connector_hot_remove(struct vkms_device *vkmsdev,
> +			       struct vkms_connector *connector);
> +
> +/**
> + * vkms_connector_hot_attach_encoder() - Attach a connector to a encoder after
> + * the device is created.
> + * @vkmsdev: Device containing the connector and the encoder
> + * @connector: Connector to attach to @encoder
> + * @encoder: Target encoder
> + *
> + * Returns:
> + * 0 on success or an error on failure.
> + */
> +int vkms_connector_hot_attach_encoder(struct vkms_device *vkmsdev,
> +				      struct vkms_connector *connector,
> +				      struct drm_encoder *encoder);
> +
>  #endif /* _VKMS_CONNECTOR_H_ */
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 217f054d9598..aba2f9ab243d 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -92,7 +92,7 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  		}
>  	}
>  
> -	vkms_config_for_each_connector(vkmsdev->config, connector_cfg) {
> +	vkms_config_for_each_connector_static(vkmsdev->config, connector_cfg) {
>  		struct vkms_config_encoder *possible_encoder;
>  		unsigned long idx = 0;
>  
> @@ -116,5 +116,14 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  
>  	drm_mode_config_reset(dev);
>  
> +	vkms_config_for_each_connector_dynamic(vkmsdev->config, connector_cfg) {
> +		if (connector_cfg->enabled) {
> +			connector_cfg->connector = vkms_connector_hot_add(vkmsdev, connector_cfg);
> +
> +			if (IS_ERR(connector_cfg->connector))
> +				return PTR_ERR(connector_cfg->connector);
> +		}
> +	}
> +
>  	return 0;
>  }
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime
  2025-10-18  2:01 ` [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime Louis Chauvet
@ 2025-10-27 15:17   ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-27 15:17 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Sat, Oct 18, 2025 at 04:01:22AM +0200, Louis Chauvet wrote:
> DRM allows the connector to be created after the device. To allows
> emulating this, add two configfs attributes to connector to allows this.
> 
> Using the dynamic attribute you can set if a connector will be dynamic or
> not.
> Using the enabled attribute, you can set at runtime if a dynamic connector
> is present or not.
> 
> Co-developed-by: José Expósito <jose.exposito89@gmail.com>
> Signed-off-by: José Expósito <jose.exposito89@gmail.com>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>  Documentation/gpu/vkms.rst           |   6 +-
>  drivers/gpu/drm/vkms/vkms_configfs.c | 146 ++++++++++++++++++++++++++++++++---
>  2 files changed, 139 insertions(+), 13 deletions(-)
> 
> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
> index bbd03f61e61c..8b17aaa28eeb 100644
> --- a/Documentation/gpu/vkms.rst
> +++ b/Documentation/gpu/vkms.rst
> @@ -135,7 +135,7 @@ Last but not least, create one or more connectors::
>  
>    sudo mkdir /config/vkms/my-vkms/connectors/connector0
>  
> -Connectors have 5 configurable attribute:
> +Connectors have 7 configurable attribute:
>  
>  - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
>    as those exposed by the "status" property of a connector)
> @@ -147,7 +147,9 @@ Connectors have 5 configurable attribute:
>  - edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
>    EDID but just a list of modes, this attribute allows to disable EDID property.
>  - edid: Content of the EDID. Ignored if edid_enabled is not set
> -
> +- dynamic: Set to 1 while configuring the device to create a dynamic connector. A dynamic
> +  connector can be used to emulate DP MST connectors.
> +- enabled: For dynamic connector, set it to 1 to create the connector, 0 to remove it.
>  
>  To finish the configuration, link the different pipeline items::
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
> index a977c0842cd6..937b749142ad 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -1115,8 +1115,12 @@ static ssize_t connector_status_store(struct config_item *item,
>  	scoped_guard(mutex, &connector->dev->lock) {
>  		vkms_config_connector_set_status(connector->config, status);
>  
> -		if (connector->dev->enabled)
> -			vkms_trigger_connector_hotplug(connector->dev->config->dev);
> +		if (connector->dev->enabled) {
> +			if (connector->config->dynamic && connector->config->enabled)
> +				vkms_trigger_connector_hotplug(connector->dev->config->dev);
> +			if (!connector->config->dynamic)
> +				vkms_trigger_connector_hotplug(connector->dev->config->dev);
To avoid duplicating code, we could do something like:
	bool hotplug = !connector->config->dynamic ||
		       (connector->config->dynamic && connector->config->enabled);
	if (hotplug)
		vkms_trigger_connector_hotplug(connector->dev->config->dev);
> +		}
>  	}
>  
>  	return (ssize_t)count;
> @@ -1176,8 +1180,12 @@ static ssize_t connector_type_store(struct config_item *item,
>  	}
>  
>  	scoped_guard(mutex, &connector->dev->lock) {
> -		if (connector->dev->enabled)
> -			return -EINVAL;
> +		if (connector->dev->enabled) {
> +			if (connector->config->dynamic && connector->config->enabled)
> +				return -EBUSY;
> +			if (!connector->config->dynamic)
> +				return -EBUSY;
> +		}
And something similar here. Also, instead of returning -EINVAL
in "drm/vkms: Introduce configfs for connector type", you could return
-EBUSY and avoid changing the return type here.
>  		vkms_config_connector_set_type(connector->config, val);
>  	}
>  
> @@ -1293,6 +1301,102 @@ static ssize_t connector_edid_store(struct config_item *item,
>  		    connector_status_disconnected)
>  			vkms_trigger_connector_hotplug(connector->dev->config->dev);
>  	}
> +	return count;
> +}
> +
> +static ssize_t connector_enabled_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_connector *connector;
> +	bool enabled;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +
> +	scoped_guard(mutex, &connector->dev->lock)
> +		enabled = vkms_config_connector_is_enabled(connector->config);
> +
> +	return sprintf(page, "%d\n", enabled);
> +}
> +
> +static ssize_t connector_enabled_store(struct config_item *item,
> +				       const char *page, size_t count)
> +{
> +	struct vkms_configfs_connector *connector;
> +	struct vkms_config_connector *connector_cfg;
> +	bool enabled, was_enabled;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +	connector_cfg = connector->config;
> +
> +	if (kstrtobool(page, &enabled))
> +		return -EINVAL;
> +
> +	if (!connector->dev->enabled) {
> +		vkms_config_connector_set_enabled(connector_cfg, enabled);
> +	} else {
> +		// Only dynamic connector can be enabled/disabled at runtime
> +		if (!connector_cfg->dynamic)
> +			return -EBUSY;
> +
> +		was_enabled = vkms_config_connector_is_enabled(connector_cfg);
> +		vkms_config_connector_set_enabled(connector_cfg, enabled);
> +
> +		// Resulting configuration is invalid (missing encoder for example)
> +		// Early return to avoid drm core issue
> +		if (!vkms_config_is_valid(connector->dev->config)) {
> +			vkms_config_connector_set_enabled(connector_cfg, was_enabled);
> +			return -EINVAL;
> +		}
> +
> +		if (!was_enabled && enabled) {
> +			// Adding the connector
> +			connector_cfg->connector = vkms_connector_hot_add(connector->dev->config->dev,
> +									  connector_cfg);
> +			if (IS_ERR(connector_cfg->connector)) {
> +				vkms_config_connector_set_enabled(connector_cfg, was_enabled);
> +				return PTR_ERR(connector_cfg->connector);
> +			}
> +		} else if (was_enabled && !enabled) {
> +			vkms_connector_hot_remove(connector->dev->config->dev,
> +						  connector_cfg->connector);
> +		}
> +	}
> +	return count;
As a suggestion, we could add a "goto rollback;" and avoid duplicating error
handling:
	rollback:
		vkms_config_connector_set_enabled(connector_cfg, was_enabled);
		return ret;
> +}
> +
> +static ssize_t connector_dynamic_show(struct config_item *item, char *page)
> +{
> +	struct vkms_configfs_connector *connector;
> +	bool enabled;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +
> +	scoped_guard(mutex, &connector->dev->lock) {
> +		enabled = vkms_config_connector_is_dynamic(connector->config);
> +	}
> +
> +	return sprintf(page, "%d\n", enabled);
> +}
> +
> +static ssize_t connector_dynamic_store(struct config_item *item,
> +				       const char *page, size_t count)
> +{
> +	struct vkms_configfs_connector *connector;
> +	struct vkms_config_connector *connector_cfg;
> +	bool dynamic;
> +
> +	connector = connector_item_to_vkms_configfs_connector(item);
> +	connector_cfg = connector->config;
> +
> +	if (kstrtobool(page, &dynamic))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &connector->dev->lock) {
> +		// Can't change the dynamic status when the device is activated
> +		if (connector->dev->enabled)
> +			return -EBUSY;
> +
> +		vkms_config_connector_set_dynamic(connector_cfg, dynamic);
> +	}
>  
>  	return count;
>  }
> @@ -1302,6 +1406,8 @@ CONFIGFS_ATTR(connector_, type);
>  CONFIGFS_ATTR(connector_, supported_colorspaces);
>  CONFIGFS_ATTR(connector_, edid_enabled);
>  CONFIGFS_ATTR(connector_, edid);
> +CONFIGFS_ATTR(connector_, dynamic);
> +CONFIGFS_ATTR(connector_, enabled);
>  
>  static struct configfs_attribute *connector_item_attrs[] = {
>  	&connector_attr_status,
> @@ -1309,19 +1415,28 @@ static struct configfs_attribute *connector_item_attrs[] = {
>  	&connector_attr_supported_colorspaces,
>  	&connector_attr_edid_enabled,
>  	&connector_attr_edid,
> +	&connector_attr_dynamic,
> +	&connector_attr_enabled,
>  	NULL,
>  };
>  
>  static void connector_release(struct config_item *item)
>  {
>  	struct vkms_configfs_connector *connector;
> +	struct vkms_config_connector *connector_cfg;
>  	struct mutex *lock;
>  
>  	connector = connector_item_to_vkms_configfs_connector(item);
> +	connector_cfg = connector->config;
>  	lock = &connector->dev->lock;
>  
>  	scoped_guard(mutex, lock) {
> +		if (connector->dev->enabled && connector_cfg->dynamic && connector_cfg->enabled)
> +			vkms_connector_hot_remove(connector->dev->config->dev,
> +						  connector_cfg->connector);
> +
>  		vkms_config_destroy_connector(connector->config);
> +
>  		kfree(connector);
>  	}
>  }
> @@ -1340,6 +1455,7 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
>  						  struct config_item *target)
>  {
>  	struct vkms_configfs_connector *connector;
> +	struct vkms_config_connector *connector_cfg;
>  	struct vkms_configfs_encoder *encoder;
>  	int ret;
>  
> @@ -1347,16 +1463,25 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
>  		return -EINVAL;
>  
>  	connector = connector_possible_encoders_item_to_vkms_configfs_connector(src);
> +	connector_cfg = connector->config;
>  	encoder = encoder_item_to_vkms_configfs_encoder(target);
>  
>  	scoped_guard(mutex, &connector->dev->lock) {
> -		if (connector->dev->enabled)
> -			return -EBUSY;
> +		if (connector->dev->enabled && connector_cfg->enabled) {
> +			if (!connector_cfg->dynamic)
> +				return -EBUSY;
> +			ret = vkms_connector_hot_attach_encoder(connector->dev->config->dev,
> +								connector->config->connector,
> +								encoder->config->encoder);
> +			if (ret)
> +				return ret;
> +		}
>  
>  		ret = vkms_config_connector_attach_encoder(connector->config,
>  							   encoder->config);
> +		if (ret)
> +			return ret;
>  	}
> -
>  	return ret;
>  }
>  
> @@ -1394,9 +1519,6 @@ static struct config_group *make_connector_group(struct config_group *group,
>  	dev = child_group_to_vkms_configfs_device(group);
>  
>  	scoped_guard(mutex, &dev->lock) {
> -		if (dev->enabled)
> -			return ERR_PTR(-EBUSY);
> -
>  		connector = kzalloc(sizeof(*connector), GFP_KERNEL);
>  		if (!connector)
>  			return ERR_PTR(-ENOMEM);
> @@ -1409,9 +1531,11 @@ static struct config_group *make_connector_group(struct config_group *group,
>  			return ERR_CAST(connector->config);
>  		}
>  
> +		vkms_config_connector_set_dynamic(connector->config, connector->dev->enabled);
> +		vkms_config_connector_set_enabled(connector->config, !connector->dev->enabled);
> +
>  		config_group_init_type_name(&connector->group, name,
>  					    &connector_item_type);
> -
>  		config_group_init_type_name(&connector->possible_encoders_group,
>  					    "possible_encoders",
>  					    &connector_possible_encoders_group_type);
> 
> -- 
> 2.51.0
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 00/22] VKMS: Introduce multiple configFS attributes
  2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
                   ` (21 preceding siblings ...)
  2025-10-18  2:01 ` [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime Louis Chauvet
@ 2025-10-27 15:22 ` José Expósito
  2025-10-27 15:53   ` Louis Chauvet
  22 siblings, 1 reply; 48+ messages in thread
From: José Expósito @ 2025-10-27 15:22 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
Hey Louis,
On Sat, Oct 18, 2025 at 04:01:00AM +0200, Louis Chauvet wrote:
> VKMS have a wide range of options. The aim of this series is to introduce
> many configfs attribute so VKMS can be used to test a wide range of
> configurations.
> 
> This series depends on [1] that should be applied soon.
> 
> PATCH 1-13 are for configuring planes
> - name
> - rotation
> - color encoding
> - color range
> - plane formats
> - zpos
> PATCH 14-19 are for configuring the connector
> - type
> - supported colorspace
> - edid
> PATCH 20-22 are to enable dynamic connectors
> 
> [1]:https://lore.kernel.org/all/20251016175618.10051-1-jose.exposito89@gmail.com
> 
> PS: Each pair of config/configfs patch are independant. I could
> technically create ≈10 different series, but there will be a lot of
> (trivial) conflicts between them. I will be happy to reordoer, split and
> partially apply this series to help the review process.
I just finished reviewing the series.
Amazing work, thanks a lot for adding all of these new properties!!
I'd like to see KUnit and IGT coverage to test coner cases and, since this
is uAPI, to have a mechanishm to catch regressions without lots of manual
testing.
Let's talk so we can start working on them on v2, I'll be able to help in
that front if needed.
Best wishes,
Jose
 
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
> Louis Chauvet (22):
>       drm/vkms: Introduce config for plane name
>       drm/vkms: Introduce configfs for plane name
>       drm/vkms: Introduce config for plane rotation
>       drm/vkms: Introduce configfs for plane rotation
>       drm/vkms: Introduce config for plane color encoding
>       drm/vkms: Introduce configfs for plane color encoding
>       drm/vkms: Introduce config for plane color range
>       drm/vkms: Introduce configfs for plane color range
>       drm/vkms: Introduce config for plane format
>       drm/vkms: Introduce configfs for plane format
>       drm/vkms: Properly render plane using their zpos
>       drm/vkms: Introduce config for plane zpos property
>       drm/vkms: Introduce configfs for plane zpos property
>       drm/vkms: Introduce config for connector type
>       drm/vkms: Introduce configfs for connector type
>       drm/vkms: Introduce config for connector supported colorspace
>       drm/vkms: Introduce configfs for connector supported colorspace
>       drm/vkms: Introduce config for connector EDID
>       drm/vkms: Introduce configfs for connector EDID
>       drm/vkms: Store the enabled/disabled status for connector
>       drm/vkms: Allow to hot-add connectors
>       drm/vkms: Allows the creation of connector at runtime
> 
>  Documentation/gpu/vkms.rst                    |  42 +-
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c |  18 +
>  drivers/gpu/drm/vkms/vkms_config.c            | 183 ++++++
>  drivers/gpu/drm/vkms/vkms_config.h            | 524 +++++++++++++++
>  drivers/gpu/drm/vkms/vkms_configfs.c          | 893 +++++++++++++++++++++++++-
>  drivers/gpu/drm/vkms/vkms_connector.c         | 137 +++-
>  drivers/gpu/drm/vkms/vkms_connector.h         |  36 +-
>  drivers/gpu/drm/vkms/vkms_crtc.c              |  11 +-
>  drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
>  drivers/gpu/drm/vkms/vkms_output.c            |  19 +-
>  drivers/gpu/drm/vkms/vkms_plane.c             |  73 +--
>  11 files changed, 1865 insertions(+), 77 deletions(-)
> ---
> base-commit: b291e4f1a4951204ce858cd01801291d34962a33
> change-id: 20251017-vkms-all-config-bd0c2a01846f
> prerequisite-message-id: 20251016175618.10051-1-jose.exposito89@gmail.com
> prerequisite-patch-id: 74083a8806b1f26d9b4cd2a5107c756b971c4d11
> prerequisite-patch-id: f982390487699921b625b413e8460d67ca7a74c9
> prerequisite-patch-id: 0afca639e43c8fbfea2af1bc395e489efc8e1f10
> prerequisite-patch-id: 6285108b2fd90d30d15d4cb4fdddfef953fad51b
> prerequisite-patch-id: 2eacf5ad4f25f54a60958aa7a2df633d5642ce2f
> prerequisite-patch-id: 81e98ac3aeb3b6128098ab7bab56d3446a3a2705
> prerequisite-patch-id: 973f94c4edb4a5822c84a57d4479ca40e9cf25de
> prerequisite-patch-id: 0efbaf1b0e962a1c40bf5a744b5089d8be696f62
> prerequisite-patch-id: afa0cff94085e6ab216ffd9b99cd3dc882a0a687
> prerequisite-patch-id: 3561347f2b586392985a8e3af9ed1c5c7d3eefd5
> prerequisite-patch-id: 94030044ae8d404f7cdaed9137bddd59cfb22e79
> prerequisite-patch-id: a54b483797d5ffb7ce13b56a8943025181cd0d7a
> prerequisite-patch-id: f148fe7f445cb42437e7e2ba8b59e7e0fd40da8b
> prerequisite-patch-id: 1ef2045872843670c452816c5d6187b713c9258c
> prerequisite-patch-id: 3b9963ea3ae3455ae15ee36b67042c06a2ef6006
> prerequisite-patch-id: 519ee42dfabb4de734e41e59bd07d7a723d810bb
> 
> Best regards,
> -- 
> Louis Chauvet <louis.chauvet@bootlin.com>
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 00/22] VKMS: Introduce multiple configFS attributes
  2025-10-27 15:22 ` [PATCH 00/22] VKMS: Introduce multiple configFS attributes José Expósito
@ 2025-10-27 15:53   ` Louis Chauvet
  2025-10-28  7:32     ` José Expósito
  0 siblings, 1 reply; 48+ messages in thread
From: Louis Chauvet @ 2025-10-27 15:53 UTC (permalink / raw)
  To: José Expósito
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
Le 27/10/2025 à 16:22, José Expósito a écrit :
> Hey Louis,
> 
> On Sat, Oct 18, 2025 at 04:01:00AM +0200, Louis Chauvet wrote:
>> VKMS have a wide range of options. The aim of this series is to introduce
>> many configfs attribute so VKMS can be used to test a wide range of
>> configurations.
>>
>> This series depends on [1] that should be applied soon.
>>
>> PATCH 1-13 are for configuring planes
>> - name
>> - rotation
>> - color encoding
>> - color range
>> - plane formats
>> - zpos
>> PATCH 14-19 are for configuring the connector
>> - type
>> - supported colorspace
>> - edid
>> PATCH 20-22 are to enable dynamic connectors
>>
>> [1]:https://lore.kernel.org/all/20251016175618.10051-1-jose.exposito89@gmail.com
>>
>> PS: Each pair of config/configfs patch are independant. I could
>> technically create ≈10 different series, but there will be a lot of
>> (trivial) conflicts between them. I will be happy to reordoer, split and
>> partially apply this series to help the review process.
> 
> I just finished reviewing the series.
Thanks a lot, I started to apply your suggestions (I agree to most of them).
> Amazing work, thanks a lot for adding all of these new properties!!
> 
> I'd like to see KUnit and IGT coverage to test coner cases and, since this
> is uAPI, to have a mechanishm to catch regressions without lots of manual
> testing.
I started to add some Kunits for vkms_config.c, for the format parsing too.
> Let's talk so we can start working on them on v2, I'll be able to help in
> that front if needed.
I finish to apply your suggestions and I will send the v2 soon, so we 
can discuss on the same ground. I think we can add a little bit of 
vkms_config.c testing, but for vkms_configfs I need to see if we can 
mock configfs interations from kunit tests.
Have a nice week,
Louis Chauvet
> Best wishes,
> Jose
>   
>> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
>> ---
>> Louis Chauvet (22):
>>        drm/vkms: Introduce config for plane name
>>        drm/vkms: Introduce configfs for plane name
>>        drm/vkms: Introduce config for plane rotation
>>        drm/vkms: Introduce configfs for plane rotation
>>        drm/vkms: Introduce config for plane color encoding
>>        drm/vkms: Introduce configfs for plane color encoding
>>        drm/vkms: Introduce config for plane color range
>>        drm/vkms: Introduce configfs for plane color range
>>        drm/vkms: Introduce config for plane format
>>        drm/vkms: Introduce configfs for plane format
>>        drm/vkms: Properly render plane using their zpos
>>        drm/vkms: Introduce config for plane zpos property
>>        drm/vkms: Introduce configfs for plane zpos property
>>        drm/vkms: Introduce config for connector type
>>        drm/vkms: Introduce configfs for connector type
>>        drm/vkms: Introduce config for connector supported colorspace
>>        drm/vkms: Introduce configfs for connector supported colorspace
>>        drm/vkms: Introduce config for connector EDID
>>        drm/vkms: Introduce configfs for connector EDID
>>        drm/vkms: Store the enabled/disabled status for connector
>>        drm/vkms: Allow to hot-add connectors
>>        drm/vkms: Allows the creation of connector at runtime
>>
>>   Documentation/gpu/vkms.rst                    |  42 +-
>>   drivers/gpu/drm/vkms/tests/vkms_config_test.c |  18 +
>>   drivers/gpu/drm/vkms/vkms_config.c            | 183 ++++++
>>   drivers/gpu/drm/vkms/vkms_config.h            | 524 +++++++++++++++
>>   drivers/gpu/drm/vkms/vkms_configfs.c          | 893 +++++++++++++++++++++++++-
>>   drivers/gpu/drm/vkms/vkms_connector.c         | 137 +++-
>>   drivers/gpu/drm/vkms/vkms_connector.h         |  36 +-
>>   drivers/gpu/drm/vkms/vkms_crtc.c              |  11 +-
>>   drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
>>   drivers/gpu/drm/vkms/vkms_output.c            |  19 +-
>>   drivers/gpu/drm/vkms/vkms_plane.c             |  73 +--
>>   11 files changed, 1865 insertions(+), 77 deletions(-)
>> ---
>> base-commit: b291e4f1a4951204ce858cd01801291d34962a33
>> change-id: 20251017-vkms-all-config-bd0c2a01846f
>> prerequisite-message-id: 20251016175618.10051-1-jose.exposito89@gmail.com
>> prerequisite-patch-id: 74083a8806b1f26d9b4cd2a5107c756b971c4d11
>> prerequisite-patch-id: f982390487699921b625b413e8460d67ca7a74c9
>> prerequisite-patch-id: 0afca639e43c8fbfea2af1bc395e489efc8e1f10
>> prerequisite-patch-id: 6285108b2fd90d30d15d4cb4fdddfef953fad51b
>> prerequisite-patch-id: 2eacf5ad4f25f54a60958aa7a2df633d5642ce2f
>> prerequisite-patch-id: 81e98ac3aeb3b6128098ab7bab56d3446a3a2705
>> prerequisite-patch-id: 973f94c4edb4a5822c84a57d4479ca40e9cf25de
>> prerequisite-patch-id: 0efbaf1b0e962a1c40bf5a744b5089d8be696f62
>> prerequisite-patch-id: afa0cff94085e6ab216ffd9b99cd3dc882a0a687
>> prerequisite-patch-id: 3561347f2b586392985a8e3af9ed1c5c7d3eefd5
>> prerequisite-patch-id: 94030044ae8d404f7cdaed9137bddd59cfb22e79
>> prerequisite-patch-id: a54b483797d5ffb7ce13b56a8943025181cd0d7a
>> prerequisite-patch-id: f148fe7f445cb42437e7e2ba8b59e7e0fd40da8b
>> prerequisite-patch-id: 1ef2045872843670c452816c5d6187b713c9258c
>> prerequisite-patch-id: 3b9963ea3ae3455ae15ee36b67042c06a2ef6006
>> prerequisite-patch-id: 519ee42dfabb4de734e41e59bd07d7a723d810bb
>>
>> Best regards,
>> -- 
>> Louis Chauvet <louis.chauvet@bootlin.com>
>>
-- 
--
Louis Chauvet, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 19/22] drm/vkms: Introduce configfs for connector EDID
  2025-10-27 10:16   ` José Expósito
@ 2025-10-27 17:18     ` Louis Chauvet
  0 siblings, 0 replies; 48+ messages in thread
From: Louis Chauvet @ 2025-10-27 17:18 UTC (permalink / raw)
  To: José Expósito
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
Le 27/10/2025 à 11:16, José Expósito a écrit :
> On Sat, Oct 18, 2025 at 04:01:19AM +0200, Louis Chauvet wrote:
>> Introduce new attributes to configure EDID of a connector:
>> - edid_enable - chose if the connector will have an EDD or not
>> - edid - raw edid content
>>
>> Due to limitation of ConfigFS, the max len of EDID is PAGE_SIZE (4kB on
>> x86), it should be sufficient for many tests. One possible evolution is
>> using a ConfigFS blob to allow bigger EDID.
>>
>> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
>> ---
> 
> Hey Louis,
> 
> I wasn't able to set the EDID, could you provide an example?
Your usage is good, I expect it to work
But I forgot one very important call, probably lost during my multiple 
rebases: drm_connector_attach_edid_property
But you also need to call modetest to properly refresh the EDID property 
(I don't know exactly how it works, but if I don't call modetest first, 
drm_info does not see the EDID)
> This is what I tried:
> 
> # I'm using QEMU's EDID:
> $ cat /sys/class/drm/card0-Virtual-1/edid > qemu-edid.bin
> 
> # Create a simple device:
> $ sudo mkdir /sys/kernel/config/vkms/gpu1 && \
> sudo mkdir /sys/kernel/config/vkms/gpu1/planes/plane0  && \
> echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/planes/plane0/type && \
> sudo mkdir /sys/kernel/config/vkms/gpu1/crtcs/crtc0 && \
> echo "0" | sudo tee /sys/kernel/config/vkms/gpu1/crtcs/crtc0/writeback && \
> sudo mkdir /sys/kernel/config/vkms/gpu1/encoders/encoder0 && \
> sudo mkdir /sys/kernel/config/vkms/gpu1/connectors/connector0 && \
> sudo ln -s /sys/kernel/config/vkms/gpu1/crtcs/crtc0 /sys/kernel/config/vkms/gpu1/planes/plane0/possible_crtcs && \
> sudo ln -s /sys/kernel/config/vkms/gpu1/crtcs/crtc0 /sys/kernel/config/vkms/gpu1/encoders/encoder0/possible_crtcs && \
> sudo ln -s /sys/kernel/config/vkms/gpu1/encoders/encoder0 /sys/kernel/config/vkms/gpu1/connectors/connector0/possible_encoders
> 
> $ cat qemu-edid.bin | sudo tee /sys/kernel/config/vkms/gpu1/connectors/connector0/edid
> 
> # The EDID is stored and it is correct:
> $ cat /sys/kernel/config/vkms/gpu1/connectors/connector0/edid | edid-decode
> 
> $ echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/connectors/connector0/edid_enabled
> $ echo "1" | sudo tee /sys/kernel/config/vkms/gpu1/enabled
> 
> # After enabling the device, the EDID is not present:
> $ cat /sys/class/drm/card1-Virtual-2/edid
> <empty>
> 
> And drm_info does not show the EDID property.
> 
> Am I missing something?
> 
>>   Documentation/gpu/vkms.rst           |  5 ++-
>>   drivers/gpu/drm/vkms/vkms_configfs.c | 81 +++++++++++++++++++++++++++++++++++-
>>   2 files changed, 84 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
>> index 650d6f6e79fd..bbd03f61e61c 100644
>> --- a/Documentation/gpu/vkms.rst
>> +++ b/Documentation/gpu/vkms.rst
>> @@ -135,7 +135,7 @@ Last but not least, create one or more connectors::
>>   
>>     sudo mkdir /config/vkms/my-vkms/connectors/connector0
>>   
>> -Connectors have 3 configurable attribute:
>> +Connectors have 5 configurable attribute:
>>   
>>   - status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
>>     as those exposed by the "status" property of a connector)
>> @@ -144,6 +144,9 @@ Connectors have 3 configurable attribute:
>>     If supported_colorspaces is not 0, the HDR_OUTPUT_METADATA will also be created.
>>     Value is a bitfield, 0x1 = NO_DATA, 0x2 = SMPTE_170M_YCC... see enum drm_colorspace
>>     for full list.
>> +- edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
>> +  EDID but just a list of modes, this attribute allows to disable EDID property.
>> +- edid: Content of the EDID. Ignored if edid_enabled is not set
>>   
>>   
>>   To finish the configuration, link the different pipeline items::
>> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
>> index 909f4557caec..a977c0842cd6 100644
>> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
>> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
>> @@ -1,5 +1,4 @@
>>   // SPDX-License-Identifier: GPL-2.0+
>> -#include "asm-generic/errno-base.h"
>>   #include <linux/cleanup.h>
>>   #include <linux/configfs.h>
>>   #include <linux/mutex.h>
>> @@ -1222,14 +1221,94 @@ static ssize_t connector_supported_colorspaces_store(struct config_item *item,
>>   	return count;
>>   }
>>   
>> +static ssize_t connector_edid_enabled_show(struct config_item *item, char *page)
>> +{
>> +	struct vkms_configfs_connector *connector;
>> +	bool enabled;
>> +
>> +	connector = connector_item_to_vkms_configfs_connector(item);
>> +
>> +	scoped_guard(mutex, &connector->dev->lock)
>> +		enabled = vkms_config_connector_get_edid_enabled(connector->config);
>> +
>> +	return sprintf(page, "%d\n", enabled);
>> +}
>> +
>> +static ssize_t connector_edid_enabled_store(struct config_item *item,
>> +					    const char *page, size_t count)
>> +{
>> +	struct vkms_configfs_connector *connector;
>> +	struct vkms_config_connector *connector_cfg;
>> +	bool enabled;
>> +
>> +	connector = connector_item_to_vkms_configfs_connector(item);
>> +	connector_cfg = connector->config;
>> +
>> +	if (kstrtobool(page, &enabled))
>> +		return -EINVAL;
>> +
>> +	scoped_guard(mutex, &connector->dev->lock)
>> +	{
>> +		vkms_config_connector_set_edid_enabled(connector_cfg, enabled);
>> +
>> +		if (connector->dev->enabled &&
>> +		    vkms_config_connector_get_status(connector_cfg) !=
>> +		    connector_status_disconnected)
>> +			vkms_trigger_connector_hotplug(connector->dev->config->dev);
>> +	}
>> +	return count;
>> +}
>> +
>> +static ssize_t connector_edid_show(struct config_item *item, char *page)
>> +{
>> +	struct vkms_configfs_connector *connector;
>> +
>> +	connector = connector_item_to_vkms_configfs_connector(item);
>> +
>> +	scoped_guard(mutex, &connector->dev->lock)
>> +	{
>> +		unsigned int len = 0;
>> +		const u8 *edid = vkms_config_connector_get_edid(connector->config, &len);
>> +
>> +		memcpy(page, edid, min(len, PAGE_SIZE));
>> +		return min(len, PAGE_SIZE);
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static ssize_t connector_edid_store(struct config_item *item,
>> +				    const char *page, size_t count)
>> +{
>> +	struct vkms_configfs_connector *connector;
>> +
>> +	connector = connector_item_to_vkms_configfs_connector(item);
>> +
>> +	scoped_guard(mutex, &connector->dev->lock)
>> +	{
>> +		vkms_config_connector_set_edid(connector->config, page, count);
>> +
>> +		if (connector->dev->enabled &&
>> +		    vkms_config_connector_get_status(connector->config) !=
>> +		    connector_status_disconnected)
>> +			vkms_trigger_connector_hotplug(connector->dev->config->dev);
>> +	}
>> +
>> +	return count;
>> +}
>> +
>>   CONFIGFS_ATTR(connector_, status);
>>   CONFIGFS_ATTR(connector_, type);
>>   CONFIGFS_ATTR(connector_, supported_colorspaces);
>> +CONFIGFS_ATTR(connector_, edid_enabled);
>> +CONFIGFS_ATTR(connector_, edid);
>>   
>>   static struct configfs_attribute *connector_item_attrs[] = {
>>   	&connector_attr_status,
>>   	&connector_attr_type,
>>   	&connector_attr_supported_colorspaces,
>> +	&connector_attr_edid_enabled,
>> +	&connector_attr_edid,
>>   	NULL,
>>   };
>>   
>>
>> -- 
>> 2.51.0
>>
-- 
--
Louis Chauvet, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH 00/22] VKMS: Introduce multiple configFS attributes
  2025-10-27 15:53   ` Louis Chauvet
@ 2025-10-28  7:32     ` José Expósito
  0 siblings, 0 replies; 48+ messages in thread
From: José Expósito @ 2025-10-28  7:32 UTC (permalink / raw)
  To: Louis Chauvet
  Cc: Haneen Mohammed, Simona Vetter, Melissa Wen, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Jonathan Corbet,
	victoria, sebastian.wick, thomas.petazzoni, dri-devel,
	linux-kernel, linux-doc
On Mon, Oct 27, 2025 at 04:53:03PM +0100, Louis Chauvet wrote:
> 
> 
> Le 27/10/2025 à 16:22, José Expósito a écrit :
> > Hey Louis,
> > 
> > On Sat, Oct 18, 2025 at 04:01:00AM +0200, Louis Chauvet wrote:
> > > VKMS have a wide range of options. The aim of this series is to introduce
> > > many configfs attribute so VKMS can be used to test a wide range of
> > > configurations.
> > > 
> > > This series depends on [1] that should be applied soon.
> > > 
> > > PATCH 1-13 are for configuring planes
> > > - name
> > > - rotation
> > > - color encoding
> > > - color range
> > > - plane formats
> > > - zpos
> > > PATCH 14-19 are for configuring the connector
> > > - type
> > > - supported colorspace
> > > - edid
> > > PATCH 20-22 are to enable dynamic connectors
> > > 
> > > [1]:https://lore.kernel.org/all/20251016175618.10051-1-jose.exposito89@gmail.com
> > > 
> > > PS: Each pair of config/configfs patch are independant. I could
> > > technically create ≈10 different series, but there will be a lot of
> > > (trivial) conflicts between them. I will be happy to reordoer, split and
> > > partially apply this series to help the review process.
> > 
> > I just finished reviewing the series.
> 
> Thanks a lot, I started to apply your suggestions (I agree to most of them).
> 
> > Amazing work, thanks a lot for adding all of these new properties!!
> > 
> > I'd like to see KUnit and IGT coverage to test coner cases and, since this
> > is uAPI, to have a mechanishm to catch regressions without lots of manual
> > testing.
> 
> I started to add some Kunits for vkms_config.c, for the format parsing too.
> 
> > Let's talk so we can start working on them on v2, I'll be able to help in
> > that front if needed.
> 
> I finish to apply your suggestions and I will send the v2 soon, so we can
> discuss on the same ground. I think we can add a little bit of vkms_config.c
> testing, but for vkms_configfs I need to see if we can mock configfs
> interations from kunit tests.
For vkms_configfs I find more convinient IGT than mocking in KUnit.
It saves maintaining a bunch of mocking code and it is a good way to
test end-to-end VKMS.
Jose
> Have a nice week,
> Louis Chauvet
> 
> > Best wishes,
> > Jose
> > > Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> > > ---
> > > Louis Chauvet (22):
> > >        drm/vkms: Introduce config for plane name
> > >        drm/vkms: Introduce configfs for plane name
> > >        drm/vkms: Introduce config for plane rotation
> > >        drm/vkms: Introduce configfs for plane rotation
> > >        drm/vkms: Introduce config for plane color encoding
> > >        drm/vkms: Introduce configfs for plane color encoding
> > >        drm/vkms: Introduce config for plane color range
> > >        drm/vkms: Introduce configfs for plane color range
> > >        drm/vkms: Introduce config for plane format
> > >        drm/vkms: Introduce configfs for plane format
> > >        drm/vkms: Properly render plane using their zpos
> > >        drm/vkms: Introduce config for plane zpos property
> > >        drm/vkms: Introduce configfs for plane zpos property
> > >        drm/vkms: Introduce config for connector type
> > >        drm/vkms: Introduce configfs for connector type
> > >        drm/vkms: Introduce config for connector supported colorspace
> > >        drm/vkms: Introduce configfs for connector supported colorspace
> > >        drm/vkms: Introduce config for connector EDID
> > >        drm/vkms: Introduce configfs for connector EDID
> > >        drm/vkms: Store the enabled/disabled status for connector
> > >        drm/vkms: Allow to hot-add connectors
> > >        drm/vkms: Allows the creation of connector at runtime
> > > 
> > >   Documentation/gpu/vkms.rst                    |  42 +-
> > >   drivers/gpu/drm/vkms/tests/vkms_config_test.c |  18 +
> > >   drivers/gpu/drm/vkms/vkms_config.c            | 183 ++++++
> > >   drivers/gpu/drm/vkms/vkms_config.h            | 524 +++++++++++++++
> > >   drivers/gpu/drm/vkms/vkms_configfs.c          | 893 +++++++++++++++++++++++++-
> > >   drivers/gpu/drm/vkms/vkms_connector.c         | 137 +++-
> > >   drivers/gpu/drm/vkms/vkms_connector.h         |  36 +-
> > >   drivers/gpu/drm/vkms/vkms_crtc.c              |  11 +-
> > >   drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
> > >   drivers/gpu/drm/vkms/vkms_output.c            |  19 +-
> > >   drivers/gpu/drm/vkms/vkms_plane.c             |  73 +--
> > >   11 files changed, 1865 insertions(+), 77 deletions(-)
> > > ---
> > > base-commit: b291e4f1a4951204ce858cd01801291d34962a33
> > > change-id: 20251017-vkms-all-config-bd0c2a01846f
> > > prerequisite-message-id: 20251016175618.10051-1-jose.exposito89@gmail.com
> > > prerequisite-patch-id: 74083a8806b1f26d9b4cd2a5107c756b971c4d11
> > > prerequisite-patch-id: f982390487699921b625b413e8460d67ca7a74c9
> > > prerequisite-patch-id: 0afca639e43c8fbfea2af1bc395e489efc8e1f10
> > > prerequisite-patch-id: 6285108b2fd90d30d15d4cb4fdddfef953fad51b
> > > prerequisite-patch-id: 2eacf5ad4f25f54a60958aa7a2df633d5642ce2f
> > > prerequisite-patch-id: 81e98ac3aeb3b6128098ab7bab56d3446a3a2705
> > > prerequisite-patch-id: 973f94c4edb4a5822c84a57d4479ca40e9cf25de
> > > prerequisite-patch-id: 0efbaf1b0e962a1c40bf5a744b5089d8be696f62
> > > prerequisite-patch-id: afa0cff94085e6ab216ffd9b99cd3dc882a0a687
> > > prerequisite-patch-id: 3561347f2b586392985a8e3af9ed1c5c7d3eefd5
> > > prerequisite-patch-id: 94030044ae8d404f7cdaed9137bddd59cfb22e79
> > > prerequisite-patch-id: a54b483797d5ffb7ce13b56a8943025181cd0d7a
> > > prerequisite-patch-id: f148fe7f445cb42437e7e2ba8b59e7e0fd40da8b
> > > prerequisite-patch-id: 1ef2045872843670c452816c5d6187b713c9258c
> > > prerequisite-patch-id: 3b9963ea3ae3455ae15ee36b67042c06a2ef6006
> > > prerequisite-patch-id: 519ee42dfabb4de734e41e59bd07d7a723d810bb
> > > 
> > > Best regards,
> > > -- 
> > > Louis Chauvet <louis.chauvet@bootlin.com>
> > > 
> 
> -- 
> --
> Louis Chauvet, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 
^ permalink raw reply	[flat|nested] 48+ messages in thread
end of thread, other threads:[~2025-10-28  7:32 UTC | newest]
Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-18  2:01 [PATCH 00/22] VKMS: Introduce multiple configFS attributes Louis Chauvet
2025-10-18  2:01 ` [PATCH 01/22] drm/vkms: Introduce config for plane name Louis Chauvet
2025-10-24 11:16   ` José Expósito
2025-10-27 10:15   ` Jani Nikula
2025-10-18  2:01 ` [PATCH 02/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-24 11:20   ` José Expósito
2025-10-18  2:01 ` [PATCH 03/22] drm/vkms: Introduce config for plane rotation Louis Chauvet
2025-10-24 11:53   ` José Expósito
2025-10-18  2:01 ` [PATCH 04/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-24 14:50   ` José Expósito
2025-10-18  2:01 ` [PATCH 05/22] drm/vkms: Introduce config for plane color encoding Louis Chauvet
2025-10-24 15:14   ` José Expósito
2025-10-18  2:01 ` [PATCH 06/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-24 15:16   ` José Expósito
2025-10-18  2:01 ` [PATCH 07/22] drm/vkms: Introduce config for plane color range Louis Chauvet
2025-10-24 15:25   ` José Expósito
2025-10-18  2:01 ` [PATCH 08/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-24 15:27   ` José Expósito
2025-10-18  2:01 ` [PATCH 09/22] drm/vkms: Introduce config for plane format Louis Chauvet
2025-10-24 15:44   ` José Expósito
2025-10-18  2:01 ` [PATCH 10/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-27  8:55   ` José Expósito
2025-10-18  2:01 ` [PATCH 11/22] drm/vkms: Properly render plane using their zpos Louis Chauvet
2025-10-18  2:01 ` [PATCH 12/22] drm/vkms: Introduce config for plane zpos property Louis Chauvet
2025-10-27  9:12   ` José Expósito
2025-10-18  2:01 ` [PATCH 13/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-27  9:19   ` José Expósito
2025-10-18  2:01 ` [PATCH 14/22] drm/vkms: Introduce config for connector type Louis Chauvet
2025-10-27  9:27   ` José Expósito
2025-10-18  2:01 ` [PATCH 15/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-18  2:01 ` [PATCH 16/22] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
2025-10-27  9:35   ` José Expósito
2025-10-27  9:38   ` José Expósito
2025-10-18  2:01 ` [PATCH 17/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-18  2:01 ` [PATCH 18/22] drm/vkms: Introduce config for connector EDID Louis Chauvet
2025-10-27 10:02   ` José Expósito
2025-10-18  2:01 ` [PATCH 19/22] drm/vkms: Introduce configfs " Louis Chauvet
2025-10-27 10:16   ` José Expósito
2025-10-27 17:18     ` Louis Chauvet
2025-10-18  2:01 ` [PATCH 20/22] drm/vkms: Store the enabled/disabled status for connector Louis Chauvet
2025-10-27 14:52   ` José Expósito
2025-10-18  2:01 ` [PATCH 21/22] drm/vkms: Allow to hot-add connectors Louis Chauvet
2025-10-27 15:01   ` José Expósito
2025-10-18  2:01 ` [PATCH 22/22] drm/vkms: Allows the creation of connector at runtime Louis Chauvet
2025-10-27 15:17   ` José Expósito
2025-10-27 15:22 ` [PATCH 00/22] VKMS: Introduce multiple configFS attributes José Expósito
2025-10-27 15:53   ` Louis Chauvet
2025-10-28  7:32     ` José Expósito
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).