LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_encoder.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 100 6.0 %
Date: 2023-04-06 08:38:28 Functions: 2 11 18.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Intel Corporation
       3             :  *
       4             :  * Permission to use, copy, modify, distribute, and sell this software and its
       5             :  * documentation for any purpose is hereby granted without fee, provided that
       6             :  * the above copyright notice appear in all copies and that both that copyright
       7             :  * notice and this permission notice appear in supporting documentation, and
       8             :  * that the name of the copyright holders not be used in advertising or
       9             :  * publicity pertaining to distribution of the software without specific,
      10             :  * written prior permission.  The copyright holders make no representations
      11             :  * about the suitability of this software for any purpose.  It is provided "as
      12             :  * is" without express or implied warranty.
      13             :  *
      14             :  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
      15             :  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
      16             :  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
      17             :  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
      18             :  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
      19             :  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      20             :  * OF THIS SOFTWARE.
      21             :  */
      22             : 
      23             : #include <linux/export.h>
      24             : 
      25             : #include <drm/drm_bridge.h>
      26             : #include <drm/drm_device.h>
      27             : #include <drm/drm_drv.h>
      28             : #include <drm/drm_encoder.h>
      29             : #include <drm/drm_managed.h>
      30             : #include <drm/drm_print.h>
      31             : 
      32             : #include "drm_crtc_internal.h"
      33             : 
      34             : /**
      35             :  * DOC: overview
      36             :  *
      37             :  * Encoders represent the connecting element between the CRTC (as the overall
      38             :  * pixel pipeline, represented by &struct drm_crtc) and the connectors (as the
      39             :  * generic sink entity, represented by &struct drm_connector). An encoder takes
      40             :  * pixel data from a CRTC and converts it to a format suitable for any attached
      41             :  * connector. Encoders are objects exposed to userspace, originally to allow
      42             :  * userspace to infer cloning and connector/CRTC restrictions. Unfortunately
      43             :  * almost all drivers get this wrong, making the uabi pretty much useless. On
      44             :  * top of that the exposed restrictions are too simple for today's hardware, and
      45             :  * the recommended way to infer restrictions is by using the
      46             :  * DRM_MODE_ATOMIC_TEST_ONLY flag for the atomic IOCTL.
      47             :  *
      48             :  * Otherwise encoders aren't used in the uapi at all (any modeset request from
      49             :  * userspace directly connects a connector with a CRTC), drivers are therefore
      50             :  * free to use them however they wish. Modeset helper libraries make strong use
      51             :  * of encoders to facilitate code sharing. But for more complex settings it is
      52             :  * usually better to move shared code into a separate &drm_bridge. Compared to
      53             :  * encoders, bridges also have the benefit of being purely an internal
      54             :  * abstraction since they are not exposed to userspace at all.
      55             :  *
      56             :  * Encoders are initialized with drm_encoder_init() and cleaned up using
      57             :  * drm_encoder_cleanup().
      58             :  */
      59             : static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
      60             :         { DRM_MODE_ENCODER_NONE, "None" },
      61             :         { DRM_MODE_ENCODER_DAC, "DAC" },
      62             :         { DRM_MODE_ENCODER_TMDS, "TMDS" },
      63             :         { DRM_MODE_ENCODER_LVDS, "LVDS" },
      64             :         { DRM_MODE_ENCODER_TVDAC, "TV" },
      65             :         { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
      66             :         { DRM_MODE_ENCODER_DSI, "DSI" },
      67             :         { DRM_MODE_ENCODER_DPMST, "DP MST" },
      68             :         { DRM_MODE_ENCODER_DPI, "DPI" },
      69             : };
      70             : 
      71           1 : int drm_encoder_register_all(struct drm_device *dev)
      72             : {
      73             :         struct drm_encoder *encoder;
      74           1 :         int ret = 0;
      75             : 
      76           1 :         drm_for_each_encoder(encoder, dev) {
      77           0 :                 if (encoder->funcs && encoder->funcs->late_register)
      78           0 :                         ret = encoder->funcs->late_register(encoder);
      79           0 :                 if (ret)
      80             :                         return ret;
      81             :         }
      82             : 
      83             :         return 0;
      84             : }
      85             : 
      86           1 : void drm_encoder_unregister_all(struct drm_device *dev)
      87             : {
      88             :         struct drm_encoder *encoder;
      89             : 
      90           1 :         drm_for_each_encoder(encoder, dev) {
      91           0 :                 if (encoder->funcs && encoder->funcs->early_unregister)
      92           0 :                         encoder->funcs->early_unregister(encoder);
      93             :         }
      94           1 : }
      95             : 
      96             : __printf(5, 0)
      97           0 : static int __drm_encoder_init(struct drm_device *dev,
      98             :                               struct drm_encoder *encoder,
      99             :                               const struct drm_encoder_funcs *funcs,
     100             :                               int encoder_type, const char *name, va_list ap)
     101             : {
     102             :         int ret;
     103             : 
     104             :         /* encoder index is used with 32bit bitmasks */
     105           0 :         if (WARN_ON(dev->mode_config.num_encoder >= 32))
     106             :                 return -EINVAL;
     107             : 
     108           0 :         ret = drm_mode_object_add(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
     109           0 :         if (ret)
     110             :                 return ret;
     111             : 
     112           0 :         encoder->dev = dev;
     113           0 :         encoder->encoder_type = encoder_type;
     114           0 :         encoder->funcs = funcs;
     115           0 :         if (name) {
     116           0 :                 encoder->name = kvasprintf(GFP_KERNEL, name, ap);
     117             :         } else {
     118           0 :                 encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
     119             :                                           drm_encoder_enum_list[encoder_type].name,
     120             :                                           encoder->base.id);
     121             :         }
     122           0 :         if (!encoder->name) {
     123             :                 ret = -ENOMEM;
     124             :                 goto out_put;
     125             :         }
     126             : 
     127           0 :         INIT_LIST_HEAD(&encoder->bridge_chain);
     128           0 :         list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
     129           0 :         encoder->index = dev->mode_config.num_encoder++;
     130             : 
     131             : out_put:
     132           0 :         if (ret)
     133           0 :                 drm_mode_object_unregister(dev, &encoder->base);
     134             : 
     135             :         return ret;
     136             : }
     137             : 
     138             : /**
     139             :  * drm_encoder_init - Init a preallocated encoder
     140             :  * @dev: drm device
     141             :  * @encoder: the encoder to init
     142             :  * @funcs: callbacks for this encoder
     143             :  * @encoder_type: user visible type of the encoder
     144             :  * @name: printf style format string for the encoder name, or NULL for default name
     145             :  *
     146             :  * Initializes a preallocated encoder. Encoder should be subclassed as part of
     147             :  * driver encoder objects. At driver unload time the driver's
     148             :  * &drm_encoder_funcs.destroy hook should call drm_encoder_cleanup() and kfree()
     149             :  * the encoder structure. The encoder structure should not be allocated with
     150             :  * devm_kzalloc().
     151             :  *
     152             :  * Note: consider using drmm_encoder_alloc() or drmm_encoder_init()
     153             :  * instead of drm_encoder_init() to let the DRM managed resource
     154             :  * infrastructure take care of cleanup and deallocation.
     155             :  *
     156             :  * Returns:
     157             :  * Zero on success, error code on failure.
     158             :  */
     159           0 : int drm_encoder_init(struct drm_device *dev,
     160             :                      struct drm_encoder *encoder,
     161             :                      const struct drm_encoder_funcs *funcs,
     162             :                      int encoder_type, const char *name, ...)
     163             : {
     164             :         va_list ap;
     165             :         int ret;
     166             : 
     167           0 :         WARN_ON(!funcs->destroy);
     168             : 
     169           0 :         va_start(ap, name);
     170           0 :         ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
     171           0 :         va_end(ap);
     172             : 
     173           0 :         return ret;
     174             : }
     175             : EXPORT_SYMBOL(drm_encoder_init);
     176             : 
     177             : /**
     178             :  * drm_encoder_cleanup - cleans up an initialised encoder
     179             :  * @encoder: encoder to cleanup
     180             :  *
     181             :  * Cleans up the encoder but doesn't free the object.
     182             :  */
     183           0 : void drm_encoder_cleanup(struct drm_encoder *encoder)
     184             : {
     185           0 :         struct drm_device *dev = encoder->dev;
     186             :         struct drm_bridge *bridge, *next;
     187             : 
     188             :         /* Note that the encoder_list is considered to be static; should we
     189             :          * remove the drm_encoder at runtime we would have to decrement all
     190             :          * the indices on the drm_encoder after us in the encoder_list.
     191             :          */
     192             : 
     193           0 :         list_for_each_entry_safe(bridge, next, &encoder->bridge_chain,
     194             :                                  chain_node)
     195           0 :                 drm_bridge_detach(bridge);
     196             : 
     197           0 :         drm_mode_object_unregister(dev, &encoder->base);
     198           0 :         kfree(encoder->name);
     199           0 :         list_del(&encoder->head);
     200           0 :         dev->mode_config.num_encoder--;
     201             : 
     202           0 :         memset(encoder, 0, sizeof(*encoder));
     203           0 : }
     204             : EXPORT_SYMBOL(drm_encoder_cleanup);
     205             : 
     206           0 : static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr)
     207             : {
     208           0 :         struct drm_encoder *encoder = ptr;
     209             : 
     210           0 :         if (WARN_ON(!encoder->dev))
     211             :                 return;
     212             : 
     213           0 :         drm_encoder_cleanup(encoder);
     214             : }
     215             : 
     216             : __printf(5, 0)
     217           0 : static int __drmm_encoder_init(struct drm_device *dev,
     218             :                                struct drm_encoder *encoder,
     219             :                                const struct drm_encoder_funcs *funcs,
     220             :                                int encoder_type,
     221             :                                const char *name,
     222             :                                va_list args)
     223             : {
     224             :         int ret;
     225             : 
     226           0 :         if (drm_WARN_ON(dev, funcs && funcs->destroy))
     227             :                 return -EINVAL;
     228             : 
     229           0 :         ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, args);
     230           0 :         if (ret)
     231             :                 return ret;
     232             : 
     233           0 :         ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
     234           0 :         if (ret)
     235             :                 return ret;
     236             : 
     237           0 :         return 0;
     238             : }
     239             : 
     240           0 : void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
     241             :                            const struct drm_encoder_funcs *funcs,
     242             :                            int encoder_type, const char *name, ...)
     243             : {
     244             :         void *container;
     245             :         struct drm_encoder *encoder;
     246             :         va_list ap;
     247             :         int ret;
     248             : 
     249           0 :         container = drmm_kzalloc(dev, size, GFP_KERNEL);
     250           0 :         if (!container)
     251             :                 return ERR_PTR(-ENOMEM);
     252             : 
     253           0 :         encoder = container + offset;
     254             : 
     255           0 :         va_start(ap, name);
     256           0 :         ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
     257           0 :         va_end(ap);
     258           0 :         if (ret)
     259           0 :                 return ERR_PTR(ret);
     260             : 
     261             :         return container;
     262             : }
     263             : EXPORT_SYMBOL(__drmm_encoder_alloc);
     264             : 
     265             : /**
     266             :  * drmm_encoder_init - Initialize a preallocated encoder
     267             :  * @dev: drm device
     268             :  * @encoder: the encoder to init
     269             :  * @funcs: callbacks for this encoder (optional)
     270             :  * @encoder_type: user visible type of the encoder
     271             :  * @name: printf style format string for the encoder name, or NULL for default name
     272             :  *
     273             :  * Initializes a preallocated encoder. Encoder should be subclassed as
     274             :  * part of driver encoder objects. Cleanup is automatically handled
     275             :  * through registering drm_encoder_cleanup() with drmm_add_action(). The
     276             :  * encoder structure should be allocated with drmm_kzalloc().
     277             :  *
     278             :  * The @drm_encoder_funcs.destroy hook must be NULL.
     279             :  *
     280             :  * Returns:
     281             :  * Zero on success, error code on failure.
     282             :  */
     283           0 : int drmm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder,
     284             :                       const struct drm_encoder_funcs *funcs,
     285             :                       int encoder_type, const char *name, ...)
     286             : {
     287             :         va_list ap;
     288             :         int ret;
     289             : 
     290           0 :         va_start(ap, name);
     291           0 :         ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
     292           0 :         va_end(ap);
     293           0 :         if (ret)
     294             :                 return ret;
     295             : 
     296           0 :         return 0;
     297             : }
     298             : EXPORT_SYMBOL(drmm_encoder_init);
     299             : 
     300           0 : static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
     301             : {
     302             :         struct drm_connector *connector;
     303           0 :         struct drm_device *dev = encoder->dev;
     304           0 :         bool uses_atomic = false;
     305             :         struct drm_connector_list_iter conn_iter;
     306             : 
     307             :         /* For atomic drivers only state objects are synchronously updated and
     308             :          * protected by modeset locks, so check those first. */
     309           0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     310           0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     311           0 :                 if (!connector->state)
     312           0 :                         continue;
     313             : 
     314           0 :                 uses_atomic = true;
     315             : 
     316           0 :                 if (connector->state->best_encoder != encoder)
     317           0 :                         continue;
     318             : 
     319           0 :                 drm_connector_list_iter_end(&conn_iter);
     320           0 :                 return connector->state->crtc;
     321             :         }
     322           0 :         drm_connector_list_iter_end(&conn_iter);
     323             : 
     324             :         /* Don't return stale data (e.g. pending async disable). */
     325           0 :         if (uses_atomic)
     326             :                 return NULL;
     327             : 
     328           0 :         return encoder->crtc;
     329             : }
     330             : 
     331           0 : int drm_mode_getencoder(struct drm_device *dev, void *data,
     332             :                         struct drm_file *file_priv)
     333             : {
     334           0 :         struct drm_mode_get_encoder *enc_resp = data;
     335             :         struct drm_encoder *encoder;
     336             :         struct drm_crtc *crtc;
     337             : 
     338           0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     339             :                 return -EOPNOTSUPP;
     340             : 
     341           0 :         encoder = drm_encoder_find(dev, file_priv, enc_resp->encoder_id);
     342           0 :         if (!encoder)
     343             :                 return -ENOENT;
     344             : 
     345           0 :         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
     346           0 :         crtc = drm_encoder_get_crtc(encoder);
     347           0 :         if (crtc && drm_lease_held(file_priv, crtc->base.id))
     348           0 :                 enc_resp->crtc_id = crtc->base.id;
     349             :         else
     350           0 :                 enc_resp->crtc_id = 0;
     351           0 :         drm_modeset_unlock(&dev->mode_config.connection_mutex);
     352             : 
     353           0 :         enc_resp->encoder_type = encoder->encoder_type;
     354           0 :         enc_resp->encoder_id = encoder->base.id;
     355           0 :         enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
     356             :                                                           encoder->possible_crtcs);
     357           0 :         enc_resp->possible_clones = encoder->possible_clones;
     358             : 
     359           0 :         return 0;
     360             : }

Generated by: LCOV version 1.14