crc.h 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/* SPDX-License-Identifier: MIT */
#ifndef __NV50_CRC_H__
#define __NV50_CRC_H__

#include <linux/mutex.h>
#include <drm/drm_crtc.h>
#include <drm/drm_vblank_work.h>

#include <nvif/mem.h>
#include <nvkm/subdev/bios.h>
#include "nouveau_encoder.h"

13
struct nv50_atom;
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
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;
	/* Only used for gv100+ */
	u8 wndw : 4;
};

struct nv50_crc_func {
53 54
	int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type,
		       struct nv50_crc_notifier_ctx *, u32 wndw);
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
	void (*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 *);

86 87 88
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);
89
void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *);
90 91
void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *);
void nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *);
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
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;

#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 *) {}
static inline void
nv50_crc_handle_vblank(struct nv50_head *head) { return 0; }

static inline int
114 115 116
nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *,
			   struct nv50_head_atom *) {}
static inline void nv50_crc_atomic_check_outp(struct nv50_atom *atom) {}
117 118 119
static inline void
nv50_crc_atomic_stop_reporting(struct drm_atomic_state *) {}
static inline void
120 121 122
nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *) {}
static inline void
nv50_crc_atomic_release_notifier_contexts(struct drm_atomic_state *) {}
123 124 125 126 127 128 129 130 131
static inline void
nv50_crc_atomic_start_reporting(struct drm_atomic_state *) {}
static inline void
nv50_crc_atomic_set(struct nv50_head *, struct nv50_head_atom *) {}
static inline void
nv50_crc_atomic_clr(struct nv50_head *) {}

#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
#endif /* !__NV50_CRC_H__ */