linux/drivers/gpu/drm/xylon/xylon_connector.c
<<
>>
Prefs
   1/*
   2 * Xylon DRM connector functions
   3 *
   4 * Copyright (C) 2014 Xylon d.o.o.
   5 * Author: Davor Joja <davor.joja@logicbricks.com>
   6 *
   7 * Reused Xilinx DRM connector driver.
   8 * Copyright (C) 2013 Xilinx, Inc.
   9 *
  10 * This software is licensed under the terms of the GNU General Public
  11 * License version 2, as published by the Free Software Foundation, and
  12 * may be copied, distributed, and modified under those terms.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <drm/drmP.h>
  21#include <drm/drm_crtc.h>
  22#include <drm/drm_crtc_helper.h>
  23#include <drm/drm_encoder_slave.h>
  24
  25#include <linux/device.h>
  26
  27#include "xylon_connector.h"
  28#include "xylon_drv.h"
  29
  30struct xylon_drm_connector {
  31        struct drm_connector base;
  32        struct drm_encoder *encoder;
  33};
  34
  35#define to_xylon_connector(x) container_of(x, struct xylon_drm_connector, base)
  36
  37static int xylon_drm_connector_get_modes(struct drm_connector *base_connector)
  38{
  39        struct xylon_drm_connector *connector =
  40                to_xylon_connector(base_connector);
  41        struct drm_encoder *encoder = connector->encoder;
  42        struct drm_encoder_slave *encoder_slave = to_encoder_slave(encoder);
  43        struct drm_encoder_slave_funcs *encoder_sfuncs =
  44                encoder_slave->slave_funcs;
  45        int count = 0;
  46
  47        if (encoder_sfuncs->get_modes)
  48                count = encoder_sfuncs->get_modes(encoder, base_connector);
  49
  50        return count;
  51}
  52
  53static int xylon_drm_connector_mode_valid(struct drm_connector *base_connector,
  54                                          struct drm_display_mode *mode)
  55{
  56        struct xylon_drm_connector *connector =
  57                to_xylon_connector(base_connector);
  58        struct drm_encoder *encoder = connector->encoder;
  59        struct drm_encoder_slave *encoder_slave = to_encoder_slave(encoder);
  60        struct drm_encoder_slave_funcs *encoder_sfuncs =
  61                encoder_slave->slave_funcs;
  62        int ret = MODE_OK;
  63
  64        if (encoder_sfuncs->mode_valid)
  65                ret = encoder_sfuncs->mode_valid(encoder, mode);
  66
  67        return ret;
  68}
  69
  70static struct drm_encoder *
  71xylon_drm_connector_best_encoder(struct drm_connector *base_connector)
  72{
  73        struct xylon_drm_connector *connector =
  74                to_xylon_connector(base_connector);
  75
  76        return connector->encoder;
  77}
  78
  79static struct drm_connector_helper_funcs xylon_drm_connector_helper_funcs = {
  80        .get_modes = xylon_drm_connector_get_modes,
  81        .mode_valid = xylon_drm_connector_mode_valid,
  82        .best_encoder = xylon_drm_connector_best_encoder,
  83};
  84
  85static enum drm_connector_status
  86xylon_drm_connector_detect(struct drm_connector *base_connector, bool force)
  87{
  88        struct xylon_drm_connector *connector =
  89                to_xylon_connector(base_connector);
  90        enum drm_connector_status status = connector_status_unknown;
  91        struct drm_encoder *encoder = connector->encoder;
  92        struct drm_encoder_slave *encoder_slave = to_encoder_slave(encoder);
  93        struct drm_encoder_slave_funcs *encoder_sfuncs =
  94                encoder_slave->slave_funcs;
  95
  96        if (encoder_sfuncs->detect)
  97                status = encoder_sfuncs->detect(encoder, base_connector);
  98
  99        if (force && (status != connector_status_connected))
 100                status = encoder_sfuncs->detect(encoder, base_connector);
 101
 102        return status;
 103}
 104
 105static void xylon_drm_connector_destroy(struct drm_connector *base_connector)
 106{
 107        drm_connector_unregister(base_connector);
 108        drm_connector_cleanup(base_connector);
 109}
 110
 111static struct drm_connector_funcs xylon_drm_connector_funcs = {
 112        .dpms = drm_helper_connector_dpms,
 113        .fill_modes = drm_helper_probe_single_connector_modes,
 114        .detect = xylon_drm_connector_detect,
 115        .destroy = xylon_drm_connector_destroy,
 116};
 117
 118struct drm_connector *
 119xylon_drm_connector_create(struct drm_device *dev,
 120                           struct drm_encoder *base_encoder)
 121{
 122        struct xylon_drm_connector *connector;
 123        int ret;
 124
 125        connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL);
 126        if (!connector)
 127                return ERR_PTR(-ENOMEM);
 128
 129        connector->base.encoder = base_encoder;
 130        connector->base.polled = DRM_CONNECTOR_POLL_CONNECT |
 131                                 DRM_CONNECTOR_POLL_DISCONNECT;
 132
 133        ret = drm_connector_init(dev, &connector->base,
 134                                 &xylon_drm_connector_funcs,
 135                                 DRM_MODE_CONNECTOR_HDMIA);
 136        if (ret) {
 137                DRM_ERROR("failed initialize connector\n");
 138                return ERR_PTR(ret);
 139        }
 140
 141        drm_connector_helper_add(&connector->base,
 142                                 &xylon_drm_connector_helper_funcs);
 143
 144        ret = drm_connector_register(&connector->base);
 145        if (ret) {
 146                DRM_ERROR("failed register encoder connector\n");
 147                goto err_register;
 148        }
 149
 150        ret = drm_mode_connector_attach_encoder(&connector->base, base_encoder);
 151        if (ret) {
 152                DRM_ERROR("failed attach encoder connector\n");
 153                goto err_attach;
 154        }
 155        connector->encoder = base_encoder;
 156
 157        return &connector->base;
 158
 159err_attach:
 160        drm_connector_unregister(&connector->base);
 161err_register:
 162        drm_connector_cleanup(&connector->base);
 163        return ERR_PTR(ret);
 164}
 165