1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include "vkms_connector.h" 4 #include "vkms_drv.h" 5 #include <drm/drm_managed.h> 6 7 int vkms_output_init(struct vkms_device *vkmsdev) 8 { 9 struct drm_device *dev = &vkmsdev->drm; 10 struct vkms_connector *connector; 11 struct drm_encoder *encoder; 12 struct vkms_output *output; 13 struct vkms_plane *primary, *overlay, *cursor = NULL; 14 int ret; 15 int writeback; 16 unsigned int n; 17 18 /* 19 * Initialize used plane. One primary plane is required to perform the composition. 20 * 21 * The overlay and cursor planes are not mandatory, but can be used to perform complex 22 * composition. 23 */ 24 primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY); 25 if (IS_ERR(primary)) 26 return PTR_ERR(primary); 27 28 if (vkmsdev->config->cursor) { 29 cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR); 30 if (IS_ERR(cursor)) 31 return PTR_ERR(cursor); 32 } 33 34 output = vkms_crtc_init(dev, &primary->base, 35 cursor ? &cursor->base : NULL); 36 if (IS_ERR(output)) { 37 DRM_ERROR("Failed to allocate CRTC\n"); 38 return PTR_ERR(output); 39 } 40 41 if (vkmsdev->config->overlay) { 42 for (n = 0; n < NUM_OVERLAY_PLANES; n++) { 43 overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY); 44 if (IS_ERR(overlay)) { 45 DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); 46 return PTR_ERR(overlay); 47 } 48 overlay->base.possible_crtcs = drm_crtc_mask(&output->crtc); 49 } 50 } 51 52 connector = vkms_connector_init(vkmsdev); 53 if (IS_ERR(connector)) { 54 DRM_ERROR("Failed to init connector\n"); 55 return PTR_ERR(connector); 56 } 57 58 encoder = drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); 59 if (!encoder) { 60 DRM_ERROR("Failed to allocate encoder\n"); 61 return -ENOMEM; 62 } 63 ret = drmm_encoder_init(dev, encoder, NULL, 64 DRM_MODE_ENCODER_VIRTUAL, NULL); 65 if (ret) { 66 DRM_ERROR("Failed to init encoder\n"); 67 return ret; 68 } 69 encoder->possible_crtcs = drm_crtc_mask(&output->crtc); 70 71 /* Attach the encoder and the connector */ 72 ret = drm_connector_attach_encoder(&connector->base, encoder); 73 if (ret) { 74 DRM_ERROR("Failed to attach connector to encoder\n"); 75 return ret; 76 } 77 78 /* Initialize the writeback component */ 79 if (vkmsdev->config->writeback) { 80 writeback = vkms_enable_writeback_connector(vkmsdev, output); 81 if (writeback) 82 DRM_ERROR("Failed to init writeback connector\n"); 83 } 84 85 drm_mode_config_reset(dev); 86 87 return ret; 88 } 89