linux/drivers/gpu/drm/i915/intel_atomic_plane.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2014 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21 * DEALINGS IN THE SOFTWARE.
  22 */
  23
  24/**
  25 * DOC: atomic plane helpers
  26 *
  27 * The functions here are used by the atomic plane helper functions to
  28 * implement legacy plane updates (i.e., drm_plane->update_plane() and
  29 * drm_plane->disable_plane()).  This allows plane updates to use the
  30 * atomic state infrastructure and perform plane updates as separate
  31 * prepare/check/commit/cleanup steps.
  32 */
  33
  34#include <drm/drmP.h>
  35#include <drm/drm_atomic_helper.h>
  36#include <drm/drm_plane_helper.h>
  37#include "intel_drv.h"
  38
  39/**
  40 * intel_create_plane_state - create plane state object
  41 * @plane: drm plane
  42 *
  43 * Allocates a fresh plane state for the given plane and sets some of
  44 * the state values to sensible initial values.
  45 *
  46 * Returns: A newly allocated plane state, or NULL on failure
  47 */
  48struct intel_plane_state *
  49intel_create_plane_state(struct drm_plane *plane)
  50{
  51        struct intel_plane_state *state;
  52
  53        state = kzalloc(sizeof(*state), GFP_KERNEL);
  54        if (!state)
  55                return NULL;
  56
  57        state->base.plane = plane;
  58        state->base.rotation = DRM_MODE_ROTATE_0;
  59        state->ckey.flags = I915_SET_COLORKEY_NONE;
  60
  61        return state;
  62}
  63
  64/**
  65 * intel_plane_duplicate_state - duplicate plane state
  66 * @plane: drm plane
  67 *
  68 * Allocates and returns a copy of the plane state (both common and
  69 * Intel-specific) for the specified plane.
  70 *
  71 * Returns: The newly allocated plane state, or NULL on failure.
  72 */
  73struct drm_plane_state *
  74intel_plane_duplicate_state(struct drm_plane *plane)
  75{
  76        struct drm_plane_state *state;
  77        struct intel_plane_state *intel_state;
  78
  79        intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
  80
  81        if (!intel_state)
  82                return NULL;
  83
  84        state = &intel_state->base;
  85
  86        __drm_atomic_helper_plane_duplicate_state(plane, state);
  87
  88        intel_state->vma = NULL;
  89
  90        return state;
  91}
  92
  93/**
  94 * intel_plane_destroy_state - destroy plane state
  95 * @plane: drm plane
  96 * @state: state object to destroy
  97 *
  98 * Destroys the plane state (both common and Intel-specific) for the
  99 * specified plane.
 100 */
 101void
 102intel_plane_destroy_state(struct drm_plane *plane,
 103                          struct drm_plane_state *state)
 104{
 105        WARN_ON(to_intel_plane_state(state)->vma);
 106
 107        drm_atomic_helper_plane_destroy_state(plane, state);
 108}
 109
 110int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state,
 111                                        struct intel_plane_state *intel_state)
 112{
 113        struct drm_plane *plane = intel_state->base.plane;
 114        struct drm_i915_private *dev_priv = to_i915(plane->dev);
 115        struct drm_plane_state *state = &intel_state->base;
 116        struct intel_plane *intel_plane = to_intel_plane(plane);
 117        const struct drm_display_mode *adjusted_mode =
 118                &crtc_state->base.adjusted_mode;
 119        int ret;
 120
 121        /*
 122         * Both crtc and plane->crtc could be NULL if we're updating a
 123         * property while the plane is disabled.  We don't actually have
 124         * anything driver-specific we need to test in that case, so
 125         * just return success.
 126         */
 127        if (!intel_state->base.crtc && !plane->state->crtc)
 128                return 0;
 129
 130        /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */
 131        intel_state->clip.x1 = 0;
 132        intel_state->clip.y1 = 0;
 133        intel_state->clip.x2 =
 134                crtc_state->base.enable ? crtc_state->pipe_src_w : 0;
 135        intel_state->clip.y2 =
 136                crtc_state->base.enable ? crtc_state->pipe_src_h : 0;
 137
 138        if (state->fb && drm_rotation_90_or_270(state->rotation)) {
 139                struct drm_format_name_buf format_name;
 140
 141                if (state->fb->modifier != I915_FORMAT_MOD_Y_TILED &&
 142                    state->fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
 143                        DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
 144                        return -EINVAL;
 145                }
 146
 147                /*
 148                 * 90/270 is not allowed with RGB64 16:16:16:16,
 149                 * RGB 16-bit 5:6:5, and Indexed 8-bit.
 150                 * TBD: Add RGB64 case once its added in supported format list.
 151                 */
 152                switch (state->fb->format->format) {
 153                case DRM_FORMAT_C8:
 154                case DRM_FORMAT_RGB565:
 155                        DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
 156                                      drm_get_format_name(state->fb->format->format,
 157                                                          &format_name));
 158                        return -EINVAL;
 159
 160                default:
 161                        break;
 162                }
 163        }
 164
 165        /* CHV ignores the mirror bit when the rotate bit is set :( */
 166        if (IS_CHERRYVIEW(dev_priv) &&
 167            state->rotation & DRM_MODE_ROTATE_180 &&
 168            state->rotation & DRM_MODE_REFLECT_X) {
 169                DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
 170                return -EINVAL;
 171        }
 172
 173        intel_state->base.visible = false;
 174        ret = intel_plane->check_plane(intel_plane, crtc_state, intel_state);
 175        if (ret)
 176                return ret;
 177
 178        /*
 179         * Y-tiling is not supported in IF-ID Interlace mode in
 180         * GEN9 and above.
 181         */
 182        if (state->fb && INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable &&
 183            adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 184                if (state->fb->modifier == I915_FORMAT_MOD_Y_TILED ||
 185                    state->fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
 186                        DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
 187                        return -EINVAL;
 188                }
 189        }
 190
 191        /* FIXME pre-g4x don't work like this */
 192        if (intel_state->base.visible)
 193                crtc_state->active_planes |= BIT(intel_plane->id);
 194        else
 195                crtc_state->active_planes &= ~BIT(intel_plane->id);
 196
 197        return intel_plane_atomic_calc_changes(&crtc_state->base, state);
 198}
 199
 200static int intel_plane_atomic_check(struct drm_plane *plane,
 201                                    struct drm_plane_state *state)
 202{
 203        struct drm_crtc *crtc = state->crtc;
 204        struct drm_crtc_state *drm_crtc_state;
 205
 206        crtc = crtc ? crtc : plane->state->crtc;
 207
 208        /*
 209         * Both crtc and plane->crtc could be NULL if we're updating a
 210         * property while the plane is disabled.  We don't actually have
 211         * anything driver-specific we need to test in that case, so
 212         * just return success.
 213         */
 214        if (!crtc)
 215                return 0;
 216
 217        drm_crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
 218        if (WARN_ON(!drm_crtc_state))
 219                return -EINVAL;
 220
 221        return intel_plane_atomic_check_with_state(to_intel_crtc_state(drm_crtc_state),
 222                                                   to_intel_plane_state(state));
 223}
 224
 225static void intel_plane_atomic_update(struct drm_plane *plane,
 226                                      struct drm_plane_state *old_state)
 227{
 228        struct intel_plane *intel_plane = to_intel_plane(plane);
 229        struct intel_plane_state *intel_state =
 230                to_intel_plane_state(plane->state);
 231        struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
 232
 233        if (intel_state->base.visible) {
 234                trace_intel_update_plane(plane,
 235                                         to_intel_crtc(crtc));
 236
 237                intel_plane->update_plane(intel_plane,
 238                                          to_intel_crtc_state(crtc->state),
 239                                          intel_state);
 240        } else {
 241                trace_intel_disable_plane(plane,
 242                                          to_intel_crtc(crtc));
 243
 244                intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
 245        }
 246}
 247
 248const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
 249        .prepare_fb = intel_prepare_plane_fb,
 250        .cleanup_fb = intel_cleanup_plane_fb,
 251        .atomic_check = intel_plane_atomic_check,
 252        .atomic_update = intel_plane_atomic_update,
 253};
 254
 255/**
 256 * intel_plane_atomic_get_property - fetch plane property value
 257 * @plane: plane to fetch property for
 258 * @state: state containing the property value
 259 * @property: property to look up
 260 * @val: pointer to write property value into
 261 *
 262 * The DRM core does not store shadow copies of properties for
 263 * atomic-capable drivers.  This entrypoint is used to fetch
 264 * the current value of a driver-specific plane property.
 265 */
 266int
 267intel_plane_atomic_get_property(struct drm_plane *plane,
 268                                const struct drm_plane_state *state,
 269                                struct drm_property *property,
 270                                uint64_t *val)
 271{
 272        DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name);
 273        return -EINVAL;
 274}
 275
 276/**
 277 * intel_plane_atomic_set_property - set plane property value
 278 * @plane: plane to set property for
 279 * @state: state to update property value in
 280 * @property: property to set
 281 * @val: value to set property to
 282 *
 283 * Writes the specified property value for a plane into the provided atomic
 284 * state object.
 285 *
 286 * Returns 0 on success, -EINVAL on unrecognized properties
 287 */
 288int
 289intel_plane_atomic_set_property(struct drm_plane *plane,
 290                                struct drm_plane_state *state,
 291                                struct drm_property *property,
 292                                uint64_t val)
 293{
 294        DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name);
 295        return -EINVAL;
 296}
 297