/* SPDX-License-Identifier: MIT */ #ifndef __NV50_CRC_H__ #define __NV50_CRC_H__ #include #include #include #include #include #include "nouveau_encoder.h" struct nv50_atom; struct nv50_disp; struct nv50_head; #if IS_ENABLED(CONFIG_DEBUG_FS) enum nv50_crc_source { NV50_CRC_SOURCE_NONE = 0, NV50_CRC_SOURCE_AUTO, NV50_CRC_SOURCE_RG, NV50_CRC_SOURCE_OUTP_ACTIVE, NV50_CRC_SOURCE_OUTP_COMPLETE, NV50_CRC_SOURCE_OUTP_INACTIVE, }; /* RG -> SF (DP only) * -> SOR * -> PIOR * -> DAC */ enum nv50_crc_source_type { NV50_CRC_SOURCE_TYPE_NONE = 0, NV50_CRC_SOURCE_TYPE_SOR, NV50_CRC_SOURCE_TYPE_PIOR, NV50_CRC_SOURCE_TYPE_DAC, NV50_CRC_SOURCE_TYPE_RG, NV50_CRC_SOURCE_TYPE_SF, }; struct nv50_crc_notifier_ctx { struct nvif_mem mem; struct nvif_object ntfy; }; struct nv50_crc_atom { enum nv50_crc_source src; }; struct nv50_crc_func { int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type type, struct nv50_crc_notifier_ctx *ctx); int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *); u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *, enum nv50_crc_source, int idx); bool (*ctx_finished)(struct nv50_head *, struct nv50_crc_notifier_ctx *); short flip_threshold; short num_entries; size_t notifier_len; }; struct nv50_crc { spinlock_t lock; struct nv50_crc_notifier_ctx ctx[2]; struct drm_vblank_work flip_work; enum nv50_crc_source src; u64 frame; short entry_idx; short flip_threshold; u8 ctx_idx : 1; bool ctx_changed : 1; }; void nv50_crc_init(struct drm_device *dev); int nv50_head_crc_late_register(struct nv50_head *); void nv50_crc_handle_vblank(struct nv50_head *head); int nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *); const char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *); int nv50_crc_set_source(struct drm_crtc *, const char *); int nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *, struct nv50_head_atom *); void nv50_crc_atomic_check_outp(struct nv50_atom *atom); void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *); void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *); void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *); void nv50_crc_atomic_start_reporting(struct drm_atomic_state *); void nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *); void nv50_crc_atomic_clr(struct nv50_head *); extern const struct nv50_crc_func crc907d; extern const struct nv50_crc_func crcc37d; extern const struct nv50_crc_func crcc57d; #else /* IS_ENABLED(CONFIG_DEBUG_FS) */ struct nv50_crc {}; struct nv50_crc_func {}; struct nv50_crc_atom {}; #define nv50_crc_verify_source NULL #define nv50_crc_get_sources NULL #define nv50_crc_set_source NULL static inline void nv50_crc_init(struct drm_device *dev) {} static inline int nv50_head_crc_late_register(struct nv50_head *head) { return 0; } static inline void nv50_crc_handle_vblank(struct nv50_head *head) {} static inline int nv50_crc_atomic_check_head(struct nv50_head *head, struct nv50_head_atom *asyh, struct nv50_head_atom *armh) { return 0; } static inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {} static inline void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {} static inline void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {} static inline void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {} static inline void nv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {} static inline void nv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {} static inline void nv50_crc_atomic_clr(struct nv50_head *head) {} #endif /* IS_ENABLED(CONFIG_DEBUG_FS) */ #endif /* !__NV50_CRC_H__ */