summaryrefslogtreecommitdiff
path: root/nvkm/subdev/fb/ramfuc.h
blob: 430261a307a471974c0abc6694142ee254a232ba (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
#ifndef __NVKM_FBRAM_FUC_H__
#define __NVKM_FBRAM_FUC_H__

#include <subdev/pwr.h>

struct ramfuc {
	struct nouveau_memx *memx;
	struct nouveau_fb *pfb;
	int sequence;
};

struct ramfuc_reg {
	int sequence;
	bool force;
	u32 addr[2];
	u32 data;
};

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

static noinline struct ramfuc_reg
ramfuc_reg(u32 addr)
{
	return ramfuc_reg2(addr, addr);
}

static inline int
ramfuc_init(struct ramfuc *ram, struct nouveau_fb *pfb)
{
	struct nouveau_pwr *ppwr = nouveau_pwr(pfb);
	int ret;

	ret = nouveau_memx_init(ppwr, &ram->memx);
	if (ret)
		return ret;

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

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

static inline u32
ramfuc_rd32(struct ramfuc *ram, struct ramfuc_reg *reg)
{
	if (reg->sequence != ram->sequence)
		reg->data = nv_rd32(ram->pfb, reg->addr[0]);
	return reg->data;
}

static inline void
ramfuc_wr32(struct ramfuc *ram, struct ramfuc_reg *reg, u32 data)
{
	reg->sequence = ram->sequence;
	reg->data = data;
	if (reg->addr[0] != reg->addr[1])
		nouveau_memx_wr32(ram->memx, reg->addr[1], reg->data);
	nouveau_memx_wr32(ram->memx, reg->addr[0], reg->data);
}

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)
{
	nouveau_memx_wait(ram->memx, addr, mask, data, nsec);
}

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

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

static inline void
ramfuc_fb_disable(struct ramfuc *ram)
{
	nouveau_memx_fb_disable(ram->memx);
}

static inline void
ramfuc_fb_enable(struct ramfuc *ram)
{
	nouveau_memx_fb_enable(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[0] != 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_fb_disable(s)    ramfuc_fb_disable(&(s)->base)
#define ram_fb_enable(s)     ramfuc_fb_enable(&(s)->base)

#endif