Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 271c2766 authored by Roy Spliet's avatar Roy Spliet Committed by Ben Skeggs
Browse files

drm/nouveau/bus/hwsq: Implement VBLANK waiting heuristic



Avoids waiting for VBLANKS that never arrive on headless or otherwise
unconventional set-ups. Strategy taken from MEMX.

Signed-off-by: default avatarRoy Spliet <rspliet@eclipso.eu>
Tested-by: default avatarPierre Moreau <pierre.morrow@free.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4d9faafa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ int nvkm_hwsq_fini(struct nvkm_hwsq **, bool exec);
void nvkm_hwsq_wr32(struct nvkm_hwsq *, u32 addr, u32 data);
void nvkm_hwsq_setf(struct nvkm_hwsq *, u8 flag, int data);
void nvkm_hwsq_wait(struct nvkm_hwsq *, u8 flag, u8 data);
void nvkm_hwsq_wait_vblank(struct nvkm_hwsq *);
void nvkm_hwsq_nsec(struct nvkm_hwsq *, u32 nsec);

int nv04_bus_new(struct nvkm_device *, int, struct nvkm_bus **);
+32 −0
Original line number Diff line number Diff line
@@ -131,6 +131,38 @@ nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data)
	hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, data });
}

void
nvkm_hwsq_wait_vblank(struct nvkm_hwsq *hwsq)
{
	struct nvkm_subdev *subdev = hwsq->subdev;
	struct nvkm_device *device = subdev->device;
	u32 heads, x, y, px = 0;
	int i, head_sync;

	heads = nvkm_rd32(device, 0x610050);
	for (i = 0; i < 2; i++) {
		/* Heuristic: sync to head with biggest resolution */
		if (heads & (2 << (i << 3))) {
			x = nvkm_rd32(device, 0x610b40 + (0x540 * i));
			y = (x & 0xffff0000) >> 16;
			x &= 0x0000ffff;
			if ((x * y) > px) {
				px = (x * y);
				head_sync = i;
			}
		}
	}

	if (px == 0) {
		nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n");
		return;
	}

	nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync);
	nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x0);
	nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x1);
}

void
nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec)
{
+6 −0
Original line number Diff line number Diff line
@@ -133,6 +133,12 @@ hwsq_wait(struct hwsq *ram, u8 flag, u8 data)
	nvkm_hwsq_wait(ram->hwsq, flag, data);
}

static inline void
hwsq_wait_vblank(struct hwsq *ram)
{
	nvkm_hwsq_wait_vblank(ram->hwsq);
}

static inline void
hwsq_nsec(struct hwsq *ram, u32 nsec)
{
+1 −2
Original line number Diff line number Diff line
@@ -308,8 +308,7 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
	/* Always disable this bit during reclock */
	ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000);

	ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */
	ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */
	ram_wait_vblank(hwsq);
	ram_wr32(hwsq, 0x611200, 0x00003300);
	ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */
	ram_nsec(hwsq, 8000);
+1 −0
Original line number Diff line number Diff line
@@ -11,5 +11,6 @@
#define ram_mask(s,r,m,d)   hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d))
#define ram_setf(s,f,d)     hwsq_setf(&(s)->base, (f), (d))
#define ram_wait(s,f,d)     hwsq_wait(&(s)->base, (f), (d))
#define ram_wait_vblank(s)  hwsq_wait_vblank(&(s)->base)
#define ram_nsec(s,n)       hwsq_nsec(&(s)->base, (n))
#endif