linux/drivers/gpu/drm/vkms/vkms_output.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2
   3#include "vkms_drv.h"
   4#include <drm/drm_atomic_helper.h>
   5#include <drm/drm_probe_helper.h>
   6#include <drm/drm_simple_kms_helper.h>
   7
   8static void vkms_connector_destroy(struct drm_connector *connector)
   9{
  10        drm_connector_cleanup(connector);
  11}
  12
  13static const struct drm_connector_funcs vkms_connector_funcs = {
  14        .fill_modes = drm_helper_probe_single_connector_modes,
  15        .destroy = vkms_connector_destroy,
  16        .reset = drm_atomic_helper_connector_reset,
  17        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  18        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  19};
  20
  21static int vkms_conn_get_modes(struct drm_connector *connector)
  22{
  23        int count;
  24
  25        count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
  26        drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
  27
  28        return count;
  29}
  30
  31static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
  32        .get_modes    = vkms_conn_get_modes,
  33};
  34
  35int vkms_output_init(struct vkms_device *vkmsdev, int index)
  36{
  37        struct vkms_output *output = &vkmsdev->output;
  38        struct drm_device *dev = &vkmsdev->drm;
  39        struct drm_connector *connector = &output->connector;
  40        struct drm_encoder *encoder = &output->encoder;
  41        struct drm_crtc *crtc = &output->crtc;
  42        struct vkms_plane *primary, *cursor = NULL, *overlay = NULL;
  43        int ret;
  44        int writeback;
  45
  46        primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
  47        if (IS_ERR(primary))
  48                return PTR_ERR(primary);
  49
  50        if (vkmsdev->config->overlay) {
  51                overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
  52                if (IS_ERR(overlay))
  53                        return PTR_ERR(overlay);
  54
  55                if (!overlay->base.possible_crtcs)
  56                        overlay->base.possible_crtcs = drm_crtc_mask(crtc);
  57        }
  58
  59        if (vkmsdev->config->cursor) {
  60                cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
  61                if (IS_ERR(cursor))
  62                        return PTR_ERR(cursor);
  63        }
  64
  65        ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base);
  66        if (ret)
  67                return ret;
  68
  69        ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
  70                                 DRM_MODE_CONNECTOR_VIRTUAL);
  71        if (ret) {
  72                DRM_ERROR("Failed to init connector\n");
  73                goto err_connector;
  74        }
  75
  76        drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
  77
  78        ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
  79        if (ret) {
  80                DRM_ERROR("Failed to init encoder\n");
  81                goto err_encoder;
  82        }
  83        encoder->possible_crtcs = 1;
  84
  85        ret = drm_connector_attach_encoder(connector, encoder);
  86        if (ret) {
  87                DRM_ERROR("Failed to attach connector to encoder\n");
  88                goto err_attach;
  89        }
  90
  91        if (vkmsdev->config->writeback) {
  92                writeback = vkms_enable_writeback_connector(vkmsdev);
  93                if (writeback)
  94                        DRM_ERROR("Failed to init writeback connector\n");
  95        }
  96
  97        drm_mode_config_reset(dev);
  98
  99        return 0;
 100
 101err_attach:
 102        drm_encoder_cleanup(encoder);
 103
 104err_encoder:
 105        drm_connector_cleanup(connector);
 106
 107err_connector:
 108        drm_crtc_cleanup(crtc);
 109
 110        return ret;
 111}
 112