@@ -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;
@@ -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
@@ -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;
@@ -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);
Signed-off-by: Louis Chauvet <louis.chauvet@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(-)