root/drivers/gpu/drm/drm_plane_helper.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_connectors_for_crtc
  2. drm_plane_helper_check_update
  3. drm_primary_helper_update
  4. drm_primary_helper_disable
  5. drm_primary_helper_destroy

   1 /*
   2  * Copyright (C) 2014 Intel Corporation
   3  *
   4  * DRM universal plane helper functions
   5  *
   6  * Permission is hereby granted, free of charge, to any person obtaining a
   7  * copy of this software and associated documentation files (the "Software"),
   8  * to deal in the Software without restriction, including without limitation
   9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10  * and/or sell copies of the Software, and to permit persons to whom the
  11  * Software is furnished to do so, subject to the following conditions:
  12  *
  13  * The above copyright notice and this permission notice (including the next
  14  * paragraph) shall be included in all copies or substantial portions of the
  15  * Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23  * SOFTWARE.
  24  */
  25 
  26 #include <linux/list.h>
  27 
  28 #include <drm/drm_atomic.h>
  29 #include <drm/drm_atomic_helper.h>
  30 #include <drm/drm_atomic_uapi.h>
  31 #include <drm/drm_crtc_helper.h>
  32 #include <drm/drm_device.h>
  33 #include <drm/drm_encoder.h>
  34 #include <drm/drm_plane_helper.h>
  35 #include <drm/drm_rect.h>
  36 
  37 #define SUBPIXEL_MASK 0xffff
  38 
  39 /**
  40  * DOC: overview
  41  *
  42  * This helper library has two parts. The first part has support to implement
  43  * primary plane support on top of the normal CRTC configuration interface.
  44  * Since the legacy &drm_mode_config_funcs.set_config interface ties the primary
  45  * plane together with the CRTC state this does not allow userspace to disable
  46  * the primary plane itself. The default primary plane only expose XRBG8888 and
  47  * ARGB8888 as valid pixel formats for the attached framebuffer.
  48  *
  49  * Drivers are highly recommended to implement proper support for primary
  50  * planes, and newly merged drivers must not rely upon these transitional
  51  * helpers.
  52  *
  53  * The second part also implements transitional helpers which allow drivers to
  54  * gradually switch to the atomic helper infrastructure for plane updates. Once
  55  * that switch is complete drivers shouldn't use these any longer, instead using
  56  * the proper legacy implementations for update and disable plane hooks provided
  57  * by the atomic helpers.
  58  *
  59  * Again drivers are strongly urged to switch to the new interfaces.
  60  *
  61  * The plane helpers share the function table structures with other helpers,
  62  * specifically also the atomic helpers. See &struct drm_plane_helper_funcs for
  63  * the details.
  64  */
  65 
  66 /*
  67  * Returns the connectors currently associated with a CRTC.  This function
  68  * should be called twice:  once with a NULL connector list to retrieve
  69  * the list size, and once with the properly allocated list to be filled in.
  70  */
  71 static int get_connectors_for_crtc(struct drm_crtc *crtc,
  72                                    struct drm_connector **connector_list,
  73                                    int num_connectors)
  74 {
  75         struct drm_device *dev = crtc->dev;
  76         struct drm_connector *connector;
  77         struct drm_connector_list_iter conn_iter;
  78         int count = 0;
  79 
  80         /*
  81          * Note: Once we change the plane hooks to more fine-grained locking we
  82          * need to grab the connection_mutex here to be able to make these
  83          * checks.
  84          */
  85         WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
  86 
  87         drm_connector_list_iter_begin(dev, &conn_iter);
  88         drm_for_each_connector_iter(connector, &conn_iter) {
  89                 if (connector->encoder && connector->encoder->crtc == crtc) {
  90                         if (connector_list != NULL && count < num_connectors)
  91                                 *(connector_list++) = connector;
  92 
  93                         count++;
  94                 }
  95         }
  96         drm_connector_list_iter_end(&conn_iter);
  97 
  98         return count;
  99 }
 100 
 101 static int drm_plane_helper_check_update(struct drm_plane *plane,
 102                                          struct drm_crtc *crtc,
 103                                          struct drm_framebuffer *fb,
 104                                          struct drm_rect *src,
 105                                          struct drm_rect *dst,
 106                                          unsigned int rotation,
 107                                          int min_scale,
 108                                          int max_scale,
 109                                          bool can_position,
 110                                          bool can_update_disabled,
 111                                          bool *visible)
 112 {
 113         struct drm_plane_state plane_state = {
 114                 .plane = plane,
 115                 .crtc = crtc,
 116                 .fb = fb,
 117                 .src_x = src->x1,
 118                 .src_y = src->y1,
 119                 .src_w = drm_rect_width(src),
 120                 .src_h = drm_rect_height(src),
 121                 .crtc_x = dst->x1,
 122                 .crtc_y = dst->y1,
 123                 .crtc_w = drm_rect_width(dst),
 124                 .crtc_h = drm_rect_height(dst),
 125                 .rotation = rotation,
 126                 .visible = *visible,
 127         };
 128         struct drm_crtc_state crtc_state = {
 129                 .crtc = crtc,
 130                 .enable = crtc->enabled,
 131                 .mode = crtc->mode,
 132         };
 133         int ret;
 134 
 135         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 136                                                   min_scale, max_scale,
 137                                                   can_position,
 138                                                   can_update_disabled);
 139         if (ret)
 140                 return ret;
 141 
 142         *src = plane_state.src;
 143         *dst = plane_state.dst;
 144         *visible = plane_state.visible;
 145 
 146         return 0;
 147 }
 148 
 149 static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
 150                                      struct drm_framebuffer *fb,
 151                                      int crtc_x, int crtc_y,
 152                                      unsigned int crtc_w, unsigned int crtc_h,
 153                                      uint32_t src_x, uint32_t src_y,
 154                                      uint32_t src_w, uint32_t src_h,
 155                                      struct drm_modeset_acquire_ctx *ctx)
 156 {
 157         struct drm_mode_set set = {
 158                 .crtc = crtc,
 159                 .fb = fb,
 160                 .mode = &crtc->mode,
 161                 .x = src_x >> 16,
 162                 .y = src_y >> 16,
 163         };
 164         struct drm_rect src = {
 165                 .x1 = src_x,
 166                 .y1 = src_y,
 167                 .x2 = src_x + src_w,
 168                 .y2 = src_y + src_h,
 169         };
 170         struct drm_rect dest = {
 171                 .x1 = crtc_x,
 172                 .y1 = crtc_y,
 173                 .x2 = crtc_x + crtc_w,
 174                 .y2 = crtc_y + crtc_h,
 175         };
 176         struct drm_connector **connector_list;
 177         int num_connectors, ret;
 178         bool visible;
 179 
 180         ret = drm_plane_helper_check_update(plane, crtc, fb,
 181                                             &src, &dest,
 182                                             DRM_MODE_ROTATE_0,
 183                                             DRM_PLANE_HELPER_NO_SCALING,
 184                                             DRM_PLANE_HELPER_NO_SCALING,
 185                                             false, false, &visible);
 186         if (ret)
 187                 return ret;
 188 
 189         if (!visible)
 190                 /*
 191                  * Primary plane isn't visible.  Note that unless a driver
 192                  * provides their own disable function, this will just
 193                  * wind up returning -EINVAL to userspace.
 194                  */
 195                 return plane->funcs->disable_plane(plane, ctx);
 196 
 197         /* Find current connectors for CRTC */
 198         num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
 199         BUG_ON(num_connectors == 0);
 200         connector_list = kcalloc(num_connectors, sizeof(*connector_list),
 201                                  GFP_KERNEL);
 202         if (!connector_list)
 203                 return -ENOMEM;
 204         get_connectors_for_crtc(crtc, connector_list, num_connectors);
 205 
 206         set.connectors = connector_list;
 207         set.num_connectors = num_connectors;
 208 
 209         /*
 210          * We call set_config() directly here rather than using
 211          * drm_mode_set_config_internal.  We're reprogramming the same
 212          * connectors that were already in use, so we shouldn't need the extra
 213          * cross-CRTC fb refcounting to accomodate stealing connectors.
 214          * drm_mode_setplane() already handles the basic refcounting for the
 215          * framebuffers involved in this operation.
 216          */
 217         ret = crtc->funcs->set_config(&set, ctx);
 218 
 219         kfree(connector_list);
 220         return ret;
 221 }
 222 
 223 static int drm_primary_helper_disable(struct drm_plane *plane,
 224                                       struct drm_modeset_acquire_ctx *ctx)
 225 {
 226         return -EINVAL;
 227 }
 228 
 229 /**
 230  * drm_primary_helper_destroy() - Helper for primary plane destruction
 231  * @plane: plane to destroy
 232  *
 233  * Provides a default plane destroy handler for primary planes.  This handler
 234  * is called during CRTC destruction.  We disable the primary plane, remove
 235  * it from the DRM plane list, and deallocate the plane structure.
 236  */
 237 void drm_primary_helper_destroy(struct drm_plane *plane)
 238 {
 239         drm_plane_cleanup(plane);
 240         kfree(plane);
 241 }
 242 EXPORT_SYMBOL(drm_primary_helper_destroy);
 243 
 244 const struct drm_plane_funcs drm_primary_helper_funcs = {
 245         .update_plane = drm_primary_helper_update,
 246         .disable_plane = drm_primary_helper_disable,
 247         .destroy = drm_primary_helper_destroy,
 248 };
 249 EXPORT_SYMBOL(drm_primary_helper_funcs);

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