18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: MIT */
28c2ecf20Sopenharmony_ci#ifndef __NV50_CRC_H__
38c2ecf20Sopenharmony_ci#define __NV50_CRC_H__
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/mutex.h>
68c2ecf20Sopenharmony_ci#include <drm/drm_crtc.h>
78c2ecf20Sopenharmony_ci#include <drm/drm_vblank_work.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <nvif/mem.h>
108c2ecf20Sopenharmony_ci#include <nvkm/subdev/bios.h>
118c2ecf20Sopenharmony_ci#include "nouveau_encoder.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistruct nv50_atom;
148c2ecf20Sopenharmony_cistruct nv50_disp;
158c2ecf20Sopenharmony_cistruct nv50_head;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DEBUG_FS)
188c2ecf20Sopenharmony_cienum nv50_crc_source {
198c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_NONE = 0,
208c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_AUTO,
218c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_RG,
228c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_ACTIVE,
238c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_COMPLETE,
248c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_INACTIVE,
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* RG -> SF (DP only)
288c2ecf20Sopenharmony_ci *    -> SOR
298c2ecf20Sopenharmony_ci *    -> PIOR
308c2ecf20Sopenharmony_ci *    -> DAC
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_cienum nv50_crc_source_type {
338c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_NONE = 0,
348c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_SOR,
358c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_PIOR,
368c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_DAC,
378c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_RG,
388c2ecf20Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_SF,
398c2ecf20Sopenharmony_ci};
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistruct nv50_crc_notifier_ctx {
428c2ecf20Sopenharmony_ci	struct nvif_mem mem;
438c2ecf20Sopenharmony_ci	struct nvif_object ntfy;
448c2ecf20Sopenharmony_ci};
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistruct nv50_crc_atom {
478c2ecf20Sopenharmony_ci	enum nv50_crc_source src;
488c2ecf20Sopenharmony_ci	/* Only used for gv100+ */
498c2ecf20Sopenharmony_ci	u8 wndw : 4;
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistruct nv50_crc_func {
538c2ecf20Sopenharmony_ci	int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type,
548c2ecf20Sopenharmony_ci		       struct nv50_crc_notifier_ctx *, u32 wndw);
558c2ecf20Sopenharmony_ci	int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *);
568c2ecf20Sopenharmony_ci	u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *,
578c2ecf20Sopenharmony_ci			 enum nv50_crc_source, int idx);
588c2ecf20Sopenharmony_ci	bool (*ctx_finished)(struct nv50_head *,
598c2ecf20Sopenharmony_ci			     struct nv50_crc_notifier_ctx *);
608c2ecf20Sopenharmony_ci	short flip_threshold;
618c2ecf20Sopenharmony_ci	short num_entries;
628c2ecf20Sopenharmony_ci	size_t notifier_len;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct nv50_crc {
668c2ecf20Sopenharmony_ci	spinlock_t lock;
678c2ecf20Sopenharmony_ci	struct nv50_crc_notifier_ctx ctx[2];
688c2ecf20Sopenharmony_ci	struct drm_vblank_work flip_work;
698c2ecf20Sopenharmony_ci	enum nv50_crc_source src;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	u64 frame;
728c2ecf20Sopenharmony_ci	short entry_idx;
738c2ecf20Sopenharmony_ci	short flip_threshold;
748c2ecf20Sopenharmony_ci	u8 ctx_idx : 1;
758c2ecf20Sopenharmony_ci	bool ctx_changed : 1;
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_civoid nv50_crc_init(struct drm_device *dev);
798c2ecf20Sopenharmony_ciint nv50_head_crc_late_register(struct nv50_head *);
808c2ecf20Sopenharmony_civoid nv50_crc_handle_vblank(struct nv50_head *head);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciint nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *);
838c2ecf20Sopenharmony_ciconst char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *);
848c2ecf20Sopenharmony_ciint nv50_crc_set_source(struct drm_crtc *, const char *);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciint nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
878c2ecf20Sopenharmony_ci			       struct nv50_head_atom *);
888c2ecf20Sopenharmony_civoid nv50_crc_atomic_check_outp(struct nv50_atom *atom);
898c2ecf20Sopenharmony_civoid nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
908c2ecf20Sopenharmony_civoid nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
918c2ecf20Sopenharmony_civoid nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
928c2ecf20Sopenharmony_civoid nv50_crc_atomic_start_reporting(struct drm_atomic_state *);
938c2ecf20Sopenharmony_civoid nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *);
948c2ecf20Sopenharmony_civoid nv50_crc_atomic_clr(struct nv50_head *);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ciextern const struct nv50_crc_func crc907d;
978c2ecf20Sopenharmony_ciextern const struct nv50_crc_func crcc37d;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci#else /* IS_ENABLED(CONFIG_DEBUG_FS) */
1008c2ecf20Sopenharmony_cistruct nv50_crc {};
1018c2ecf20Sopenharmony_cistruct nv50_crc_func {};
1028c2ecf20Sopenharmony_cistruct nv50_crc_atom {};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci#define nv50_crc_verify_source NULL
1058c2ecf20Sopenharmony_ci#define nv50_crc_get_sources NULL
1068c2ecf20Sopenharmony_ci#define nv50_crc_set_source NULL
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic inline void nv50_crc_init(struct drm_device *dev) {}
1098c2ecf20Sopenharmony_cistatic inline int
1108c2ecf20Sopenharmony_cinv50_head_crc_late_register(struct nv50_head *head) { return 0; }
1118c2ecf20Sopenharmony_cistatic inline void nv50_crc_handle_vblank(struct nv50_head *head) {}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic inline int
1148c2ecf20Sopenharmony_cinv50_crc_atomic_check_head(struct nv50_head *head,
1158c2ecf20Sopenharmony_ci			   struct nv50_head_atom *asyh,
1168c2ecf20Sopenharmony_ci			   struct nv50_head_atom *armh) { return 0; }
1178c2ecf20Sopenharmony_cistatic inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
1188c2ecf20Sopenharmony_cistatic inline void
1198c2ecf20Sopenharmony_cinv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {}
1208c2ecf20Sopenharmony_cistatic inline void
1218c2ecf20Sopenharmony_cinv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {}
1228c2ecf20Sopenharmony_cistatic inline void
1238c2ecf20Sopenharmony_cinv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {}
1248c2ecf20Sopenharmony_cistatic inline void
1258c2ecf20Sopenharmony_cinv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {}
1268c2ecf20Sopenharmony_cistatic inline void
1278c2ecf20Sopenharmony_cinv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {}
1288c2ecf20Sopenharmony_cistatic inline void
1298c2ecf20Sopenharmony_cinv50_crc_atomic_clr(struct nv50_head *head) {}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
1328c2ecf20Sopenharmony_ci#endif /* !__NV50_CRC_H__ */
133