linux/drivers/gpu/drm/i915/display/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/drm_atomic_helper.h>
  35#include <drm/drm_fourcc.h>
  36#include <drm/drm_plane_helper.h>
  37
  38#include "i915_trace.h"
  39#include "intel_atomic_plane.h"
  40#include "intel_display_types.h"
  41#include "intel_pm.h"
  42#include "intel_sprite.h"
  43
  44struct intel_plane *intel_plane_alloc(void)
  45{
  46        struct intel_plane_state *plane_state;
  47        struct intel_plane *plane;
  48
  49        plane = kzalloc(sizeof(*plane), GFP_KERNEL);
  50        if (!plane)
  51                return ERR_PTR(-ENOMEM);
  52
  53        plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
  54        if (!plane_state) {
  55                kfree(plane);
  56                return ERR_PTR(-ENOMEM);
  57        }
  58
  59        __drm_atomic_helper_plane_reset(&plane->base, &plane_state->base);
  60        plane_state->scaler_id = -1;
  61
  62        return plane;
  63}
  64
  65void intel_plane_free(struct intel_plane *plane)
  66{
  67        intel_plane_destroy_state(&plane->base, plane->base.state);
  68        kfree(plane);
  69}
  70
  71/**
  72 * intel_plane_duplicate_state - duplicate plane state
  73 * @plane: drm plane
  74 *
  75 * Allocates and returns a copy of the plane state (both common and
  76 * Intel-specific) for the specified plane.
  77 *
  78 * Returns: The newly allocated plane state, or NULL on failure.
  79 */
  80struct drm_plane_state *
  81intel_plane_duplicate_state(struct drm_plane *plane)
  82{
  83        struct drm_plane_state *state;
  84        struct intel_plane_state *intel_state;
  85
  86        intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
  87
  88        if (!intel_state)
  89                return NULL;
  90
  91        state = &intel_state->base;
  92
  93        __drm_atomic_helper_plane_duplicate_state(plane, state);
  94
  95        intel_state->vma = NULL;
  96        intel_state->flags = 0;
  97
  98        return state;
  99}
 100
 101/**
 102 * intel_plane_destroy_state - destroy plane state
 103 * @plane: drm plane
 104 * @state: state object to destroy
 105 *
 106 * Destroys the plane state (both common and Intel-specific) for the
 107 * specified plane.
 108 */
 109void
 110intel_plane_destroy_state(struct drm_plane *plane,
 111                          struct drm_plane_state *state)
 112{
 113        WARN_ON(to_intel_plane_state(state)->vma);
 114
 115        drm_atomic_helper_plane_destroy_state(plane, state);
 116}
 117
 118unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
 119                                   const struct intel_plane_state *plane_state)
 120{
 121        const struct drm_framebuffer *fb = plane_state->base.fb;
 122        unsigned int cpp;
 123
 124        if (!plane_state->base.visible)
 125                return 0;
 126
 127        cpp = fb->format->cpp[0];
 128
 129        /*
 130         * Based on HSD#:1408715493
 131         * NV12 cpp == 4, P010 cpp == 8
 132         *
 133         * FIXME what is the logic behind this?
 134         */
 135        if (fb->format->is_yuv && fb->format->num_planes > 1)
 136                cpp *= 4;
 137
 138        return cpp * crtc_state->pixel_rate;
 139}
 140
 141int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
 142                                        struct intel_crtc_state *new_crtc_state,
 143                                        const struct intel_plane_state *old_plane_state,
 144                                        struct intel_plane_state *new_plane_state)
 145{
 146        struct intel_plane *plane = to_intel_plane(new_plane_state->base.plane);
 147        int ret;
 148
 149        new_crtc_state->active_planes &= ~BIT(plane->id);
 150        new_crtc_state->nv12_planes &= ~BIT(plane->id);
 151        new_crtc_state->c8_planes &= ~BIT(plane->id);
 152        new_crtc_state->data_rate[plane->id] = 0;
 153        new_plane_state->base.visible = false;
 154
 155        if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
 156                return 0;
 157
 158        ret = plane->check_plane(new_crtc_state, new_plane_state);
 159        if (ret)
 160                return ret;
 161
 162        /* FIXME pre-g4x don't work like this */
 163        if (new_plane_state->base.visible)
 164                new_crtc_state->active_planes |= BIT(plane->id);
 165
 166        if (new_plane_state->base.visible &&
 167            is_planar_yuv_format(new_plane_state->base.fb->format->format))
 168                new_crtc_state->nv12_planes |= BIT(plane->id);
 169
 170        if (new_plane_state->base.visible &&
 171            new_plane_state->base.fb->format->format == DRM_FORMAT_C8)
 172                new_crtc_state->c8_planes |= BIT(plane->id);
 173
 174        if (new_plane_state->base.visible || old_plane_state->base.visible)
 175                new_crtc_state->update_planes |= BIT(plane->id);
 176
 177        new_crtc_state->data_rate[plane->id] =
 178                intel_plane_data_rate(new_crtc_state, new_plane_state);
 179
 180        return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
 181                                               old_plane_state, new_plane_state);
 182}
 183
 184static struct intel_crtc *
 185get_crtc_from_states(const struct intel_plane_state *old_plane_state,
 186                     const struct intel_plane_state *new_plane_state)
 187{
 188        if (new_plane_state->base.crtc)
 189                return to_intel_crtc(new_plane_state->base.crtc);
 190
 191        if (old_plane_state->base.crtc)
 192                return to_intel_crtc(old_plane_state->base.crtc);
 193
 194        return NULL;
 195}
 196
 197static int intel_plane_atomic_check(struct drm_plane *_plane,
 198                                    struct drm_plane_state *_new_plane_state)
 199{
 200        struct intel_plane *plane = to_intel_plane(_plane);
 201        struct intel_atomic_state *state =
 202                to_intel_atomic_state(_new_plane_state->state);
 203        struct intel_plane_state *new_plane_state =
 204                to_intel_plane_state(_new_plane_state);
 205        const struct intel_plane_state *old_plane_state =
 206                intel_atomic_get_old_plane_state(state, plane);
 207        struct intel_crtc *crtc =
 208                get_crtc_from_states(old_plane_state, new_plane_state);
 209        const struct intel_crtc_state *old_crtc_state;
 210        struct intel_crtc_state *new_crtc_state;
 211
 212        new_plane_state->base.visible = false;
 213        if (!crtc)
 214                return 0;
 215
 216        old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
 217        new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
 218
 219        return intel_plane_atomic_check_with_state(old_crtc_state,
 220                                                   new_crtc_state,
 221                                                   old_plane_state,
 222                                                   new_plane_state);
 223}
 224
 225static struct intel_plane *
 226skl_next_plane_to_commit(struct intel_atomic_state *state,
 227                         struct intel_crtc *crtc,
 228                         struct skl_ddb_entry entries_y[I915_MAX_PLANES],
 229                         struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
 230                         unsigned int *update_mask)
 231{
 232        struct intel_crtc_state *crtc_state =
 233                intel_atomic_get_new_crtc_state(state, crtc);
 234        struct intel_plane_state *plane_state;
 235        struct intel_plane *plane;
 236        int i;
 237
 238        if (*update_mask == 0)
 239                return NULL;
 240
 241        for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
 242                enum plane_id plane_id = plane->id;
 243
 244                if (crtc->pipe != plane->pipe ||
 245                    !(*update_mask & BIT(plane_id)))
 246                        continue;
 247
 248                if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
 249                                                entries_y,
 250                                                I915_MAX_PLANES, plane_id) ||
 251                    skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
 252                                                entries_uv,
 253                                                I915_MAX_PLANES, plane_id))
 254                        continue;
 255
 256                *update_mask &= ~BIT(plane_id);
 257                entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
 258                entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
 259
 260                return plane;
 261        }
 262
 263        /* should never happen */
 264        WARN_ON(1);
 265
 266        return NULL;
 267}
 268
 269void intel_update_plane(struct intel_plane *plane,
 270                        const struct intel_crtc_state *crtc_state,
 271                        const struct intel_plane_state *plane_state)
 272{
 273        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 274
 275        trace_intel_update_plane(&plane->base, crtc);
 276        plane->update_plane(plane, crtc_state, plane_state);
 277}
 278
 279void intel_update_slave(struct intel_plane *plane,
 280                        const struct intel_crtc_state *crtc_state,
 281                        const struct intel_plane_state *plane_state)
 282{
 283        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 284
 285        trace_intel_update_plane(&plane->base, crtc);
 286        plane->update_slave(plane, crtc_state, plane_state);
 287}
 288
 289void intel_disable_plane(struct intel_plane *plane,
 290                         const struct intel_crtc_state *crtc_state)
 291{
 292        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 293
 294        trace_intel_disable_plane(&plane->base, crtc);
 295        plane->disable_plane(plane, crtc_state);
 296}
 297
 298void skl_update_planes_on_crtc(struct intel_atomic_state *state,
 299                               struct intel_crtc *crtc)
 300{
 301        struct intel_crtc_state *old_crtc_state =
 302                intel_atomic_get_old_crtc_state(state, crtc);
 303        struct intel_crtc_state *new_crtc_state =
 304                intel_atomic_get_new_crtc_state(state, crtc);
 305        struct skl_ddb_entry entries_y[I915_MAX_PLANES];
 306        struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
 307        u32 update_mask = new_crtc_state->update_planes;
 308        struct intel_plane *plane;
 309
 310        memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
 311               sizeof(old_crtc_state->wm.skl.plane_ddb_y));
 312        memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
 313               sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
 314
 315        while ((plane = skl_next_plane_to_commit(state, crtc,
 316                                                 entries_y, entries_uv,
 317                                                 &update_mask))) {
 318                struct intel_plane_state *new_plane_state =
 319                        intel_atomic_get_new_plane_state(state, plane);
 320
 321                if (new_plane_state->base.visible) {
 322                        intel_update_plane(plane, new_crtc_state, new_plane_state);
 323                } else if (new_plane_state->slave) {
 324                        struct intel_plane *master =
 325                                new_plane_state->linked_plane;
 326
 327                        /*
 328                         * We update the slave plane from this function because
 329                         * programming it from the master plane's update_plane
 330                         * callback runs into issues when the Y plane is
 331                         * reassigned, disabled or used by a different plane.
 332                         *
 333                         * The slave plane is updated with the master plane's
 334                         * plane_state.
 335                         */
 336                        new_plane_state =
 337                                intel_atomic_get_new_plane_state(state, master);
 338
 339                        intel_update_slave(plane, new_crtc_state, new_plane_state);
 340                } else {
 341                        intel_disable_plane(plane, new_crtc_state);
 342                }
 343        }
 344}
 345
 346void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
 347                                struct intel_crtc *crtc)
 348{
 349        struct intel_crtc_state *new_crtc_state =
 350                intel_atomic_get_new_crtc_state(state, crtc);
 351        u32 update_mask = new_crtc_state->update_planes;
 352        struct intel_plane_state *new_plane_state;
 353        struct intel_plane *plane;
 354        int i;
 355
 356        for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
 357                if (crtc->pipe != plane->pipe ||
 358                    !(update_mask & BIT(plane->id)))
 359                        continue;
 360
 361                if (new_plane_state->base.visible)
 362                        intel_update_plane(plane, new_crtc_state, new_plane_state);
 363                else
 364                        intel_disable_plane(plane, new_crtc_state);
 365        }
 366}
 367
 368const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
 369        .prepare_fb = intel_prepare_plane_fb,
 370        .cleanup_fb = intel_cleanup_plane_fb,
 371        .atomic_check = intel_plane_atomic_check,
 372};
 373