162306a36Sopenharmony_ci/* SPDX-License-Identifier: MIT */
262306a36Sopenharmony_ci#ifndef __NV50_CRC_H__
362306a36Sopenharmony_ci#define __NV50_CRC_H__
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/mutex.h>
662306a36Sopenharmony_ci#include <drm/drm_crtc.h>
762306a36Sopenharmony_ci#include <drm/drm_vblank_work.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <nvif/mem.h>
1062306a36Sopenharmony_ci#include <nvkm/subdev/bios.h>
1162306a36Sopenharmony_ci#include "nouveau_encoder.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistruct nv50_atom;
1462306a36Sopenharmony_cistruct nv50_disp;
1562306a36Sopenharmony_cistruct nv50_head;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DEBUG_FS)
1862306a36Sopenharmony_cienum nv50_crc_source {
1962306a36Sopenharmony_ci	NV50_CRC_SOURCE_NONE = 0,
2062306a36Sopenharmony_ci	NV50_CRC_SOURCE_AUTO,
2162306a36Sopenharmony_ci	NV50_CRC_SOURCE_RG,
2262306a36Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_ACTIVE,
2362306a36Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_COMPLETE,
2462306a36Sopenharmony_ci	NV50_CRC_SOURCE_OUTP_INACTIVE,
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* RG -> SF (DP only)
2862306a36Sopenharmony_ci *    -> SOR
2962306a36Sopenharmony_ci *    -> PIOR
3062306a36Sopenharmony_ci *    -> DAC
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_cienum nv50_crc_source_type {
3362306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_NONE = 0,
3462306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_SOR,
3562306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_PIOR,
3662306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_DAC,
3762306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_RG,
3862306a36Sopenharmony_ci	NV50_CRC_SOURCE_TYPE_SF,
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct nv50_crc_notifier_ctx {
4262306a36Sopenharmony_ci	struct nvif_mem mem;
4362306a36Sopenharmony_ci	struct nvif_object ntfy;
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct nv50_crc_atom {
4762306a36Sopenharmony_ci	enum nv50_crc_source src;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct nv50_crc_func {
5162306a36Sopenharmony_ci	int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type type,
5262306a36Sopenharmony_ci		       struct nv50_crc_notifier_ctx *ctx);
5362306a36Sopenharmony_ci	int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *);
5462306a36Sopenharmony_ci	u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *,
5562306a36Sopenharmony_ci			 enum nv50_crc_source, int idx);
5662306a36Sopenharmony_ci	bool (*ctx_finished)(struct nv50_head *,
5762306a36Sopenharmony_ci			     struct nv50_crc_notifier_ctx *);
5862306a36Sopenharmony_ci	short flip_threshold;
5962306a36Sopenharmony_ci	short num_entries;
6062306a36Sopenharmony_ci	size_t notifier_len;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct nv50_crc {
6462306a36Sopenharmony_ci	spinlock_t lock;
6562306a36Sopenharmony_ci	struct nv50_crc_notifier_ctx ctx[2];
6662306a36Sopenharmony_ci	struct drm_vblank_work flip_work;
6762306a36Sopenharmony_ci	enum nv50_crc_source src;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	u64 frame;
7062306a36Sopenharmony_ci	short entry_idx;
7162306a36Sopenharmony_ci	short flip_threshold;
7262306a36Sopenharmony_ci	u8 ctx_idx : 1;
7362306a36Sopenharmony_ci	bool ctx_changed : 1;
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_civoid nv50_crc_init(struct drm_device *dev);
7762306a36Sopenharmony_ciint nv50_head_crc_late_register(struct nv50_head *);
7862306a36Sopenharmony_civoid nv50_crc_handle_vblank(struct nv50_head *head);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciint nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *);
8162306a36Sopenharmony_ciconst char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *);
8262306a36Sopenharmony_ciint nv50_crc_set_source(struct drm_crtc *, const char *);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciint nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
8562306a36Sopenharmony_ci			       struct nv50_head_atom *);
8662306a36Sopenharmony_civoid nv50_crc_atomic_check_outp(struct nv50_atom *atom);
8762306a36Sopenharmony_civoid nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
8862306a36Sopenharmony_civoid nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
8962306a36Sopenharmony_civoid nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
9062306a36Sopenharmony_civoid nv50_crc_atomic_start_reporting(struct drm_atomic_state *);
9162306a36Sopenharmony_civoid nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *);
9262306a36Sopenharmony_civoid nv50_crc_atomic_clr(struct nv50_head *);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciextern const struct nv50_crc_func crc907d;
9562306a36Sopenharmony_ciextern const struct nv50_crc_func crcc37d;
9662306a36Sopenharmony_ciextern const struct nv50_crc_func crcc57d;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#else /* IS_ENABLED(CONFIG_DEBUG_FS) */
9962306a36Sopenharmony_cistruct nv50_crc {};
10062306a36Sopenharmony_cistruct nv50_crc_func {};
10162306a36Sopenharmony_cistruct nv50_crc_atom {};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define nv50_crc_verify_source NULL
10462306a36Sopenharmony_ci#define nv50_crc_get_sources NULL
10562306a36Sopenharmony_ci#define nv50_crc_set_source NULL
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic inline void nv50_crc_init(struct drm_device *dev) {}
10862306a36Sopenharmony_cistatic inline int
10962306a36Sopenharmony_cinv50_head_crc_late_register(struct nv50_head *head) { return 0; }
11062306a36Sopenharmony_cistatic inline void nv50_crc_handle_vblank(struct nv50_head *head) {}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic inline int
11362306a36Sopenharmony_cinv50_crc_atomic_check_head(struct nv50_head *head,
11462306a36Sopenharmony_ci			   struct nv50_head_atom *asyh,
11562306a36Sopenharmony_ci			   struct nv50_head_atom *armh) { return 0; }
11662306a36Sopenharmony_cistatic inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
11762306a36Sopenharmony_cistatic inline void
11862306a36Sopenharmony_cinv50_crc_atomic_stop_reporting(struct drm_atomic_state *state) {}
11962306a36Sopenharmony_cistatic inline void
12062306a36Sopenharmony_cinv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *state) {}
12162306a36Sopenharmony_cistatic inline void
12262306a36Sopenharmony_cinv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *state) {}
12362306a36Sopenharmony_cistatic inline void
12462306a36Sopenharmony_cinv50_crc_atomic_start_reporting(struct drm_atomic_state *state) {}
12562306a36Sopenharmony_cistatic inline void
12662306a36Sopenharmony_cinv50_crc_atomic_set(struct nv50_head *head, struct nv50_head_atom *state) {}
12762306a36Sopenharmony_cistatic inline void
12862306a36Sopenharmony_cinv50_crc_atomic_clr(struct nv50_head *head) {}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
13162306a36Sopenharmony_ci#endif /* !__NV50_CRC_H__ */
132