Signed-off-by: Louis Chauvet <louis.chau...@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 105 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_config.h |  19 +++++++
 drivers/gpu/drm/vkms/vkms_plane.c  |  43 ++-------------
 3 files changed, 127 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_config.c 
b/drivers/gpu/drm/vkms/vkms_config.c
index 
c3334d3d808e5fc8cd6d855e9e1395f94f157ffb..4726929c2b54b2e670f9ef53b05ec009ca495e08
 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -6,6 +6,44 @@
 #include "vkms_config.h"
 #include "vkms_drv.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_RGBX8888,
+       DRM_FORMAT_BGRX8888,
+       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(void)
 {
        struct vkms_config *config;
@@ -120,6 +158,13 @@ struct vkms_config_plane *vkms_config_create_plane(struct 
vkms_config *vkms_conf
        if (!vkms_config_overlay)
                return NULL;
 
+       vkms_config_overlay->supported_formats = NULL;
+
+       if (vkms_config_plane_add_all_formats(vkms_config_overlay)) {
+               kfree(vkms_config_overlay);
+               return NULL;
+       }
+
        vkms_config_overlay->type = DRM_PLANE_TYPE_OVERLAY;
        vkms_config_overlay->supported_rotations = DRM_MODE_ROTATE_MASK | 
DRM_MODE_REFLECT_MASK;
        vkms_config_overlay->default_rotation = DRM_MODE_ROTATE_0;
@@ -193,6 +238,65 @@ struct vkms_config_encoder 
*vkms_config_create_encoder(struct vkms_config *vkms_
 }
 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder);
 
+int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane 
*vkms_config_plane)
+{
+       u32 *ret = krealloc_array(vkms_config_plane->supported_formats,
+                                 ARRAY_SIZE(vkms_supported_plane_formats),
+                                 sizeof(uint32_t), GFP_KERNEL);
+       if (!ret)
+               return -ENOMEM;
+       vkms_config_plane->supported_formats = ret;
+
+       memcpy(vkms_config_plane->supported_formats, 
vkms_supported_plane_formats,
+              sizeof(vkms_supported_plane_formats));
+       vkms_config_plane->supported_formats_count = 
ARRAY_SIZE(vkms_supported_plane_formats);
+       return 0;
+}
+
+int __must_check vkms_config_plane_add_format(struct vkms_config_plane 
*vkms_config_plane,
+                                             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 < 
vkms_config_plane->supported_formats_count; i++) {
+               if (vkms_config_plane->supported_formats[i] == drm_format)
+                       return 0;
+       }
+       u32 *new_ptr = krealloc_array(vkms_config_plane->supported_formats,
+                                     
vkms_config_plane->supported_formats_count + 1,
+                                     
sizeof(*vkms_config_plane->supported_formats), GFP_KERNEL);
+       if (!new_ptr)
+               return -ENOMEM;
+
+       vkms_config_plane->supported_formats = new_ptr;
+       
vkms_config_plane->supported_formats[vkms_config_plane->supported_formats_count]
 = drm_format;
+       vkms_config_plane->supported_formats_count++;
+
+       return 0;
+}
+
+void vkms_config_plane_remove_all_formats(struct vkms_config_plane 
*vkms_config_plane)
+{
+       vkms_config_plane->supported_formats_count = 0;
+}
+
+void vkms_config_plane_remove_format(struct vkms_config_plane 
*vkms_config_plane, u32 drm_format)
+{
+       for (unsigned int i = 0; i < 
vkms_config_plane->supported_formats_count; i++) {
+               if (vkms_config_plane->supported_formats[i] == drm_format) {
+                       vkms_config_plane->supported_formats[i] = 
vkms_config_plane->supported_formats[vkms_config_plane->supported_formats_count 
- 1];
+                       vkms_config_plane->supported_formats_count--;
+               }
+       }
+}
+
 void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane,
                              struct vkms_config *vkms_config)
 {
@@ -213,6 +317,7 @@ void vkms_config_delete_plane(struct vkms_config_plane 
*vkms_config_plane,
                }
        }
 
+       kfree(vkms_config_plane->supported_formats);
        kfree(vkms_config_plane->name);
        kfree(vkms_config_plane);
 }
diff --git a/drivers/gpu/drm/vkms/vkms_config.h 
b/drivers/gpu/drm/vkms/vkms_config.h
index 
c44bcafc3b34e1997f29631fda42af05e1c0c2ba..5487e0140da0e111c36f9a22d4e783a20c880a1d
 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -98,6 +98,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 */
@@ -144,6 +146,23 @@ bool vkms_config_is_valid(struct vkms_config *vkms_config);
  */
 struct vkms_config_plane *vkms_config_create_plane(struct vkms_config 
*vkms_config);
 
+/** 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.
+ *
+ * @vkms_config_plane: 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 
*vkms_config_plane,
+                                             u32 drm_format);
+int __must_check vkms_config_plane_add_all_formats(struct vkms_config_plane 
*vkms_config_plane);
+void vkms_config_plane_remove_format(struct vkms_config_plane 
*vkms_config_plane, u32 drm_format);
+void vkms_config_plane_remove_all_formats(struct vkms_config_plane 
*vkms_config_plane);
+
 struct vkms_config_connector *vkms_config_create_connector(struct vkms_config 
*vkms_config);
 
 /**
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c 
b/drivers/gpu/drm/vkms/vkms_plane.c
index 
90a5946481e47ab7cff9b9dc4942720b6bbcbe3f..b858c8ba00d97e461d70b5cc274ab4e7a3e1bb78
 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -13,44 +13,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_RGBX8888,
-       DRM_FORMAT_BGRX8888,
-       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)
 {
@@ -227,8 +189,9 @@ 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, config->type, config->name);
+                                          config->supported_formats,
+                                          config->supported_formats_count, 
NULL, config->type,
+                                          config->name);
        if (IS_ERR(plane))
                return plane;
 

-- 
2.47.0

Reply via email to