diff options
| author | José Expósito <jose.exposito89@gmail.com> | 2025-02-18 11:12:12 +0100 |
|---|---|---|
| committer | Maxime Ripard <mripard@kernel.org> | 2025-03-07 10:58:27 +0100 |
| commit | b8776fc9b2863c55193f66e1146a89bbccd2b4e0 (patch) | |
| tree | 2a284cacc72ca3908ead06a92214bc8da589746f /drivers/gpu/drm/vkms/vkms_config.c | |
| parent | drm/vkms: Allow to configure multiple encoders (diff) | |
| download | linux-b8776fc9b2863c55193f66e1146a89bbccd2b4e0.tar.gz linux-b8776fc9b2863c55193f66e1146a89bbccd2b4e0.zip | |
drm/vkms: Allow to attach encoders and CRTCs
Add a list of possible CRTCs to the encoder configuration and helpers to
attach and detach them.
Now that the default configuration has its encoder and CRTC correctly
attached, configure the output following the configuration.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Co-developed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250218101214.5790-13-jose.exposito89@gmail.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/vkms/vkms_config.c')
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_config.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c index db8be054f6f4..17262a9c2567 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -86,6 +86,9 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor, if (IS_ERR(encoder_cfg)) goto err_alloc; + if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg)) + goto err_alloc; + return config; err_alloc: @@ -216,6 +219,42 @@ static bool valid_encoder_number(const struct vkms_config *config) return true; } +static bool valid_encoder_possible_crtcs(const struct vkms_config *config) +{ + struct drm_device *dev = config->dev ? &config->dev->drm : NULL; + struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; + + vkms_config_for_each_encoder(config, encoder_cfg) { + if (xa_empty(&encoder_cfg->possible_crtcs)) { + drm_info(dev, "All encoders must have at least one possible CRTC\n"); + return false; + } + } + + vkms_config_for_each_crtc(config, crtc_cfg) { + bool crtc_has_encoder = false; + + vkms_config_for_each_encoder(config, encoder_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx = 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, + idx, possible_crtc) { + if (possible_crtc == crtc_cfg) + crtc_has_encoder = true; + } + } + + if (!crtc_has_encoder) { + drm_info(dev, "All CRTCs must have at least one possible encoder\n"); + return false; + } + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -237,6 +276,9 @@ bool vkms_config_is_valid(const struct vkms_config *config) return false; } + if (!valid_encoder_possible_crtcs(config)) + return false; + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -362,10 +404,14 @@ void vkms_config_destroy_crtc(struct vkms_config *config, struct vkms_config_crtc *crtc_cfg) { struct vkms_config_plane *plane_cfg; + struct vkms_config_encoder *encoder_cfg; vkms_config_for_each_plane(config, plane_cfg) vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); + vkms_config_for_each_encoder(config, encoder_cfg) + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } @@ -425,6 +471,8 @@ struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *confi return ERR_PTR(-ENOMEM); encoder_cfg->config = config; + xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); + list_add_tail(&encoder_cfg->link, &config->encoders); return encoder_cfg; @@ -434,7 +482,41 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); void vkms_config_destroy_encoder(struct vkms_config *config, struct vkms_config_encoder *encoder_cfg) { + xa_destroy(&encoder_cfg->possible_crtcs); list_del(&encoder_cfg->link); kfree(encoder_cfg); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); + +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *encoder_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx = 0; + u32 crtc_idx = 0; + + if (encoder_cfg->config != crtc_cfg->config) + return -EINVAL; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { + if (possible_crtc == crtc_cfg) + return -EEXIST; + } + + return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc); + +void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx = 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { + if (possible_crtc == crtc_cfg) + xa_erase(&encoder_cfg->possible_crtcs, idx); + } +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); |
