summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h
blob: a65fa5586af8a354264a0efa527dc878e9f645a9 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NVKM_FBRAM_FUC_H__
#define __NVKM_FBRAM_FUC_H__
#include <subdev/fb.h>
#include <subdev/pmu.h>

struct ramfuc {
	struct nvkm_memx *memx;
	struct nvkm_fb *fb;
	int sequence;
};

struct ramfuc_reg {
	int sequence;
	bool force;
	u32 addr;
	u32 stride; /* in bytes */
	u32 mask;
	u32 data;
};

static inline struct ramfuc_reg
ramfuc_stride(u32 addr, u32 stride, u32 mask)
{
	return (struct ramfuc_reg) {
		.sequence = 0,
		.addr = addr,
		.stride = stride,
		.mask = mask,
		.data = 0xdeadbeef,
	};
}

static inline struct ramfuc_reg
ramfuc_reg2(u32 addr1, u32 addr2)
{
	return (struct ramfuc_reg) {
		.sequence = 0,
		.addr = addr1,
		.stride = addr2 - addr1,
		.mask = 0x3,
		.data = 0xdeadbeef,
	};
}

static noinline struct ramfuc_reg
ramfuc_reg(u32 addr)
{
	return (struct ramfuc_reg) {
		.sequence = 0,
		.addr = addr,
		.stride = 0,
		.mask = 0x1,
		.data = 0xdeadbeef,
	};
}

static inline int
ramfuc_init(struct ramfuc *ram, struct nvkm_fb *fb)
{
	int ret = nvkm_memx_init(fb->subdev.device->pmu, &ram->memx);
	if (ret)
		return ret;

	ram->sequence++;
	ram->fb = fb;
	return 0;
}

static inline int
ramfuc_exec(struct ramfuc *ram, bool exec)
{
	int ret = 0;
	if (ram->fb) {
		ret = nvkm_memx_fini(&ram->memx, exec);
		ram->fb = NULL;
	}
	return ret;
}

static inline u32
ramfuc_rd32(struct ramfuc *ram, struct ramfuc_reg *reg)
{
	struct nvkm_device *device = ram->fb->subdev.device;
	if (reg->sequence != ram->sequence)
		reg->data = nvkm_rd32(device, reg->addr);
	return reg->data;
}

static inline void
ramfuc_wr32(struct ramfuc *ram, struct ramfuc_reg *reg, u32 data)
{
	unsigned int mask, off = 0;

	reg->sequence = ram->sequence;
	reg->data = data;

	for (mask = reg->mask; mask > 0; mask = (mask & ~1) >> 1) {
		if (mask & 1)
			nvkm_memx_wr32(ram->memx, reg->addr+off, reg->data);
		off += reg->stride;
	}
}

static inline void
ramfuc_nuke(struct ramfuc *ram, struct ramfuc_reg *reg)
{
	reg->force = true;
}

static inline u32
ramfuc_mask(struct ramfuc *ram, struct ramfuc_reg *reg, u32 mask, u32 data)
{
	u32 temp = ramfuc_rd32(ram, reg);
	if (temp != ((temp & ~mask) | data) || reg->force) {
		ramfuc_wr32(ram, reg, (temp & ~mask) | data);
		reg->force = false;
	}
	return temp;
}

static inline void
ramfuc_wait(struct ramfuc *ram, u32 addr, u32 mask, u32 data, u32 nsec)
{
	nvkm_memx_wait(ram->memx, addr, mask, data, nsec);
}

static inline void
ramfuc_nsec(struct ramfuc *ram, u32 nsec)
{
	nvkm_memx_nsec(ram->memx, nsec);
}

static inline void
ramfuc_wait_vblank(struct ramfuc *ram)
{
	nvkm_memx_wait_vblank(ram->memx);
}

static inline void
ramfuc_train(struct ramfuc *ram)
{
	nvkm_memx_train(ram->memx);
}

static inline int
ramfuc_train_result(struct nvkm_fb *fb, u32 *result, u32 rsize)
{
	return nvkm_memx_train_result(fb->subdev.device->pmu, result, rsize);
}

static inline void
ramfuc_block(struct ramfuc *ram)
{
	nvkm_memx_block(ram->memx);
}

static inline void
ramfuc_unblock(struct ramfuc *ram)
{
	nvkm_memx_unblock(ram->memx);
}

#define ram_init(s,p)        ramfuc_init(&(s)->base, (p))
#define ram_exec(s,e)        ramfuc_exec(&(s)->base, (e))
#define ram_have(s,r)        ((s)->r_##r.addr != 0x000000)
#define ram_rd32(s,r)        ramfuc_rd32(&(s)->base, &(s)->r_##r)
#define ram_wr32(s,r,d)      ramfuc_wr32(&(s)->base, &(s)->r_##r, (d))
#define ram_nuke(s,r)        ramfuc_nuke(&(s)->base, &(s)->r_##r)
#define ram_mask(s,r,m,d)    ramfuc_mask(&(s)->base, &(s)->r_##r, (m), (d))
#define ram_wait(s,r,m,d,n)  ramfuc_wait(&(s)->base, (r), (m), (d), (n))
#define ram_nsec(s,n)        ramfuc_nsec(&(s)->base, (n))
#define ram_wait_vblank(s)   ramfuc_wait_vblank(&(s)->base)
#define ram_train(s)         ramfuc_train(&(s)->base)
#define ram_train_result(s,r,l) ramfuc_train_result((s), (r), (l))
#define ram_block(s)         ramfuc_block(&(s)->base)
#define ram_unblock(s)       ramfuc_unblock(&(s)->base)
#endif