linux/drivers/gpu/drm/nouveau/dispnv50/crc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2#include <linux/string.h>
   3#include <drm/drm_crtc.h>
   4#include <drm/drm_atomic_helper.h>
   5#include <drm/drm_vblank.h>
   6#include <drm/drm_vblank_work.h>
   7
   8#include <nvif/class.h>
   9#include <nvif/cl0002.h>
  10#include <nvif/timer.h>
  11
  12#include <nvhw/class/cl907d.h>
  13
  14#include "nouveau_drv.h"
  15#include "core.h"
  16#include "head.h"
  17#include "wndw.h"
  18#include "handles.h"
  19#include "crc.h"
  20
  21static const char * const nv50_crc_sources[] = {
  22        [NV50_CRC_SOURCE_NONE] = "none",
  23        [NV50_CRC_SOURCE_AUTO] = "auto",
  24        [NV50_CRC_SOURCE_RG] = "rg",
  25        [NV50_CRC_SOURCE_OUTP_ACTIVE] = "outp-active",
  26        [NV50_CRC_SOURCE_OUTP_COMPLETE] = "outp-complete",
  27        [NV50_CRC_SOURCE_OUTP_INACTIVE] = "outp-inactive",
  28};
  29
  30static int nv50_crc_parse_source(const char *buf, enum nv50_crc_source *s)
  31{
  32        int i;
  33
  34        if (!buf) {
  35                *s = NV50_CRC_SOURCE_NONE;
  36                return 0;
  37        }
  38
  39        i = match_string(nv50_crc_sources, ARRAY_SIZE(nv50_crc_sources), buf);
  40        if (i < 0)
  41                return i;
  42
  43        *s = i;
  44        return 0;
  45}
  46
  47int
  48nv50_crc_verify_source(struct drm_crtc *crtc, const char *source_name,
  49                       size_t *values_cnt)
  50{
  51        struct nouveau_drm *drm = nouveau_drm(crtc->dev);
  52        enum nv50_crc_source source;
  53
  54        if (nv50_crc_parse_source(source_name, &source) < 0) {
  55                NV_DEBUG(drm, "unknown source %s\n", source_name);
  56                return -EINVAL;
  57        }
  58
  59        *values_cnt = 1;
  60        return 0;
  61}
  62
  63const char *const *nv50_crc_get_sources(struct drm_crtc *crtc, size_t *count)
  64{
  65        *count = ARRAY_SIZE(nv50_crc_sources);
  66        return nv50_crc_sources;
  67}
  68
  69static void
  70nv50_crc_program_ctx(struct nv50_head *head,
  71                     struct nv50_crc_notifier_ctx *ctx)
  72{
  73        struct nv50_disp *disp = nv50_disp(head->base.base.dev);
  74        struct nv50_core *core = disp->core;
  75        u32 interlock[NV50_DISP_INTERLOCK__SIZE] = { 0 };
  76
  77        core->func->crc->set_ctx(head, ctx);
  78        core->func->update(core, interlock, false);
  79}
  80
  81static void nv50_crc_ctx_flip_work(struct kthread_work *base)
  82{
  83        struct drm_vblank_work *work = to_drm_vblank_work(base);
  84        struct nv50_crc *crc = container_of(work, struct nv50_crc, flip_work);
  85        struct nv50_head *head = container_of(crc, struct nv50_head, crc);
  86        struct drm_crtc *crtc = &head->base.base;
  87        struct nv50_disp *disp = nv50_disp(crtc->dev);
  88        u8 new_idx = crc->ctx_idx ^ 1;
  89
  90        /*
  91         * We don't want to accidentally wait for longer then the vblank, so
  92         * try again for the next vblank if we don't grab the lock
  93         */
  94        if (!mutex_trylock(&disp->mutex)) {
  95                DRM_DEV_DEBUG_KMS(crtc->dev->dev,
  96                                  "Lock contended, delaying CRC ctx flip for head-%d\n",
  97                                  head->base.index);
  98                drm_vblank_work_schedule(work,
  99                                         drm_crtc_vblank_count(crtc) + 1,
 100                                         true);
 101                return;
 102        }
 103
 104        DRM_DEV_DEBUG_KMS(crtc->dev->dev,
 105                          "Flipping notifier ctx for head %d (%d -> %d)\n",
 106                          drm_crtc_index(crtc), crc->ctx_idx, new_idx);
 107
 108        nv50_crc_program_ctx(head, NULL);
 109        nv50_crc_program_ctx(head, &crc->ctx[new_idx]);
 110        mutex_unlock(&disp->mutex);
 111
 112        spin_lock_irq(&crc->lock);
 113        crc->ctx_changed = true;
 114        spin_unlock_irq(&crc->lock);
 115}
 116
 117static inline void nv50_crc_reset_ctx(struct nv50_crc_notifier_ctx *ctx)
 118{
 119        memset_io(ctx->mem.object.map.ptr, 0, ctx->mem.object.map.size);
 120}
 121
 122static void
 123nv50_crc_get_entries(struct nv50_head *head,
 124                     const struct nv50_crc_func *func,
 125                     enum nv50_crc_source source)
 126{
 127        struct drm_crtc *crtc = &head->base.base;
 128        struct nv50_crc *crc = &head->crc;
 129        u32 output_crc;
 130
 131        while (crc->entry_idx < func->num_entries) {
 132                /*
 133                 * While Nvidia's documentation says CRCs are written on each
 134                 * subsequent vblank after being enabled, in practice they
 135                 * aren't written immediately.
 136                 */
 137                output_crc = func->get_entry(head, &crc->ctx[crc->ctx_idx],
 138                                             source, crc->entry_idx);
 139                if (!output_crc)
 140                        return;
 141
 142                drm_crtc_add_crc_entry(crtc, true, crc->frame, &output_crc);
 143                crc->frame++;
 144                crc->entry_idx++;
 145        }
 146}
 147
 148void nv50_crc_handle_vblank(struct nv50_head *head)
 149{
 150        struct drm_crtc *crtc = &head->base.base;
 151        struct nv50_crc *crc = &head->crc;
 152        const struct nv50_crc_func *func =
 153                nv50_disp(head->base.base.dev)->core->func->crc;
 154        struct nv50_crc_notifier_ctx *ctx;
 155        bool need_reschedule = false;
 156
 157        if (!func)
 158                return;
 159
 160        /*
 161         * We don't lose events if we aren't able to report CRCs until the
 162         * next vblank, so only report CRCs if the locks we need aren't
 163         * contended to prevent missing an actual vblank event
 164         */
 165        if (!spin_trylock(&crc->lock))
 166                return;
 167
 168        if (!crc->src)
 169                goto out;
 170
 171        ctx = &crc->ctx[crc->ctx_idx];
 172        if (crc->ctx_changed && func->ctx_finished(head, ctx)) {
 173                nv50_crc_get_entries(head, func, crc->src);
 174
 175                crc->ctx_idx ^= 1;
 176                crc->entry_idx = 0;
 177                crc->ctx_changed = false;
 178
 179                /*
 180                 * Unfortunately when notifier contexts are changed during CRC
 181                 * capture, we will inevitably lose the CRC entry for the
 182                 * frame where the hardware actually latched onto the first
 183                 * UPDATE. According to Nvidia's hardware engineers, there's
 184                 * no workaround for this.
 185                 *
 186                 * Now, we could try to be smart here and calculate the number
 187                 * of missed CRCs based on audit timestamps, but those were
 188                 * removed starting with volta. Since we always flush our
 189                 * updates back-to-back without waiting, we'll just be
 190                 * optimistic and assume we always miss exactly one frame.
 191                 */
 192                DRM_DEV_DEBUG_KMS(head->base.base.dev->dev,
 193                                  "Notifier ctx flip for head-%d finished, lost CRC for frame %llu\n",
 194                                  head->base.index, crc->frame);
 195                crc->frame++;
 196
 197                nv50_crc_reset_ctx(ctx);
 198                need_reschedule = true;
 199        }
 200
 201        nv50_crc_get_entries(head, func, crc->src);
 202
 203        if (need_reschedule)
 204                drm_vblank_work_schedule(&crc->flip_work,
 205                                         drm_crtc_vblank_count(crtc)
 206                                         + crc->flip_threshold
 207                                         - crc->entry_idx,
 208                                         true);
 209
 210out:
 211        spin_unlock(&crc->lock);
 212}
 213
 214static void nv50_crc_wait_ctx_finished(struct nv50_head *head,
 215                                       const struct nv50_crc_func *func,
 216                                       struct nv50_crc_notifier_ctx *ctx)
 217{
 218        struct drm_device *dev = head->base.base.dev;
 219        struct nouveau_drm *drm = nouveau_drm(dev);
 220        s64 ret;
 221
 222        ret = nvif_msec(&drm->client.device, 50,
 223                        if (func->ctx_finished(head, ctx)) break;);
 224        if (ret == -ETIMEDOUT)
 225                NV_ERROR(drm,
 226                         "CRC notifier ctx for head %d not finished after 50ms\n",
 227                         head->base.index);
 228        else if (ret)
 229                NV_ATOMIC(drm,
 230                          "CRC notifier ctx for head-%d finished after %lldns\n",
 231                          head->base.index, ret);
 232}
 233
 234void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state)
 235{
 236        struct drm_crtc_state *crtc_state;
 237        struct drm_crtc *crtc;
 238        int i;
 239
 240        for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 241                struct nv50_head *head = nv50_head(crtc);
 242                struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
 243                struct nv50_crc *crc = &head->crc;
 244
 245                if (!asyh->clr.crc)
 246                        continue;
 247
 248                spin_lock_irq(&crc->lock);
 249                crc->src = NV50_CRC_SOURCE_NONE;
 250                spin_unlock_irq(&crc->lock);
 251
 252                drm_crtc_vblank_put(crtc);
 253                drm_vblank_work_cancel_sync(&crc->flip_work);
 254
 255                NV_ATOMIC(nouveau_drm(crtc->dev),
 256                          "CRC reporting on vblank for head-%d disabled\n",
 257                          head->base.index);
 258
 259                /* CRC generation is still enabled in hw, we'll just report
 260                 * any remaining CRC entries ourselves after it gets disabled
 261                 * in hardware
 262                 */
 263        }
 264}
 265
 266void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state)
 267{
 268        struct drm_crtc_state *new_crtc_state;
 269        struct drm_crtc *crtc;
 270        int i;
 271
 272        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
 273                struct nv50_head *head = nv50_head(crtc);
 274                struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state);
 275                struct nv50_crc *crc = &head->crc;
 276                int i;
 277
 278                if (!asyh->set.crc)
 279                        continue;
 280
 281                crc->entry_idx = 0;
 282                crc->ctx_changed = false;
 283                for (i = 0; i < ARRAY_SIZE(crc->ctx); i++)
 284                        nv50_crc_reset_ctx(&crc->ctx[i]);
 285        }
 286}
 287
 288void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state)
 289{
 290        const struct nv50_crc_func *func =
 291                nv50_disp(state->dev)->core->func->crc;
 292        struct drm_crtc_state *new_crtc_state;
 293        struct drm_crtc *crtc;
 294        int i;
 295
 296        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
 297                struct nv50_head *head = nv50_head(crtc);
 298                struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state);
 299                struct nv50_crc *crc = &head->crc;
 300                struct nv50_crc_notifier_ctx *ctx = &crc->ctx[crc->ctx_idx];
 301
 302                if (!asyh->clr.crc)
 303                        continue;
 304
 305                if (crc->ctx_changed) {
 306                        nv50_crc_wait_ctx_finished(head, func, ctx);
 307                        ctx = &crc->ctx[crc->ctx_idx ^ 1];
 308                }
 309                nv50_crc_wait_ctx_finished(head, func, ctx);
 310        }
 311}
 312
 313void nv50_crc_atomic_start_reporting(struct drm_atomic_state *state)
 314{
 315        struct drm_crtc_state *crtc_state;
 316        struct drm_crtc *crtc;
 317        int i;
 318
 319        for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 320                struct nv50_head *head = nv50_head(crtc);
 321                struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
 322                struct nv50_crc *crc = &head->crc;
 323                u64 vbl_count;
 324
 325                if (!asyh->set.crc)
 326                        continue;
 327
 328                drm_crtc_vblank_get(crtc);
 329
 330                spin_lock_irq(&crc->lock);
 331                vbl_count = drm_crtc_vblank_count(crtc);
 332                crc->frame = vbl_count;
 333                crc->src = asyh->crc.src;
 334                drm_vblank_work_schedule(&crc->flip_work,
 335                                         vbl_count + crc->flip_threshold,
 336                                         true);
 337                spin_unlock_irq(&crc->lock);
 338
 339                NV_ATOMIC(nouveau_drm(crtc->dev),
 340                          "CRC reporting on vblank for head-%d enabled\n",
 341                          head->base.index);
 342        }
 343}
 344
 345int nv50_crc_atomic_check_head(struct nv50_head *head,
 346                               struct nv50_head_atom *asyh,
 347                               struct nv50_head_atom *armh)
 348{
 349        struct nv50_atom *atom = nv50_atom(asyh->state.state);
 350        struct drm_device *dev = head->base.base.dev;
 351        struct nv50_disp *disp = nv50_disp(dev);
 352        bool changed = armh->crc.src != asyh->crc.src;
 353
 354        if (!armh->crc.src && !asyh->crc.src) {
 355                asyh->set.crc = false;
 356                asyh->clr.crc = false;
 357                return 0;
 358        }
 359
 360        /* While we don't care about entry tags, Volta+ hw always needs the
 361         * controlling wndw channel programmed to a wndw that's owned by our
 362         * head
 363         */
 364        if (asyh->crc.src && disp->disp->object.oclass >= GV100_DISP &&
 365            !(BIT(asyh->crc.wndw) & asyh->wndw.owned)) {
 366                if (!asyh->wndw.owned) {
 367                        /* TODO: once we support flexible channel ownership,
 368                         * we should write some code here to handle attempting
 369                         * to "steal" a plane: e.g. take a plane that is
 370                         * currently not-visible and owned by another head,
 371                         * and reassign it to this head. If we fail to do so,
 372                         * we shuld reject the mode outright as CRC capture
 373                         * then becomes impossible.
 374                         */
 375                        NV_ATOMIC(nouveau_drm(dev),
 376                                  "No available wndws for CRC readback\n");
 377                        return -EINVAL;
 378                }
 379                asyh->crc.wndw = ffs(asyh->wndw.owned) - 1;
 380        }
 381
 382        if (drm_atomic_crtc_needs_modeset(&asyh->state) || changed ||
 383            armh->crc.wndw != asyh->crc.wndw) {
 384                asyh->clr.crc = armh->crc.src && armh->state.active;
 385                asyh->set.crc = asyh->crc.src && asyh->state.active;
 386                if (changed)
 387                        asyh->set.or |= armh->or.crc_raster !=
 388                                        asyh->or.crc_raster;
 389
 390                if (asyh->clr.crc && asyh->set.crc)
 391                        atom->flush_disable = true;
 392        } else {
 393                asyh->set.crc = false;
 394                asyh->clr.crc = false;
 395        }
 396
 397        return 0;
 398}
 399
 400void nv50_crc_atomic_check_outp(struct nv50_atom *atom)
 401{
 402        struct drm_crtc *crtc;
 403        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
 404        int i;
 405
 406        if (atom->flush_disable)
 407                return;
 408
 409        for_each_oldnew_crtc_in_state(&atom->state, crtc, old_crtc_state,
 410                                      new_crtc_state, i) {
 411                struct nv50_head_atom *armh = nv50_head_atom(old_crtc_state);
 412                struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state);
 413                struct nv50_outp_atom *outp_atom;
 414                struct nouveau_encoder *outp =
 415                        nv50_real_outp(nv50_head_atom_get_encoder(armh));
 416                struct drm_encoder *encoder = &outp->base.base;
 417
 418                if (!asyh->clr.crc)
 419                        continue;
 420
 421                /*
 422                 * Re-programming ORs can't be done in the same flush as
 423                 * disabling CRCs
 424                 */
 425                list_for_each_entry(outp_atom, &atom->outp, head) {
 426                        if (outp_atom->encoder == encoder) {
 427                                if (outp_atom->set.mask) {
 428                                        atom->flush_disable = true;
 429                                        return;
 430                                } else {
 431                                        break;
 432                                }
 433                        }
 434                }
 435        }
 436}
 437
 438static enum nv50_crc_source_type
 439nv50_crc_source_type(struct nouveau_encoder *outp,
 440                     enum nv50_crc_source source)
 441{
 442        struct dcb_output *dcbe = outp->dcb;
 443
 444        switch (source) {
 445        case NV50_CRC_SOURCE_NONE: return NV50_CRC_SOURCE_TYPE_NONE;
 446        case NV50_CRC_SOURCE_RG:   return NV50_CRC_SOURCE_TYPE_RG;
 447        default:                   break;
 448        }
 449
 450        if (dcbe->location != DCB_LOC_ON_CHIP)
 451                return NV50_CRC_SOURCE_TYPE_PIOR;
 452
 453        switch (dcbe->type) {
 454        case DCB_OUTPUT_DP:     return NV50_CRC_SOURCE_TYPE_SF;
 455        case DCB_OUTPUT_ANALOG: return NV50_CRC_SOURCE_TYPE_DAC;
 456        default:                return NV50_CRC_SOURCE_TYPE_SOR;
 457        }
 458}
 459
 460void nv50_crc_atomic_set(struct nv50_head *head,
 461                         struct nv50_head_atom *asyh)
 462{
 463        struct drm_crtc *crtc = &head->base.base;
 464        struct drm_device *dev = crtc->dev;
 465        struct nv50_crc *crc = &head->crc;
 466        const struct nv50_crc_func *func = nv50_disp(dev)->core->func->crc;
 467        struct nouveau_encoder *outp =
 468                nv50_real_outp(nv50_head_atom_get_encoder(asyh));
 469
 470        func->set_src(head, outp->or,
 471                      nv50_crc_source_type(outp, asyh->crc.src),
 472                      &crc->ctx[crc->ctx_idx], asyh->crc.wndw);
 473}
 474
 475void nv50_crc_atomic_clr(struct nv50_head *head)
 476{
 477        const struct nv50_crc_func *func =
 478                nv50_disp(head->base.base.dev)->core->func->crc;
 479
 480        func->set_src(head, 0, NV50_CRC_SOURCE_TYPE_NONE, NULL, 0);
 481}
 482
 483static inline int
 484nv50_crc_raster_type(enum nv50_crc_source source)
 485{
 486        switch (source) {
 487        case NV50_CRC_SOURCE_NONE:
 488        case NV50_CRC_SOURCE_AUTO:
 489        case NV50_CRC_SOURCE_RG:
 490        case NV50_CRC_SOURCE_OUTP_ACTIVE:
 491                return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_ACTIVE_RASTER;
 492        case NV50_CRC_SOURCE_OUTP_COMPLETE:
 493                return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_COMPLETE_RASTER;
 494        case NV50_CRC_SOURCE_OUTP_INACTIVE:
 495                return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_NON_ACTIVE_RASTER;
 496        }
 497
 498        return 0;
 499}
 500
 501/* We handle mapping the memory for CRC notifiers ourselves, since each
 502 * notifier needs it's own handle
 503 */
 504static inline int
 505nv50_crc_ctx_init(struct nv50_head *head, struct nvif_mmu *mmu,
 506                  struct nv50_crc_notifier_ctx *ctx, size_t len, int idx)
 507{
 508        struct nv50_core *core = nv50_disp(head->base.base.dev)->core;
 509        int ret;
 510
 511        ret = nvif_mem_ctor_map(mmu, "kmsCrcNtfy", NVIF_MEM_VRAM, len, &ctx->mem);
 512        if (ret)
 513                return ret;
 514
 515        ret = nvif_object_ctor(&core->chan.base.user, "kmsCrcNtfyCtxDma",
 516                               NV50_DISP_HANDLE_CRC_CTX(head, idx),
 517                               NV_DMA_IN_MEMORY,
 518                               &(struct nv_dma_v0) {
 519                                        .target = NV_DMA_V0_TARGET_VRAM,
 520                                        .access = NV_DMA_V0_ACCESS_RDWR,
 521                                        .start = ctx->mem.addr,
 522                                        .limit =  ctx->mem.addr
 523                                                + ctx->mem.size - 1,
 524                               }, sizeof(struct nv_dma_v0),
 525                               &ctx->ntfy);
 526        if (ret)
 527                goto fail_fini;
 528
 529        return 0;
 530
 531fail_fini:
 532        nvif_mem_dtor(&ctx->mem);
 533        return ret;
 534}
 535
 536static inline void
 537nv50_crc_ctx_fini(struct nv50_crc_notifier_ctx *ctx)
 538{
 539        nvif_object_dtor(&ctx->ntfy);
 540        nvif_mem_dtor(&ctx->mem);
 541}
 542
 543int nv50_crc_set_source(struct drm_crtc *crtc, const char *source_str)
 544{
 545        struct drm_device *dev = crtc->dev;
 546        struct drm_atomic_state *state;
 547        struct drm_modeset_acquire_ctx ctx;
 548        struct nv50_head *head = nv50_head(crtc);
 549        struct nv50_crc *crc = &head->crc;
 550        const struct nv50_crc_func *func = nv50_disp(dev)->core->func->crc;
 551        struct nvif_mmu *mmu = &nouveau_drm(dev)->client.mmu;
 552        struct nv50_head_atom *asyh;
 553        struct drm_crtc_state *crtc_state;
 554        enum nv50_crc_source source;
 555        int ret = 0, ctx_flags = 0, i;
 556
 557        ret = nv50_crc_parse_source(source_str, &source);
 558        if (ret)
 559                return ret;
 560
 561        /*
 562         * Since we don't want the user to accidentally interrupt us as we're
 563         * disabling CRCs
 564         */
 565        if (source)
 566                ctx_flags |= DRM_MODESET_ACQUIRE_INTERRUPTIBLE;
 567        drm_modeset_acquire_init(&ctx, ctx_flags);
 568
 569        state = drm_atomic_state_alloc(dev);
 570        if (!state) {
 571                ret = -ENOMEM;
 572                goto out_acquire_fini;
 573        }
 574        state->acquire_ctx = &ctx;
 575
 576        if (source) {
 577                for (i = 0; i < ARRAY_SIZE(head->crc.ctx); i++) {
 578                        ret = nv50_crc_ctx_init(head, mmu, &crc->ctx[i],
 579                                                func->notifier_len, i);
 580                        if (ret)
 581                                goto out_ctx_fini;
 582                }
 583        }
 584
 585retry:
 586        crtc_state = drm_atomic_get_crtc_state(state, &head->base.base);
 587        if (IS_ERR(crtc_state)) {
 588                ret = PTR_ERR(crtc_state);
 589                if (ret == -EDEADLK)
 590                        goto deadlock;
 591                else if (ret)
 592                        goto out_drop_locks;
 593        }
 594        asyh = nv50_head_atom(crtc_state);
 595        asyh->crc.src = source;
 596        asyh->or.crc_raster = nv50_crc_raster_type(source);
 597
 598        ret = drm_atomic_commit(state);
 599        if (ret == -EDEADLK)
 600                goto deadlock;
 601        else if (ret)
 602                goto out_drop_locks;
 603
 604        if (!source) {
 605                /*
 606                 * If the user specified a custom flip threshold through
 607                 * debugfs, reset it
 608                 */
 609                crc->flip_threshold = func->flip_threshold;
 610        }
 611
 612out_drop_locks:
 613        drm_modeset_drop_locks(&ctx);
 614out_ctx_fini:
 615        if (!source || ret) {
 616                for (i = 0; i < ARRAY_SIZE(crc->ctx); i++)
 617                        nv50_crc_ctx_fini(&crc->ctx[i]);
 618        }
 619        drm_atomic_state_put(state);
 620out_acquire_fini:
 621        drm_modeset_acquire_fini(&ctx);
 622        return ret;
 623
 624deadlock:
 625        drm_atomic_state_clear(state);
 626        drm_modeset_backoff(&ctx);
 627        goto retry;
 628}
 629
 630static int
 631nv50_crc_debugfs_flip_threshold_get(struct seq_file *m, void *data)
 632{
 633        struct nv50_head *head = m->private;
 634        struct drm_crtc *crtc = &head->base.base;
 635        struct nv50_crc *crc = &head->crc;
 636        int ret;
 637
 638        ret = drm_modeset_lock_single_interruptible(&crtc->mutex);
 639        if (ret)
 640                return ret;
 641
 642        seq_printf(m, "%d\n", crc->flip_threshold);
 643
 644        drm_modeset_unlock(&crtc->mutex);
 645        return ret;
 646}
 647
 648static int
 649nv50_crc_debugfs_flip_threshold_open(struct inode *inode, struct file *file)
 650{
 651        return single_open(file, nv50_crc_debugfs_flip_threshold_get,
 652                           inode->i_private);
 653}
 654
 655static ssize_t
 656nv50_crc_debugfs_flip_threshold_set(struct file *file,
 657                                    const char __user *ubuf, size_t len,
 658                                    loff_t *offp)
 659{
 660        struct seq_file *m = file->private_data;
 661        struct nv50_head *head = m->private;
 662        struct nv50_head_atom *armh;
 663        struct drm_crtc *crtc = &head->base.base;
 664        struct nouveau_drm *drm = nouveau_drm(crtc->dev);
 665        struct nv50_crc *crc = &head->crc;
 666        const struct nv50_crc_func *func =
 667                nv50_disp(crtc->dev)->core->func->crc;
 668        int value, ret;
 669
 670        ret = kstrtoint_from_user(ubuf, len, 10, &value);
 671        if (ret)
 672                return ret;
 673
 674        if (value > func->flip_threshold)
 675                return -EINVAL;
 676        else if (value == -1)
 677                value = func->flip_threshold;
 678        else if (value < -1)
 679                return -EINVAL;
 680
 681        ret = drm_modeset_lock_single_interruptible(&crtc->mutex);
 682        if (ret)
 683                return ret;
 684
 685        armh = nv50_head_atom(crtc->state);
 686        if (armh->crc.src) {
 687                ret = -EBUSY;
 688                goto out;
 689        }
 690
 691        NV_DEBUG(drm,
 692                 "Changing CRC flip threshold for next capture on head-%d to %d\n",
 693                 head->base.index, value);
 694        crc->flip_threshold = value;
 695        ret = len;
 696
 697out:
 698        drm_modeset_unlock(&crtc->mutex);
 699        return ret;
 700}
 701
 702static const struct file_operations nv50_crc_flip_threshold_fops = {
 703        .owner = THIS_MODULE,
 704        .open = nv50_crc_debugfs_flip_threshold_open,
 705        .read = seq_read,
 706        .write = nv50_crc_debugfs_flip_threshold_set,
 707};
 708
 709int nv50_head_crc_late_register(struct nv50_head *head)
 710{
 711        struct drm_crtc *crtc = &head->base.base;
 712        const struct nv50_crc_func *func =
 713                nv50_disp(crtc->dev)->core->func->crc;
 714        struct dentry *root;
 715
 716        if (!func || !crtc->debugfs_entry)
 717                return 0;
 718
 719        root = debugfs_create_dir("nv_crc", crtc->debugfs_entry);
 720        debugfs_create_file("flip_threshold", 0644, root, head,
 721                            &nv50_crc_flip_threshold_fops);
 722
 723        return 0;
 724}
 725
 726static inline void
 727nv50_crc_init_head(struct nv50_disp *disp, const struct nv50_crc_func *func,
 728                   struct nv50_head *head)
 729{
 730        struct nv50_crc *crc = &head->crc;
 731
 732        crc->flip_threshold = func->flip_threshold;
 733        spin_lock_init(&crc->lock);
 734        drm_vblank_work_init(&crc->flip_work, &head->base.base,
 735                             nv50_crc_ctx_flip_work);
 736}
 737
 738void nv50_crc_init(struct drm_device *dev)
 739{
 740        struct nv50_disp *disp = nv50_disp(dev);
 741        struct drm_crtc *crtc;
 742        const struct nv50_crc_func *func = disp->core->func->crc;
 743
 744        if (!func)
 745                return;
 746
 747        drm_for_each_crtc(crtc, dev)
 748                nv50_crc_init_head(disp, func, nv50_head(crtc));
 749}
 750