Skip to content

Commit

Permalink
drm/nouveau/bus/hwsq: Implement VBLANK waiting heuristic
Browse files Browse the repository at this point in the history
Avoids waiting for VBLANKS that never arrive on headless or otherwise
unconventional set-ups. Strategy taken from MEMX.

Signed-off-by: Roy Spliet <rspliet@eclipso.eu>
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Roy Spliet authored and Ben Skeggs committed Nov 3, 2015
1 parent 4d9faaf commit 271c276
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 **);
Expand Down
32 changes: 32 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 271c276

Please sign in to comment.