xref: /openbmc/linux/drivers/gpu/drm/vkms/vkms_output.c (revision 5edaa2b9)
17fd56e02SRodrigo Siqueira // SPDX-License-Identifier: GPL-2.0+
2854502faSRodrigo Siqueira 
3854502faSRodrigo Siqueira #include "vkms_drv.h"
4d1648930SRodrigo Siqueira #include <drm/drm_atomic_helper.h>
5fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
6d1956157SThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
7854502faSRodrigo Siqueira 
8854502faSRodrigo Siqueira static void vkms_connector_destroy(struct drm_connector *connector)
9854502faSRodrigo Siqueira {
10854502faSRodrigo Siqueira 	drm_connector_cleanup(connector);
11854502faSRodrigo Siqueira }
12854502faSRodrigo Siqueira 
13854502faSRodrigo Siqueira static const struct drm_connector_funcs vkms_connector_funcs = {
14854502faSRodrigo Siqueira 	.fill_modes = drm_helper_probe_single_connector_modes,
15854502faSRodrigo Siqueira 	.destroy = vkms_connector_destroy,
16d1648930SRodrigo Siqueira 	.reset = drm_atomic_helper_connector_reset,
17d1648930SRodrigo Siqueira 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
18d1648930SRodrigo Siqueira 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
19854502faSRodrigo Siqueira };
20854502faSRodrigo Siqueira 
21d1648930SRodrigo Siqueira static int vkms_conn_get_modes(struct drm_connector *connector)
22d1648930SRodrigo Siqueira {
23d1648930SRodrigo Siqueira 	int count;
24d1648930SRodrigo Siqueira 
25d1648930SRodrigo Siqueira 	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
26d1648930SRodrigo Siqueira 	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
27d1648930SRodrigo Siqueira 
28d1648930SRodrigo Siqueira 	return count;
29d1648930SRodrigo Siqueira }
30d1648930SRodrigo Siqueira 
31d1648930SRodrigo Siqueira static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
32d1648930SRodrigo Siqueira 	.get_modes    = vkms_conn_get_modes,
33d1648930SRodrigo Siqueira };
34d1648930SRodrigo Siqueira 
35*5edaa2b9SJosé Expósito static int vkms_add_overlay_plane(struct vkms_device *vkmsdev, int index,
36*5edaa2b9SJosé Expósito 				  struct drm_crtc *crtc)
37*5edaa2b9SJosé Expósito {
38*5edaa2b9SJosé Expósito 	struct vkms_plane *overlay;
39*5edaa2b9SJosé Expósito 
40*5edaa2b9SJosé Expósito 	overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
41*5edaa2b9SJosé Expósito 	if (IS_ERR(overlay))
42*5edaa2b9SJosé Expósito 		return PTR_ERR(overlay);
43*5edaa2b9SJosé Expósito 
44*5edaa2b9SJosé Expósito 	if (!overlay->base.possible_crtcs)
45*5edaa2b9SJosé Expósito 		overlay->base.possible_crtcs = drm_crtc_mask(crtc);
46*5edaa2b9SJosé Expósito 
47*5edaa2b9SJosé Expósito 	return 0;
48*5edaa2b9SJosé Expósito }
49*5edaa2b9SJosé Expósito 
50e9d85f73SRodrigo Siqueira int vkms_output_init(struct vkms_device *vkmsdev, int index)
51854502faSRodrigo Siqueira {
52854502faSRodrigo Siqueira 	struct vkms_output *output = &vkmsdev->output;
53854502faSRodrigo Siqueira 	struct drm_device *dev = &vkmsdev->drm;
54854502faSRodrigo Siqueira 	struct drm_connector *connector = &output->connector;
55854502faSRodrigo Siqueira 	struct drm_encoder *encoder = &output->encoder;
56854502faSRodrigo Siqueira 	struct drm_crtc *crtc = &output->crtc;
57*5edaa2b9SJosé Expósito 	struct vkms_plane *primary, *cursor = NULL;
58854502faSRodrigo Siqueira 	int ret;
591e85b7d4SSumera Priyadarsini 	int writeback;
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) {
66*5edaa2b9SJosé Expósito 		ret = vkms_add_overlay_plane(vkmsdev, index, crtc);
67*5edaa2b9SJosé Expósito 		if (ret)
68*5edaa2b9SJosé Expósito 			return ret;
69310e506cSMelissa Wen 	}
70310e506cSMelissa Wen 
712df7af93SSumera Priyadarsini 	if (vkmsdev->config->cursor) {
72e9d85f73SRodrigo Siqueira 		cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
732f56dd8cSMelissa Wen 		if (IS_ERR(cursor))
742f56dd8cSMelissa Wen 			return PTR_ERR(cursor);
75b8789ea7SHaneen Mohammed 	}
76c27d931dSHaneen Mohammed 
772f56dd8cSMelissa Wen 	ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base);
78854502faSRodrigo Siqueira 	if (ret)
792f56dd8cSMelissa Wen 		return ret;
80854502faSRodrigo Siqueira 
81854502faSRodrigo Siqueira 	ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
82854502faSRodrigo Siqueira 				 DRM_MODE_CONNECTOR_VIRTUAL);
83854502faSRodrigo Siqueira 	if (ret) {
84854502faSRodrigo Siqueira 		DRM_ERROR("Failed to init connector\n");
85854502faSRodrigo Siqueira 		goto err_connector;
86854502faSRodrigo Siqueira 	}
87854502faSRodrigo Siqueira 
88d1648930SRodrigo Siqueira 	drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
89d1648930SRodrigo Siqueira 
90d1956157SThomas Zimmermann 	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
91854502faSRodrigo Siqueira 	if (ret) {
92854502faSRodrigo Siqueira 		DRM_ERROR("Failed to init encoder\n");
93854502faSRodrigo Siqueira 		goto err_encoder;
94854502faSRodrigo Siqueira 	}
95854502faSRodrigo Siqueira 	encoder->possible_crtcs = 1;
96854502faSRodrigo Siqueira 
97cde4c44dSDaniel Vetter 	ret = drm_connector_attach_encoder(connector, encoder);
98854502faSRodrigo Siqueira 	if (ret) {
99854502faSRodrigo Siqueira 		DRM_ERROR("Failed to attach connector to encoder\n");
100854502faSRodrigo Siqueira 		goto err_attach;
101854502faSRodrigo Siqueira 	}
102854502faSRodrigo Siqueira 
1031e85b7d4SSumera Priyadarsini 	if (vkmsdev->config->writeback) {
1041e85b7d4SSumera Priyadarsini 		writeback = vkms_enable_writeback_connector(vkmsdev);
1051e85b7d4SSumera Priyadarsini 		if (writeback)
106dbd9d80cSRodrigo Siqueira 			DRM_ERROR("Failed to init writeback connector\n");
1071e85b7d4SSumera Priyadarsini 	}
108dbd9d80cSRodrigo Siqueira 
109854502faSRodrigo Siqueira 	drm_mode_config_reset(dev);
110854502faSRodrigo Siqueira 
111854502faSRodrigo Siqueira 	return 0;
112854502faSRodrigo Siqueira 
113854502faSRodrigo Siqueira err_attach:
114854502faSRodrigo Siqueira 	drm_encoder_cleanup(encoder);
115854502faSRodrigo Siqueira 
116854502faSRodrigo Siqueira err_encoder:
117854502faSRodrigo Siqueira 	drm_connector_cleanup(connector);
118854502faSRodrigo Siqueira 
119854502faSRodrigo Siqueira err_connector:
120854502faSRodrigo Siqueira 	drm_crtc_cleanup(crtc);
121854502faSRodrigo Siqueira 
122854502faSRodrigo Siqueira 	return ret;
123854502faSRodrigo Siqueira }
124