LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_encoder.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 91 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 9 0.0 %

          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             : 
      31             : #include "drm_crtc_internal.h"
      32             : 
      33             : /**
      34             :  * DOC: overview
      35             :  *
      36             :  * Encoders represent the connecting element between the CRTC (as the overall
      37             :  * pixel pipeline, represented by &struct drm_crtc) and the connectors (as the
      38             :  * generic sink entity, represented by &struct drm_connector). An encoder takes
      39             :  * pixel data from a CRTC and converts it to a format suitable for any attached
      40             :  * connector. Encoders are objects exposed to userspace, originally to allow
      41             :  * userspace to infer cloning and connector/CRTC restrictions. Unfortunately
      42             :  * almost all drivers get this wrong, making the uabi pretty much useless. On
      43             :  * top of that the exposed restrictions are too simple for today's hardware, and
      44             :  * the recommended way to infer restrictions is by using the
      45             :  * DRM_MODE_ATOMIC_TEST_ONLY flag for the atomic IOCTL.
      46             :  *
      47             :  * Otherwise encoders aren't used in the uapi at all (any modeset request from
      48             :  * userspace directly connects a connector with a CRTC), drivers are therefore
      49             :  * free to use them however they wish. Modeset helper libraries make strong use
      50             :  * of encoders to facilitate code sharing. But for more complex settings it is
      51             :  * usually better to move shared code into a separate &drm_bridge. Compared to
      52             :  * encoders, bridges also have the benefit of being purely an internal
      53             :  * abstraction since they are not exposed to userspace at all.
      54             :  *
      55             :  * Encoders are initialized with drm_encoder_init() and cleaned up using
      56             :  * drm_encoder_cleanup().
      57             :  */
      58             : static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
      59             :         { DRM_MODE_ENCODER_NONE, "None" },
      60             :         { DRM_MODE_ENCODER_DAC, "DAC" },
      61             :         { DRM_MODE_ENCODER_TMDS, "TMDS" },
      62             :         { DRM_MODE_ENCODER_LVDS, "LVDS" },
      63             :         { DRM_MODE_ENCODER_TVDAC, "TV" },
      64             :         { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
      65             :         { DRM_MODE_ENCODER_DSI, "DSI" },
      66             :         { DRM_MODE_ENCODER_DPMST, "DP MST" },
      67             :         { DRM_MODE_ENCODER_DPI, "DPI" },
      68             : };
      69             : 
      70           0 : int drm_encoder_register_all(struct drm_device *dev)
      71             : {
      72             :         struct drm_encoder *encoder;
      73           0 :         int ret = 0;
      74             : 
      75           0 :         drm_for_each_encoder(encoder, dev) {
      76           0 :                 if (encoder->funcs && encoder->funcs->late_register)
      77           0 :                         ret = encoder->funcs->late_register(encoder);
      78           0 :                 if (ret)
      79             :                         return ret;
      80             :         }
      81             : 
      82             :         return 0;
      83             : }
      84             : 
      85           0 : void drm_encoder_unregister_all(struct drm_device *dev)
      86             : {
      87             :         struct drm_encoder *encoder;
      88             : 
      89           0 :         drm_for_each_encoder(encoder, dev) {
      90           0 :                 if (encoder->funcs && encoder->funcs->early_unregister)
      91           0 :                         encoder->funcs->early_unregister(encoder);
      92             :         }
      93           0 : }
      94             : 
      95             : __printf(5, 0)
      96           0 : static int __drm_encoder_init(struct drm_device *dev,
      97             :                               struct drm_encoder *encoder,
      98             :                               const struct drm_encoder_funcs *funcs,
      99             :                               int encoder_type, const char *name, va_list ap)
     100             : {
     101             :         int ret;
     102             : 
     103             :         /* encoder index is used with 32bit bitmasks */
     104           0 :         if (WARN_ON(dev->mode_config.num_encoder >= 32))
     105             :                 return -EINVAL;
     106             : 
     107           0 :         ret = drm_mode_object_add(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
     108           0 :         if (ret)
     109             :                 return ret;
     110             : 
     111           0 :         encoder->dev = dev;
     112           0 :         encoder->encoder_type = encoder_type;
     113           0 :         encoder->funcs = funcs;
     114           0 :         if (name) {
     115           0 :                 encoder->name = kvasprintf(GFP_KERNEL, name, ap);
     116             :         } else {
     117           0 :                 encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
     118             :                                           drm_encoder_enum_list[encoder_type].name,
     119             :                                           encoder->base.id);
     120             :         }
     121           0 :         if (!encoder->name) {
     122             :                 ret = -ENOMEM;
     123             :                 goto out_put;
     124             :         }
     125             : 
     126           0 :         INIT_LIST_HEAD(&encoder->bridge_chain);
     127           0 :         list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
     128           0 :         encoder->index = dev->mode_config.num_encoder++;
     129             : 
     130             : out_put:
     131           0 :         if (ret)
     132           0 :                 drm_mode_object_unregister(dev, &encoder->base);
     133             : 
     134             :         return ret;
     135             : }
     136             : 
     137             : /**
     138             :  * drm_encoder_init - Init a preallocated encoder
     139             :  * @dev: drm device
     140             :  * @encoder: the encoder to init
     141             :  * @funcs: callbacks for this encoder
     142             :  * @encoder_type: user visible type of the encoder
     143             :  * @name: printf style format string for the encoder name, or NULL for default name
     144             :  *
     145             :  * Initializes a preallocated encoder. Encoder should be subclassed as part of
     146             :  * driver encoder objects. At driver unload time the driver's
     147             :  * &drm_encoder_funcs.destroy hook should call drm_encoder_cleanup() and kfree()
     148             :  * the encoder structure. The encoder structure should not be allocated with
     149             :  * devm_kzalloc().
     150             :  *
     151             :  * Note: consider using drmm_encoder_alloc() instead of drm_encoder_init() to
     152             :  * let the DRM managed resource infrastructure take care of cleanup and
     153             :  * deallocation.
     154             :  *
     155             :  * Returns:
     156             :  * Zero on success, error code on failure.
     157             :  */
     158           0 : int drm_encoder_init(struct drm_device *dev,
     159             :                      struct drm_encoder *encoder,
     160             :                      const struct drm_encoder_funcs *funcs,
     161             :                      int encoder_type, const char *name, ...)
     162             : {
     163             :         va_list ap;
     164             :         int ret;
     165             : 
     166           0 :         WARN_ON(!funcs->destroy);
     167             : 
     168           0 :         va_start(ap, name);
     169           0 :         ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
     170           0 :         va_end(ap);
     171             : 
     172           0 :         return ret;
     173             : }
     174             : EXPORT_SYMBOL(drm_encoder_init);
     175             : 
     176             : /**
     177             :  * drm_encoder_cleanup - cleans up an initialised encoder
     178             :  * @encoder: encoder to cleanup
     179             :  *
     180             :  * Cleans up the encoder but doesn't free the object.
     181             :  */
     182           0 : void drm_encoder_cleanup(struct drm_encoder *encoder)
     183             : {
     184           0 :         struct drm_device *dev = encoder->dev;
     185             :         struct drm_bridge *bridge, *next;
     186             : 
     187             :         /* Note that the encoder_list is considered to be static; should we
     188             :          * remove the drm_encoder at runtime we would have to decrement all
     189             :          * the indices on the drm_encoder after us in the encoder_list.
     190             :          */
     191             : 
     192           0 :         list_for_each_entry_safe(bridge, next, &encoder->bridge_chain,
     193             :                                  chain_node)
     194           0 :                 drm_bridge_detach(bridge);
     195             : 
     196           0 :         drm_mode_object_unregister(dev, &encoder->base);
     197           0 :         kfree(encoder->name);
     198           0 :         list_del(&encoder->head);
     199           0 :         dev->mode_config.num_encoder--;
     200             : 
     201           0 :         memset(encoder, 0, sizeof(*encoder));
     202           0 : }
     203             : EXPORT_SYMBOL(drm_encoder_cleanup);
     204             : 
     205           0 : static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr)
     206             : {
     207           0 :         struct drm_encoder *encoder = ptr;
     208             : 
     209           0 :         if (WARN_ON(!encoder->dev))
     210             :                 return;
     211             : 
     212           0 :         drm_encoder_cleanup(encoder);
     213             : }
     214             : 
     215           0 : void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
     216             :                            const struct drm_encoder_funcs *funcs,
     217             :                            int encoder_type, const char *name, ...)
     218             : {
     219             :         void *container;
     220             :         struct drm_encoder *encoder;
     221             :         va_list ap;
     222             :         int ret;
     223             : 
     224           0 :         if (WARN_ON(funcs && funcs->destroy))
     225             :                 return ERR_PTR(-EINVAL);
     226             : 
     227           0 :         container = drmm_kzalloc(dev, size, GFP_KERNEL);
     228           0 :         if (!container)
     229             :                 return ERR_PTR(-EINVAL);
     230             : 
     231           0 :         encoder = container + offset;
     232             : 
     233           0 :         va_start(ap, name);
     234           0 :         ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
     235           0 :         va_end(ap);
     236           0 :         if (ret)
     237           0 :                 return ERR_PTR(ret);
     238             : 
     239           0 :         ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
     240           0 :         if (ret)
     241           0 :                 return ERR_PTR(ret);
     242             : 
     243             :         return container;
     244             : }
     245             : EXPORT_SYMBOL(__drmm_encoder_alloc);
     246             : 
     247           0 : static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
     248             : {
     249             :         struct drm_connector *connector;
     250           0 :         struct drm_device *dev = encoder->dev;
     251           0 :         bool uses_atomic = false;
     252             :         struct drm_connector_list_iter conn_iter;
     253             : 
     254             :         /* For atomic drivers only state objects are synchronously updated and
     255             :          * protected by modeset locks, so check those first. */
     256           0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     257           0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     258           0 :                 if (!connector->state)
     259           0 :                         continue;
     260             : 
     261           0 :                 uses_atomic = true;
     262             : 
     263           0 :                 if (connector->state->best_encoder != encoder)
     264           0 :                         continue;
     265             : 
     266           0 :                 drm_connector_list_iter_end(&conn_iter);
     267           0 :                 return connector->state->crtc;
     268             :         }
     269           0 :         drm_connector_list_iter_end(&conn_iter);
     270             : 
     271             :         /* Don't return stale data (e.g. pending async disable). */
     272           0 :         if (uses_atomic)
     273             :                 return NULL;
     274             : 
     275           0 :         return encoder->crtc;
     276             : }
     277             : 
     278           0 : int drm_mode_getencoder(struct drm_device *dev, void *data,
     279             :                         struct drm_file *file_priv)
     280             : {
     281           0 :         struct drm_mode_get_encoder *enc_resp = data;
     282             :         struct drm_encoder *encoder;
     283             :         struct drm_crtc *crtc;
     284             : 
     285           0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     286             :                 return -EOPNOTSUPP;
     287             : 
     288           0 :         encoder = drm_encoder_find(dev, file_priv, enc_resp->encoder_id);
     289           0 :         if (!encoder)
     290             :                 return -ENOENT;
     291             : 
     292           0 :         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
     293           0 :         crtc = drm_encoder_get_crtc(encoder);
     294           0 :         if (crtc && drm_lease_held(file_priv, crtc->base.id))
     295           0 :                 enc_resp->crtc_id = crtc->base.id;
     296             :         else
     297           0 :                 enc_resp->crtc_id = 0;
     298           0 :         drm_modeset_unlock(&dev->mode_config.connection_mutex);
     299             : 
     300           0 :         enc_resp->encoder_type = encoder->encoder_type;
     301           0 :         enc_resp->encoder_id = encoder->base.id;
     302           0 :         enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
     303             :                                                           encoder->possible_crtcs);
     304           0 :         enc_resp->possible_clones = encoder->possible_clones;
     305             : 
     306           0 :         return 0;
     307             : }

Generated by: LCOV version 1.14