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 encoder_cfg->encoder->possible_clones |= 81 drm_encoder_mask(encoder_cfg->encoder); 82 83 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 84 encoder_cfg->encoder->possible_crtcs |= 85 drm_crtc_mask(&possible_crtc->crtc->crtc); 86 87 if (vkms_config_crtc_get_writeback(possible_crtc)) { 88 struct drm_encoder *wb_encoder = 89 &possible_crtc->crtc->wb_encoder; 90 91 encoder_cfg->encoder->possible_clones |= 92 drm_encoder_mask(wb_encoder); 93 wb_encoder->possible_clones |= 94 drm_encoder_mask(encoder_cfg->encoder); 95 } 96 } 97 } 98 99 vkms_config_for_each_connector(vkmsdev->config, connector_cfg) { 100 struct vkms_config_encoder *possible_encoder; 101 unsigned long idx = 0; 102 103 connector_cfg->connector = vkms_connector_init(vkmsdev); 104 if (IS_ERR(connector_cfg->connector)) { 105 DRM_ERROR("Failed to init connector\n"); 106 return PTR_ERR(connector_cfg->connector); 107 } 108 109 vkms_config_connector_for_each_possible_encoder(connector_cfg, 110 idx, 111 possible_encoder) { 112 ret = drm_connector_attach_encoder(&connector_cfg->connector->base, 113 possible_encoder->encoder); 114 if (ret) { 115 DRM_ERROR("Failed to attach connector to encoder\n"); 116 return ret; 117 } 118 } 119 } 120 121 drm_mode_config_reset(dev); 122 123 return 0; 124 } 125