17fd56e02SRodrigo Siqueira // SPDX-License-Identifier: GPL-2.0+
2854502faSRodrigo Siqueira
3854502faSRodrigo Siqueira #include "vkms_drv.h"
4d1648930SRodrigo Siqueira #include <drm/drm_atomic_helper.h>
5255490f9SVille Syrjälä #include <drm/drm_edid.h>
6fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
7854502faSRodrigo Siqueira
8854502faSRodrigo Siqueira static const struct drm_connector_funcs vkms_connector_funcs = {
9854502faSRodrigo Siqueira .fill_modes = drm_helper_probe_single_connector_modes,
10ca0376baSJavier Martinez Canillas .destroy = drm_connector_cleanup,
11d1648930SRodrigo Siqueira .reset = drm_atomic_helper_connector_reset,
12d1648930SRodrigo Siqueira .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
13d1648930SRodrigo Siqueira .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
14854502faSRodrigo Siqueira };
15854502faSRodrigo Siqueira
16e3adc46dSJavier Martinez Canillas static const struct drm_encoder_funcs vkms_encoder_funcs = {
17e3adc46dSJavier Martinez Canillas .destroy = drm_encoder_cleanup,
18e3adc46dSJavier Martinez Canillas };
19e3adc46dSJavier Martinez Canillas
vkms_conn_get_modes(struct drm_connector * connector)20d1648930SRodrigo Siqueira static int vkms_conn_get_modes(struct drm_connector *connector)
21d1648930SRodrigo Siqueira {
22d1648930SRodrigo Siqueira int count;
23d1648930SRodrigo Siqueira
24d1648930SRodrigo Siqueira count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
25d1648930SRodrigo Siqueira drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
26d1648930SRodrigo Siqueira
27d1648930SRodrigo Siqueira return count;
28d1648930SRodrigo Siqueira }
29d1648930SRodrigo Siqueira
30d1648930SRodrigo Siqueira static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
31d1648930SRodrigo Siqueira .get_modes = vkms_conn_get_modes,
32d1648930SRodrigo Siqueira };
33d1648930SRodrigo Siqueira
vkms_add_overlay_plane(struct vkms_device * vkmsdev,int index,struct drm_crtc * crtc)345edaa2b9SJosé Expósito static int vkms_add_overlay_plane(struct vkms_device *vkmsdev, int index,
355edaa2b9SJosé Expósito struct drm_crtc *crtc)
365edaa2b9SJosé Expósito {
375edaa2b9SJosé Expósito struct vkms_plane *overlay;
385edaa2b9SJosé Expósito
395edaa2b9SJosé Expósito overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
405edaa2b9SJosé Expósito if (IS_ERR(overlay))
415edaa2b9SJosé Expósito return PTR_ERR(overlay);
425edaa2b9SJosé Expósito
435edaa2b9SJosé Expósito if (!overlay->base.possible_crtcs)
445edaa2b9SJosé Expósito overlay->base.possible_crtcs = drm_crtc_mask(crtc);
455edaa2b9SJosé Expósito
465edaa2b9SJosé Expósito return 0;
475edaa2b9SJosé Expósito }
485edaa2b9SJosé Expósito
vkms_output_init(struct vkms_device * vkmsdev,int index)49e9d85f73SRodrigo Siqueira int vkms_output_init(struct vkms_device *vkmsdev, int index)
50854502faSRodrigo Siqueira {
51854502faSRodrigo Siqueira struct vkms_output *output = &vkmsdev->output;
52854502faSRodrigo Siqueira struct drm_device *dev = &vkmsdev->drm;
53854502faSRodrigo Siqueira struct drm_connector *connector = &output->connector;
54854502faSRodrigo Siqueira struct drm_encoder *encoder = &output->encoder;
55854502faSRodrigo Siqueira struct drm_crtc *crtc = &output->crtc;
565edaa2b9SJosé Expósito struct vkms_plane *primary, *cursor = NULL;
57854502faSRodrigo Siqueira int ret;
581e85b7d4SSumera Priyadarsini int writeback;
59df2d385cSJosé Expósito unsigned int n;
60854502faSRodrigo Siqueira
61e9d85f73SRodrigo Siqueira primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
62854502faSRodrigo Siqueira if (IS_ERR(primary))
63854502faSRodrigo Siqueira return PTR_ERR(primary);
64854502faSRodrigo Siqueira
65310e506cSMelissa Wen if (vkmsdev->config->overlay) {
66df2d385cSJosé Expósito for (n = 0; n < NUM_OVERLAY_PLANES; n++) {
675edaa2b9SJosé Expósito ret = vkms_add_overlay_plane(vkmsdev, index, crtc);
685edaa2b9SJosé Expósito if (ret)
695edaa2b9SJosé Expósito return ret;
70310e506cSMelissa Wen }
71df2d385cSJosé Expósito }
72310e506cSMelissa Wen
732df7af93SSumera Priyadarsini if (vkmsdev->config->cursor) {
74e9d85f73SRodrigo Siqueira cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
752f56dd8cSMelissa Wen if (IS_ERR(cursor))
762f56dd8cSMelissa Wen return PTR_ERR(cursor);
77b8789ea7SHaneen Mohammed }
78c27d931dSHaneen Mohammed
792f56dd8cSMelissa Wen ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base);
80854502faSRodrigo Siqueira if (ret)
812f56dd8cSMelissa Wen return ret;
82854502faSRodrigo Siqueira
83854502faSRodrigo Siqueira ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
84854502faSRodrigo Siqueira DRM_MODE_CONNECTOR_VIRTUAL);
85854502faSRodrigo Siqueira if (ret) {
86854502faSRodrigo Siqueira DRM_ERROR("Failed to init connector\n");
87*23c3f600SJosé Expósito return ret;
88854502faSRodrigo Siqueira }
89854502faSRodrigo Siqueira
90d1648930SRodrigo Siqueira drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
91d1648930SRodrigo Siqueira
92e3adc46dSJavier Martinez Canillas ret = drm_encoder_init(dev, encoder, &vkms_encoder_funcs,
93e3adc46dSJavier Martinez Canillas DRM_MODE_ENCODER_VIRTUAL, NULL);
94854502faSRodrigo Siqueira if (ret) {
95854502faSRodrigo Siqueira DRM_ERROR("Failed to init encoder\n");
96854502faSRodrigo Siqueira goto err_encoder;
97854502faSRodrigo Siqueira }
98854502faSRodrigo Siqueira encoder->possible_crtcs = 1;
99854502faSRodrigo Siqueira
100cde4c44dSDaniel Vetter ret = drm_connector_attach_encoder(connector, encoder);
101854502faSRodrigo Siqueira if (ret) {
102854502faSRodrigo Siqueira DRM_ERROR("Failed to attach connector to encoder\n");
103854502faSRodrigo Siqueira goto err_attach;
104854502faSRodrigo Siqueira }
105854502faSRodrigo Siqueira
1061e85b7d4SSumera Priyadarsini if (vkmsdev->config->writeback) {
1071e85b7d4SSumera Priyadarsini writeback = vkms_enable_writeback_connector(vkmsdev);
1081e85b7d4SSumera Priyadarsini if (writeback)
109dbd9d80cSRodrigo Siqueira DRM_ERROR("Failed to init writeback connector\n");
1101e85b7d4SSumera Priyadarsini }
111dbd9d80cSRodrigo Siqueira
112854502faSRodrigo Siqueira drm_mode_config_reset(dev);
113854502faSRodrigo Siqueira
114854502faSRodrigo Siqueira return 0;
115854502faSRodrigo Siqueira
116854502faSRodrigo Siqueira err_attach:
117854502faSRodrigo Siqueira drm_encoder_cleanup(encoder);
118854502faSRodrigo Siqueira
119854502faSRodrigo Siqueira err_encoder:
120854502faSRodrigo Siqueira drm_connector_cleanup(connector);
121854502faSRodrigo Siqueira
122854502faSRodrigo Siqueira return ret;
123854502faSRodrigo Siqueira }
124