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_connector *connector; 12 struct drm_encoder *encoder; 13 struct vkms_config_plane *plane_cfg; 14 struct vkms_config_crtc *crtc_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 connector = vkms_connector_init(vkmsdev); 65 if (IS_ERR(connector)) { 66 DRM_ERROR("Failed to init connector\n"); 67 return PTR_ERR(connector); 68 } 69 70 encoder = drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); 71 if (!encoder) { 72 DRM_ERROR("Failed to allocate encoder\n"); 73 return -ENOMEM; 74 } 75 ret = drmm_encoder_init(dev, encoder, NULL, 76 DRM_MODE_ENCODER_VIRTUAL, NULL); 77 if (ret) { 78 DRM_ERROR("Failed to init encoder\n"); 79 return ret; 80 } 81 82 vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) 83 encoder->possible_crtcs = drm_crtc_mask(&crtc_cfg->crtc->crtc); 84 85 /* Attach the encoder and the connector */ 86 ret = drm_connector_attach_encoder(&connector->base, encoder); 87 if (ret) { 88 DRM_ERROR("Failed to attach connector to encoder\n"); 89 return ret; 90 } 91 92 drm_mode_config_reset(dev); 93 94 return ret; 95 } 96