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
vkms_output_init(struct vkms_device * vkmsdev)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