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
21 static 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
nv50_crc_parse_source(const char *buf, enum nv50_crc_source *s)30 static 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
47 int
nv50_crc_verify_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt)48 nv50_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
nv50_crc_get_sources(struct drm_crtc *crtc, size_t *count)63 const 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
69 static void
nv50_crc_program_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx)70 nv50_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
nv50_crc_ctx_flip_work(struct kthread_work *base)81 static 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
nv50_crc_reset_ctx(struct nv50_crc_notifier_ctx *ctx)117 static 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
122 static void
nv50_crc_get_entries(struct nv50_head *head, const struct nv50_crc_func *func, enum nv50_crc_source source)123 nv50_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
nv50_crc_handle_vblank(struct nv50_head *head)148 void 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
210 out:
211 spin_unlock(&crc->lock);
212 }
213
nv50_crc_wait_ctx_finished(struct nv50_head *head, const struct nv50_crc_func *func, struct nv50_crc_notifier_ctx *ctx)214 static 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
nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state)234 void 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
nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state)266 void 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
nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state)288 void 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
nv50_crc_atomic_start_reporting(struct drm_atomic_state *state)313 void 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
nv50_crc_atomic_check_head(struct nv50_head *head, struct nv50_head_atom *asyh, struct nv50_head_atom *armh)345 int 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
nv50_crc_atomic_check_outp(struct nv50_atom *atom)400 void 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 struct drm_encoder *encoder, *enc;
416
417 enc = nv50_head_atom_get_encoder(armh);
418 if (!enc)
419 continue;
420
421 outp = nv50_real_outp(enc);
422 if (!outp)
423 continue;
424
425 encoder = &outp->base.base;
426
427 if (!asyh->clr.crc)
428 continue;
429
430 /*
431 * Re-programming ORs can't be done in the same flush as
432 * disabling CRCs
433 */
434 list_for_each_entry(outp_atom, &atom->outp, head) {
435 if (outp_atom->encoder == encoder) {
436 if (outp_atom->set.mask) {
437 atom->flush_disable = true;
438 return;
439 } else {
440 break;
441 }
442 }
443 }
444 }
445 }
446
447 static enum nv50_crc_source_type
nv50_crc_source_type(struct nouveau_encoder *outp, enum nv50_crc_source source)448 nv50_crc_source_type(struct nouveau_encoder *outp,
449 enum nv50_crc_source source)
450 {
451 struct dcb_output *dcbe = outp->dcb;
452
453 switch (source) {
454 case NV50_CRC_SOURCE_NONE: return NV50_CRC_SOURCE_TYPE_NONE;
455 case NV50_CRC_SOURCE_RG: return NV50_CRC_SOURCE_TYPE_RG;
456 default: break;
457 }
458
459 if (dcbe->location != DCB_LOC_ON_CHIP)
460 return NV50_CRC_SOURCE_TYPE_PIOR;
461
462 switch (dcbe->type) {
463 case DCB_OUTPUT_DP: return NV50_CRC_SOURCE_TYPE_SF;
464 case DCB_OUTPUT_ANALOG: return NV50_CRC_SOURCE_TYPE_DAC;
465 default: return NV50_CRC_SOURCE_TYPE_SOR;
466 }
467 }
468
nv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *asyh)469 void nv50_crc_atomic_set(struct nv50_head *head,
470 struct nv50_head_atom *asyh)
471 {
472 struct drm_crtc *crtc = &head->base.base;
473 struct drm_device *dev = crtc->dev;
474 struct nv50_crc *crc = &head->crc;
475 const struct nv50_crc_func *func = nv50_disp(dev)->core->func->crc;
476 struct nouveau_encoder *outp;
477 struct drm_encoder *encoder;
478
479 encoder = nv50_head_atom_get_encoder(asyh);
480 if (!encoder)
481 return;
482
483 outp = nv50_real_outp(encoder);
484 if (!outp)
485 return;
486
487 func->set_src(head, outp->or,
488 nv50_crc_source_type(outp, asyh->crc.src),
489 &crc->ctx[crc->ctx_idx], asyh->crc.wndw);
490 }
491
nv50_crc_atomic_clr(struct nv50_head *head)492 void nv50_crc_atomic_clr(struct nv50_head *head)
493 {
494 const struct nv50_crc_func *func =
495 nv50_disp(head->base.base.dev)->core->func->crc;
496
497 func->set_src(head, 0, NV50_CRC_SOURCE_TYPE_NONE, NULL, 0);
498 }
499
500 static inline int
nv50_crc_raster_type(enum nv50_crc_source source)501 nv50_crc_raster_type(enum nv50_crc_source source)
502 {
503 switch (source) {
504 case NV50_CRC_SOURCE_NONE:
505 case NV50_CRC_SOURCE_AUTO:
506 case NV50_CRC_SOURCE_RG:
507 case NV50_CRC_SOURCE_OUTP_ACTIVE:
508 return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_ACTIVE_RASTER;
509 case NV50_CRC_SOURCE_OUTP_COMPLETE:
510 return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_COMPLETE_RASTER;
511 case NV50_CRC_SOURCE_OUTP_INACTIVE:
512 return NV907D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_CRC_MODE_NON_ACTIVE_RASTER;
513 }
514
515 return 0;
516 }
517
518 /* We handle mapping the memory for CRC notifiers ourselves, since each
519 * notifier needs it's own handle
520 */
521 static inline int
nv50_crc_ctx_init(struct nv50_head *head, struct nvif_mmu *mmu, struct nv50_crc_notifier_ctx *ctx, size_t len, int idx)522 nv50_crc_ctx_init(struct nv50_head *head, struct nvif_mmu *mmu,
523 struct nv50_crc_notifier_ctx *ctx, size_t len, int idx)
524 {
525 struct nv50_core *core = nv50_disp(head->base.base.dev)->core;
526 int ret;
527
528 ret = nvif_mem_ctor_map(mmu, "kmsCrcNtfy", NVIF_MEM_VRAM, len, &ctx->mem);
529 if (ret)
530 return ret;
531
532 ret = nvif_object_ctor(&core->chan.base.user, "kmsCrcNtfyCtxDma",
533 NV50_DISP_HANDLE_CRC_CTX(head, idx),
534 NV_DMA_IN_MEMORY,
535 &(struct nv_dma_v0) {
536 .target = NV_DMA_V0_TARGET_VRAM,
537 .access = NV_DMA_V0_ACCESS_RDWR,
538 .start = ctx->mem.addr,
539 .limit = ctx->mem.addr
540 + ctx->mem.size - 1,
541 }, sizeof(struct nv_dma_v0),
542 &ctx->ntfy);
543 if (ret)
544 goto fail_fini;
545
546 return 0;
547
548 fail_fini:
549 nvif_mem_dtor(&ctx->mem);
550 return ret;
551 }
552
553 static inline void
nv50_crc_ctx_fini(struct nv50_crc_notifier_ctx *ctx)554 nv50_crc_ctx_fini(struct nv50_crc_notifier_ctx *ctx)
555 {
556 nvif_object_dtor(&ctx->ntfy);
557 nvif_mem_dtor(&ctx->mem);
558 }
559
nv50_crc_set_source(struct drm_crtc *crtc, const char *source_str)560 int nv50_crc_set_source(struct drm_crtc *crtc, const char *source_str)
561 {
562 struct drm_device *dev = crtc->dev;
563 struct drm_atomic_state *state;
564 struct drm_modeset_acquire_ctx ctx;
565 struct nv50_head *head = nv50_head(crtc);
566 struct nv50_crc *crc = &head->crc;
567 const struct nv50_crc_func *func = nv50_disp(dev)->core->func->crc;
568 struct nvif_mmu *mmu = &nouveau_drm(dev)->client.mmu;
569 struct nv50_head_atom *asyh;
570 struct drm_crtc_state *crtc_state;
571 enum nv50_crc_source source;
572 int ret = 0, ctx_flags = 0, i;
573
574 ret = nv50_crc_parse_source(source_str, &source);
575 if (ret)
576 return ret;
577
578 /*
579 * Since we don't want the user to accidentally interrupt us as we're
580 * disabling CRCs
581 */
582 if (source)
583 ctx_flags |= DRM_MODESET_ACQUIRE_INTERRUPTIBLE;
584 drm_modeset_acquire_init(&ctx, ctx_flags);
585
586 state = drm_atomic_state_alloc(dev);
587 if (!state) {
588 ret = -ENOMEM;
589 goto out_acquire_fini;
590 }
591 state->acquire_ctx = &ctx;
592
593 if (source) {
594 for (i = 0; i < ARRAY_SIZE(head->crc.ctx); i++) {
595 ret = nv50_crc_ctx_init(head, mmu, &crc->ctx[i],
596 func->notifier_len, i);
597 if (ret)
598 goto out_ctx_fini;
599 }
600 }
601
602 retry:
603 crtc_state = drm_atomic_get_crtc_state(state, &head->base.base);
604 if (IS_ERR(crtc_state)) {
605 ret = PTR_ERR(crtc_state);
606 if (ret == -EDEADLK)
607 goto deadlock;
608 else if (ret)
609 goto out_drop_locks;
610 }
611 asyh = nv50_head_atom(crtc_state);
612 asyh->crc.src = source;
613 asyh->or.crc_raster = nv50_crc_raster_type(source);
614
615 ret = drm_atomic_commit(state);
616 if (ret == -EDEADLK)
617 goto deadlock;
618 else if (ret)
619 goto out_drop_locks;
620
621 if (!source) {
622 /*
623 * If the user specified a custom flip threshold through
624 * debugfs, reset it
625 */
626 crc->flip_threshold = func->flip_threshold;
627 }
628
629 out_drop_locks:
630 drm_modeset_drop_locks(&ctx);
631 out_ctx_fini:
632 if (!source || ret) {
633 for (i = 0; i < ARRAY_SIZE(crc->ctx); i++)
634 nv50_crc_ctx_fini(&crc->ctx[i]);
635 }
636 drm_atomic_state_put(state);
637 out_acquire_fini:
638 drm_modeset_acquire_fini(&ctx);
639 return ret;
640
641 deadlock:
642 drm_atomic_state_clear(state);
643 drm_modeset_backoff(&ctx);
644 goto retry;
645 }
646
647 static int
nv50_crc_debugfs_flip_threshold_get(struct seq_file *m, void *data)648 nv50_crc_debugfs_flip_threshold_get(struct seq_file *m, void *data)
649 {
650 struct nv50_head *head = m->private;
651 struct drm_crtc *crtc = &head->base.base;
652 struct nv50_crc *crc = &head->crc;
653 int ret;
654
655 ret = drm_modeset_lock_single_interruptible(&crtc->mutex);
656 if (ret)
657 return ret;
658
659 seq_printf(m, "%d\n", crc->flip_threshold);
660
661 drm_modeset_unlock(&crtc->mutex);
662 return ret;
663 }
664
665 static int
nv50_crc_debugfs_flip_threshold_open(struct inode *inode, struct file *file)666 nv50_crc_debugfs_flip_threshold_open(struct inode *inode, struct file *file)
667 {
668 return single_open(file, nv50_crc_debugfs_flip_threshold_get,
669 inode->i_private);
670 }
671
672 static ssize_t
nv50_crc_debugfs_flip_threshold_set(struct file *file, const char __user *ubuf, size_t len, loff_t *offp)673 nv50_crc_debugfs_flip_threshold_set(struct file *file,
674 const char __user *ubuf, size_t len,
675 loff_t *offp)
676 {
677 struct seq_file *m = file->private_data;
678 struct nv50_head *head = m->private;
679 struct nv50_head_atom *armh;
680 struct drm_crtc *crtc = &head->base.base;
681 struct nouveau_drm *drm = nouveau_drm(crtc->dev);
682 struct nv50_crc *crc = &head->crc;
683 const struct nv50_crc_func *func =
684 nv50_disp(crtc->dev)->core->func->crc;
685 int value, ret;
686
687 ret = kstrtoint_from_user(ubuf, len, 10, &value);
688 if (ret)
689 return ret;
690
691 if (value > func->flip_threshold)
692 return -EINVAL;
693 else if (value == -1)
694 value = func->flip_threshold;
695 else if (value < -1)
696 return -EINVAL;
697
698 ret = drm_modeset_lock_single_interruptible(&crtc->mutex);
699 if (ret)
700 return ret;
701
702 armh = nv50_head_atom(crtc->state);
703 if (armh->crc.src) {
704 ret = -EBUSY;
705 goto out;
706 }
707
708 NV_DEBUG(drm,
709 "Changing CRC flip threshold for next capture on head-%d to %d\n",
710 head->base.index, value);
711 crc->flip_threshold = value;
712 ret = len;
713
714 out:
715 drm_modeset_unlock(&crtc->mutex);
716 return ret;
717 }
718
719 static const struct file_operations nv50_crc_flip_threshold_fops = {
720 .owner = THIS_MODULE,
721 .open = nv50_crc_debugfs_flip_threshold_open,
722 .read = seq_read,
723 .write = nv50_crc_debugfs_flip_threshold_set,
724 .release = single_release,
725 };
726
nv50_head_crc_late_register(struct nv50_head *head)727 int nv50_head_crc_late_register(struct nv50_head *head)
728 {
729 struct drm_crtc *crtc = &head->base.base;
730 const struct nv50_crc_func *func =
731 nv50_disp(crtc->dev)->core->func->crc;
732 struct dentry *root;
733
734 if (!func || !crtc->debugfs_entry)
735 return 0;
736
737 root = debugfs_create_dir("nv_crc", crtc->debugfs_entry);
738 debugfs_create_file("flip_threshold", 0644, root, head,
739 &nv50_crc_flip_threshold_fops);
740
741 return 0;
742 }
743
744 static inline void
nv50_crc_init_head(struct nv50_disp *disp, const struct nv50_crc_func *func, struct nv50_head *head)745 nv50_crc_init_head(struct nv50_disp *disp, const struct nv50_crc_func *func,
746 struct nv50_head *head)
747 {
748 struct nv50_crc *crc = &head->crc;
749
750 crc->flip_threshold = func->flip_threshold;
751 spin_lock_init(&crc->lock);
752 drm_vblank_work_init(&crc->flip_work, &head->base.base,
753 nv50_crc_ctx_flip_work);
754 }
755
nv50_crc_init(struct drm_device *dev)756 void nv50_crc_init(struct drm_device *dev)
757 {
758 struct nv50_disp *disp = nv50_disp(dev);
759 struct drm_crtc *crtc;
760 const struct nv50_crc_func *func = disp->core->func->crc;
761
762 if (!func)
763 return;
764
765 drm_for_each_crtc(crtc, dev)
766 nv50_crc_init_head(disp, func, nv50_head(crtc));
767 }
768