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