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