[PATCH RFC 06/15] drm/vkms: Introduce plane configuration
Louis Chauvet
louis.chauvet at bootlin.com
Wed Aug 14 14:36:28 UTC 2024
The current vkms driver only allows the usage of one primary, eight
overlays and one cursor plane. This new configuration structure aims to
make the configuration more flexible.
Signed-off-by: Louis Chauvet <louis.chauvet at bootlin.com>
---
drivers/gpu/drm/vkms/vkms_config.c | 90 ++++++++++++++++++++++++++++++++++++--
drivers/gpu/drm/vkms/vkms_config.h | 44 +++++++++++++++++--
drivers/gpu/drm/vkms/vkms_drv.c | 33 +++++---------
drivers/gpu/drm/vkms/vkms_plane.c | 4 +-
drivers/gpu/drm/vkms/vkms_plane.h | 3 +-
5 files changed, 141 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 27b49a2ad9c8..b1c6160d350f 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -13,32 +13,111 @@ struct vkms_config *vkms_config_create(void)
if (!config)
return ERR_PTR(-ENOMEM);
+ INIT_LIST_HEAD(&config->planes);
+
return config;
}
struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable_overlay,
bool enable_cursor)
{
+ struct vkms_config_plane *plane;
struct vkms_config *vkms_config = vkms_config_create();
if (IS_ERR(vkms_config))
return vkms_config;
vkms_config->writeback = enable_writeback;
- vkms_config->overlay = enable_overlay;
- vkms_config->cursor = enable_cursor;
+
+ plane = vkms_config_create_plane(vkms_config);
+ if (!plane)
+ goto err_alloc;
+
+ plane->type = DRM_PLANE_TYPE_PRIMARY;
+
+ if (enable_overlay) {
+ for (int i = 0; i < NUM_OVERLAY_PLANES; i++) {
+ plane = vkms_config_create_plane(vkms_config);
+ if (!plane)
+ goto err_alloc;
+ plane->type = DRM_PLANE_TYPE_OVERLAY;
+ }
+ }
+ if (enable_cursor) {
+ plane = vkms_config_create_plane(vkms_config);
+ if (!plane)
+ goto err_alloc;
+ plane->type = DRM_PLANE_TYPE_CURSOR;
+ }
return vkms_config;
+err_alloc:
+ vkms_config_destroy(vkms_config);
+ return ERR_PTR(-ENOMEM);
}
+struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_config)
+{
+ if (!vkms_config)
+ return NULL;
+
+ struct vkms_config_plane *vkms_config_overlay = kzalloc(sizeof(*vkms_config_overlay),
+ GFP_KERNEL);
+
+ if (!vkms_config_overlay)
+ return NULL;
+
+ vkms_config_overlay->type = DRM_PLANE_TYPE_OVERLAY;
+
+ list_add(&vkms_config_overlay->link, &vkms_config->planes);
+
+ return vkms_config_overlay;
+}
+
+void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_overlay)
+{
+ if (!vkms_config_overlay)
+ return;
+ list_del(&vkms_config_overlay->link);
+ kfree(vkms_config_overlay);
+}
void vkms_config_destroy(struct vkms_config *config)
{
+ struct vkms_config_plane *vkms_config_plane, *tmp_plane;
+
+ list_for_each_entry_safe(vkms_config_plane, tmp_plane, &config->planes, link) {
+ vkms_config_delete_plane(vkms_config_plane);
+ }
+
kfree(config);
}
bool vkms_config_is_valid(struct vkms_config *config)
{
+ struct vkms_config_plane *config_plane;
+
+ bool has_cursor = false;
+ bool has_primary = false;
+
+ list_for_each_entry(config_plane, &config->planes, link) {
+ if (config_plane->type == DRM_PLANE_TYPE_PRIMARY) {
+ // Multiple primary planes for only one CRTC
+ if (has_primary)
+ return false;
+ has_primary = true;
+ }
+ if (config_plane->type == DRM_PLANE_TYPE_CURSOR) {
+ // Multiple cursor planes for only one CRTC
+ if (has_cursor)
+ return false;
+ has_cursor = true;
+ }
+ }
+
+ if (!has_primary)
+ return false;
+
return true;
}
@@ -47,10 +126,13 @@ static int vkms_config_show(struct seq_file *m, void *data)
struct drm_debugfs_entry *entry = m->private;
struct drm_device *dev = entry->dev;
struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
+ struct vkms_config_plane *config_plane;
seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback);
- seq_printf(m, "cursor=%d\n", vkmsdev->config->cursor);
- seq_printf(m, "overlay=%d\n", vkmsdev->config->overlay);
+ list_for_each_entry(config_plane, &vkmsdev->config->planes, link) {
+ seq_puts(m, "plane:\n");
+ seq_printf(m, "\ttype: %d\n", config_plane->type);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 50c3b021a66b..77c1c3934189 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -10,15 +10,34 @@
* struct vkms_config - General configuration for VKMS driver
*
* @writeback: If true, a writeback buffer can be attached to the CRTC
- * @cursor: If true, a cursor plane is created in the VKMS device
- * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS device
+ * @planes: List of planes configured for this device. They are created by the function
+ * vkms_config_create_plane().
* @dev: Used to store the current vkms device. Only set when the device is instancied.
*/
struct vkms_config {
bool writeback;
- bool cursor;
- bool overlay;
struct vkms_device *dev;
+
+ struct list_head planes;
+};
+
+/**
+ * struct vkms_config_plane
+ *
+ * @link: Link to the others planes
+ * @type: Type of the plane. The creator of configuration needs to ensures that at least one
+ * plane is primary.
+ * @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 must be managed by other means.
+ */
+struct vkms_config_plane {
+ struct list_head link;
+
+ enum drm_plane_type type;
+
+ /* Internal usage */
+ struct vkms_plane *plane;
};
/**
@@ -42,6 +61,23 @@ void vkms_config_destroy(struct vkms_config *config);
*/
bool vkms_config_is_valid(struct vkms_config *vkms_config);
+/**
+ * vkms_config_create_plane() - Create a plane configuration
+ *
+ * This will allocate and add a new plane to @vkms_config. This plane will have by default the
+ * maximum supported values.
+ * @vkms_config: Configuration where to insert new plane
+ */
+struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_config);
+
+/**
+ * vkms_config_delete_plane() - Remove a plane configuration and frees its memory
+ *
+ * This will delete a plane configuration from the parent configuration. This will NOT
+ * cleanup and frees the vkms_plane that can be stored in @vkms_config_plane.
+ * @vkms_config_plane: Plane configuration to cleanup
+ */
+void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane);
/**
* vkms_config_alloc_default() - Allocate the configuration for the default device
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index af237daa3c5c..403006a0bb61 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -153,38 +153,27 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
static int vkms_output_init(struct vkms_device *vkmsdev)
{
+ struct vkms_config_plane *config_plane;
struct drm_device *dev = &vkmsdev->drm;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct vkms_crtc *crtc;
struct drm_plane *plane;
- struct vkms_plane *primary, *cursor, *overlay = NULL;
+ struct vkms_plane *primary, *cursor = NULL;
int ret;
int writeback;
- unsigned int n;
- /*
- * Initialize used plane. One primary plane is required to perform the composition.
- *
- * The overlay and cursor planes are not mandatory, but can be used to perform complex
- * composition.
- */
- primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY);
- if (IS_ERR(primary))
- return PTR_ERR(primary);
-
- if (vkmsdev->config->overlay) {
- for (n = 0; n < NUM_OVERLAY_PLANES; n++) {
- overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY);
- if (IS_ERR(overlay))
- return PTR_ERR(overlay);
+ list_for_each_entry(config_plane, &vkmsdev->config->planes, link) {
+ config_plane->plane = vkms_plane_init(vkmsdev, config_plane);
+ if (IS_ERR(config_plane->plane)) {
+ ret = PTR_ERR(config_plane->plane);
+ return ret;
}
- }
- if (vkmsdev->config->cursor) {
- cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR);
- if (IS_ERR(cursor))
- return PTR_ERR(cursor);
+ if (config_plane->type == DRM_PLANE_TYPE_PRIMARY)
+ primary = config_plane->plane;
+ else if (config_plane->type == DRM_PLANE_TYPE_CURSOR)
+ cursor = config_plane->plane;
}
/* [1]: Initialize the crtc component */
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index b5740c27180b..dc9bccf60071 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -223,7 +223,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;
@@ -231,7 +231,7 @@ 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, config->type, NULL);
if (IS_ERR(plane))
return plane;
diff --git a/drivers/gpu/drm/vkms/vkms_plane.h b/drivers/gpu/drm/vkms/vkms_plane.h
index 95b2428331b8..82049966ee7e 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.h
+++ b/drivers/gpu/drm/vkms/vkms_plane.h
@@ -9,6 +9,7 @@
#include <linux/iosys-map.h>
#include "vkms_formats.h"
+#include "vkms_config.h"
struct vkms_plane {
struct drm_plane base;
@@ -54,7 +55,7 @@ struct vkms_frame_info {
* @type: type of plane to initialize
*/
struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
- enum drm_plane_type type);
+ struct vkms_config_plane *config);
#define drm_plane_state_to_vkms_plane_state(target) \
container_of(target, struct vkms_plane_state, base.base)
--
2.44.2
More information about the dri-devel
mailing list