1 /* SPDX-License-Identifier: MIT */
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 
13 struct nv50_atom;
14 struct nv50_disp;
15 struct nv50_head;
16 
17 #if IS_ENABLED(CONFIG_DEBUG_FS)
18 enum 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 /* RG -> SF (DP only)
28  *    -> SOR
29  *    -> PIOR
30  *    -> DAC
31  */
32 enum 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 
41 struct nv50_crc_notifier_ctx {
42 	struct nvif_mem mem;
43 	struct nvif_object ntfy;
44 };
45 
46 struct nv50_crc_atom {
47 	enum nv50_crc_source src;
48 	/* Only used for gv100+ */
49 	u8 wndw : 4;
50 };
51 
52 struct 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 
65 struct 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 
78 void nv50_crc_init(struct drm_device *dev);
79 int nv50_head_crc_late_register(struct nv50_head *);
80 void nv50_crc_handle_vblank(struct nv50_head *head);
81 
82 int nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *);
83 const char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *);
84 int nv50_crc_set_source(struct drm_crtc *, const char *);
85 
86 int nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
87 			       struct nv50_head_atom *);
88 void nv50_crc_atomic_check_outp(struct nv50_atom *atom);
89 void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
90 void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
91 void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
92 void nv50_crc_atomic_start_reporting(struct drm_atomic_state *);
93 void nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *);
94 void nv50_crc_atomic_clr(struct nv50_head *);
95 
96 extern const struct nv50_crc_func crc907d;
97 extern const struct nv50_crc_func crcc37d;
98 
99 #else /* IS_ENABLED(CONFIG_DEBUG_FS) */
100 struct nv50_crc {};
101 struct nv50_crc_func {};
102 struct 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 
108 static inline void nv50_crc_init(struct drm_device *dev) {}
109 static inline int
110 nv50_head_crc_late_register(struct nv50_head *head) { return 0; }
111 static inline void nv50_crc_handle_vblank(struct nv50_head *head) {}
112 
113 static inline int
114 nv50_crc_atomic_check_head(struct nv50_head *head,
115 			   struct nv50_head_atom *asyh,
116 			   struct nv50_head_atom *armh) { return 0; }
117 static inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
118 static inline void
119 nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {}
120 static inline void
121 nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {}
122 static inline void
123 nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {}
124 static inline void
125 nv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {}
126 static inline void
127 nv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {}
128 static inline void
129 nv50_crc_atomic_clr(struct nv50_head *head) {}
130 
131 #endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
132 #endif /* !__NV50_CRC_H__ */
133