root/drivers/gpu/drm/rcar-du/rcar_du_encoder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rcar_du_encoder_count_ports
  2. rcar_du_encoder_init

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * rcar_du_encoder.c  --  R-Car Display Unit Encoder
   4  *
   5  * Copyright (C) 2013-2014 Renesas Electronics Corporation
   6  *
   7  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   8  */
   9 
  10 #include <linux/export.h>
  11 
  12 #include <drm/drm_crtc.h>
  13 #include <drm/drm_modeset_helper_vtables.h>
  14 #include <drm/drm_panel.h>
  15 
  16 #include "rcar_du_drv.h"
  17 #include "rcar_du_encoder.h"
  18 #include "rcar_du_kms.h"
  19 #include "rcar_lvds.h"
  20 
  21 /* -----------------------------------------------------------------------------
  22  * Encoder
  23  */
  24 
  25 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
  26 };
  27 
  28 static const struct drm_encoder_funcs encoder_funcs = {
  29         .destroy = drm_encoder_cleanup,
  30 };
  31 
  32 static unsigned int rcar_du_encoder_count_ports(struct device_node *node)
  33 {
  34         struct device_node *ports;
  35         struct device_node *port;
  36         unsigned int num_ports = 0;
  37 
  38         ports = of_get_child_by_name(node, "ports");
  39         if (!ports)
  40                 ports = of_node_get(node);
  41 
  42         for_each_child_of_node(ports, port) {
  43                 if (of_node_name_eq(port, "port"))
  44                         num_ports++;
  45         }
  46 
  47         of_node_put(ports);
  48 
  49         return num_ports;
  50 }
  51 
  52 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
  53                          enum rcar_du_output output,
  54                          struct device_node *enc_node)
  55 {
  56         struct rcar_du_encoder *renc;
  57         struct drm_encoder *encoder;
  58         struct drm_bridge *bridge;
  59         int ret;
  60 
  61         renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
  62         if (renc == NULL)
  63                 return -ENOMEM;
  64 
  65         rcdu->encoders[output] = renc;
  66         renc->output = output;
  67         encoder = rcar_encoder_to_drm_encoder(renc);
  68 
  69         dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n",
  70                 enc_node, output);
  71 
  72         /*
  73          * Locate the DRM bridge from the DT node. For the DPAD outputs, if the
  74          * DT node has a single port, assume that it describes a panel and
  75          * create a panel bridge.
  76          */
  77         if ((output == RCAR_DU_OUTPUT_DPAD0 ||
  78              output == RCAR_DU_OUTPUT_DPAD1) &&
  79             rcar_du_encoder_count_ports(enc_node) == 1) {
  80                 struct drm_panel *panel = of_drm_find_panel(enc_node);
  81 
  82                 if (IS_ERR(panel)) {
  83                         ret = PTR_ERR(panel);
  84                         goto done;
  85                 }
  86 
  87                 bridge = devm_drm_panel_bridge_add(rcdu->dev, panel,
  88                                                    DRM_MODE_CONNECTOR_DPI);
  89                 if (IS_ERR(bridge)) {
  90                         ret = PTR_ERR(bridge);
  91                         goto done;
  92                 }
  93         } else {
  94                 bridge = of_drm_find_bridge(enc_node);
  95                 if (!bridge) {
  96                         ret = -EPROBE_DEFER;
  97                         goto done;
  98                 }
  99         }
 100 
 101         /*
 102          * On Gen3 skip the LVDS1 output if the LVDS1 encoder is used as a
 103          * companion for LVDS0 in dual-link mode.
 104          */
 105         if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) {
 106                 if (rcar_lvds_dual_link(bridge)) {
 107                         ret = -ENOLINK;
 108                         goto done;
 109                 }
 110         }
 111 
 112         ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
 113                                DRM_MODE_ENCODER_NONE, NULL);
 114         if (ret < 0)
 115                 goto done;
 116 
 117         drm_encoder_helper_add(encoder, &encoder_helper_funcs);
 118 
 119         /*
 120          * Attach the bridge to the encoder. The bridge will create the
 121          * connector.
 122          */
 123         ret = drm_bridge_attach(encoder, bridge, NULL);
 124         if (ret) {
 125                 drm_encoder_cleanup(encoder);
 126                 return ret;
 127         }
 128 
 129 done:
 130         if (ret < 0) {
 131                 if (encoder->name)
 132                         encoder->funcs->destroy(encoder);
 133                 devm_kfree(rcdu->dev, renc);
 134         }
 135 
 136         return ret;
 137 }

/* [<][>][^][v][top][bottom][index][help] */