xref: /openbmc/linux/drivers/gpu/drm/vkms/vkms_output.c (revision e9d85f73)
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>
6854502faSRodrigo Siqueira 
7854502faSRodrigo Siqueira static void vkms_connector_destroy(struct drm_connector *connector)
8854502faSRodrigo Siqueira {
9854502faSRodrigo Siqueira 	drm_connector_cleanup(connector);
10854502faSRodrigo Siqueira }
11854502faSRodrigo Siqueira 
12854502faSRodrigo Siqueira static const struct drm_connector_funcs vkms_connector_funcs = {
13854502faSRodrigo Siqueira 	.fill_modes = drm_helper_probe_single_connector_modes,
14854502faSRodrigo Siqueira 	.destroy = vkms_connector_destroy,
15d1648930SRodrigo Siqueira 	.reset = drm_atomic_helper_connector_reset,
16d1648930SRodrigo Siqueira 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
17d1648930SRodrigo Siqueira 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
18854502faSRodrigo Siqueira };
19854502faSRodrigo Siqueira 
20854502faSRodrigo Siqueira static const struct drm_encoder_funcs vkms_encoder_funcs = {
21854502faSRodrigo Siqueira 	.destroy = drm_encoder_cleanup,
22854502faSRodrigo Siqueira };
23854502faSRodrigo Siqueira 
24d1648930SRodrigo Siqueira static int vkms_conn_get_modes(struct drm_connector *connector)
25d1648930SRodrigo Siqueira {
26d1648930SRodrigo Siqueira 	int count;
27d1648930SRodrigo Siqueira 
28d1648930SRodrigo Siqueira 	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
29d1648930SRodrigo Siqueira 	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
30d1648930SRodrigo Siqueira 
31d1648930SRodrigo Siqueira 	return count;
32d1648930SRodrigo Siqueira }
33d1648930SRodrigo Siqueira 
34d1648930SRodrigo Siqueira static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
35d1648930SRodrigo Siqueira 	.get_modes    = vkms_conn_get_modes,
36d1648930SRodrigo Siqueira };
37d1648930SRodrigo Siqueira 
38e9d85f73SRodrigo Siqueira int vkms_output_init(struct vkms_device *vkmsdev, int index)
39854502faSRodrigo Siqueira {
40854502faSRodrigo Siqueira 	struct vkms_output *output = &vkmsdev->output;
41854502faSRodrigo Siqueira 	struct drm_device *dev = &vkmsdev->drm;
42854502faSRodrigo Siqueira 	struct drm_connector *connector = &output->connector;
43854502faSRodrigo Siqueira 	struct drm_encoder *encoder = &output->encoder;
44854502faSRodrigo Siqueira 	struct drm_crtc *crtc = &output->crtc;
45c27d931dSHaneen Mohammed 	struct drm_plane *primary, *cursor = NULL;
46854502faSRodrigo Siqueira 	int ret;
47854502faSRodrigo Siqueira 
48e9d85f73SRodrigo Siqueira 	primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
49854502faSRodrigo Siqueira 	if (IS_ERR(primary))
50854502faSRodrigo Siqueira 		return PTR_ERR(primary);
51854502faSRodrigo Siqueira 
52b8789ea7SHaneen Mohammed 	if (enable_cursor) {
53e9d85f73SRodrigo Siqueira 		cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
54c27d931dSHaneen Mohammed 		if (IS_ERR(cursor)) {
55c27d931dSHaneen Mohammed 			ret = PTR_ERR(cursor);
56c27d931dSHaneen Mohammed 			goto err_cursor;
57c27d931dSHaneen Mohammed 		}
58b8789ea7SHaneen Mohammed 	}
59c27d931dSHaneen Mohammed 
60c27d931dSHaneen Mohammed 	ret = vkms_crtc_init(dev, crtc, primary, cursor);
61854502faSRodrigo Siqueira 	if (ret)
62854502faSRodrigo Siqueira 		goto err_crtc;
63854502faSRodrigo Siqueira 
64854502faSRodrigo Siqueira 	ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
65854502faSRodrigo Siqueira 				 DRM_MODE_CONNECTOR_VIRTUAL);
66854502faSRodrigo Siqueira 	if (ret) {
67854502faSRodrigo Siqueira 		DRM_ERROR("Failed to init connector\n");
68854502faSRodrigo Siqueira 		goto err_connector;
69854502faSRodrigo Siqueira 	}
70854502faSRodrigo Siqueira 
71d1648930SRodrigo Siqueira 	drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
72d1648930SRodrigo Siqueira 
73854502faSRodrigo Siqueira 	ret = drm_encoder_init(dev, encoder, &vkms_encoder_funcs,
74854502faSRodrigo Siqueira 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
75854502faSRodrigo Siqueira 	if (ret) {
76854502faSRodrigo Siqueira 		DRM_ERROR("Failed to init encoder\n");
77854502faSRodrigo Siqueira 		goto err_encoder;
78854502faSRodrigo Siqueira 	}
79854502faSRodrigo Siqueira 	encoder->possible_crtcs = 1;
80854502faSRodrigo Siqueira 
81cde4c44dSDaniel Vetter 	ret = drm_connector_attach_encoder(connector, encoder);
82854502faSRodrigo Siqueira 	if (ret) {
83854502faSRodrigo Siqueira 		DRM_ERROR("Failed to attach connector to encoder\n");
84854502faSRodrigo Siqueira 		goto err_attach;
85854502faSRodrigo Siqueira 	}
86854502faSRodrigo Siqueira 
87854502faSRodrigo Siqueira 	drm_mode_config_reset(dev);
88854502faSRodrigo Siqueira 
89854502faSRodrigo Siqueira 	return 0;
90854502faSRodrigo Siqueira 
91854502faSRodrigo Siqueira err_attach:
92854502faSRodrigo Siqueira 	drm_encoder_cleanup(encoder);
93854502faSRodrigo Siqueira 
94854502faSRodrigo Siqueira err_encoder:
95854502faSRodrigo Siqueira 	drm_connector_cleanup(connector);
96854502faSRodrigo Siqueira 
97854502faSRodrigo Siqueira err_connector:
98854502faSRodrigo Siqueira 	drm_crtc_cleanup(crtc);
99854502faSRodrigo Siqueira 
100854502faSRodrigo Siqueira err_crtc:
101b8789ea7SHaneen Mohammed 	if (enable_cursor)
102c27d931dSHaneen Mohammed 		drm_plane_cleanup(cursor);
103c27d931dSHaneen Mohammed 
104c27d931dSHaneen Mohammed err_cursor:
105854502faSRodrigo Siqueira 	drm_plane_cleanup(primary);
106c27d931dSHaneen Mohammed 
107854502faSRodrigo Siqueira 	return ret;
108854502faSRodrigo Siqueira }
109