1
2#ifndef __NV50_CRC_H__
3#define __NV50_CRC_H__
4
5#include <linux/mutex.h>
6#include <drm/drm_crtc.h>
7#include <drm/drm_vblank_work.h>
8
9#include <nvif/mem.h>
10#include <nvkm/subdev/bios.h>
11#include "nouveau_encoder.h"
12
13struct nv50_atom;
14struct nv50_disp;
15struct nv50_head;
16
17#if IS_ENABLED(CONFIG_DEBUG_FS)
18enum nv50_crc_source {
19 NV50_CRC_SOURCE_NONE = 0,
20 NV50_CRC_SOURCE_AUTO,
21 NV50_CRC_SOURCE_RG,
22 NV50_CRC_SOURCE_OUTP_ACTIVE,
23 NV50_CRC_SOURCE_OUTP_COMPLETE,
24 NV50_CRC_SOURCE_OUTP_INACTIVE,
25};
26
27
28
29
30
31
32enum nv50_crc_source_type {
33 NV50_CRC_SOURCE_TYPE_NONE = 0,
34 NV50_CRC_SOURCE_TYPE_SOR,
35 NV50_CRC_SOURCE_TYPE_PIOR,
36 NV50_CRC_SOURCE_TYPE_DAC,
37 NV50_CRC_SOURCE_TYPE_RG,
38 NV50_CRC_SOURCE_TYPE_SF,
39};
40
41struct nv50_crc_notifier_ctx {
42 struct nvif_mem mem;
43 struct nvif_object ntfy;
44};
45
46struct nv50_crc_atom {
47 enum nv50_crc_source src;
48
49 u8 wndw : 4;
50};
51
52struct nv50_crc_func {
53 int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type,
54 struct nv50_crc_notifier_ctx *, u32 wndw);
55 int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *);
56 u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *,
57 enum nv50_crc_source, int idx);
58 bool (*ctx_finished)(struct nv50_head *,
59 struct nv50_crc_notifier_ctx *);
60 short flip_threshold;
61 short num_entries;
62 size_t notifier_len;
63};
64
65struct nv50_crc {
66 spinlock_t lock;
67 struct nv50_crc_notifier_ctx ctx[2];
68 struct drm_vblank_work flip_work;
69 enum nv50_crc_source src;
70
71 u64 frame;
72 short entry_idx;
73 short flip_threshold;
74 u8 ctx_idx : 1;
75 bool ctx_changed : 1;
76};
77
78void nv50_crc_init(struct drm_device *dev);
79int nv50_head_crc_late_register(struct nv50_head *);
80void nv50_crc_handle_vblank(struct nv50_head *head);
81
82int nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *);
83const char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *);
84int nv50_crc_set_source(struct drm_crtc *, const char *);
85
86int nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
87 struct nv50_head_atom *);
88void nv50_crc_atomic_check_outp(struct nv50_atom *atom);
89void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
90void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
91void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
92void nv50_crc_atomic_start_reporting(struct drm_atomic_state *);
93void nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *);
94void nv50_crc_atomic_clr(struct nv50_head *);
95
96extern const struct nv50_crc_func crc907d;
97extern const struct nv50_crc_func crcc37d;
98
99#else
100struct nv50_crc {};
101struct nv50_crc_func {};
102struct nv50_crc_atom {};
103
104#define nv50_crc_verify_source NULL
105#define nv50_crc_get_sources NULL
106#define nv50_crc_set_source NULL
107
108static inline void nv50_crc_init(struct drm_device *dev) {}
109static inline int
110nv50_head_crc_late_register(struct nv50_head *head) { return 0; }
111static inline void nv50_crc_handle_vblank(struct nv50_head *head) {}
112
113static inline int
114nv50_crc_atomic_check_head(struct nv50_head *head,
115 struct nv50_head_atom *asyh,
116 struct nv50_head_atom *armh) { return 0; }
117static inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
118static inline void
119nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {}
120static inline void
121nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {}
122static inline void
123nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {}
124static inline void
125nv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {}
126static inline void
127nv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {}
128static inline void
129nv50_crc_atomic_clr(struct nv50_head *head) {}
130
131#endif
132#endif
133