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_cdclk.h"
  41#include "intel_display_types.h"
  42#include "intel_pm.h"
  43#include "intel_sprite.h"
  44
  45static void intel_plane_state_reset(struct intel_plane_state *plane_state,
  46                                    struct intel_plane *plane)
  47{
  48        memset(plane_state, 0, sizeof(*plane_state));
  49
  50        __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base);
  51
  52        plane_state->scaler_id = -1;
  53}
  54
  55struct intel_plane *intel_plane_alloc(void)
  56{
  57        struct intel_plane_state *plane_state;
  58        struct intel_plane *plane;
  59
  60        plane = kzalloc(sizeof(*plane), GFP_KERNEL);
  61        if (!plane)
  62                return ERR_PTR(-ENOMEM);
  63
  64        plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
  65        if (!plane_state) {
  66                kfree(plane);
  67                return ERR_PTR(-ENOMEM);
  68        }
  69
  70        intel_plane_state_reset(plane_state, plane);
  71
  72        plane->base.state = &plane_state->uapi;
  73
  74        return plane;
  75}
  76
  77void intel_plane_free(struct intel_plane *plane)
  78{
  79        intel_plane_destroy_state(&plane->base, plane->base.state);
  80        kfree(plane);
  81}
  82
  83/**
  84 * intel_plane_duplicate_state - duplicate plane state
  85 * @plane: drm plane
  86 *
  87 * Allocates and returns a copy of the plane state (both common and
  88 * Intel-specific) for the specified plane.
  89 *
  90 * Returns: The newly allocated plane state, or NULL on failure.
  91 */
  92struct drm_plane_state *
  93intel_plane_duplicate_state(struct drm_plane *plane)
  94{
  95        struct intel_plane_state *intel_state;
  96
  97        intel_state = to_intel_plane_state(plane->state);
  98        intel_state = kmemdup(intel_state, sizeof(*intel_state), GFP_KERNEL);
  99
 100        if (!intel_state)
 101                return NULL;
 102
 103        __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi);
 104
 105        intel_state->vma = NULL;
 106        intel_state->flags = 0;
 107
 108        /* add reference to fb */
 109        if (intel_state->hw.fb)
 110                drm_framebuffer_get(intel_state->hw.fb);
 111
 112        return &intel_state->uapi;
 113}
 114
 115/**
 116 * intel_plane_destroy_state - destroy plane state
 117 * @plane: drm plane
 118 * @state: state object to destroy
 119 *
 120 * Destroys the plane state (both common and Intel-specific) for the
 121 * specified plane.
 122 */
 123void
 124intel_plane_destroy_state(struct drm_plane *plane,
 125                          struct drm_plane_state *state)
 126{
 127        struct intel_plane_state *plane_state = to_intel_plane_state(state);
 128        drm_WARN_ON(plane->dev, plane_state->vma);
 129
 130        __drm_atomic_helper_plane_destroy_state(&plane_state->uapi);
 131        if (plane_state->hw.fb)
 132                drm_framebuffer_put(plane_state->hw.fb);
 133        kfree(plane_state);
 134}
 135
 136unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
 137                                    const struct intel_plane_state *plane_state)
 138{
 139        unsigned int src_w, src_h, dst_w, dst_h;
 140        unsigned int pixel_rate = crtc_state->pixel_rate;
 141
 142        src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 143        src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 144        dst_w = drm_rect_width(&plane_state->uapi.dst);
 145        dst_h = drm_rect_height(&plane_state->uapi.dst);
 146
 147        /* Downscaling limits the maximum pixel rate */
 148        dst_w = min(src_w, dst_w);
 149        dst_h = min(src_h, dst_h);
 150
 151        return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, src_w * src_h),
 152                                dst_w * dst_h);
 153}
 154
 155unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
 156                                   const struct intel_plane_state *plane_state)
 157{
 158        const struct drm_framebuffer *fb = plane_state->hw.fb;
 159        unsigned int cpp;
 160        unsigned int pixel_rate;
 161
 162        if (!plane_state->uapi.visible)
 163                return 0;
 164
 165        pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
 166
 167        cpp = fb->format->cpp[0];
 168
 169        /*
 170         * Based on HSD#:1408715493
 171         * NV12 cpp == 4, P010 cpp == 8
 172         *
 173         * FIXME what is the logic behind this?
 174         */
 175        if (fb->format->is_yuv && fb->format->num_planes > 1)
 176                cpp *= 4;
 177
 178        return pixel_rate * cpp;
 179}
 180
 181int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
 182                               struct intel_plane *plane,
 183                               bool *need_cdclk_calc)
 184{
 185        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 186        const struct intel_plane_state *plane_state =
 187                intel_atomic_get_new_plane_state(state, plane);
 188        struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc);
 189        const struct intel_cdclk_state *cdclk_state;
 190        const struct intel_crtc_state *old_crtc_state;
 191        struct intel_crtc_state *new_crtc_state;
 192
 193        if (!plane_state->uapi.visible || !plane->min_cdclk)
 194                return 0;
 195
 196        old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
 197        new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
 198
 199        new_crtc_state->min_cdclk[plane->id] =
 200                plane->min_cdclk(new_crtc_state, plane_state);
 201
 202        /*
 203         * No need to check against the cdclk state if
 204         * the min cdclk for the plane doesn't increase.
 205         *
 206         * Ie. we only ever increase the cdclk due to plane
 207         * requirements. This can reduce back and forth
 208         * display blinking due to constant cdclk changes.
 209         */
 210        if (new_crtc_state->min_cdclk[plane->id] <=
 211            old_crtc_state->min_cdclk[plane->id])
 212                return 0;
 213
 214        cdclk_state = intel_atomic_get_cdclk_state(state);
 215        if (IS_ERR(cdclk_state))
 216                return PTR_ERR(cdclk_state);
 217
 218        /*
 219         * No need to recalculate the cdclk state if
 220         * the min cdclk for the pipe doesn't increase.
 221         *
 222         * Ie. we only ever increase the cdclk due to plane
 223         * requirements. This can reduce back and forth
 224         * display blinking due to constant cdclk changes.
 225         */
 226        if (new_crtc_state->min_cdclk[plane->id] <=
 227            cdclk_state->min_cdclk[crtc->pipe])
 228                return 0;
 229
 230        drm_dbg_kms(&dev_priv->drm,
 231                    "[PLANE:%d:%s] min cdclk (%d kHz) > [CRTC:%d:%s] min cdclk (%d kHz)\n",
 232                    plane->base.base.id, plane->base.name,
 233                    new_crtc_state->min_cdclk[plane->id],
 234                    crtc->base.base.id, crtc->base.name,
 235                    cdclk_state->min_cdclk[crtc->pipe]);
 236        *need_cdclk_calc = true;
 237
 238        return 0;
 239}
 240
 241static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state)
 242{
 243        if (plane_state->hw.fb)
 244                drm_framebuffer_put(plane_state->hw.fb);
 245
 246        memset(&plane_state->hw, 0, sizeof(plane_state->hw));
 247}
 248
 249void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
 250                                       const struct intel_plane_state *from_plane_state)
 251{
 252        intel_plane_clear_hw_state(plane_state);
 253
 254        plane_state->hw.crtc = from_plane_state->uapi.crtc;
 255        plane_state->hw.fb = from_plane_state->uapi.fb;
 256        if (plane_state->hw.fb)
 257                drm_framebuffer_get(plane_state->hw.fb);
 258
 259        plane_state->hw.alpha = from_plane_state->uapi.alpha;
 260        plane_state->hw.pixel_blend_mode =
 261                from_plane_state->uapi.pixel_blend_mode;
 262        plane_state->hw.rotation = from_plane_state->uapi.rotation;
 263        plane_state->hw.color_encoding = from_plane_state->uapi.color_encoding;
 264        plane_state->hw.color_range = from_plane_state->uapi.color_range;
 265}
 266
 267void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
 268                               struct intel_plane_state *plane_state)
 269{
 270        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 271
 272        crtc_state->active_planes &= ~BIT(plane->id);
 273        crtc_state->nv12_planes &= ~BIT(plane->id);
 274        crtc_state->c8_planes &= ~BIT(plane->id);
 275        crtc_state->data_rate[plane->id] = 0;
 276        crtc_state->min_cdclk[plane->id] = 0;
 277
 278        plane_state->uapi.visible = false;
 279}
 280
 281int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
 282                                        struct intel_crtc_state *new_crtc_state,
 283                                        const struct intel_plane_state *old_plane_state,
 284                                        struct intel_plane_state *new_plane_state)
 285{
 286        struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
 287        const struct drm_framebuffer *fb = new_plane_state->hw.fb;
 288        int ret;
 289
 290        intel_plane_set_invisible(new_crtc_state, new_plane_state);
 291
 292        if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc)
 293                return 0;
 294
 295        ret = plane->check_plane(new_crtc_state, new_plane_state);
 296        if (ret)
 297                return ret;
 298
 299        /* FIXME pre-g4x don't work like this */
 300        if (new_plane_state->uapi.visible)
 301                new_crtc_state->active_planes |= BIT(plane->id);
 302
 303        if (new_plane_state->uapi.visible &&
 304            intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
 305                new_crtc_state->nv12_planes |= BIT(plane->id);
 306
 307        if (new_plane_state->uapi.visible &&
 308            fb->format->format == DRM_FORMAT_C8)
 309                new_crtc_state->c8_planes |= BIT(plane->id);
 310
 311        if (new_plane_state->uapi.visible || old_plane_state->uapi.visible)
 312                new_crtc_state->update_planes |= BIT(plane->id);
 313
 314        new_crtc_state->data_rate[plane->id] =
 315                intel_plane_data_rate(new_crtc_state, new_plane_state);
 316
 317        return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
 318                                               old_plane_state, new_plane_state);
 319}
 320
 321static struct intel_crtc *
 322get_crtc_from_states(const struct intel_plane_state *old_plane_state,
 323                     const struct intel_plane_state *new_plane_state)
 324{
 325        if (new_plane_state->uapi.crtc)
 326                return to_intel_crtc(new_plane_state->uapi.crtc);
 327
 328        if (old_plane_state->uapi.crtc)
 329                return to_intel_crtc(old_plane_state->uapi.crtc);
 330
 331        return NULL;
 332}
 333
 334int intel_plane_atomic_check(struct intel_atomic_state *state,
 335                             struct intel_plane *plane)
 336{
 337        struct intel_plane_state *new_plane_state =
 338                intel_atomic_get_new_plane_state(state, plane);
 339        const struct intel_plane_state *old_plane_state =
 340                intel_atomic_get_old_plane_state(state, plane);
 341        struct intel_crtc *crtc =
 342                get_crtc_from_states(old_plane_state, new_plane_state);
 343        const struct intel_crtc_state *old_crtc_state;
 344        struct intel_crtc_state *new_crtc_state;
 345
 346        intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state);
 347        new_plane_state->uapi.visible = false;
 348        if (!crtc)
 349                return 0;
 350
 351        old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
 352        new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
 353
 354        return intel_plane_atomic_check_with_state(old_crtc_state,
 355                                                   new_crtc_state,
 356                                                   old_plane_state,
 357                                                   new_plane_state);
 358}
 359
 360static struct intel_plane *
 361skl_next_plane_to_commit(struct intel_atomic_state *state,
 362                         struct intel_crtc *crtc,
 363                         struct skl_ddb_entry entries_y[I915_MAX_PLANES],
 364                         struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
 365                         unsigned int *update_mask)
 366{
 367        struct intel_crtc_state *crtc_state =
 368                intel_atomic_get_new_crtc_state(state, crtc);
 369        struct intel_plane_state *plane_state;
 370        struct intel_plane *plane;
 371        int i;
 372
 373        if (*update_mask == 0)
 374                return NULL;
 375
 376        for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
 377                enum plane_id plane_id = plane->id;
 378
 379                if (crtc->pipe != plane->pipe ||
 380                    !(*update_mask & BIT(plane_id)))
 381                        continue;
 382
 383                if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
 384                                                entries_y,
 385                                                I915_MAX_PLANES, plane_id) ||
 386                    skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
 387                                                entries_uv,
 388                                                I915_MAX_PLANES, plane_id))
 389                        continue;
 390
 391                *update_mask &= ~BIT(plane_id);
 392                entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
 393                entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
 394
 395                return plane;
 396        }
 397
 398        /* should never happen */
 399        drm_WARN_ON(state->base.dev, 1);
 400
 401        return NULL;
 402}
 403
 404void intel_update_plane(struct intel_plane *plane,
 405                        const struct intel_crtc_state *crtc_state,
 406                        const struct intel_plane_state *plane_state)
 407{
 408        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 409
 410        trace_intel_update_plane(&plane->base, crtc);
 411        plane->update_plane(plane, crtc_state, plane_state);
 412}
 413
 414void intel_disable_plane(struct intel_plane *plane,
 415                         const struct intel_crtc_state *crtc_state)
 416{
 417        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 418
 419        trace_intel_disable_plane(&plane->base, crtc);
 420        plane->disable_plane(plane, crtc_state);
 421}
 422
 423void skl_update_planes_on_crtc(struct intel_atomic_state *state,
 424                               struct intel_crtc *crtc)
 425{
 426        struct intel_crtc_state *old_crtc_state =
 427                intel_atomic_get_old_crtc_state(state, crtc);
 428        struct intel_crtc_state *new_crtc_state =
 429                intel_atomic_get_new_crtc_state(state, crtc);
 430        struct skl_ddb_entry entries_y[I915_MAX_PLANES];
 431        struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
 432        u32 update_mask = new_crtc_state->update_planes;
 433        struct intel_plane *plane;
 434
 435        memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
 436               sizeof(old_crtc_state->wm.skl.plane_ddb_y));
 437        memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
 438               sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
 439
 440        while ((plane = skl_next_plane_to_commit(state, crtc,
 441                                                 entries_y, entries_uv,
 442                                                 &update_mask))) {
 443                struct intel_plane_state *new_plane_state =
 444                        intel_atomic_get_new_plane_state(state, plane);
 445
 446                if (new_plane_state->uapi.visible ||
 447                    new_plane_state->planar_slave) {
 448                        intel_update_plane(plane, new_crtc_state, new_plane_state);
 449                } else {
 450                        intel_disable_plane(plane, new_crtc_state);
 451                }
 452        }
 453}
 454
 455void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
 456                                struct intel_crtc *crtc)
 457{
 458        struct intel_crtc_state *new_crtc_state =
 459                intel_atomic_get_new_crtc_state(state, crtc);
 460        u32 update_mask = new_crtc_state->update_planes;
 461        struct intel_plane_state *new_plane_state;
 462        struct intel_plane *plane;
 463        int i;
 464
 465        for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
 466                if (crtc->pipe != plane->pipe ||
 467                    !(update_mask & BIT(plane->id)))
 468                        continue;
 469
 470                if (new_plane_state->uapi.visible)
 471                        intel_update_plane(plane, new_crtc_state, new_plane_state);
 472                else
 473                        intel_disable_plane(plane, new_crtc_state);
 474        }
 475}
 476
 477const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
 478        .prepare_fb = intel_prepare_plane_fb,
 479        .cleanup_fb = intel_cleanup_plane_fb,
 480};
 481