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
  35static int vkms_add_overlay_plane(struct vkms_device *vkmsdev, int index,
  36                                  struct drm_crtc *crtc)
  37{
  38        struct vkms_plane *overlay;
  39
  40        overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
  41        if (IS_ERR(overlay))
  42                return PTR_ERR(overlay);
  43
  44        if (!overlay->base.possible_crtcs)
  45                overlay->base.possible_crtcs = drm_crtc_mask(crtc);
  46
  47        return 0;
  48}
  49
  50int vkms_output_init(struct vkms_device *vkmsdev, int index)
  51{
  52        struct vkms_output *output = &vkmsdev->output;
  53        struct drm_device *dev = &vkmsdev->drm;
  54        struct drm_connector *connector = &output->connector;
  55        struct drm_encoder *encoder = &output->encoder;
  56        struct drm_crtc *crtc = &output->crtc;
  57        struct vkms_plane *primary, *cursor = NULL;
  58        int ret;
  59        int writeback;
  60        unsigned int n;
  61
  62        primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
  63        if (IS_ERR(primary))
  64                return PTR_ERR(primary);
  65
  66        if (vkmsdev->config->overlay) {
  67                for (n = 0; n < NUM_OVERLAY_PLANES; n++) {
  68                        ret = vkms_add_overlay_plane(vkmsdev, index, crtc);
  69                        if (ret)
  70                                return ret;
  71                }
  72        }
  73
  74        if (vkmsdev->config->cursor) {
  75                cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
  76                if (IS_ERR(cursor))
  77                        return PTR_ERR(cursor);
  78        }
  79
  80        ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base);
  81        if (ret)
  82                return ret;
  83
  84        ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
  85                                 DRM_MODE_CONNECTOR_VIRTUAL);
  86        if (ret) {
  87                DRM_ERROR("Failed to init connector\n");
  88                goto err_connector;
  89        }
  90
  91        drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
  92
  93        ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
  94        if (ret) {
  95                DRM_ERROR("Failed to init encoder\n");
  96                goto err_encoder;
  97        }
  98        encoder->possible_crtcs = 1;
  99
 100        ret = drm_connector_attach_encoder(connector, encoder);
 101        if (ret) {
 102                DRM_ERROR("Failed to attach connector to encoder\n");
 103                goto err_attach;
 104        }
 105
 106        if (vkmsdev->config->writeback) {
 107                writeback = vkms_enable_writeback_connector(vkmsdev);
 108                if (writeback)
 109                        DRM_ERROR("Failed to init writeback connector\n");
 110        }
 111
 112        drm_mode_config_reset(dev);
 113
 114        return 0;
 115
 116err_attach:
 117        drm_encoder_cleanup(encoder);
 118
 119err_encoder:
 120        drm_connector_cleanup(connector);
 121
 122err_connector:
 123        drm_crtc_cleanup(crtc);
 124
 125        return ret;
 126}
 127