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