LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_modeset_helper.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 55 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 6 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 <drm/drm_atomic_helper.h>
      24             : #include <drm/drm_fb_helper.h>
      25             : #include <drm/drm_fourcc.h>
      26             : #include <drm/drm_modeset_helper.h>
      27             : #include <drm/drm_plane_helper.h>
      28             : #include <drm/drm_print.h>
      29             : #include <drm/drm_probe_helper.h>
      30             : 
      31             : /**
      32             :  * DOC: aux kms helpers
      33             :  *
      34             :  * This helper library contains various one-off functions which don't really fit
      35             :  * anywhere else in the DRM modeset helper library.
      36             :  */
      37             : 
      38             : /**
      39             :  * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
      40             :  *                                              connector list
      41             :  * @dev: drm device to operate on
      42             :  *
      43             :  * Some userspace presumes that the first connected connector is the main
      44             :  * display, where it's supposed to display e.g. the login screen. For
      45             :  * laptops, this should be the main panel. Use this function to sort all
      46             :  * (eDP/LVDS/DSI) panels to the front of the connector list, instead of
      47             :  * painstakingly trying to initialize them in the right order.
      48             :  */
      49           0 : void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
      50             : {
      51             :         struct drm_connector *connector, *tmp;
      52             :         struct list_head panel_list;
      53             : 
      54           0 :         INIT_LIST_HEAD(&panel_list);
      55             : 
      56           0 :         spin_lock_irq(&dev->mode_config.connector_list_lock);
      57           0 :         list_for_each_entry_safe(connector, tmp,
      58             :                                  &dev->mode_config.connector_list, head) {
      59           0 :                 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
      60           0 :                     connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
      61             :                     connector->connector_type == DRM_MODE_CONNECTOR_DSI)
      62           0 :                         list_move_tail(&connector->head, &panel_list);
      63             :         }
      64             : 
      65           0 :         list_splice(&panel_list, &dev->mode_config.connector_list);
      66           0 :         spin_unlock_irq(&dev->mode_config.connector_list_lock);
      67           0 : }
      68             : EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
      69             : 
      70             : /**
      71             :  * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
      72             :  * @dev: DRM device
      73             :  * @fb: drm_framebuffer object to fill out
      74             :  * @mode_cmd: metadata from the userspace fb creation request
      75             :  *
      76             :  * This helper can be used in a drivers fb_create callback to pre-fill the fb's
      77             :  * metadata fields.
      78             :  */
      79           0 : void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
      80             :                                     struct drm_framebuffer *fb,
      81             :                                     const struct drm_mode_fb_cmd2 *mode_cmd)
      82             : {
      83             :         int i;
      84             : 
      85           0 :         fb->dev = dev;
      86           0 :         fb->format = drm_get_format_info(dev, mode_cmd);
      87           0 :         fb->width = mode_cmd->width;
      88           0 :         fb->height = mode_cmd->height;
      89           0 :         for (i = 0; i < 4; i++) {
      90           0 :                 fb->pitches[i] = mode_cmd->pitches[i];
      91           0 :                 fb->offsets[i] = mode_cmd->offsets[i];
      92             :         }
      93           0 :         fb->modifier = mode_cmd->modifier[0];
      94           0 :         fb->flags = mode_cmd->flags;
      95           0 : }
      96             : EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
      97             : 
      98             : /*
      99             :  * This is the minimal list of formats that seem to be safe for modeset use
     100             :  * with all current DRM drivers.  Most hardware can actually support more
     101             :  * formats than this and drivers may specify a more accurate list when
     102             :  * creating the primary plane.  However drivers that still call
     103             :  * drm_plane_init() will use this minimal format list as the default.
     104             :  */
     105             : static const uint32_t safe_modeset_formats[] = {
     106             :         DRM_FORMAT_XRGB8888,
     107             :         DRM_FORMAT_ARGB8888,
     108             : };
     109             : 
     110           0 : static struct drm_plane *create_primary_plane(struct drm_device *dev)
     111             : {
     112             :         struct drm_plane *primary;
     113             :         int ret;
     114             : 
     115           0 :         primary = kzalloc(sizeof(*primary), GFP_KERNEL);
     116           0 :         if (primary == NULL) {
     117           0 :                 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
     118           0 :                 return NULL;
     119             :         }
     120             : 
     121             :         /*
     122             :          * Remove the format_default field from drm_plane when dropping
     123             :          * this helper.
     124             :          */
     125           0 :         primary->format_default = true;
     126             : 
     127             :         /* possible_crtc's will be filled in later by crtc_init */
     128           0 :         ret = drm_universal_plane_init(dev, primary, 0,
     129             :                                        &drm_primary_helper_funcs,
     130             :                                        safe_modeset_formats,
     131             :                                        ARRAY_SIZE(safe_modeset_formats),
     132             :                                        NULL,
     133             :                                        DRM_PLANE_TYPE_PRIMARY, NULL);
     134           0 :         if (ret) {
     135           0 :                 kfree(primary);
     136           0 :                 primary = NULL;
     137             :         }
     138             : 
     139             :         return primary;
     140             : }
     141             : 
     142             : /**
     143             :  * drm_crtc_init - Legacy CRTC initialization function
     144             :  * @dev: DRM device
     145             :  * @crtc: CRTC object to init
     146             :  * @funcs: callbacks for the new CRTC
     147             :  *
     148             :  * Initialize a CRTC object with a default helper-provided primary plane and no
     149             :  * cursor plane.
     150             :  *
     151             :  * Note that we make some assumptions about hardware limitations that may not be
     152             :  * true for all hardware:
     153             :  *
     154             :  * 1. Primary plane cannot be repositioned.
     155             :  * 2. Primary plane cannot be scaled.
     156             :  * 3. Primary plane must cover the entire CRTC.
     157             :  * 4. Subpixel positioning is not supported.
     158             :  * 5. The primary plane must always be on if the CRTC is enabled.
     159             :  *
     160             :  * This is purely a backwards compatibility helper for old drivers. Drivers
     161             :  * should instead implement their own primary plane. Atomic drivers must do so.
     162             :  * Drivers with the above hardware restriction can look into using &struct
     163             :  * drm_simple_display_pipe, which encapsulates the above limitations into a nice
     164             :  * interface.
     165             :  *
     166             :  * Returns:
     167             :  * Zero on success, error code on failure.
     168             :  */
     169           0 : int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
     170             :                   const struct drm_crtc_funcs *funcs)
     171             : {
     172             :         struct drm_plane *primary;
     173             : 
     174           0 :         primary = create_primary_plane(dev);
     175           0 :         return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
     176             :                                          NULL);
     177             : }
     178             : EXPORT_SYMBOL(drm_crtc_init);
     179             : 
     180             : /**
     181             :  * drm_mode_config_helper_suspend - Modeset suspend helper
     182             :  * @dev: DRM device
     183             :  *
     184             :  * This helper function takes care of suspending the modeset side. It disables
     185             :  * output polling if initialized, suspends fbdev if used and finally calls
     186             :  * drm_atomic_helper_suspend().
     187             :  * If suspending fails, fbdev and polling is re-enabled.
     188             :  *
     189             :  * Returns:
     190             :  * Zero on success, negative error code on error.
     191             :  *
     192             :  * See also:
     193             :  * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked().
     194             :  */
     195           0 : int drm_mode_config_helper_suspend(struct drm_device *dev)
     196             : {
     197             :         struct drm_atomic_state *state;
     198             : 
     199           0 :         if (!dev)
     200             :                 return 0;
     201             : 
     202           0 :         drm_kms_helper_poll_disable(dev);
     203           0 :         drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
     204           0 :         state = drm_atomic_helper_suspend(dev);
     205           0 :         if (IS_ERR(state)) {
     206           0 :                 drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
     207           0 :                 drm_kms_helper_poll_enable(dev);
     208           0 :                 return PTR_ERR(state);
     209             :         }
     210             : 
     211           0 :         dev->mode_config.suspend_state = state;
     212             : 
     213           0 :         return 0;
     214             : }
     215             : EXPORT_SYMBOL(drm_mode_config_helper_suspend);
     216             : 
     217             : /**
     218             :  * drm_mode_config_helper_resume - Modeset resume helper
     219             :  * @dev: DRM device
     220             :  *
     221             :  * This helper function takes care of resuming the modeset side. It calls
     222             :  * drm_atomic_helper_resume(), resumes fbdev if used and enables output polling
     223             :  * if initiaized.
     224             :  *
     225             :  * Returns:
     226             :  * Zero on success, negative error code on error.
     227             :  *
     228             :  * See also:
     229             :  * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable().
     230             :  */
     231           0 : int drm_mode_config_helper_resume(struct drm_device *dev)
     232             : {
     233             :         int ret;
     234             : 
     235           0 :         if (!dev)
     236             :                 return 0;
     237             : 
     238           0 :         if (WARN_ON(!dev->mode_config.suspend_state))
     239             :                 return -EINVAL;
     240             : 
     241           0 :         ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
     242           0 :         if (ret)
     243           0 :                 DRM_ERROR("Failed to resume (%d)\n", ret);
     244           0 :         dev->mode_config.suspend_state = NULL;
     245             : 
     246           0 :         drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
     247           0 :         drm_kms_helper_poll_enable(dev);
     248             : 
     249           0 :         return ret;
     250             : }
     251             : EXPORT_SYMBOL(drm_mode_config_helper_resume);

Generated by: LCOV version 1.14