root/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c

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

DEFINITIONS

This source file includes following definitions.
  1. fsl_dcu_drm_encoder_destroy
  2. fsl_dcu_drm_encoder_create
  3. fsl_dcu_drm_connector_destroy
  4. fsl_dcu_drm_connector_get_modes
  5. fsl_dcu_drm_connector_mode_valid
  6. fsl_dcu_attach_panel
  7. fsl_dcu_create_outputs

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2015 Freescale Semiconductor, Inc.
   4  *
   5  * Freescale DCU drm device driver
   6  */
   7 
   8 #include <linux/backlight.h>
   9 #include <linux/of_graph.h>
  10 
  11 #include <drm/drm_atomic_helper.h>
  12 #include <drm/drm_of.h>
  13 #include <drm/drm_panel.h>
  14 #include <drm/drm_probe_helper.h>
  15 
  16 #include "fsl_dcu_drm_drv.h"
  17 #include "fsl_tcon.h"
  18 
  19 static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
  20 {
  21         drm_encoder_cleanup(encoder);
  22 }
  23 
  24 static const struct drm_encoder_funcs encoder_funcs = {
  25         .destroy = fsl_dcu_drm_encoder_destroy,
  26 };
  27 
  28 int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
  29                                struct drm_crtc *crtc)
  30 {
  31         struct drm_encoder *encoder = &fsl_dev->encoder;
  32         int ret;
  33 
  34         encoder->possible_crtcs = 1;
  35 
  36         /* Use bypass mode for parallel RGB/LVDS encoder */
  37         if (fsl_dev->tcon)
  38                 fsl_tcon_bypass_enable(fsl_dev->tcon);
  39 
  40         ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs,
  41                                DRM_MODE_ENCODER_LVDS, NULL);
  42         if (ret < 0)
  43                 return ret;
  44 
  45         return 0;
  46 }
  47 
  48 static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
  49 {
  50         struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
  51 
  52         drm_connector_unregister(connector);
  53         drm_panel_detach(fsl_con->panel);
  54         drm_connector_cleanup(connector);
  55 }
  56 
  57 static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
  58         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  59         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  60         .destroy = fsl_dcu_drm_connector_destroy,
  61         .fill_modes = drm_helper_probe_single_connector_modes,
  62         .reset = drm_atomic_helper_connector_reset,
  63 };
  64 
  65 static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
  66 {
  67         struct fsl_dcu_drm_connector *fsl_connector;
  68 
  69         fsl_connector = to_fsl_dcu_connector(connector);
  70         return drm_panel_get_modes(fsl_connector->panel);
  71 }
  72 
  73 static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
  74                                             struct drm_display_mode *mode)
  75 {
  76         if (mode->hdisplay & 0xf)
  77                 return MODE_ERROR;
  78 
  79         return MODE_OK;
  80 }
  81 
  82 static const struct drm_connector_helper_funcs connector_helper_funcs = {
  83         .get_modes = fsl_dcu_drm_connector_get_modes,
  84         .mode_valid = fsl_dcu_drm_connector_mode_valid,
  85 };
  86 
  87 static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
  88                                  struct drm_panel *panel)
  89 {
  90         struct drm_encoder *encoder = &fsl_dev->encoder;
  91         struct drm_connector *connector = &fsl_dev->connector.base;
  92         int ret;
  93 
  94         fsl_dev->connector.encoder = encoder;
  95 
  96         ret = drm_connector_init(fsl_dev->drm, connector,
  97                                  &fsl_dcu_drm_connector_funcs,
  98                                  DRM_MODE_CONNECTOR_LVDS);
  99         if (ret < 0)
 100                 return ret;
 101 
 102         drm_connector_helper_add(connector, &connector_helper_funcs);
 103         ret = drm_connector_register(connector);
 104         if (ret < 0)
 105                 goto err_cleanup;
 106 
 107         ret = drm_connector_attach_encoder(connector, encoder);
 108         if (ret < 0)
 109                 goto err_sysfs;
 110 
 111         ret = drm_panel_attach(panel, connector);
 112         if (ret) {
 113                 dev_err(fsl_dev->dev, "failed to attach panel\n");
 114                 goto err_sysfs;
 115         }
 116 
 117         return 0;
 118 
 119 err_sysfs:
 120         drm_connector_unregister(connector);
 121 err_cleanup:
 122         drm_connector_cleanup(connector);
 123         return ret;
 124 }
 125 
 126 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 127 {
 128         struct device_node *panel_node;
 129         struct drm_panel *panel;
 130         struct drm_bridge *bridge;
 131         int ret;
 132 
 133         /* This is for backward compatibility */
 134         panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
 135         if (panel_node) {
 136                 fsl_dev->connector.panel = of_drm_find_panel(panel_node);
 137                 of_node_put(panel_node);
 138                 if (IS_ERR(fsl_dev->connector.panel))
 139                         return PTR_ERR(fsl_dev->connector.panel);
 140 
 141                 return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
 142         }
 143 
 144         ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
 145         if (ret)
 146                 return ret;
 147 
 148         if (panel) {
 149                 fsl_dev->connector.panel = panel;
 150                 return fsl_dcu_attach_panel(fsl_dev, panel);
 151         }
 152 
 153         return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 154 }

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