1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include "vkms_config.h" 4 #include "vkms_connector.h" 5 #include "vkms_drv.h" 6 #include <drm/drm_managed.h> 7 8 int vkms_output_init(struct vkms_device *vkmsdev) 9 { 10 struct drm_device *dev = &vkmsdev->drm; 11 struct vkms_config_plane *plane_cfg; 12 struct vkms_config_crtc *crtc_cfg; 13 struct vkms_config_encoder *encoder_cfg; 14 struct vkms_config_connector *connector_cfg; 15 int ret; 16 int writeback; 17 18 if (!vkms_config_is_valid(vkmsdev->config)) 19 return -EINVAL; 20 21 vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { 22 enum drm_plane_type type; 23 24 type = vkms_config_plane_get_type(plane_cfg); 25 26 plane_cfg->plane = vkms_plane_init(vkmsdev, type); 27 if (IS_ERR(plane_cfg->plane)) { 28 DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); 29 return PTR_ERR(plane_cfg->plane); 30 } 31 } 32 33 vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) { 34 struct vkms_config_plane *primary, *cursor; 35 36 primary = vkms_config_crtc_primary_plane(vkmsdev->config, crtc_cfg); 37 cursor = vkms_config_crtc_cursor_plane(vkmsdev->config, crtc_cfg); 38 39 crtc_cfg->crtc = vkms_crtc_init(dev, &primary->plane->base, 40 cursor ? &cursor->plane->base : NULL); 41 if (IS_ERR(crtc_cfg->crtc)) { 42 DRM_ERROR("Failed to allocate CRTC\n"); 43 return PTR_ERR(crtc_cfg->crtc); 44 } 45 46 /* Initialize the writeback component */ 47 if (vkms_config_crtc_get_writeback(crtc_cfg)) { 48 writeback = vkms_enable_writeback_connector(vkmsdev, crtc_cfg->crtc); 49 if (writeback) 50 DRM_ERROR("Failed to init writeback connector\n"); 51 } 52 } 53 54 vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { 55 struct vkms_config_crtc *possible_crtc; 56 unsigned long idx = 0; 57 58 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 59 plane_cfg->plane->base.possible_crtcs |= 60 drm_crtc_mask(&possible_crtc->crtc->crtc); 61 } 62 } 63 64 vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { 65 struct vkms_config_crtc *possible_crtc; 66 unsigned long idx = 0; 67 68 encoder_cfg->encoder = drmm_kzalloc(dev, sizeof(*encoder_cfg->encoder), GFP_KERNEL); 69 if (!encoder_cfg->encoder) { 70 DRM_ERROR("Failed to allocate encoder\n"); 71 return -ENOMEM; 72 } 73 ret = drmm_encoder_init(dev, encoder_cfg->encoder, NULL, 74 DRM_MODE_ENCODER_VIRTUAL, NULL); 75 if (ret) { 76 DRM_ERROR("Failed to init encoder\n"); 77 return ret; 78 } 79 80 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 81 encoder_cfg->encoder->possible_crtcs |= 82 drm_crtc_mask(&possible_crtc->crtc->crtc); 83 } 84 } 85 86 vkms_config_for_each_connector(vkmsdev->config, connector_cfg) { 87 struct vkms_config_encoder *possible_encoder; 88 unsigned long idx = 0; 89 90 connector_cfg->connector = vkms_connector_init(vkmsdev); 91 if (IS_ERR(connector_cfg->connector)) { 92 DRM_ERROR("Failed to init connector\n"); 93 return PTR_ERR(connector_cfg->connector); 94 } 95 96 vkms_config_connector_for_each_possible_encoder(connector_cfg, 97 idx, 98 possible_encoder) { 99 ret = drm_connector_attach_encoder(&connector_cfg->connector->base, 100 possible_encoder->encoder); 101 if (ret) { 102 DRM_ERROR("Failed to attach connector to encoder\n"); 103 return ret; 104 } 105 } 106 } 107 108 drm_mode_config_reset(dev); 109 110 return 0; 111 } 112