Subversion Repositories Kolibri OS

Rev

Rev 5271 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. #include <drm/drmP.h>
  28. #include <drm/drm_plane_helper.h>
  29. #include <drm/drm_rect.h>
  30. #include <drm/drm_plane_helper.h>
  31.  
  32. #define SUBPIXEL_MASK 0xffff
  33.  
  34. /*
  35.  * This is the minimal list of formats that seem to be safe for modeset use
  36.  * with all current DRM drivers.  Most hardware can actually support more
  37.  * formats than this and drivers may specify a more accurate list when
  38.  * creating the primary plane.  However drivers that still call
  39.  * drm_plane_init() will use this minimal format list as the default.
  40.  */
  41. static const uint32_t safe_modeset_formats[] = {
  42.         DRM_FORMAT_XRGB8888,
  43.         DRM_FORMAT_ARGB8888,
  44. };
  45.  
  46. /*
  47.  * Returns the connectors currently associated with a CRTC.  This function
  48.  * should be called twice:  once with a NULL connector list to retrieve
  49.  * the list size, and once with the properly allocated list to be filled in.
  50.  */
  51. static int get_connectors_for_crtc(struct drm_crtc *crtc,
  52.                                    struct drm_connector **connector_list,
  53.                                    int num_connectors)
  54. {
  55.         struct drm_device *dev = crtc->dev;
  56.         struct drm_connector *connector;
  57.         int count = 0;
  58.  
  59.         /*
  60.          * Note: Once we change the plane hooks to more fine-grained locking we
  61.          * need to grab the connection_mutex here to be able to make these
  62.          * checks.
  63.          */
  64.         WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
  65.  
  66.         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  67.                 if (connector->encoder && connector->encoder->crtc == crtc) {
  68.                         if (connector_list != NULL && count < num_connectors)
  69.                                 *(connector_list++) = connector;
  70.  
  71.                         count++;
  72.                 }
  73.  
  74.         return count;
  75. }
  76.  
  77. /**
  78.  * drm_plane_helper_check_update() - Check plane update for validity
  79.  * @plane: plane object to update
  80.  * @crtc: owning CRTC of owning plane
  81.  * @fb: framebuffer to flip onto plane
  82.  * @src: source coordinates in 16.16 fixed point
  83.  * @dest: integer destination coordinates
  84.  * @clip: integer clipping coordinates
  85.  * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
  86.  * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
  87.  * @can_position: is it legal to position the plane such that it
  88.  *                doesn't cover the entire crtc?  This will generally
  89.  *                only be false for primary planes.
  90.  * @can_update_disabled: can the plane be updated while the crtc
  91.  *                       is disabled?
  92.  * @visible: output parameter indicating whether plane is still visible after
  93.  *           clipping
  94.  *
  95.  * Checks that a desired plane update is valid.  Drivers that provide
  96.  * their own plane handling rather than helper-provided implementations may
  97.  * still wish to call this function to avoid duplication of error checking
  98.  * code.
  99.  *
  100.  * RETURNS:
  101.  * Zero if update appears valid, error code on failure
  102.  */
  103. int drm_plane_helper_check_update(struct drm_plane *plane,
  104.                                     struct drm_crtc *crtc,
  105.                                     struct drm_framebuffer *fb,
  106.                                     struct drm_rect *src,
  107.                                     struct drm_rect *dest,
  108.                                     const struct drm_rect *clip,
  109.                                     int min_scale,
  110.                                     int max_scale,
  111.                                     bool can_position,
  112.                                     bool can_update_disabled,
  113.                                     bool *visible)
  114. {
  115.         int hscale, vscale;
  116.  
  117.         if (!crtc->enabled && !can_update_disabled) {
  118.                 DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
  119.                 return -EINVAL;
  120.         }
  121.  
  122.         /* Check scaling */
  123.         hscale = drm_rect_calc_hscale(src, dest, min_scale, max_scale);
  124.         vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
  125.         if (hscale < 0 || vscale < 0) {
  126.                 DRM_DEBUG_KMS("Invalid scaling of plane\n");
  127.                 return -ERANGE;
  128.         }
  129.  
  130.         *visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
  131.         if (!*visible)
  132.                 /*
  133.                  * Plane isn't visible; some drivers can handle this
  134.                  * so we just return success here.  Drivers that can't
  135.                  * (including those that use the primary plane helper's
  136.                  * update function) will return an error from their
  137.                  * update_plane handler.
  138.                  */
  139.                 return 0;
  140.  
  141.         if (!can_position && !drm_rect_equals(dest, clip)) {
  142.                 DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
  143.                 return -EINVAL;
  144.         }
  145.  
  146.         return 0;
  147. }
  148. EXPORT_SYMBOL(drm_plane_helper_check_update);
  149.  
  150. /**
  151.  * drm_primary_helper_update() - Helper for primary plane update
  152.  * @plane: plane object to update
  153.  * @crtc: owning CRTC of owning plane
  154.  * @fb: framebuffer to flip onto plane
  155.  * @crtc_x: x offset of primary plane on crtc
  156.  * @crtc_y: y offset of primary plane on crtc
  157.  * @crtc_w: width of primary plane rectangle on crtc
  158.  * @crtc_h: height of primary plane rectangle on crtc
  159.  * @src_x: x offset of @fb for panning
  160.  * @src_y: y offset of @fb for panning
  161.  * @src_w: width of source rectangle in @fb
  162.  * @src_h: height of source rectangle in @fb
  163.  *
  164.  * Provides a default plane update handler for primary planes.  This is handler
  165.  * is called in response to a userspace SetPlane operation on the plane with a
  166.  * non-NULL framebuffer.  We call the driver's modeset handler to update the
  167.  * framebuffer.
  168.  *
  169.  * SetPlane() on a primary plane of a disabled CRTC is not supported, and will
  170.  * return an error.
  171.  *
  172.  * Note that we make some assumptions about hardware limitations that may not be
  173.  * true for all hardware --
  174.  *   1) Primary plane cannot be repositioned.
  175.  *   2) Primary plane cannot be scaled.
  176.  *   3) Primary plane must cover the entire CRTC.
  177.  *   4) Subpixel positioning is not supported.
  178.  * Drivers for hardware that don't have these restrictions can provide their
  179.  * own implementation rather than using this helper.
  180.  *
  181.  * RETURNS:
  182.  * Zero on success, error code on failure
  183.  */
  184. int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
  185.                               struct drm_framebuffer *fb,
  186.                               int crtc_x, int crtc_y,
  187.                               unsigned int crtc_w, unsigned int crtc_h,
  188.                               uint32_t src_x, uint32_t src_y,
  189.                               uint32_t src_w, uint32_t src_h)
  190. {
  191.         struct drm_mode_set set = {
  192.                 .crtc = crtc,
  193.                 .fb = fb,
  194.                 .mode = &crtc->mode,
  195.                 .x = src_x >> 16,
  196.                 .y = src_y >> 16,
  197.         };
  198.         struct drm_rect src = {
  199.                 .x1 = src_x,
  200.                 .y1 = src_y,
  201.                 .x2 = src_x + src_w,
  202.                 .y2 = src_y + src_h,
  203.         };
  204.         struct drm_rect dest = {
  205.                 .x1 = crtc_x,
  206.                 .y1 = crtc_y,
  207.                 .x2 = crtc_x + crtc_w,
  208.                 .y2 = crtc_y + crtc_h,
  209.         };
  210.         const struct drm_rect clip = {
  211.                 .x2 = crtc->mode.hdisplay,
  212.                 .y2 = crtc->mode.vdisplay,
  213.         };
  214.         struct drm_connector **connector_list;
  215.         int num_connectors, ret;
  216.         bool visible;
  217.  
  218.         ret = drm_plane_helper_check_update(plane, crtc, fb,
  219.                                             &src, &dest, &clip,
  220.                                             DRM_PLANE_HELPER_NO_SCALING,
  221.                                             DRM_PLANE_HELPER_NO_SCALING,
  222.                                             false, false, &visible);
  223.         if (ret)
  224.                 return ret;
  225.  
  226.         if (!visible)
  227.                 /*
  228.                  * Primary plane isn't visible.  Note that unless a driver
  229.                  * provides their own disable function, this will just
  230.                  * wind up returning -EINVAL to userspace.
  231.                  */
  232.                 return plane->funcs->disable_plane(plane);
  233.  
  234.         /* Find current connectors for CRTC */
  235.         num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
  236.         BUG_ON(num_connectors == 0);
  237.         connector_list = kzalloc(num_connectors * sizeof(*connector_list),
  238.                                  GFP_KERNEL);
  239.         if (!connector_list)
  240.                 return -ENOMEM;
  241.         get_connectors_for_crtc(crtc, connector_list, num_connectors);
  242.  
  243.         set.connectors = connector_list;
  244.         set.num_connectors = num_connectors;
  245.  
  246.         /*
  247.          * We call set_config() directly here rather than using
  248.          * drm_mode_set_config_internal.  We're reprogramming the same
  249.          * connectors that were already in use, so we shouldn't need the extra
  250.          * cross-CRTC fb refcounting to accomodate stealing connectors.
  251.          * drm_mode_setplane() already handles the basic refcounting for the
  252.          * framebuffers involved in this operation.
  253.          */
  254.         ret = crtc->funcs->set_config(&set);
  255.  
  256.         kfree(connector_list);
  257.         return ret;
  258. }
  259. EXPORT_SYMBOL(drm_primary_helper_update);
  260.  
  261. /**
  262.  * drm_primary_helper_disable() - Helper for primary plane disable
  263.  * @plane: plane to disable
  264.  *
  265.  * Provides a default plane disable handler for primary planes.  This is handler
  266.  * is called in response to a userspace SetPlane operation on the plane with a
  267.  * NULL framebuffer parameter.  It unconditionally fails the disable call with
  268.  * -EINVAL the only way to disable the primary plane without driver support is
  269.  * to disable the entier CRTC. Which does not match the plane ->disable hook.
  270.  *
  271.  * Note that some hardware may be able to disable the primary plane without
  272.  * disabling the whole CRTC.  Drivers for such hardware should provide their
  273.  * own disable handler that disables just the primary plane (and they'll likely
  274.  * need to provide their own update handler as well to properly re-enable a
  275.  * disabled primary plane).
  276.  *
  277.  * RETURNS:
  278.  * Unconditionally returns -EINVAL.
  279.  */
  280. int drm_primary_helper_disable(struct drm_plane *plane)
  281. {
  282.         return -EINVAL;
  283. }
  284. EXPORT_SYMBOL(drm_primary_helper_disable);
  285.  
  286. /**
  287.  * drm_primary_helper_destroy() - Helper for primary plane destruction
  288.  * @plane: plane to destroy
  289.  *
  290.  * Provides a default plane destroy handler for primary planes.  This handler
  291.  * is called during CRTC destruction.  We disable the primary plane, remove
  292.  * it from the DRM plane list, and deallocate the plane structure.
  293.  */
  294. void drm_primary_helper_destroy(struct drm_plane *plane)
  295. {
  296.         drm_plane_cleanup(plane);
  297.         kfree(plane);
  298. }
  299. EXPORT_SYMBOL(drm_primary_helper_destroy);
  300.  
  301. const struct drm_plane_funcs drm_primary_helper_funcs = {
  302.         .update_plane = drm_primary_helper_update,
  303.         .disable_plane = drm_primary_helper_disable,
  304.         .destroy = drm_primary_helper_destroy,
  305. };
  306. EXPORT_SYMBOL(drm_primary_helper_funcs);
  307.  
  308. /**
  309.  * drm_primary_helper_create_plane() - Create a generic primary plane
  310.  * @dev: drm device
  311.  * @formats: pixel formats supported, or NULL for a default safe list
  312.  * @num_formats: size of @formats; ignored if @formats is NULL
  313.  *
  314.  * Allocates and initializes a primary plane that can be used with the primary
  315.  * plane helpers.  Drivers that wish to use driver-specific plane structures or
  316.  * provide custom handler functions may perform their own allocation and
  317.  * initialization rather than calling this function.
  318.  */
  319. struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
  320.                                                   const uint32_t *formats,
  321.                                                   int num_formats)
  322. {
  323.         struct drm_plane *primary;
  324.         int ret;
  325.  
  326.         primary = kzalloc(sizeof(*primary), GFP_KERNEL);
  327.         if (primary == NULL) {
  328.                 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
  329.                 return NULL;
  330.         }
  331.  
  332.         if (formats == NULL) {
  333.                 formats = safe_modeset_formats;
  334.                 num_formats = ARRAY_SIZE(safe_modeset_formats);
  335.         }
  336.  
  337.         /* possible_crtc's will be filled in later by crtc_init */
  338.         ret = drm_universal_plane_init(dev, primary, 0,
  339.                                        &drm_primary_helper_funcs,
  340.                              formats, num_formats,
  341.                              DRM_PLANE_TYPE_PRIMARY);
  342.         if (ret) {
  343.                 kfree(primary);
  344.                 primary = NULL;
  345.         }
  346.  
  347.         return primary;
  348. }
  349. EXPORT_SYMBOL(drm_primary_helper_create_plane);
  350.  
  351. /**
  352.  * drm_crtc_init - Legacy CRTC initialization function
  353.  * @dev: DRM device
  354.  * @crtc: CRTC object to init
  355.  * @funcs: callbacks for the new CRTC
  356.  *
  357.  * Initialize a CRTC object with a default helper-provided primary plane and no
  358.  * cursor plane.
  359.  *
  360.  * Returns:
  361.  * Zero on success, error code on failure.
  362.  */
  363. int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
  364.                   const struct drm_crtc_funcs *funcs)
  365. {
  366.         struct drm_plane *primary;
  367.  
  368.         primary = drm_primary_helper_create_plane(dev, NULL, 0);
  369.         return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs);
  370. }
  371. EXPORT_SYMBOL(drm_crtc_init);
  372.