linux/drivers/gpu/drm/i915/intel_atomic.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2015 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 modeset support
  26 *
  27 * The functions here implement the state management and hardware programming
  28 * dispatch required by the atomic modeset infrastructure.
  29 * See intel_atomic_plane.c for the plane-specific atomic functionality.
  30 */
  31
  32#include <drm/drmP.h>
  33#include <drm/drm_atomic.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_plane_helper.h>
  36#include "intel_drv.h"
  37
  38/**
  39 * intel_digital_connector_atomic_get_property - hook for connector->atomic_get_property.
  40 * @connector: Connector to get the property for.
  41 * @state: Connector state to retrieve the property from.
  42 * @property: Property to retrieve.
  43 * @val: Return value for the property.
  44 *
  45 * Returns the atomic property value for a digital connector.
  46 */
  47int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
  48                                                const struct drm_connector_state *state,
  49                                                struct drm_property *property,
  50                                                uint64_t *val)
  51{
  52        struct drm_device *dev = connector->dev;
  53        struct drm_i915_private *dev_priv = to_i915(dev);
  54        struct intel_digital_connector_state *intel_conn_state =
  55                to_intel_digital_connector_state(state);
  56
  57        if (property == dev_priv->force_audio_property)
  58                *val = intel_conn_state->force_audio;
  59        else if (property == dev_priv->broadcast_rgb_property)
  60                *val = intel_conn_state->broadcast_rgb;
  61        else {
  62                DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
  63                                 property->base.id, property->name);
  64                return -EINVAL;
  65        }
  66
  67        return 0;
  68}
  69
  70/**
  71 * intel_digital_connector_atomic_set_property - hook for connector->atomic_set_property.
  72 * @connector: Connector to set the property for.
  73 * @state: Connector state to set the property on.
  74 * @property: Property to set.
  75 * @val: New value for the property.
  76 *
  77 * Sets the atomic property value for a digital connector.
  78 */
  79int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
  80                                                struct drm_connector_state *state,
  81                                                struct drm_property *property,
  82                                                uint64_t val)
  83{
  84        struct drm_device *dev = connector->dev;
  85        struct drm_i915_private *dev_priv = to_i915(dev);
  86        struct intel_digital_connector_state *intel_conn_state =
  87                to_intel_digital_connector_state(state);
  88
  89        if (property == dev_priv->force_audio_property) {
  90                intel_conn_state->force_audio = val;
  91                return 0;
  92        }
  93
  94        if (property == dev_priv->broadcast_rgb_property) {
  95                intel_conn_state->broadcast_rgb = val;
  96                return 0;
  97        }
  98
  99        DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
 100                         property->base.id, property->name);
 101        return -EINVAL;
 102}
 103
 104int intel_digital_connector_atomic_check(struct drm_connector *conn,
 105                                         struct drm_connector_state *new_state)
 106{
 107        struct intel_digital_connector_state *new_conn_state =
 108                to_intel_digital_connector_state(new_state);
 109        struct drm_connector_state *old_state =
 110                drm_atomic_get_old_connector_state(new_state->state, conn);
 111        struct intel_digital_connector_state *old_conn_state =
 112                to_intel_digital_connector_state(old_state);
 113        struct drm_crtc_state *crtc_state;
 114
 115        intel_hdcp_atomic_check(conn, old_state, new_state);
 116
 117        if (!new_state->crtc)
 118                return 0;
 119
 120        crtc_state = drm_atomic_get_new_crtc_state(new_state->state, new_state->crtc);
 121
 122        /*
 123         * These properties are handled by fastset, and might not end
 124         * up in a modeset.
 125         */
 126        if (new_conn_state->force_audio != old_conn_state->force_audio ||
 127            new_conn_state->broadcast_rgb != old_conn_state->broadcast_rgb ||
 128            new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
 129            new_conn_state->base.content_type != old_conn_state->base.content_type ||
 130            new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode)
 131                crtc_state->mode_changed = true;
 132
 133        return 0;
 134}
 135
 136/**
 137 * intel_digital_connector_duplicate_state - duplicate connector state
 138 * @connector: digital connector
 139 *
 140 * Allocates and returns a copy of the connector state (both common and
 141 * digital connector specific) for the specified connector.
 142 *
 143 * Returns: The newly allocated connector state, or NULL on failure.
 144 */
 145struct drm_connector_state *
 146intel_digital_connector_duplicate_state(struct drm_connector *connector)
 147{
 148        struct intel_digital_connector_state *state;
 149
 150        state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
 151        if (!state)
 152                return NULL;
 153
 154        __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
 155        return &state->base;
 156}
 157
 158/**
 159 * intel_crtc_duplicate_state - duplicate crtc state
 160 * @crtc: drm crtc
 161 *
 162 * Allocates and returns a copy of the crtc state (both common and
 163 * Intel-specific) for the specified crtc.
 164 *
 165 * Returns: The newly allocated crtc state, or NULL on failure.
 166 */
 167struct drm_crtc_state *
 168intel_crtc_duplicate_state(struct drm_crtc *crtc)
 169{
 170        struct intel_crtc_state *crtc_state;
 171
 172        crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL);
 173        if (!crtc_state)
 174                return NULL;
 175
 176        __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
 177
 178        crtc_state->update_pipe = false;
 179        crtc_state->disable_lp_wm = false;
 180        crtc_state->disable_cxsr = false;
 181        crtc_state->update_wm_pre = false;
 182        crtc_state->update_wm_post = false;
 183        crtc_state->fb_changed = false;
 184        crtc_state->fifo_changed = false;
 185        crtc_state->wm.need_postvbl_update = false;
 186        crtc_state->fb_bits = 0;
 187        crtc_state->update_planes = 0;
 188
 189        return &crtc_state->base;
 190}
 191
 192/**
 193 * intel_crtc_destroy_state - destroy crtc state
 194 * @crtc: drm crtc
 195 * @state: the state to destroy
 196 *
 197 * Destroys the crtc state (both common and Intel-specific) for the
 198 * specified crtc.
 199 */
 200void
 201intel_crtc_destroy_state(struct drm_crtc *crtc,
 202                         struct drm_crtc_state *state)
 203{
 204        drm_atomic_helper_crtc_destroy_state(crtc, state);
 205}
 206
 207static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
 208                                      int num_scalers_need, struct intel_crtc *intel_crtc,
 209                                      const char *name, int idx,
 210                                      struct intel_plane_state *plane_state,
 211                                      int *scaler_id)
 212{
 213        struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 214        int j;
 215        u32 mode;
 216
 217        if (*scaler_id < 0) {
 218                /* find a free scaler */
 219                for (j = 0; j < intel_crtc->num_scalers; j++) {
 220                        if (scaler_state->scalers[j].in_use)
 221                                continue;
 222
 223                        *scaler_id = j;
 224                        scaler_state->scalers[*scaler_id].in_use = 1;
 225                        break;
 226                }
 227        }
 228
 229        if (WARN(*scaler_id < 0, "Cannot find scaler for %s:%d\n", name, idx))
 230                return;
 231
 232        /* set scaler mode */
 233        if (plane_state && plane_state->base.fb &&
 234            plane_state->base.fb->format->is_yuv &&
 235            plane_state->base.fb->format->num_planes > 1) {
 236                if (IS_GEN9(dev_priv) &&
 237                    !IS_GEMINILAKE(dev_priv)) {
 238                        mode = SKL_PS_SCALER_MODE_NV12;
 239                } else if (icl_is_hdr_plane(to_intel_plane(plane_state->base.plane))) {
 240                        /*
 241                         * On gen11+'s HDR planes we only use the scaler for
 242                         * scaling. They have a dedicated chroma upsampler, so
 243                         * we don't need the scaler to upsample the UV plane.
 244                         */
 245                        mode = PS_SCALER_MODE_NORMAL;
 246                } else {
 247                        mode = PS_SCALER_MODE_PLANAR;
 248
 249                        if (plane_state->linked_plane)
 250                                mode |= PS_PLANE_Y_SEL(plane_state->linked_plane->id);
 251                }
 252        } else if (INTEL_GEN(dev_priv) > 9 || IS_GEMINILAKE(dev_priv)) {
 253                mode = PS_SCALER_MODE_NORMAL;
 254        } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
 255                /*
 256                 * when only 1 scaler is in use on a pipe with 2 scalers
 257                 * scaler 0 operates in high quality (HQ) mode.
 258                 * In this case use scaler 0 to take advantage of HQ mode
 259                 */
 260                scaler_state->scalers[*scaler_id].in_use = 0;
 261                *scaler_id = 0;
 262                scaler_state->scalers[0].in_use = 1;
 263                mode = SKL_PS_SCALER_MODE_HQ;
 264        } else {
 265                mode = SKL_PS_SCALER_MODE_DYN;
 266        }
 267
 268        DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
 269                      intel_crtc->pipe, *scaler_id, name, idx);
 270        scaler_state->scalers[*scaler_id].mode = mode;
 271}
 272
 273/**
 274 * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
 275 * @dev_priv: i915 device
 276 * @intel_crtc: intel crtc
 277 * @crtc_state: incoming crtc_state to validate and setup scalers
 278 *
 279 * This function sets up scalers based on staged scaling requests for
 280 * a @crtc and its planes. It is called from crtc level check path. If request
 281 * is a supportable request, it attaches scalers to requested planes and crtc.
 282 *
 283 * This function takes into account the current scaler(s) in use by any planes
 284 * not being part of this atomic state
 285 *
 286 *  Returns:
 287 *         0 - scalers were setup succesfully
 288 *         error code - otherwise
 289 */
 290int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 291                               struct intel_crtc *intel_crtc,
 292                               struct intel_crtc_state *crtc_state)
 293{
 294        struct drm_plane *plane = NULL;
 295        struct intel_plane *intel_plane;
 296        struct intel_plane_state *plane_state = NULL;
 297        struct intel_crtc_scaler_state *scaler_state =
 298                &crtc_state->scaler_state;
 299        struct drm_atomic_state *drm_state = crtc_state->base.state;
 300        struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
 301        int num_scalers_need;
 302        int i;
 303
 304        num_scalers_need = hweight32(scaler_state->scaler_users);
 305
 306        /*
 307         * High level flow:
 308         * - staged scaler requests are already in scaler_state->scaler_users
 309         * - check whether staged scaling requests can be supported
 310         * - add planes using scalers that aren't in current transaction
 311         * - assign scalers to requested users
 312         * - as part of plane commit, scalers will be committed
 313         *   (i.e., either attached or detached) to respective planes in hw
 314         * - as part of crtc_commit, scaler will be either attached or detached
 315         *   to crtc in hw
 316         */
 317
 318        /* fail if required scalers > available scalers */
 319        if (num_scalers_need > intel_crtc->num_scalers){
 320                DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
 321                        num_scalers_need, intel_crtc->num_scalers);
 322                return -EINVAL;
 323        }
 324
 325        /* walkthrough scaler_users bits and start assigning scalers */
 326        for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
 327                int *scaler_id;
 328                const char *name;
 329                int idx;
 330
 331                /* skip if scaler not required */
 332                if (!(scaler_state->scaler_users & (1 << i)))
 333                        continue;
 334
 335                if (i == SKL_CRTC_INDEX) {
 336                        name = "CRTC";
 337                        idx = intel_crtc->base.base.id;
 338
 339                        /* panel fitter case: assign as a crtc scaler */
 340                        scaler_id = &scaler_state->scaler_id;
 341                } else {
 342                        name = "PLANE";
 343
 344                        /* plane scaler case: assign as a plane scaler */
 345                        /* find the plane that set the bit as scaler_user */
 346                        plane = drm_state->planes[i].ptr;
 347
 348                        /*
 349                         * to enable/disable hq mode, add planes that are using scaler
 350                         * into this transaction
 351                         */
 352                        if (!plane) {
 353                                struct drm_plane_state *state;
 354                                plane = drm_plane_from_index(&dev_priv->drm, i);
 355                                state = drm_atomic_get_plane_state(drm_state, plane);
 356                                if (IS_ERR(state)) {
 357                                        DRM_DEBUG_KMS("Failed to add [PLANE:%d] to drm_state\n",
 358                                                plane->base.id);
 359                                        return PTR_ERR(state);
 360                                }
 361
 362                                /*
 363                                 * the plane is added after plane checks are run,
 364                                 * but since this plane is unchanged just do the
 365                                 * minimum required validation.
 366                                 */
 367                                crtc_state->base.planes_changed = true;
 368                        }
 369
 370                        intel_plane = to_intel_plane(plane);
 371                        idx = plane->base.id;
 372
 373                        /* plane on different crtc cannot be a scaler user of this crtc */
 374                        if (WARN_ON(intel_plane->pipe != intel_crtc->pipe))
 375                                continue;
 376
 377                        plane_state = intel_atomic_get_new_plane_state(intel_state,
 378                                                                       intel_plane);
 379                        scaler_id = &plane_state->scaler_id;
 380                }
 381
 382                intel_atomic_setup_scaler(scaler_state, num_scalers_need,
 383                                          intel_crtc, name, idx,
 384                                          plane_state, scaler_id);
 385        }
 386
 387        return 0;
 388}
 389
 390struct drm_atomic_state *
 391intel_atomic_state_alloc(struct drm_device *dev)
 392{
 393        struct intel_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
 394
 395        if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
 396                kfree(state);
 397                return NULL;
 398        }
 399
 400        return &state->base;
 401}
 402
 403void intel_atomic_state_clear(struct drm_atomic_state *s)
 404{
 405        struct intel_atomic_state *state = to_intel_atomic_state(s);
 406        drm_atomic_state_default_clear(&state->base);
 407        state->dpll_set = state->modeset = false;
 408}
 409