linux/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
<<
>>
Prefs
   1/*
   2 * rcar_du_encoder.c  --  R-Car Display Unit Encoder
   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 <linux/export.h>
  15
  16#include <drm/drmP.h>
  17#include <drm/drm_crtc.h>
  18#include <drm/drm_crtc_helper.h>
  19#include <drm/drm_panel.h>
  20
  21#include "rcar_du_drv.h"
  22#include "rcar_du_encoder.h"
  23#include "rcar_du_kms.h"
  24
  25/* -----------------------------------------------------------------------------
  26 * Encoder
  27 */
  28
  29static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
  30                                     struct drm_crtc_state *crtc_state,
  31                                     struct drm_connector_state *conn_state)
  32{
  33        struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
  34
  35        rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
  36}
  37
  38static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
  39        .atomic_mode_set = rcar_du_encoder_mode_set,
  40};
  41
  42static const struct drm_encoder_funcs encoder_funcs = {
  43        .destroy = drm_encoder_cleanup,
  44};
  45
  46int rcar_du_encoder_init(struct rcar_du_device *rcdu,
  47                         enum rcar_du_output output,
  48                         struct device_node *enc_node,
  49                         struct device_node *con_node)
  50{
  51        struct rcar_du_encoder *renc;
  52        struct drm_encoder *encoder;
  53        struct drm_bridge *bridge = NULL;
  54        int ret;
  55
  56        renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
  57        if (renc == NULL)
  58                return -ENOMEM;
  59
  60        renc->output = output;
  61        encoder = rcar_encoder_to_drm_encoder(renc);
  62
  63        dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n",
  64                enc_node, output);
  65
  66        /* Locate the DRM bridge from the encoder DT node. */
  67        bridge = of_drm_find_bridge(enc_node);
  68        if (!bridge) {
  69                ret = -EPROBE_DEFER;
  70                goto done;
  71        }
  72
  73        ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
  74                               DRM_MODE_ENCODER_NONE, NULL);
  75        if (ret < 0)
  76                goto done;
  77
  78        drm_encoder_helper_add(encoder, &encoder_helper_funcs);
  79
  80        /*
  81         * Attach the bridge to the encoder. The bridge will create the
  82         * connector.
  83         */
  84        ret = drm_bridge_attach(encoder, bridge, NULL);
  85        if (ret) {
  86                drm_encoder_cleanup(encoder);
  87                return ret;
  88        }
  89
  90done:
  91        if (ret < 0) {
  92                if (encoder->name)
  93                        encoder->funcs->destroy(encoder);
  94                devm_kfree(rcdu->dev, renc);
  95        }
  96
  97        return ret;
  98}
  99