Signed-off-by: Louis Chauvet <louis.chau...@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 62 +++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_config.h | 18 +++++++++--
 drivers/gpu/drm/vkms/vkms_drv.c    |  2 +-
 drivers/gpu/drm/vkms/vkms_output.c | 37 ++++++++++++-----------
 4 files changed, 98 insertions(+), 21 deletions(-)

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

-- 
2.47.0

Reply via email to