linux/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
<<
>>
Prefs
   1/*
   2 * rcar_du_lvdscon.c  --  R-Car Display Unit LVDS Connector
   3 *
   4 * Copyright (C) 2013-2014 Renesas Electronics Corporation
   5 *
   6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 */
  13
  14#include <drm/drmP.h>
  15#include <drm/drm_atomic_helper.h>
  16#include <drm/drm_crtc.h>
  17#include <drm/drm_crtc_helper.h>
  18#include <drm/drm_panel.h>
  19
  20#include <video/display_timing.h>
  21#include <video/of_display_timing.h>
  22#include <video/videomode.h>
  23
  24#include "rcar_du_drv.h"
  25#include "rcar_du_encoder.h"
  26#include "rcar_du_kms.h"
  27#include "rcar_du_lvdscon.h"
  28
  29static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
  30{
  31        struct rcar_du_connector *rcon = to_rcar_connector(connector);
  32
  33        return drm_panel_get_modes(rcon->panel);
  34}
  35
  36static const struct drm_connector_helper_funcs connector_helper_funcs = {
  37        .get_modes = rcar_du_lvds_connector_get_modes,
  38};
  39
  40static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
  41{
  42        struct rcar_du_connector *rcon = to_rcar_connector(connector);
  43
  44        drm_panel_detach(rcon->panel);
  45        drm_connector_cleanup(connector);
  46}
  47
  48static const struct drm_connector_funcs connector_funcs = {
  49        .reset = drm_atomic_helper_connector_reset,
  50        .fill_modes = drm_helper_probe_single_connector_modes,
  51        .destroy = rcar_du_lvds_connector_destroy,
  52        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  53        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  54};
  55
  56int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
  57                                struct rcar_du_encoder *renc,
  58                                const struct device_node *np)
  59{
  60        struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
  61        struct rcar_du_connector *rcon;
  62        struct drm_connector *connector;
  63        int ret;
  64
  65        rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
  66        if (rcon == NULL)
  67                return -ENOMEM;
  68
  69        connector = &rcon->connector;
  70
  71        rcon->panel = of_drm_find_panel(np);
  72        if (!rcon->panel)
  73                return -EPROBE_DEFER;
  74
  75        ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
  76                                 DRM_MODE_CONNECTOR_LVDS);
  77        if (ret < 0)
  78                return ret;
  79
  80        drm_connector_helper_add(connector, &connector_helper_funcs);
  81
  82        connector->dpms = DRM_MODE_DPMS_OFF;
  83        drm_object_property_set_value(&connector->base,
  84                rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
  85
  86        ret = drm_mode_connector_attach_encoder(connector, encoder);
  87        if (ret < 0)
  88                return ret;
  89
  90        ret = drm_panel_attach(rcon->panel, connector);
  91        if (ret < 0)
  92                return ret;
  93
  94        rcon->encoder = renc;
  95
  96        return 0;
  97}
  98