summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/dispnv50/crc.h
blob: 4fce871b04c89702f245e8550438b7d7b01218b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
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
53
54
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* 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"

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;
	/* Only used for gv100+ */
	u8 wndw : 4;
};

struct nv50_crc_func {
	int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type,
		       struct nv50_crc_notifier_ctx *, u32 wndw);
	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;

#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__ */