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