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