aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/include/core/device.h
blob: 2ec2e50d3676607208ac8c1e5c5e58fc7ca9596a (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
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
179
180
181
182
183
184
#ifndef __NOUVEAU_DEVICE_H__
#define __NOUVEAU_DEVICE_H__

#include <core/object.h>
#include <core/subdev.h>
#include <core/engine.h>
#include <core/event.h>

enum nv_subdev_type {
	NVDEV_ENGINE_DEVICE,
	NVDEV_SUBDEV_VBIOS,

	/* All subdevs from DEVINIT to DEVINIT_LAST will be created before
	 * *any* of them are initialised.  This subdev category is used
	 * for any subdevs that the VBIOS init table parsing may call out
	 * to during POST.
	 */
	NVDEV_SUBDEV_DEVINIT,
	NVDEV_SUBDEV_IBUS,
	NVDEV_SUBDEV_GPIO,
	NVDEV_SUBDEV_I2C,
	NVDEV_SUBDEV_DEVINIT_LAST = NVDEV_SUBDEV_I2C,

	/* This grouping of subdevs are initialised right after they've
	 * been created, and are allowed to assume any subdevs in the
	 * list above them exist and have been initialised.
	 */
	NVDEV_SUBDEV_FUSE,
	NVDEV_SUBDEV_MXM,
	NVDEV_SUBDEV_MC,
	NVDEV_SUBDEV_BUS,
	NVDEV_SUBDEV_TIMER,
	NVDEV_SUBDEV_FB,
	NVDEV_SUBDEV_LTC,
	NVDEV_SUBDEV_INSTMEM,
	NVDEV_SUBDEV_VM,
	NVDEV_SUBDEV_BAR,
	NVDEV_SUBDEV_PWR,
	NVDEV_SUBDEV_VOLT,
	NVDEV_SUBDEV_THERM,
	NVDEV_SUBDEV_CLOCK,

	NVDEV_ENGINE_FIRST,
	NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
	NVDEV_ENGINE_IFB,
	NVDEV_ENGINE_FIFO,
	NVDEV_ENGINE_SW,
	NVDEV_ENGINE_GR,
	NVDEV_ENGINE_MPEG,
	NVDEV_ENGINE_ME,
	NVDEV_ENGINE_VP,
	NVDEV_ENGINE_CRYPT,
	NVDEV_ENGINE_BSP,
	NVDEV_ENGINE_PPP,
	NVDEV_ENGINE_COPY0,
	NVDEV_ENGINE_COPY1,
	NVDEV_ENGINE_COPY2,
	NVDEV_ENGINE_VIC,
	NVDEV_ENGINE_VENC,
	NVDEV_ENGINE_DISP,
	NVDEV_ENGINE_PERFMON,

	NVDEV_SUBDEV_NR,
};

struct nouveau_device {
	struct nouveau_engine base;
	struct list_head head;

	struct pci_dev *pdev;
	struct platform_device *platformdev;
	u64 handle;

	struct nvkm_event event;

	const char *cfgopt;
	const char *dbgopt;
	const char *name;
	const char *cname;
	u64 disable_mask;

	enum {
		NV_04    = 0x04,
		NV_10    = 0x10,
		NV_11    = 0x11,
		NV_20    = 0x20,
		NV_30    = 0x30,
		NV_40    = 0x40,
		NV_50    = 0x50,
		NV_C0    = 0xc0,
		NV_E0    = 0xe0,
		GM100    = 0x110,
	} card_type;
	u32 chipset;
	u8  chiprev;
	u32 crystal;

	struct nouveau_oclass *oclass[NVDEV_SUBDEV_NR];
	struct nouveau_object *subdev[NVDEV_SUBDEV_NR];

	struct {
		struct notifier_block nb;
	} acpi;
};

int nouveau_device_list(u64 *name, int size);

static inline struct nouveau_device *
nv_device(void *obj)
{
	struct nouveau_object *object = nv_object(obj);
	struct nouveau_object *device = object;

	if (device->engine)
		device = device->engine;
	if (device->parent)
		device = device->parent;

#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
	if (unlikely(!nv_iclass(device, NV_SUBDEV_CLASS) ||
		     (nv_hclass(device) & 0xff) != NVDEV_ENGINE_DEVICE)) {
		nv_assert("BAD CAST -> NvDevice, 0x%08x 0x%08x",
			  nv_hclass(object), nv_hclass(device));
	}
#endif

	return (void *)device;
}

static inline struct nouveau_subdev *
nouveau_subdev(void *obj, int sub)
{
	if (nv_device(obj)->subdev[sub])
		return nv_subdev(nv_device(obj)->subdev[sub]);
	return NULL;
}

static inline struct nouveau_engine *
nouveau_engine(void *obj, int sub)
{
	struct nouveau_subdev *subdev = nouveau_subdev(obj, sub);
	if (subdev && nv_iclass(subdev, NV_ENGINE_CLASS))
		return nv_engine(subdev);
	return NULL;
}

static inline bool
nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub)
{
	struct nouveau_device *device = nv_device(object);
	return device->pdev->device == dev &&
	       device->pdev->subsystem_vendor == ven &&
	       device->pdev->subsystem_device == sub;
}

static inline bool
nv_device_is_pci(struct nouveau_device *device)
{
	return device->pdev != NULL;
}

static inline bool
nv_device_is_cpu_coherent(struct nouveau_device *device)
{
	return (!IS_ENABLED(CONFIG_ARM) && nv_device_is_pci(device));
}

static inline struct device *
nv_device_base(struct nouveau_device *device)
{
	return nv_device_is_pci(device) ? &device->pdev->dev :
					  &device->platformdev->dev;
}

resource_size_t
nv_device_resource_start(struct nouveau_device *device, unsigned int bar);

resource_size_t
nv_device_resource_len(struct nouveau_device *device, unsigned int bar);

int
nv_device_get_irq(struct nouveau_device *device, bool stall);

#endif