drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
Extension
.c
Size
33537 bytes
Lines
1255
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct gv100_disp_caps {
	struct nvkm_object object;
	struct nvkm_disp *disp;
};

static int
gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc,
		    enum nvkm_object_map *type, u64 *addr, u64 *size)
{
	struct gv100_disp_caps *caps = gv100_disp_caps(object);
	struct nvkm_device *device = caps->disp->engine.subdev.device;
	*type = NVKM_OBJECT_MAP_IO;
	*addr = 0x640000 + device->func->resource_addr(device, NVKM_BAR0_PRI);
	*size = 0x1000;
	return 0;
}

static const struct nvkm_object_func
gv100_disp_caps = {
	.map = gv100_disp_caps_map,
};

int
gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
		    struct nvkm_object **pobject)
{
	struct nvkm_disp *disp = nvkm_udisp(oclass->parent);
	struct gv100_disp_caps *caps;

	if (!(caps = kzalloc_obj(*caps)))
		return -ENOMEM;
	*pobject = &caps->object;

	nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object);
	caps->disp = disp;
	return 0;
}

void
gv100_disp_super(struct work_struct *work)
{
	struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work);
	struct nvkm_subdev *subdev = &disp->engine.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_head *head;
	u32 stat, mask[4];

	mutex_lock(&disp->super.mutex);
	stat = nvkm_rd32(device, 0x6107a8);

	nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat);
	list_for_each_entry(head, &disp->heads, head) {
		mask[head->id] = nvkm_rd32(device, 0x6107ac + (head->id * 4));
		HEAD_DBG(head, "%08x", mask[head->id]);
	}

	if (disp->super.pending & 0x00000001) {
		nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
		nv50_disp_super_1(disp);
		list_for_each_entry(head, &disp->heads, head) {
			if (!(mask[head->id] & 0x00001000))
				continue;
			nv50_disp_super_1_0(disp, head);
		}
	} else
	if (disp->super.pending & 0x00000002) {
		list_for_each_entry(head, &disp->heads, head) {
			if (!(mask[head->id] & 0x00001000))
				continue;
			nv50_disp_super_2_0(disp, head);
		}
		list_for_each_entry(head, &disp->heads, head) {
			if (!(mask[head->id] & 0x00010000))
				continue;
			nv50_disp_super_2_1(disp, head);
		}
		list_for_each_entry(head, &disp->heads, head) {
			if (!(mask[head->id] & 0x00001000))
				continue;
			nv50_disp_super_2_2(disp, head);
		}
	} else
	if (disp->super.pending & 0x00000004) {
		list_for_each_entry(head, &disp->heads, head) {
			if (!(mask[head->id] & 0x00001000))
				continue;
			nv50_disp_super_3_0(disp, head);
		}
	}

Annotation

Implementation Notes