root/drivers/gpu/drm/drm_modeset_helper.c

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

DEFINITIONS

This source file includes following definitions.
  1. drm_helper_move_panel_connectors_to_head
  2. drm_helper_mode_fill_fb_struct
  3. create_primary_plane
  4. drm_crtc_init
  5. drm_mode_config_helper_suspend
  6. drm_mode_config_helper_resume

   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 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         INIT_LIST_HEAD(&panel_list);
  55 
  56         spin_lock_irq(&dev->mode_config.connector_list_lock);
  57         list_for_each_entry_safe(connector, tmp,
  58                                  &dev->mode_config.connector_list, head) {
  59                 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
  60                     connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
  61                     connector->connector_type == DRM_MODE_CONNECTOR_DSI)
  62                         list_move_tail(&connector->head, &panel_list);
  63         }
  64 
  65         list_splice(&panel_list, &dev->mode_config.connector_list);
  66         spin_unlock_irq(&dev->mode_config.connector_list_lock);
  67 }
  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 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         fb->dev = dev;
  86         fb->format = drm_get_format_info(dev, mode_cmd);
  87         fb->width = mode_cmd->width;
  88         fb->height = mode_cmd->height;
  89         for (i = 0; i < 4; i++) {
  90                 fb->pitches[i] = mode_cmd->pitches[i];
  91                 fb->offsets[i] = mode_cmd->offsets[i];
  92         }
  93         fb->modifier = mode_cmd->modifier[0];
  94         fb->flags = mode_cmd->flags;
  95 }
  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 static struct drm_plane *create_primary_plane(struct drm_device *dev)
 111 {
 112         struct drm_plane *primary;
 113         int ret;
 114 
 115         primary = kzalloc(sizeof(*primary), GFP_KERNEL);
 116         if (primary == NULL) {
 117                 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
 118                 return NULL;
 119         }
 120 
 121         /*
 122          * Remove the format_default field from drm_plane when dropping
 123          * this helper.
 124          */
 125         primary->format_default = true;
 126 
 127         /* possible_crtc's will be filled in later by crtc_init */
 128         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         if (ret) {
 135                 kfree(primary);
 136                 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 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         primary = create_primary_plane(dev);
 175         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 int drm_mode_config_helper_suspend(struct drm_device *dev)
 196 {
 197         struct drm_atomic_state *state;
 198 
 199         if (!dev)
 200                 return 0;
 201 
 202         drm_kms_helper_poll_disable(dev);
 203         drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
 204         state = drm_atomic_helper_suspend(dev);
 205         if (IS_ERR(state)) {
 206                 drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
 207                 drm_kms_helper_poll_enable(dev);
 208                 return PTR_ERR(state);
 209         }
 210 
 211         dev->mode_config.suspend_state = state;
 212 
 213         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 int drm_mode_config_helper_resume(struct drm_device *dev)
 232 {
 233         int ret;
 234 
 235         if (!dev)
 236                 return 0;
 237 
 238         if (WARN_ON(!dev->mode_config.suspend_state))
 239                 return -EINVAL;
 240 
 241         ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
 242         if (ret)
 243                 DRM_ERROR("Failed to resume (%d)\n", ret);
 244         dev->mode_config.suspend_state = NULL;
 245 
 246         drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
 247         drm_kms_helper_poll_enable(dev);
 248 
 249         return ret;
 250 }
 251 EXPORT_SYMBOL(drm_mode_config_helper_resume);

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