112885ecbSLyude Paul /* SPDX-License-Identifier: MIT */
212885ecbSLyude Paul #ifndef __NV50_CRC_H__
312885ecbSLyude Paul #define __NV50_CRC_H__
412885ecbSLyude Paul 
512885ecbSLyude Paul #include <linux/mutex.h>
612885ecbSLyude Paul #include <drm/drm_crtc.h>
712885ecbSLyude Paul #include <drm/drm_vblank_work.h>
812885ecbSLyude Paul 
912885ecbSLyude Paul #include <nvif/mem.h>
1012885ecbSLyude Paul #include <nvkm/subdev/bios.h>
1112885ecbSLyude Paul #include "nouveau_encoder.h"
1212885ecbSLyude Paul 
132d786508SLyude Paul struct nv50_atom;
1412885ecbSLyude Paul struct nv50_disp;
1512885ecbSLyude Paul struct nv50_head;
1612885ecbSLyude Paul 
1712885ecbSLyude Paul #if IS_ENABLED(CONFIG_DEBUG_FS)
1812885ecbSLyude Paul enum nv50_crc_source {
1912885ecbSLyude Paul 	NV50_CRC_SOURCE_NONE = 0,
2012885ecbSLyude Paul 	NV50_CRC_SOURCE_AUTO,
2112885ecbSLyude Paul 	NV50_CRC_SOURCE_RG,
2212885ecbSLyude Paul 	NV50_CRC_SOURCE_OUTP_ACTIVE,
2312885ecbSLyude Paul 	NV50_CRC_SOURCE_OUTP_COMPLETE,
2412885ecbSLyude Paul 	NV50_CRC_SOURCE_OUTP_INACTIVE,
2512885ecbSLyude Paul };
2612885ecbSLyude Paul 
2712885ecbSLyude Paul /* RG -> SF (DP only)
2812885ecbSLyude Paul  *    -> SOR
2912885ecbSLyude Paul  *    -> PIOR
3012885ecbSLyude Paul  *    -> DAC
3112885ecbSLyude Paul  */
3212885ecbSLyude Paul enum nv50_crc_source_type {
3312885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_NONE = 0,
3412885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_SOR,
3512885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_PIOR,
3612885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_DAC,
3712885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_RG,
3812885ecbSLyude Paul 	NV50_CRC_SOURCE_TYPE_SF,
3912885ecbSLyude Paul };
4012885ecbSLyude Paul 
4112885ecbSLyude Paul struct nv50_crc_notifier_ctx {
4212885ecbSLyude Paul 	struct nvif_mem mem;
4312885ecbSLyude Paul 	struct nvif_object ntfy;
4412885ecbSLyude Paul };
4512885ecbSLyude Paul 
4612885ecbSLyude Paul struct nv50_crc_atom {
4712885ecbSLyude Paul 	enum nv50_crc_source src;
4812885ecbSLyude Paul };
4912885ecbSLyude Paul 
5012885ecbSLyude Paul struct nv50_crc_func {
51*57cbdbe6SLyude Paul 	int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type type,
52*57cbdbe6SLyude Paul 		       struct nv50_crc_notifier_ctx *ctx);
53ae09163aSBen Skeggs 	int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *);
5412885ecbSLyude Paul 	u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *,
5512885ecbSLyude Paul 			 enum nv50_crc_source, int idx);
5612885ecbSLyude Paul 	bool (*ctx_finished)(struct nv50_head *,
5712885ecbSLyude Paul 			     struct nv50_crc_notifier_ctx *);
5812885ecbSLyude Paul 	short flip_threshold;
5912885ecbSLyude Paul 	short num_entries;
6012885ecbSLyude Paul 	size_t notifier_len;
6112885ecbSLyude Paul };
6212885ecbSLyude Paul 
6312885ecbSLyude Paul struct nv50_crc {
6412885ecbSLyude Paul 	spinlock_t lock;
6512885ecbSLyude Paul 	struct nv50_crc_notifier_ctx ctx[2];
6612885ecbSLyude Paul 	struct drm_vblank_work flip_work;
6712885ecbSLyude Paul 	enum nv50_crc_source src;
6812885ecbSLyude Paul 
6912885ecbSLyude Paul 	u64 frame;
7012885ecbSLyude Paul 	short entry_idx;
7112885ecbSLyude Paul 	short flip_threshold;
7212885ecbSLyude Paul 	u8 ctx_idx : 1;
7312885ecbSLyude Paul 	bool ctx_changed : 1;
7412885ecbSLyude Paul };
7512885ecbSLyude Paul 
7612885ecbSLyude Paul void nv50_crc_init(struct drm_device *dev);
7712885ecbSLyude Paul int nv50_head_crc_late_register(struct nv50_head *);
7812885ecbSLyude Paul void nv50_crc_handle_vblank(struct nv50_head *head);
7912885ecbSLyude Paul 
8012885ecbSLyude Paul int nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *);
8112885ecbSLyude Paul const char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *);
8212885ecbSLyude Paul int nv50_crc_set_source(struct drm_crtc *, const char *);
8312885ecbSLyude Paul 
842d786508SLyude Paul int nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
8512885ecbSLyude Paul 			       struct nv50_head_atom *);
862d786508SLyude Paul void nv50_crc_atomic_check_outp(struct nv50_atom *atom);
8712885ecbSLyude Paul void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
882d786508SLyude Paul void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
892d786508SLyude Paul void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
9012885ecbSLyude Paul void nv50_crc_atomic_start_reporting(struct drm_atomic_state *);
9112885ecbSLyude Paul void nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *);
9212885ecbSLyude Paul void nv50_crc_atomic_clr(struct nv50_head *);
9312885ecbSLyude Paul 
9412885ecbSLyude Paul extern const struct nv50_crc_func crc907d;
9512885ecbSLyude Paul extern const struct nv50_crc_func crcc37d;
96*57cbdbe6SLyude Paul extern const struct nv50_crc_func crcc57d;
9712885ecbSLyude Paul 
9812885ecbSLyude Paul #else /* IS_ENABLED(CONFIG_DEBUG_FS) */
9912885ecbSLyude Paul struct nv50_crc {};
10012885ecbSLyude Paul struct nv50_crc_func {};
10112885ecbSLyude Paul struct nv50_crc_atom {};
10212885ecbSLyude Paul 
10312885ecbSLyude Paul #define nv50_crc_verify_source NULL
10412885ecbSLyude Paul #define nv50_crc_get_sources NULL
10512885ecbSLyude Paul #define nv50_crc_set_source NULL
10612885ecbSLyude Paul 
nv50_crc_init(struct drm_device * dev)10712885ecbSLyude Paul static inline void nv50_crc_init(struct drm_device *dev) {}
1080059a908SLyude Paul static inline int
nv50_head_crc_late_register(struct nv50_head * head)1090059a908SLyude Paul nv50_head_crc_late_register(struct nv50_head *head) { return 0; }
nv50_crc_handle_vblank(struct nv50_head * head)1100059a908SLyude Paul static inline void nv50_crc_handle_vblank(struct nv50_head *head) {}
11112885ecbSLyude Paul 
11212885ecbSLyude Paul static inline int
nv50_crc_atomic_check_head(struct nv50_head * head,struct nv50_head_atom * asyh,struct nv50_head_atom * armh)1130059a908SLyude Paul nv50_crc_atomic_check_head(struct nv50_head *head,
1140059a908SLyude Paul 			   struct nv50_head_atom *asyh,
1150059a908SLyude Paul 			   struct nv50_head_atom *armh) { return 0; }
nv50_crc_atomic_check_outp(struct nv50_atom * atom)1162d786508SLyude Paul static inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
11712885ecbSLyude Paul static inline void
nv50_crc_atomic_stop_reporting(struct drm_atomic_state * state)1180059a908SLyude Paul nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {}
11912885ecbSLyude Paul static inline void
nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state * state)1200059a908SLyude Paul nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {}
1212d786508SLyude Paul static inline void
nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state * state)1220059a908SLyude Paul nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {}
12312885ecbSLyude Paul static inline void
nv50_crc_atomic_start_reporting(struct drm_atomic_state * state)1240059a908SLyude Paul nv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {}
12512885ecbSLyude Paul static inline void
nv50_crc_atomic_set(struct nv50_head * head,struct nv50_head_atom * state)1260059a908SLyude Paul nv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {}
12712885ecbSLyude Paul static inline void
nv50_crc_atomic_clr(struct nv50_head * head)1280059a908SLyude Paul nv50_crc_atomic_clr(struct nv50_head *head) {}
12912885ecbSLyude Paul 
13012885ecbSLyude Paul #endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
13112885ecbSLyude Paul #endif /* !__NV50_CRC_H__ */
132